mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-02 22:06:21 +01:00
perf(physics): performance.multithreading switches the work over many threads, which each job sizes by how much it has: the physics steps a thread per 128 vehicle steps, up to all logical cores
This commit is contained in:
@@ -14,13 +14,16 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <semaphore>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
// threads for work split into independent parts, as many as Global.performance_cpucores asks for (0: all logical cores of the
|
||||
// machine). the thread which asks for the work takes part in it too, so the pool keeps one thread fewer. the threads wait between
|
||||
// the jobs, and the pool is made again when the setting changes
|
||||
// threads for work split into independent parts (Global.performance_multithreading). each job says how many threads its work is
|
||||
// worth, up to all the logical cores of the machine; the thread which asks for the work takes part in it too. the threads are
|
||||
// made when a job asks for more of them than there are, and wait between the jobs: a job wakes as many of them as it wants, each
|
||||
// by a semaphore of its own
|
||||
class worker_pool
|
||||
{
|
||||
public:
|
||||
@@ -29,32 +32,41 @@ class worker_pool
|
||||
worker_pool &operator=(worker_pool const &) = delete;
|
||||
~worker_pool();
|
||||
|
||||
// threads which take part in run(), the calling one included, by the current setting
|
||||
std::size_t size();
|
||||
// calls Work(index) once for each index below Count, spread over the threads, and returns when all the calls are done. the
|
||||
// calls of one index follow no order. not reentrant: Work can't call run(). an exception thrown by Work is passed on, once
|
||||
// the other calls are done
|
||||
void run(std::size_t const Count, std::function<void(std::size_t)> const &Work);
|
||||
// threads a job can get, the calling one included: all the logical cores with Global.performance_multithreading, otherwise one
|
||||
static std::size_t capacity();
|
||||
// calls Work(index) once for each index below Count, on at most Threads threads (the calling one included, at most capacity()),
|
||||
// and returns when all the calls are done. the calls follow no order. not reentrant: Work can't call run(). an exception
|
||||
// thrown by Work is passed on, once the other calls are done
|
||||
void run(std::size_t const Count, std::size_t const Threads, std::function<void(std::size_t)> const &Work);
|
||||
// threads made so far, the calling one included
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_threads.size() + 1;
|
||||
}
|
||||
|
||||
private:
|
||||
void resize(std::size_t const Workers);
|
||||
// Generation: of the last job begun before the thread was made
|
||||
void worker(unsigned int Generation);
|
||||
struct thread_data
|
||||
{
|
||||
std::binary_semaphore start{0}; // released for each job the thread takes part in, and to stop it
|
||||
std::thread thread;
|
||||
};
|
||||
|
||||
// makes threads up to the given count
|
||||
void grow(std::size_t const Workers);
|
||||
void worker(thread_data &Data);
|
||||
// takes the indices left of the current job
|
||||
void work(std::function<void(std::size_t)> const &Work, std::size_t const Count);
|
||||
|
||||
std::vector<std::thread> m_threads;
|
||||
std::vector<std::unique_ptr<thread_data>> m_threads;
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_start;
|
||||
std::condition_variable m_done;
|
||||
// the current job
|
||||
// the current job, set before the threads are woken for it
|
||||
std::function<void(std::size_t)> const *m_work{nullptr};
|
||||
std::size_t m_count{0};
|
||||
std::atomic<std::size_t> m_next{0};
|
||||
std::size_t m_busy{0}; // threads of the pool still in it
|
||||
unsigned int m_generation{0}; // of the jobs, for the threads to tell a new one
|
||||
std::size_t m_busy{0}; // threads of the pool woken for it which aren't done
|
||||
std::exception_ptr m_exception;
|
||||
bool m_stop{false};
|
||||
std::atomic<bool> m_stop{false};
|
||||
};
|
||||
|
||||
// the pool of the application
|
||||
|
||||
Reference in New Issue
Block a user