From 2dc94d4041aedc780815a68e4dca58a98d71c114 Mon Sep 17 00:00:00 2001 From: fspadoni Date: Fri, 15 Feb 2019 16:16:30 +0100 Subject: [PATCH 01/10] [TaskScheduler] Change the interface for Task class and add the CpuTask implementation base class for all tasks executed on the CPU --- .../simulation/TaskSchedulerTestTasks.cpp | 4 +- .../simulation/TaskSchedulerTests.cpp | 4 +- .../sofa/simulation/DefaultTaskScheduler.cpp | 10 +- .../sofa/simulation/DefaultTaskScheduler.h | 23 +-- .../framework/sofa/simulation/InitTasks.cpp | 2 +- SofaKernel/framework/sofa/simulation/Task.cpp | 75 ++++---- SofaKernel/framework/sofa/simulation/Task.h | 160 ++++++++++-------- .../sofa/simulation/TaskScheduler.cpp | 44 ++--- .../framework/sofa/simulation/TaskScheduler.h | 5 +- .../src/AnimationLoopParallelScheduler.cpp | 2 +- .../src/BeamLinearMapping_mt.inl | 6 +- 11 files changed, 189 insertions(+), 146 deletions(-) diff --git a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.cpp b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.cpp index e5b425c1a87..85c3170e2b2 100644 --- a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.cpp +++ b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.cpp @@ -16,7 +16,7 @@ namespace sofa return MemoryAlloc::Stack; } - Task::Status status; + simulation::CpuTask::Status status; int64_t x, y; @@ -48,7 +48,7 @@ namespace sofa const int64_t mid = _first + (count / 2); - Task::Status status; + simulation::CpuTask::Status status; int64_t x, y; diff --git a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTests.cpp b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTests.cpp index f22fe39bcd1..e0dd61c04eb 100644 --- a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTests.cpp +++ b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTests.cpp @@ -13,7 +13,7 @@ namespace sofa simulation::TaskScheduler* scheduler = simulation::TaskScheduler::create(simulation::DefaultTaskScheduler::name()); scheduler->init(nbThread); - simulation::Task::Status status; + simulation::CpuTask::Status status; int64_t result = 0; FibonacciTask task(N, &result, &status); @@ -31,7 +31,7 @@ namespace sofa simulation::TaskScheduler* scheduler = simulation::TaskScheduler::create(simulation::DefaultTaskScheduler::name()); scheduler->init(nbThread); - simulation::Task::Status status; + simulation::CpuTask::Status status; int64_t result = 0; IntSumTask task(1, N, &result, &status); diff --git a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp index 52a4df92ddf..a6e48744bab 100644 --- a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp +++ b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp @@ -185,6 +185,12 @@ namespace sofa return thread->getName(); } + int DefaultTaskScheduler::GetCurrentThreadType() + { + WorkerThread* thread = WorkerThread::getCurrent(); + return thread->getType(); + } + bool DefaultTaskScheduler::addTask(Task* task) { WorkerThread* thread = WorkerThread::getCurrent(); @@ -220,8 +226,8 @@ namespace sofa WorkerThread::WorkerThread(DefaultTaskScheduler* const& pScheduler, const int index, const std::string& name) - : _name(name + std::to_string(index)) - , _index(index) + : _type(0) + , _name(name + std::to_string(index)) , _tasks() , _taskScheduler(pScheduler) { diff --git a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h index 85750f886c0..3e2042880f6 100644 --- a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h +++ b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h @@ -86,9 +86,9 @@ namespace sofa { Task::Status* getCurrentStatus() const { return _currentStatus; } - const char* getName() { return _name.c_str(); } + const char* getName() const { return _name.c_str(); } - const size_t getIndex() { return _index; } + int getType() const { return _type; } const std::thread::id getId(); @@ -139,7 +139,7 @@ namespace sofa { const std::string _name; - const size_t _index; + const int _type; simulation::SpinLock _taskMutex; @@ -170,14 +170,17 @@ namespace sofa { public: // interface - void init(const unsigned int nbThread = 0) final; - void stop(void) final; - unsigned int getThreadCount(void) const final { return _threadCount; } - const char* getCurrentThreadName() final; + + virtual void init(const unsigned int nbThread = 0) final; + virtual void stop(void) final; + virtual unsigned int getThreadCount(void) const final { return _threadCount; } + virtual const char* getCurrentThreadName() override final; + virtual int GetCurrentThreadType() override final; + // queue task if there is space, and run it otherwise - bool addTask(Task* task) final; - void workUntilDone(Task::Status* status) final; - Task::Allocator* getTaskAllocator() final; + bool addTask(Task* task) override final; + void workUntilDone(Task::Status* status) override final; + Task::Allocator* getTaskAllocator() override final; public: diff --git a/SofaKernel/framework/sofa/simulation/InitTasks.cpp b/SofaKernel/framework/sofa/simulation/InitTasks.cpp index 463a9a5be3e..24a50e0470b 100644 --- a/SofaKernel/framework/sofa/simulation/InitTasks.cpp +++ b/SofaKernel/framework/sofa/simulation/InitTasks.cpp @@ -63,7 +63,7 @@ namespace sofa std::mutex InitThreadSpecificMutex; - Task::Status status; + CpuTask::Status status; const int nbThread = scheduler->getThreadCount(); for (int i = 0; i* atomicCounter, std::mutex* mutex, const Task::Status* status ) - : Task(status) - , _atomicCounter(atomicCounter) - , _threadSpecificMutex(mutex) - {} - - ThreadSpecificTask::~ThreadSpecificTask() - { - } - - Task::MemoryAlloc ThreadSpecificTask::run() - { - - runThreadSpecific(); - - { - std::lock_guard lock(*_threadSpecificMutex); - runCriticalThreadSpecific(); - } - - _atomicCounter->fetch_sub(1, std::memory_order_acq_rel); - - while(_atomicCounter->load(std::memory_order_relaxed) > 0) - { - // yield while waiting - std::this_thread::yield(); - } - return Task::MemoryAlloc::Stack; - } + CpuTask::CpuTask(const CpuTask::Status* status, int scheduledThread) + : Task(status, scheduledThread) + { + } + + CpuTask::~CpuTask() + { + } + + + + +// ThreadSpecificTask::ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, const Task::Status* status ) +// : Task(status) +// , _atomicCounter(atomicCounter) +// , _threadSpecificMutex(mutex) +// {} +// +// ThreadSpecificTask::~ThreadSpecificTask() +// { +// } +// +// Task::MemoryAlloc ThreadSpecificTask::run() +// { +// +// runThreadSpecific(); +// +// { +// std::lock_guard lock(*_threadSpecificMutex); +// runCriticalThreadSpecific(); +// } +// +// _atomicCounter->fetch_sub(1, std::memory_order_acq_rel); +// +// while(_atomicCounter->load(std::memory_order_relaxed) > 0) +// { +// // yield while waiting +// std::this_thread::yield(); +// } +// return Task::MemoryAlloc::Stack; +// } } // namespace simulation diff --git a/SofaKernel/framework/sofa/simulation/Task.h b/SofaKernel/framework/sofa/simulation/Task.h index a027ae642b8..f1958d6b2e7 100644 --- a/SofaKernel/framework/sofa/simulation/Task.h +++ b/SofaKernel/framework/sofa/simulation/Task.h @@ -37,62 +37,41 @@ namespace sofa class SOFA_SIMULATION_CORE_API Task { public: - + // Task Status class definition class Status { public: - Status() : _busy(0) {} - - bool isBusy() const - { - return (_busy.load(std::memory_order_relaxed) > 0); - } - - int setBusy(bool busy) - { - if (busy) - { - return _busy.fetch_add(1, std::memory_order_relaxed); - } - else - { - return _busy.fetch_sub(1, std::memory_order_relaxed); - } - } - - private: - std::atomic _busy; + + virtual bool isBusy() const = 0; + virtual int setBusy(bool busy) = 0; }; - - + class Allocator { public: virtual void* allocate(std::size_t sz) = 0; - + virtual void free(void* ptr, std::size_t sz) = 0; }; - - - Task(const Task::Status* status = nullptr); - + + + Task(const Task::Status* status = nullptr, int scheduledThread = 0); + virtual ~Task(); - - public: - + enum MemoryAlloc { Stack = 1 << 0, Dynamic = 1 << 1, Static = 1 << 2, }; - - + + + // Task interface: override these two functions virtual MemoryAlloc run() = 0; - - - + + static void* operator new (std::size_t sz) { return _allocator->allocate(sz); @@ -104,71 +83,110 @@ namespace sofa { _allocator->free(ptr, 0); } - - // only available in c++14. + + // only available in c++14. static void operator delete (void* ptr, std::size_t sz) { _allocator->free(ptr, sz); } - + // no array new and delete operators static void* operator new[](std::size_t sz) = delete; - + // visual studio 2015 complains about the = delete but it doens't explain where this operator is call // no problem with other sompilers included visual studio 2017 //static void operator delete[](void* ptr) = delete; - - - public: - inline Task::Status* getStatus(void) const - { - return const_cast(_status); - } - - + + inline Task::Status* getStatus(void) const { return const_cast(_status); } + + int getScheduledThread() const { return _scheduledThread; } + static Task::Allocator* getAllocator() { return _allocator; } - + static void setAllocator(Task::Allocator* allocator) { _allocator = allocator; } - + protected: - - const Task::Status* _status; - + + const Task::Status* _status; + + int _scheduledThread; + public: int _id; - + private: - + static Task::Allocator * _allocator; }; + + + class SOFA_SIMULATION_CORE_API CpuTask : public Task + { + public: + // Task Status class definition + class Status : public Task::Status + { + public: + Status() : _busy(0) {} + virtual bool isBusy() const override final + { + return (_busy.load(std::memory_order_relaxed) > 0); + } - // This task is called once by each thread used by the TasScheduler - // this is useful to initialize the thread specific variables - class SOFA_SIMULATION_CORE_API ThreadSpecificTask : public Task - { + virtual int setBusy(bool busy) override final + { + if (busy) + { + return _busy.fetch_add(1, std::memory_order_relaxed); + } + else + { + return _busy.fetch_sub(1, std::memory_order_relaxed); + } + } - public: + private: + std::atomic _busy; + }; - ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, const Task::Status* status); - ~ThreadSpecificTask() override; - MemoryAlloc run() final; + CpuTask(const CpuTask::Status* status = nullptr, int scheduledThread = 0); + virtual ~CpuTask(); - private: + }; - virtual bool runThreadSpecific() { return true; } - virtual bool runCriticalThreadSpecific() { return true; } - std::atomic* _atomicCounter; - std::mutex* _threadSpecificMutex; - }; +// // This task is called once by each thread used by the TasScheduler +// // this is useful to initialize the thread specific variables +// class SOFA_SIMULATION_CORE_API ThreadSpecificTask : public Task +// { +// +// public: +// +// ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, const Task::Status* status); +// +// ~ThreadSpecificTask() override; +// +// MemoryAlloc run() final; +// +// +// private: +// +// virtual bool runThreadSpecific() { return true; } +// +// virtual bool runCriticalThreadSpecific() { return true; } +// +// +// std::atomic* _atomicCounter; +// std::mutex* _threadSpecificMutex; +// }; } // namespace simulation diff --git a/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp b/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp index 667b8066989..917312fb88c 100644 --- a/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp +++ b/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp @@ -79,28 +79,28 @@ namespace sofa // called once by each thread used // by the TaskScheduler - bool runThreadSpecificTask(const Task* task) - { - SOFA_UNUSED(task); - std::atomic atomicCounter; - TaskScheduler* scheduler = TaskScheduler::getInstance(); - atomicCounter = scheduler->getThreadCount(); - - std::mutex InitThreadSpecificMutex; - - Task::Status status; - - const int nbThread = scheduler->getThreadCount(); - - for (int i = 0; iaddTask(new ThreadSpecificTask(&atomicCounter, &InitThreadSpecificMutex, &status)); - } - - scheduler->workUntilDone(&status); - - return true; - } +// bool runThreadSpecificTask(const Task* task) +// { +// SOFA_UNUSED(task); +// std::atomic atomicCounter; +// TaskScheduler* scheduler = TaskScheduler::getInstance(); +// atomicCounter = scheduler->getThreadCount(); +// +// std::mutex InitThreadSpecificMutex; +// +// CpuTask::Status status; +// +// const int nbThread = scheduler->getThreadCount(); +// +// for (int i = 0; iaddTask(new ThreadSpecificTask(&atomicCounter, &InitThreadSpecificMutex, &status)); +// } +// +// scheduler->workUntilDone(&status); +// +// return true; +// } } // namespace simulation diff --git a/SofaKernel/framework/sofa/simulation/TaskScheduler.h b/SofaKernel/framework/sofa/simulation/TaskScheduler.h index d677fa27bf5..61d4784004f 100644 --- a/SofaKernel/framework/sofa/simulation/TaskScheduler.h +++ b/SofaKernel/framework/sofa/simulation/TaskScheduler.h @@ -46,7 +46,8 @@ namespace sofa class SOFA_SIMULATION_CORE_API TaskScheduler { - public: + public: + virtual ~TaskScheduler(); @@ -69,6 +70,8 @@ namespace sofa virtual const char* getCurrentThreadName() = 0; + virtual int GetCurrentThreadType() = 0; + // queue task if there is space, and run it otherwise virtual bool addTask(Task* task) = 0; diff --git a/applications/plugins/MultiThreading/src/AnimationLoopParallelScheduler.cpp b/applications/plugins/MultiThreading/src/AnimationLoopParallelScheduler.cpp index 3a7bd97fd26..9a618f901cf 100644 --- a/applications/plugins/MultiThreading/src/AnimationLoopParallelScheduler.cpp +++ b/applications/plugins/MultiThreading/src/AnimationLoopParallelScheduler.cpp @@ -139,7 +139,7 @@ namespace simulation dt = this->gnode->getDt(); - Task::Status status; + simulation::CpuTask::Status status; typedef Node::Sequence::iterator ChildIterator; for (ChildIterator it = gnode->child.begin(), itend = gnode->child.end(); it != itend; ++it) diff --git a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl index 9f8fef12126..a40a95c3cb7 100644 --- a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl +++ b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl @@ -92,7 +92,7 @@ namespace mapping // create tasks - simulation::Task::Status status; + simulation::CpuTask::Status status; simulation::TaskScheduler* scheduler = simulation::TaskScheduler::getInstance(); const int taskSize = 2*mGrainSize.getValue(); @@ -186,7 +186,7 @@ namespace mapping out.resize(this->points.size()); - simulation::Task::Status status; + simulation::CpuTask::Status status; simulation::TaskScheduler* scheduler = simulation::TaskScheduler::getInstance(); const int taskSize = 2*mGrainSize.getValue(); @@ -273,7 +273,7 @@ namespace mapping helper::ReadAccessor< Data< typename Out::VecDeriv > > in = _in; - simulation::Task::Status status; + simulation::CpuTask::Status status; simulation::TaskScheduler* scheduler = simulation::TaskScheduler::getInstance(); const int taskSize = 2*mGrainSize.getValue(); From 9abf52febb173431b5f90be3e0c20d452bb29534 Mon Sep 17 00:00:00 2001 From: fspadoni Date: Sun, 17 Mar 2019 20:54:09 +0100 Subject: [PATCH 02/10] [TaskScheduler] Change the Task interface to support scheduled thread. Add a Status interface used to synchronize tasks. Implement a CpuTask class a base class for all tasks executed in the CPU --- .../simulation/TaskSchedulerTestTasks.h | 12 ++++++------ .../framework/sofa/simulation/InitTasks.cpp | 4 ++-- .../framework/sofa/simulation/InitTasks.h | 4 ++-- SofaKernel/framework/sofa/simulation/Task.h | 18 +++++++++++++----- .../MultiThreading/src/AnimationLoopTasks.cpp | 4 ++-- .../MultiThreading/src/AnimationLoopTasks.h | 4 ++-- .../MultiThreading/src/BeamLinearMapping_mt.h | 16 ++++++++-------- .../src/BeamLinearMapping_tasks.inl | 14 +++++++------- 8 files changed, 42 insertions(+), 34 deletions(-) diff --git a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.h b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.h index 6dda910f18f..638bdf7e054 100644 --- a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.h +++ b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.h @@ -6,11 +6,11 @@ namespace sofa // compute recursively the Fibonacci number for input N O(~1.6 exp(N)) // this is implemented to test the task scheduler generating super lightweight tasks and not for performance - class FibonacciTask : public simulation::Task + class FibonacciTask : public simulation::CpuTask { public: - FibonacciTask(const int64_t N, int64_t* const sum, simulation::Task::Status* status) - : Task(status) + FibonacciTask(const int64_t N, int64_t* const sum, simulation::CpuTask::Status* status) + : CpuTask(status) , _N(N) , _sum(sum) {} @@ -28,11 +28,11 @@ namespace sofa // compute recursively the sum of integers from first to last // this is implemented to test the task scheduler generating super lightweight tasks and not for performance - class IntSumTask : public simulation::Task + class IntSumTask : public simulation::CpuTask { public: - IntSumTask(const int64_t first, const int64_t last, int64_t* const sum, simulation::Task::Status* status) - : Task(status) + IntSumTask(const int64_t first, const int64_t last, int64_t* const sum, simulation::CpuTask::Status* status) + : CpuTask(status) , _first(first) , _last(last) , _sum(sum) diff --git a/SofaKernel/framework/sofa/simulation/InitTasks.cpp b/SofaKernel/framework/sofa/simulation/InitTasks.cpp index 24a50e0470b..8570ac807ab 100644 --- a/SofaKernel/framework/sofa/simulation/InitTasks.cpp +++ b/SofaKernel/framework/sofa/simulation/InitTasks.cpp @@ -14,8 +14,8 @@ namespace sofa namespace simulation { - InitPerThreadDataTask::InitPerThreadDataTask(std::atomic* atomicCounter, std::mutex* mutex, Task::Status* pStatus) - : Task(pStatus), IdFactorygetIDMutex(mutex), _atomicCounter(atomicCounter) + InitPerThreadDataTask::InitPerThreadDataTask(std::atomic* atomicCounter, std::mutex* mutex, CpuTask::Status* status) + : CpuTask(status), IdFactorygetIDMutex(mutex), _atomicCounter(atomicCounter) {} InitPerThreadDataTask::~InitPerThreadDataTask() diff --git a/SofaKernel/framework/sofa/simulation/InitTasks.h b/SofaKernel/framework/sofa/simulation/InitTasks.h index 478a1a0cd9f..e798eaee35b 100644 --- a/SofaKernel/framework/sofa/simulation/InitTasks.h +++ b/SofaKernel/framework/sofa/simulation/InitTasks.h @@ -33,12 +33,12 @@ namespace sofa - class SOFA_SIMULATION_CORE_API InitPerThreadDataTask : public Task + class SOFA_SIMULATION_CORE_API InitPerThreadDataTask : public CpuTask { public: - InitPerThreadDataTask(std::atomic* atomicCounter, std::mutex* mutex, Task::Status* pStatus); + InitPerThreadDataTask(std::atomic* atomicCounter, std::mutex* mutex, CpuTask::Status* status); ~InitPerThreadDataTask() override; diff --git a/SofaKernel/framework/sofa/simulation/Task.h b/SofaKernel/framework/sofa/simulation/Task.h index f1958d6b2e7..3b126e9cd7d 100644 --- a/SofaKernel/framework/sofa/simulation/Task.h +++ b/SofaKernel/framework/sofa/simulation/Task.h @@ -34,19 +34,21 @@ namespace sofa { + /** Task class interface */ class SOFA_SIMULATION_CORE_API Task { public: - // Task Status class definition + // Task Status class interface used to synchronize tasks class Status { public: - + virtual ~Status() {} virtual bool isBusy() const = 0; virtual int setBusy(bool busy) = 0; }; + // Task Allocator class interface used to allocate tasks class Allocator { public: @@ -56,7 +58,7 @@ namespace sofa }; - Task(const Task::Status* status = nullptr, int scheduledThread = 0); + Task(const Task::Status* status, int scheduledThread); virtual ~Task(); @@ -121,11 +123,15 @@ namespace sofa + /** Base class to implement a CPU task + * all the tasks running on the CPU should inherits from this class + */ class SOFA_SIMULATION_CORE_API CpuTask : public Task { public: - // Task Status class definition + /** CPU Task Status class definition: + * used to synchronize CPU tasks */ class Status : public Task::Status { public: @@ -154,7 +160,9 @@ namespace sofa - CpuTask(const CpuTask::Status* status = nullptr, int scheduledThread = 0); + public: + + CpuTask(const CpuTask::Status* status, int scheduledThread = -1); virtual ~CpuTask(); diff --git a/applications/plugins/MultiThreading/src/AnimationLoopTasks.cpp b/applications/plugins/MultiThreading/src/AnimationLoopTasks.cpp index 79b4751441a..368d2671f05 100644 --- a/applications/plugins/MultiThreading/src/AnimationLoopTasks.cpp +++ b/applications/plugins/MultiThreading/src/AnimationLoopTasks.cpp @@ -18,8 +18,8 @@ namespace sofa - StepTask::StepTask(core::behavior::BaseAnimationLoop* aloop, const double t, Task::Status* status) - : Task(status) + StepTask::StepTask(core::behavior::BaseAnimationLoop* aloop, const double t, CpuTask::Status* status) + : CpuTask(status) , animationloop(aloop) , dt(t) { diff --git a/applications/plugins/MultiThreading/src/AnimationLoopTasks.h b/applications/plugins/MultiThreading/src/AnimationLoopTasks.h index d8bf65d3011..050aab60af7 100644 --- a/applications/plugins/MultiThreading/src/AnimationLoopTasks.h +++ b/applications/plugins/MultiThreading/src/AnimationLoopTasks.h @@ -45,10 +45,10 @@ namespace sofa using namespace sofa; - class StepTask : public Task + class StepTask : public CpuTask { public: - StepTask(core::behavior::BaseAnimationLoop* aloop, const double t, Task::Status* pStatus); + StepTask(core::behavior::BaseAnimationLoop* aloop, const double t, CpuTask::Status* pStatus); ~StepTask() override; diff --git a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h index 92c24bfd2fc..b939052bbe9 100644 --- a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h +++ b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h @@ -103,7 +103,7 @@ class BeamLinearMapping_mt : public BeamLinearMapping // all tasks here - class applyTask : public simulation::Task + class applyTask : public simulation::CpuTask { typedef typename BeamLinearMapping::Out::VecCoord VecCoord; @@ -115,7 +115,7 @@ class BeamLinearMapping_mt : public BeamLinearMapping protected: - applyTask( const simulation::Task::Status* status ); + applyTask( const simulation::CpuTask::Status* status ); private: @@ -131,7 +131,7 @@ class BeamLinearMapping_mt : public BeamLinearMapping }; - class applyJTask : public simulation::Task + class applyJTask : public simulation::CpuTask { typedef typename BeamLinearMapping::Out::VecDeriv VecDeriv; @@ -139,7 +139,7 @@ class BeamLinearMapping_mt : public BeamLinearMapping public: - applyJTask( const simulation::Task::Status* status ); + applyJTask( const simulation::CpuTask::Status* status ); MemoryAlloc run() final; @@ -157,14 +157,14 @@ class BeamLinearMapping_mt : public BeamLinearMapping }; - class applyJTmechTask : public simulation::Task + class applyJTmechTask : public simulation::CpuTask { typedef typename BeamLinearMapping::Out::VecDeriv VecDeriv; typedef typename BeamLinearMapping::In::VecDeriv InVecDeriv; public: - applyJTmechTask( const simulation::Task::Status* status ); + applyJTmechTask( const simulation::CpuTask::Status* status ); MemoryAlloc run() final; @@ -182,10 +182,10 @@ class BeamLinearMapping_mt : public BeamLinearMapping }; - //class applyJTconstrTask : public simulation::Task + //class applyJTconstrTask : public simulation::CpuTask //{ //public: - // applyJTconstrTask( const simulation::Task::Status* status ); + // applyJTconstrTask( const simulation::CpuTask::Status* status ); // virtual bool run( simulation::WorkerThread* ); diff --git a/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl b/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl index b019ae1979c..81cab42f0cc 100644 --- a/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl +++ b/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl @@ -38,8 +38,8 @@ namespace mapping template - BeamLinearMapping_mt< TIn, TOut>::applyTask::applyTask( const Task::Status* status ) - : Task( status ) + BeamLinearMapping_mt< TIn, TOut>::applyTask::applyTask( const simulation::CpuTask::Status* status ) + : CpuTask( status ) , _mapping(0) , _in(0) , _out(0) @@ -84,8 +84,8 @@ namespace mapping template - BeamLinearMapping_mt< TIn, TOut>::applyJTask::applyJTask( const Task::Status* status ) - : Task( status ) + BeamLinearMapping_mt< TIn, TOut>::applyJTask::applyJTask( const simulation::CpuTask::Status* status ) + : CpuTask( status ) , _mapping(0) , _in(0) , _out(0) @@ -133,8 +133,8 @@ namespace mapping template - BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask::applyJTmechTask( const Task::Status* status ) - : Task( status ) + BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask::applyJTmechTask( const simulation::CpuTask::Status* status ) + : CpuTask( status ) , _mapping(0) , _in(0) , _out(0) @@ -189,7 +189,7 @@ namespace mapping //template //BeamLinearMapping_mt< TIn, TOut>::applyJTconstrTask::applyJTconstrTask( const simulation::Task::Status* status ) - // : Task( status ) + // : CpuTask( status ) // , _mapping(0) // , _in(0) // , _out(0) From 2e3d654896d94cc9341544f46ba5e364f0b7e016 Mon Sep 17 00:00:00 2001 From: fspadoni Date: Sun, 17 Mar 2019 21:20:51 +0100 Subject: [PATCH 03/10] [TaskScheduler] Reimplement ThreadSpecificTask class --- SofaKernel/framework/sofa/simulation/Task.cpp | 58 +++++++++---------- SofaKernel/framework/sofa/simulation/Task.h | 48 +++++++-------- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/SofaKernel/framework/sofa/simulation/Task.cpp b/SofaKernel/framework/sofa/simulation/Task.cpp index 1486bd43629..353394390ea 100644 --- a/SofaKernel/framework/sofa/simulation/Task.cpp +++ b/SofaKernel/framework/sofa/simulation/Task.cpp @@ -37,35 +37,35 @@ namespace sofa -// ThreadSpecificTask::ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, const Task::Status* status ) -// : Task(status) -// , _atomicCounter(atomicCounter) -// , _threadSpecificMutex(mutex) -// {} -// -// ThreadSpecificTask::~ThreadSpecificTask() -// { -// } -// -// Task::MemoryAlloc ThreadSpecificTask::run() -// { -// -// runThreadSpecific(); -// -// { -// std::lock_guard lock(*_threadSpecificMutex); -// runCriticalThreadSpecific(); -// } -// -// _atomicCounter->fetch_sub(1, std::memory_order_acq_rel); -// -// while(_atomicCounter->load(std::memory_order_relaxed) > 0) -// { -// // yield while waiting -// std::this_thread::yield(); -// } -// return Task::MemoryAlloc::Stack; -// } + ThreadSpecificTask::ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, const CpuTask::Status* status ) + : CpuTask(status) + , _atomicCounter(atomicCounter) + , _threadSpecificMutex(mutex) + {} + + ThreadSpecificTask::~ThreadSpecificTask() + { + } + + Task::MemoryAlloc ThreadSpecificTask::run() + { + + runThreadSpecific(); + + { + std::lock_guard lock(*_threadSpecificMutex); + runCriticalThreadSpecific(); + } + + _atomicCounter->fetch_sub(1, std::memory_order_acq_rel); + + while(_atomicCounter->load(std::memory_order_relaxed) > 0) + { + // yield while waiting + std::this_thread::yield(); + } + return Task::MemoryAlloc::Stack; + } } // namespace simulation diff --git a/SofaKernel/framework/sofa/simulation/Task.h b/SofaKernel/framework/sofa/simulation/Task.h index 3b126e9cd7d..94683d122e8 100644 --- a/SofaKernel/framework/sofa/simulation/Task.h +++ b/SofaKernel/framework/sofa/simulation/Task.h @@ -171,30 +171,30 @@ namespace sofa -// // This task is called once by each thread used by the TasScheduler -// // this is useful to initialize the thread specific variables -// class SOFA_SIMULATION_CORE_API ThreadSpecificTask : public Task -// { -// -// public: -// -// ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, const Task::Status* status); -// -// ~ThreadSpecificTask() override; -// -// MemoryAlloc run() final; -// -// -// private: -// -// virtual bool runThreadSpecific() { return true; } -// -// virtual bool runCriticalThreadSpecific() { return true; } -// -// -// std::atomic* _atomicCounter; -// std::mutex* _threadSpecificMutex; -// }; + // This task is called once by each thread used by the TasScheduler + // this is useful to initialize the thread specific variables + class SOFA_SIMULATION_CORE_API ThreadSpecificTask : public CpuTask + { + + public: + + ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, const CpuTask::Status* status); + + ~ThreadSpecificTask() override; + + MemoryAlloc run() final; + + + private: + + virtual bool runThreadSpecific() { return true; } + + virtual bool runCriticalThreadSpecific() { return true; } + + + std::atomic* _atomicCounter; + std::mutex* _threadSpecificMutex; + }; } // namespace simulation From 97ff3029576f62c08028a9e990fd816089dd29a6 Mon Sep 17 00:00:00 2001 From: fspadoni Date: Mon, 18 Mar 2019 22:31:26 +0100 Subject: [PATCH 04/10] [TaskScheduler] Add const qualifiers for status class pointers --- .../sofa/simulation/DefaultTaskScheduler.cpp | 2 +- .../framework/sofa/simulation/DefaultTaskScheduler.h | 6 +++--- SofaKernel/framework/sofa/simulation/Task.h | 11 +++++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp index a6e48744bab..eab9df91e21 100644 --- a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp +++ b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp @@ -361,7 +361,7 @@ namespace sofa void WorkerThread::runTask(Task* task) { - Task::Status* prevStatus = _currentStatus; + const Task::Status* prevStatus = _currentStatus; _currentStatus = task->getStatus(); { diff --git a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h index 3e2042880f6..60150e095d6 100644 --- a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h +++ b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h @@ -84,7 +84,7 @@ namespace sofa { void workUntilDone(Task::Status* status); - Task::Status* getCurrentStatus() const { return _currentStatus; } + const Task::Status* getCurrentStatus() const { return _currentStatus; } const char* getName() const { return _name.c_str(); } @@ -147,7 +147,7 @@ namespace sofa { std::thread _stdThread; - Task::Status* _currentStatus; + const Task::Status* _currentStatus; DefaultTaskScheduler* _taskScheduler; @@ -216,7 +216,7 @@ namespace sofa { //static thread_local WorkerThread* _workerThreadIndex; static std::map< std::thread::id, WorkerThread*> _threads; - Task::Status* _mainTaskStatus; + const Task::Status* _mainTaskStatus; std::mutex _wakeUpMutex; diff --git a/SofaKernel/framework/sofa/simulation/Task.h b/SofaKernel/framework/sofa/simulation/Task.h index 94683d122e8..a323a4bae2c 100644 --- a/SofaKernel/framework/sofa/simulation/Task.h +++ b/SofaKernel/framework/sofa/simulation/Task.h @@ -45,7 +45,7 @@ namespace sofa public: virtual ~Status() {} virtual bool isBusy() const = 0; - virtual int setBusy(bool busy) = 0; + virtual int setBusy(bool busy) const = 0; }; // Task Allocator class interface used to allocate tasks @@ -99,7 +99,7 @@ namespace sofa // no problem with other sompilers included visual studio 2017 //static void operator delete[](void* ptr) = delete; - inline Task::Status* getStatus(void) const { return const_cast(_status); } + virtual const Task::Status* getStatus(void) const = 0; int getScheduledThread() const { return _scheduledThread; } @@ -142,7 +142,7 @@ namespace sofa return (_busy.load(std::memory_order_relaxed) > 0); } - virtual int setBusy(bool busy) override final + virtual int setBusy(bool busy) const override final { if (busy) { @@ -155,10 +155,13 @@ namespace sofa } private: - std::atomic _busy; + mutable std::atomic _busy; }; + virtual const CpuTask::Status* getStatus(void) const override final + { return dynamic_cast(_status); } + public: From bc2d457c7b51bfcb9f4d113ee11d427e763a03fe Mon Sep 17 00:00:00 2001 From: fspadoni Date: Tue, 19 Mar 2019 20:01:57 +0100 Subject: [PATCH 05/10] [TaskScheduler] Minor changes: rename member vars with prefix m_ , remove commented code. --- .../sofa/simulation/DefaultTaskScheduler.cpp | 136 +++++++++--------- .../sofa/simulation/DefaultTaskScheduler.h | 50 +++---- SofaKernel/framework/sofa/simulation/Locks.h | 18 +-- SofaKernel/framework/sofa/simulation/Task.cpp | 16 +-- SofaKernel/framework/sofa/simulation/Task.h | 26 ++-- .../sofa/simulation/TaskScheduler.cpp | 25 ---- .../framework/sofa/simulation/TaskScheduler.h | 6 +- 7 files changed, 125 insertions(+), 152 deletions(-) diff --git a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp index eab9df91e21..e0f10d4c7bb 100644 --- a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp +++ b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp @@ -49,9 +49,9 @@ namespace sofa DefaultTaskScheduler::DefaultTaskScheduler() : TaskScheduler() { - _isInitialized = false; - _threadCount = 0; - _isClosing = false; + m_isInitialized = false; + m_threadCount = 0; + m_isClosing = false; // init global static thread local var workerThreadIndex = new WorkerThread(this, 0, "Main "); @@ -61,7 +61,7 @@ namespace sofa DefaultTaskScheduler::~DefaultTaskScheduler() { - if ( _isInitialized ) + if ( m_isInitialized ) { stop(); } @@ -91,9 +91,9 @@ namespace sofa void DefaultTaskScheduler::init(const unsigned int NbThread ) { - if ( _isInitialized ) + if ( m_isInitialized ) { - if ( (NbThread == _threadCount) || (NbThread==0 && _threadCount==GetHardwareThreadsCount()) ) + if ( (NbThread == m_threadCount) || (NbThread==0 && m_threadCount==GetHardwareThreadsCount()) ) { return; } @@ -107,20 +107,20 @@ namespace sofa { stop(); - _isClosing = false; - _workerThreadsIdle = true; - _mainTaskStatus = nullptr; + m_isClosing = false; + m_workerThreadsIdle = true; + m_mainTaskStatus = nullptr; // default number of thread: only physicsal cores. no advantage from hyperthreading. - _threadCount = GetHardwareThreadsCount(); + m_threadCount = GetHardwareThreadsCount(); if ( NbThread > 0 )//&& NbThread <= MAX_THREADS ) { - _threadCount = NbThread; + m_threadCount = NbThread; } /* start worker threads */ - for( unsigned int i=1; i<_threadCount; ++i) + for( unsigned int i=1; icreate_and_attach(this); @@ -128,8 +128,8 @@ namespace sofa thread->start(this); } - _workerThreadCount = _threadCount; - _isInitialized = true; + m_workerThreadCount = m_threadCount; + m_isInitialized = true; return; } @@ -137,14 +137,14 @@ namespace sofa void DefaultTaskScheduler::stop() { - _isClosing = true; + m_isClosing = true; - if ( _isInitialized ) + if ( m_isInitialized ) { // wait for all WaitForWorkersToBeReady(); wakeUpWorkers(); - _isInitialized = false; + m_isInitialized = false; for (auto it : _threads) { @@ -167,8 +167,8 @@ namespace sofa it.second = nullptr; } - _threadCount = 1; - _workerThreadCount = 1; + m_threadCount = 1; + m_workerThreadCount = 1; auto mainThreadIt = _threads.find(std::this_thread::get_id()); WorkerThread* mainThread = mainThreadIt->second; @@ -185,7 +185,7 @@ namespace sofa return thread->getName(); } - int DefaultTaskScheduler::GetCurrentThreadType() + int DefaultTaskScheduler::getCurrentThreadType() { WorkerThread* thread = WorkerThread::getCurrent(); return thread->getType(); @@ -206,15 +206,15 @@ namespace sofa void DefaultTaskScheduler::wakeUpWorkers() { { - std::lock_guard guard(_wakeUpMutex); - _workerThreadsIdle = false; + std::lock_guard guard(m_wakeUpMutex); + m_workerThreadsIdle = false; } - _wakeUpEvent.notify_all(); + m_wakeUpEvent.notify_all(); } void DefaultTaskScheduler::WaitForWorkersToBeReady() { - _workerThreadsIdle = true; + m_workerThreadsIdle = true; } @@ -226,36 +226,36 @@ namespace sofa WorkerThread::WorkerThread(DefaultTaskScheduler* const& pScheduler, const int index, const std::string& name) - : _type(0) - , _name(name + std::to_string(index)) - , _tasks() - , _taskScheduler(pScheduler) + : m_type(0) + , m_name(name + std::to_string(index)) + , m_tasks() + , m_taskScheduler(pScheduler) { assert(pScheduler); - _finished = false; - _currentStatus = nullptr; + m_finished.store(false, std::memory_order_relaxed); + m_currentStatus = nullptr; } WorkerThread::~WorkerThread() { - if (_stdThread.joinable()) + if (m_stdThread.joinable()) { - _stdThread.join(); + m_stdThread.join(); } - _finished = true; + m_finished.store(true, std::memory_order_relaxed); } bool WorkerThread::isFinished() { - return _finished; + return m_finished.load(std::memory_order_relaxed);; } bool WorkerThread::start(DefaultTaskScheduler* const& taskScheduler) { assert(taskScheduler); - _taskScheduler = taskScheduler; - _currentStatus = nullptr; + m_taskScheduler = taskScheduler; + m_currentStatus = nullptr; return true; } @@ -263,8 +263,8 @@ namespace sofa std::thread* WorkerThread::create_and_attach(DefaultTaskScheduler* const & taskScheduler) { SOFA_UNUSED(taskScheduler); - _stdThread = std::thread(std::bind(&WorkerThread::run, this)); - return &_stdThread; + m_stdThread = std::thread(std::bind(&WorkerThread::run, this)); + return &m_stdThread; } WorkerThread* WorkerThread::getCurrent() @@ -285,42 +285,42 @@ namespace sofa //TaskSchedulerDefault::_threads[std::this_thread::get_id()] = this; // main loop - while ( !_taskScheduler->isClosing() ) + while ( !m_taskScheduler->isClosing() ) { Idle(); - while ( _taskScheduler->_mainTaskStatus != nullptr) + while ( m_taskScheduler->m_mainTaskStatus != nullptr) { doWork(nullptr); - if (_taskScheduler->isClosing() ) + if (m_taskScheduler->isClosing() ) { break; } } } - _finished = true; + m_finished.store(true, std::memory_order_relaxed); return; } const std::thread::id WorkerThread::getId() { - return _stdThread.get_id(); + return m_stdThread.get_id(); } void WorkerThread::Idle() { { - std::unique_lock lock( _taskScheduler->_wakeUpMutex ); + std::unique_lock lock( m_taskScheduler->m_wakeUpMutex ); //if (!_taskScheduler->_workerThreadsIdle) //{ // return; //} // cpu free wait - _taskScheduler->_wakeUpEvent.wait(lock, [&] {return !_taskScheduler->_workerThreadsIdle; }); + m_taskScheduler->m_wakeUpEvent.wait(lock, [&] {return !m_taskScheduler->m_workerThreadsIdle; }); } return; } @@ -343,7 +343,7 @@ namespace sofa } // check if main work is finished - if (_taskScheduler->_mainTaskStatus == nullptr) + if (m_taskScheduler->m_mainTaskStatus == nullptr) return; if (!stealTask(&task)) @@ -361,8 +361,8 @@ namespace sofa void WorkerThread::runTask(Task* task) { - const Task::Status* prevStatus = _currentStatus; - _currentStatus = task->getStatus(); + const Task::Status* prevStatus = m_currentStatus; + m_currentStatus = task->getStatus(); { if (task->run() & Task::MemoryAlloc::Dynamic) @@ -374,8 +374,8 @@ namespace sofa } } - _currentStatus->setBusy(false); - _currentStatus = prevStatus; + m_currentStatus->setBusy(false); + m_currentStatus = prevStatus; } void WorkerThread::workUntilDone(Task::Status* status) @@ -385,9 +385,9 @@ namespace sofa doWork(status); } - if (_taskScheduler->_mainTaskStatus == status) + if (m_taskScheduler->m_mainTaskStatus == status) { - _taskScheduler->_mainTaskStatus = nullptr; + m_taskScheduler->m_mainTaskStatus = nullptr; } } @@ -396,11 +396,11 @@ namespace sofa { TASK_SCHEDULER_PROFILER(Pop); - simulation::ScopedLock lock( _taskMutex ); - if (!_tasks.empty() ) + simulation::ScopedLock lock( m_taskMutex ); + if (!m_tasks.empty() ) { - *task = _tasks.back(); - _tasks.pop_back(); + *task = m_tasks.back(); + m_tasks.pop_back(); return true; } *task = nullptr; @@ -411,7 +411,7 @@ namespace sofa bool WorkerThread::pushTask(Task* task) { // if we're single threaded return false - if ( _taskScheduler->getThreadCount()<2 ) + if ( m_taskScheduler->getThreadCount()<2 ) { return false; } @@ -419,17 +419,17 @@ namespace sofa { TASK_SCHEDULER_PROFILER(Push); - simulation::ScopedLock lock(_taskMutex); + simulation::ScopedLock lock(m_taskMutex); int taskId = task->getStatus()->setBusy(true); - task->_id = taskId; - _tasks.push_back(task); + task->m_id = taskId; + m_tasks.push_back(task); } - if (!_taskScheduler->_mainTaskStatus) + if (!m_taskScheduler->m_mainTaskStatus) { - _taskScheduler->_mainTaskStatus = task->getStatus(); - _taskScheduler->wakeUpWorkers(); + m_taskScheduler->m_mainTaskStatus = task->getStatus(); + m_taskScheduler->wakeUpWorkers(); } return true; @@ -453,7 +453,7 @@ namespace sofa { //TASK_SCHEDULER_PROFILER(StealTask); - for (auto it : _taskScheduler->_threads) + for (auto it : m_taskScheduler->_threads) { // if this is the main thread continue if (std::this_thread::get_id() == it.first) @@ -466,11 +466,11 @@ namespace sofa { TASK_SCHEDULER_PROFILER(Steal); - simulation::ScopedLock lock(otherThread->_taskMutex); - if (!otherThread->_tasks.empty()) + simulation::ScopedLock lock(otherThread->m_taskMutex); + if (!otherThread->m_tasks.empty()) { - *task = otherThread->_tasks.front(); - otherThread->_tasks.pop_front(); + *task = otherThread->m_tasks.front(); + otherThread->m_tasks.pop_front(); return true; } } diff --git a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h index 60150e095d6..a85b446560c 100644 --- a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h +++ b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h @@ -84,17 +84,17 @@ namespace sofa { void workUntilDone(Task::Status* status); - const Task::Status* getCurrentStatus() const { return _currentStatus; } + const Task::Status* getCurrentStatus() const { return m_currentStatus; } - const char* getName() const { return _name.c_str(); } + const char* getName() const { return m_name.c_str(); } - int getType() const { return _type; } + int getType() const { return m_type; } const std::thread::id getId(); - const std::deque* getTasksQueue() { return &_tasks; } + const std::deque* getTasksQueue() { return &m_tasks; } - std::uint64_t getTaskCount() { return _tasks.size(); } + std::uint64_t getTaskCount() { return m_tasks.size(); } int GetWorkerIndex(); @@ -137,22 +137,22 @@ namespace sofa { Max_TasksPerThread = 256 }; - const std::string _name; + const std::string m_name; - const int _type; + const int m_type; - simulation::SpinLock _taskMutex; + simulation::SpinLock m_taskMutex; - std::deque _tasks; + std::deque m_tasks; - std::thread _stdThread; + std::thread m_stdThread; - const Task::Status* _currentStatus; + const Task::Status* m_currentStatus; - DefaultTaskScheduler* _taskScheduler; + DefaultTaskScheduler* m_taskScheduler; // The following members may be accessed by _multiple_ threads at the same time: - volatile bool _finished; + std::atomic m_finished; friend class DefaultTaskScheduler; }; @@ -173,9 +173,9 @@ namespace sofa { virtual void init(const unsigned int nbThread = 0) final; virtual void stop(void) final; - virtual unsigned int getThreadCount(void) const final { return _threadCount; } + virtual unsigned int getThreadCount(void) const final { return m_threadCount; } virtual const char* getCurrentThreadName() override final; - virtual int GetCurrentThreadType() override final; + virtual int getCurrentThreadType() override final; // queue task if there is space, and run it otherwise bool addTask(Task* task) override final; @@ -193,9 +193,9 @@ namespace sofa { private: - bool isInitialized() { return _isInitialized; } + bool isInitialized() { return m_isInitialized; } - bool isClosing(void) const { return _isClosing; } + bool isClosing(void) const { return m_isClosing; } void WaitForWorkersToBeReady(); @@ -216,11 +216,11 @@ namespace sofa { //static thread_local WorkerThread* _workerThreadIndex; static std::map< std::thread::id, WorkerThread*> _threads; - const Task::Status* _mainTaskStatus; + const Task::Status* m_mainTaskStatus; - std::mutex _wakeUpMutex; + std::mutex m_wakeUpMutex; - std::condition_variable _wakeUpEvent; + std::condition_variable m_wakeUpEvent; private: @@ -232,15 +232,15 @@ namespace sofa { void start(unsigned int NbThread); - bool _isInitialized; + bool m_isInitialized; - unsigned _workerThreadCount; + unsigned m_workerThreadCount; - bool _workerThreadsIdle; + bool m_workerThreadsIdle; - bool _isClosing; + bool m_isClosing; - unsigned _threadCount; + unsigned m_threadCount; friend class WorkerThread; diff --git a/SofaKernel/framework/sofa/simulation/Locks.h b/SofaKernel/framework/sofa/simulation/Locks.h index d04bc0cb56a..b37c318e14b 100644 --- a/SofaKernel/framework/sofa/simulation/Locks.h +++ b/SofaKernel/framework/sofa/simulation/Locks.h @@ -42,7 +42,7 @@ namespace sofa public: SpinLock() - :_flag() + :m_flag() {} ~SpinLock() @@ -52,12 +52,12 @@ namespace sofa bool try_lock() { - return !_flag.test_and_set( std::memory_order_acquire ); + return !m_flag.test_and_set( std::memory_order_acquire ); } void lock() { - while( _flag.test_and_set(std::memory_order_acquire) ) + while( m_flag.test_and_set(std::memory_order_acquire) ) { // cpu busy wait //std::this_thread::yield(); @@ -66,12 +66,12 @@ namespace sofa void unlock() { - _flag.clear( std::memory_order_release ); + m_flag.clear( std::memory_order_release ); } private: - std::atomic_flag _flag; + std::atomic_flag m_flag; char _pad [CACHE_LINE - sizeof(std::atomic_flag)]; }; @@ -82,14 +82,14 @@ namespace sofa { public: - explicit ScopedLock( SpinLock & lock ): _spinlock( lock ) + explicit ScopedLock( SpinLock & lock ): m_spinlock( lock ) { - _spinlock.lock(); + m_spinlock.lock(); } ~ScopedLock() { - _spinlock.unlock(); + m_spinlock.unlock(); } ScopedLock( ScopedLock const & ) = delete; @@ -97,7 +97,7 @@ namespace sofa private: - SpinLock& _spinlock; + SpinLock& m_spinlock; }; } // namespace simulation diff --git a/SofaKernel/framework/sofa/simulation/Task.cpp b/SofaKernel/framework/sofa/simulation/Task.cpp index 353394390ea..08bf62e7b7e 100644 --- a/SofaKernel/framework/sofa/simulation/Task.cpp +++ b/SofaKernel/framework/sofa/simulation/Task.cpp @@ -14,9 +14,9 @@ namespace sofa Task::Task(const Task::Status* status, int scheduledThread) - : _scheduledThread(scheduledThread) - , _status(status) - , _id(0) + : m_scheduledThread(scheduledThread) + , m_status(status) + , m_id(0) { } @@ -39,8 +39,8 @@ namespace sofa ThreadSpecificTask::ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, const CpuTask::Status* status ) : CpuTask(status) - , _atomicCounter(atomicCounter) - , _threadSpecificMutex(mutex) + , m_atomicCounter(atomicCounter) + , m_threadSpecificMutex(mutex) {} ThreadSpecificTask::~ThreadSpecificTask() @@ -53,13 +53,13 @@ namespace sofa runThreadSpecific(); { - std::lock_guard lock(*_threadSpecificMutex); + std::lock_guard lock(*m_threadSpecificMutex); runCriticalThreadSpecific(); } - _atomicCounter->fetch_sub(1, std::memory_order_acq_rel); + m_atomicCounter->fetch_sub(1, std::memory_order_acq_rel); - while(_atomicCounter->load(std::memory_order_relaxed) > 0) + while(m_atomicCounter->load(std::memory_order_relaxed) > 0) { // yield while waiting std::this_thread::yield(); diff --git a/SofaKernel/framework/sofa/simulation/Task.h b/SofaKernel/framework/sofa/simulation/Task.h index a323a4bae2c..f7eb4812822 100644 --- a/SofaKernel/framework/sofa/simulation/Task.h +++ b/SofaKernel/framework/sofa/simulation/Task.h @@ -58,10 +58,12 @@ namespace sofa }; + Task(const Task::Status* status, int scheduledThread); virtual ~Task(); + enum MemoryAlloc { Stack = 1 << 0, @@ -101,7 +103,7 @@ namespace sofa virtual const Task::Status* getStatus(void) const = 0; - int getScheduledThread() const { return _scheduledThread; } + int getScheduledThread() const { return m_scheduledThread; } static Task::Allocator* getAllocator() { return _allocator; } @@ -109,12 +111,12 @@ namespace sofa protected: - const Task::Status* _status; + const Task::Status* m_status; - int _scheduledThread; + int m_scheduledThread; public: - int _id; + int m_id; private: @@ -135,32 +137,32 @@ namespace sofa class Status : public Task::Status { public: - Status() : _busy(0) {} + Status() : m_busy(0) {} virtual bool isBusy() const override final { - return (_busy.load(std::memory_order_relaxed) > 0); + return (m_busy.load(std::memory_order_relaxed) > 0); } virtual int setBusy(bool busy) const override final { if (busy) { - return _busy.fetch_add(1, std::memory_order_relaxed); + return m_busy.fetch_add(1, std::memory_order_relaxed); } else { - return _busy.fetch_sub(1, std::memory_order_relaxed); + return m_busy.fetch_sub(1, std::memory_order_relaxed); } } private: - mutable std::atomic _busy; + mutable std::atomic m_busy; }; virtual const CpuTask::Status* getStatus(void) const override final - { return dynamic_cast(_status); } + { return dynamic_cast(m_status); } public: @@ -195,8 +197,8 @@ namespace sofa virtual bool runCriticalThreadSpecific() { return true; } - std::atomic* _atomicCounter; - std::mutex* _threadSpecificMutex; + std::atomic* m_atomicCounter; + std::mutex* m_threadSpecificMutex; }; diff --git a/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp b/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp index 917312fb88c..48515a842f1 100644 --- a/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp +++ b/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp @@ -77,31 +77,6 @@ namespace sofa } - // called once by each thread used - // by the TaskScheduler -// bool runThreadSpecificTask(const Task* task) -// { -// SOFA_UNUSED(task); -// std::atomic atomicCounter; -// TaskScheduler* scheduler = TaskScheduler::getInstance(); -// atomicCounter = scheduler->getThreadCount(); -// -// std::mutex InitThreadSpecificMutex; -// -// CpuTask::Status status; -// -// const int nbThread = scheduler->getThreadCount(); -// -// for (int i = 0; iaddTask(new ThreadSpecificTask(&atomicCounter, &InitThreadSpecificMutex, &status)); -// } -// -// scheduler->workUntilDone(&status); -// -// return true; -// } - } // namespace simulation } // namespace sofa diff --git a/SofaKernel/framework/sofa/simulation/TaskScheduler.h b/SofaKernel/framework/sofa/simulation/TaskScheduler.h index 61d4784004f..1f2c5e27e18 100644 --- a/SofaKernel/framework/sofa/simulation/TaskScheduler.h +++ b/SofaKernel/framework/sofa/simulation/TaskScheduler.h @@ -70,7 +70,7 @@ namespace sofa virtual const char* getCurrentThreadName() = 0; - virtual int GetCurrentThreadType() = 0; + virtual int getCurrentThreadType() = 0; // queue task if there is space, and run it otherwise virtual bool addTask(Task* task) = 0; @@ -94,10 +94,6 @@ namespace sofa - - SOFA_SIMULATION_CORE_API bool runThreadSpecificTask(const Task *pTask); - - } // namespace simulation } // namespace sofa From 5ea4f91b91a4cda21a5b0fd1a05d878968e4d955 Mon Sep 17 00:00:00 2001 From: fspadoni Date: Tue, 26 Mar 2019 23:57:22 +0100 Subject: [PATCH 06/10] [TaskScheduler] Remove const qualifier for Task::Status* member var --- .../sofa/simulation/DefaultTaskScheduler.cpp | 2 +- .../sofa/simulation/DefaultTaskScheduler.h | 2 +- SofaKernel/framework/sofa/simulation/Task.cpp | 9 ++++---- SofaKernel/framework/sofa/simulation/Task.h | 21 ++++++++++--------- .../MultiThreading/src/BeamLinearMapping_mt.h | 6 +++--- .../src/BeamLinearMapping_tasks.inl | 8 +++---- 6 files changed, 25 insertions(+), 23 deletions(-) diff --git a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp index e0f10d4c7bb..67577476ecb 100644 --- a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp +++ b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp @@ -361,7 +361,7 @@ namespace sofa void WorkerThread::runTask(Task* task) { - const Task::Status* prevStatus = m_currentStatus; + Task::Status* prevStatus = m_currentStatus; m_currentStatus = task->getStatus(); { diff --git a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h index a85b446560c..cc106979c27 100644 --- a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h +++ b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h @@ -147,7 +147,7 @@ namespace sofa { std::thread m_stdThread; - const Task::Status* m_currentStatus; + Task::Status* m_currentStatus; DefaultTaskScheduler* m_taskScheduler; diff --git a/SofaKernel/framework/sofa/simulation/Task.cpp b/SofaKernel/framework/sofa/simulation/Task.cpp index 08bf62e7b7e..ff9cbc10db3 100644 --- a/SofaKernel/framework/sofa/simulation/Task.cpp +++ b/SofaKernel/framework/sofa/simulation/Task.cpp @@ -13,9 +13,9 @@ namespace sofa Task::Allocator* Task::_allocator = nullptr; - Task::Task(const Task::Status* status, int scheduledThread) + Task::Task(Task::Status* status, int scheduledThread) : m_scheduledThread(scheduledThread) - , m_status(status) +// , m_status(status) , m_id(0) { } @@ -25,8 +25,9 @@ namespace sofa } - CpuTask::CpuTask(const CpuTask::Status* status, int scheduledThread) + CpuTask::CpuTask(CpuTask::Status* status, int scheduledThread) : Task(status, scheduledThread) + , m_status(status) { } @@ -37,7 +38,7 @@ namespace sofa - ThreadSpecificTask::ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, const CpuTask::Status* status ) + ThreadSpecificTask::ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, CpuTask::Status* status ) : CpuTask(status) , m_atomicCounter(atomicCounter) , m_threadSpecificMutex(mutex) diff --git a/SofaKernel/framework/sofa/simulation/Task.h b/SofaKernel/framework/sofa/simulation/Task.h index f7eb4812822..25b2b6619b4 100644 --- a/SofaKernel/framework/sofa/simulation/Task.h +++ b/SofaKernel/framework/sofa/simulation/Task.h @@ -45,7 +45,7 @@ namespace sofa public: virtual ~Status() {} virtual bool isBusy() const = 0; - virtual int setBusy(bool busy) const = 0; + virtual int setBusy(bool busy) = 0; }; // Task Allocator class interface used to allocate tasks @@ -59,7 +59,7 @@ namespace sofa - Task(const Task::Status* status, int scheduledThread); + Task(Task::Status* status, int scheduledThread); virtual ~Task(); @@ -101,7 +101,7 @@ namespace sofa // no problem with other sompilers included visual studio 2017 //static void operator delete[](void* ptr) = delete; - virtual const Task::Status* getStatus(void) const = 0; + virtual Task::Status* getStatus(void) const = 0; int getScheduledThread() const { return m_scheduledThread; } @@ -111,7 +111,7 @@ namespace sofa protected: - const Task::Status* m_status; +// Task::Status* m_status; int m_scheduledThread; @@ -144,7 +144,7 @@ namespace sofa return (m_busy.load(std::memory_order_relaxed) > 0); } - virtual int setBusy(bool busy) const override final + virtual int setBusy(bool busy) override final { if (busy) { @@ -157,20 +157,21 @@ namespace sofa } private: - mutable std::atomic m_busy; + std::atomic m_busy; }; - virtual const CpuTask::Status* getStatus(void) const override final - { return dynamic_cast(m_status); } + virtual CpuTask::Status* getStatus(void) const override final { return m_status; } public: - CpuTask(const CpuTask::Status* status, int scheduledThread = -1); + CpuTask(CpuTask::Status* status, int scheduledThread = -1); virtual ~CpuTask(); + private: + CpuTask::Status* m_status; }; @@ -183,7 +184,7 @@ namespace sofa public: - ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, const CpuTask::Status* status); + ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, CpuTask::Status* status); ~ThreadSpecificTask() override; diff --git a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h index b939052bbe9..a01ace5fb09 100644 --- a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h +++ b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h @@ -115,7 +115,7 @@ class BeamLinearMapping_mt : public BeamLinearMapping protected: - applyTask( const simulation::CpuTask::Status* status ); + applyTask( simulation::CpuTask::Status* status ); private: @@ -139,7 +139,7 @@ class BeamLinearMapping_mt : public BeamLinearMapping public: - applyJTask( const simulation::CpuTask::Status* status ); + applyJTask( simulation::CpuTask::Status* status ); MemoryAlloc run() final; @@ -164,7 +164,7 @@ class BeamLinearMapping_mt : public BeamLinearMapping public: - applyJTmechTask( const simulation::CpuTask::Status* status ); + applyJTmechTask( simulation::CpuTask::Status* status ); MemoryAlloc run() final; diff --git a/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl b/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl index 81cab42f0cc..b51ee0146b4 100644 --- a/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl +++ b/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl @@ -37,8 +37,8 @@ namespace mapping using namespace sofa::defaulttype; - template - BeamLinearMapping_mt< TIn, TOut>::applyTask::applyTask( const simulation::CpuTask::Status* status ) + template + BeamLinearMapping_mt< TIn, TOut>::applyTask::applyTask( simulation::CpuTask::Status* status ) : CpuTask( status ) , _mapping(0) , _in(0) @@ -84,7 +84,7 @@ namespace mapping template - BeamLinearMapping_mt< TIn, TOut>::applyJTask::applyJTask( const simulation::CpuTask::Status* status ) + BeamLinearMapping_mt< TIn, TOut>::applyJTask::applyJTask( simulation::CpuTask::Status* status ) : CpuTask( status ) , _mapping(0) , _in(0) @@ -133,7 +133,7 @@ namespace mapping template - BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask::applyJTmechTask( const simulation::CpuTask::Status* status ) + BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask::applyJTmechTask( simulation::CpuTask::Status* status ) : CpuTask( status ) , _mapping(0) , _in(0) From 41feb6e74f7b3e7566a13e9d5c0f1336c797161a Mon Sep 17 00:00:00 2001 From: fspadoni Date: Wed, 27 Mar 2019 00:05:08 +0100 Subject: [PATCH 07/10] [TaskScheduler] clean Task class constructor --- SofaKernel/framework/sofa/simulation/Task.cpp | 9 ++++----- SofaKernel/framework/sofa/simulation/Task.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/SofaKernel/framework/sofa/simulation/Task.cpp b/SofaKernel/framework/sofa/simulation/Task.cpp index ff9cbc10db3..108700d88ea 100644 --- a/SofaKernel/framework/sofa/simulation/Task.cpp +++ b/SofaKernel/framework/sofa/simulation/Task.cpp @@ -13,9 +13,8 @@ namespace sofa Task::Allocator* Task::_allocator = nullptr; - Task::Task(Task::Status* status, int scheduledThread) - : m_scheduledThread(scheduledThread) -// , m_status(status) + Task::Task(int scheduledThread) + : m_scheduledThread(scheduledThread) , m_id(0) { } @@ -26,8 +25,8 @@ namespace sofa CpuTask::CpuTask(CpuTask::Status* status, int scheduledThread) - : Task(status, scheduledThread) - , m_status(status) + : Task(scheduledThread) + , m_status(status) { } diff --git a/SofaKernel/framework/sofa/simulation/Task.h b/SofaKernel/framework/sofa/simulation/Task.h index 25b2b6619b4..3be4ac11c17 100644 --- a/SofaKernel/framework/sofa/simulation/Task.h +++ b/SofaKernel/framework/sofa/simulation/Task.h @@ -59,7 +59,7 @@ namespace sofa - Task(Task::Status* status, int scheduledThread); + Task(int scheduledThread); virtual ~Task(); From 0458bd2d1fb9b5accecc20a1f57ee0009a3a5243 Mon Sep 17 00:00:00 2001 From: fspadoni Date: Wed, 27 Mar 2019 10:28:58 +0100 Subject: [PATCH 08/10] [TaskScheduler] Re-indent files --- .../sofa/simulation/DefaultTaskScheduler.cpp | 474 +++++++++--------- .../sofa/simulation/DefaultTaskScheduler.h | 158 +++--- 2 files changed, 316 insertions(+), 316 deletions(-) diff --git a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp index 67577476ecb..26fa6e1aae6 100644 --- a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp +++ b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.cpp @@ -7,88 +7,88 @@ namespace sofa { - namespace simulation - { + namespace simulation + { DEFINE_TASK_SCHEDULER_PROFILER(Push); DEFINE_TASK_SCHEDULER_PROFILER(Pop); DEFINE_TASK_SCHEDULER_PROFILER(Steal); - - + + class StdTaskAllocator : public Task::Allocator { public: - + void* allocate(std::size_t sz) final { return ::operator new(sz); } - + void free(void* ptr, std::size_t sz) final { ::operator delete(ptr); } }; - + static StdTaskAllocator defaultTaskAllocator; - - - + + + // mac clang 3.5 doesn't support thread_local vars //static WorkerThread* WorkerThread::_workerThreadIndex = nullptr; SOFA_THREAD_SPECIFIC_PTR(WorkerThread, workerThreadIndex); - + std::map< std::thread::id, WorkerThread*> DefaultTaskScheduler::_threads; - - + + DefaultTaskScheduler* DefaultTaskScheduler::create() { return new DefaultTaskScheduler(); } - + DefaultTaskScheduler::DefaultTaskScheduler() - : TaskScheduler() - { - m_isInitialized = false; - m_threadCount = 0; - m_isClosing = false; - + : TaskScheduler() + { + m_isInitialized = false; + m_threadCount = 0; + m_isClosing = false; + // init global static thread local var workerThreadIndex = new WorkerThread(this, 0, "Main "); _threads[std::this_thread::get_id()] = workerThreadIndex;// new WorkerThread(this, 0, "Main "); - - } - + + } + DefaultTaskScheduler::~DefaultTaskScheduler() - { - if ( m_isInitialized ) - { - stop(); - } - } - - - unsigned DefaultTaskScheduler::GetHardwareThreadsCount() - { - return std::thread::hardware_concurrency() / 2; - } - - - const WorkerThread* DefaultTaskScheduler::getWorkerThread(const std::thread::id id) - { - auto thread =_threads.find(id); - if (thread == _threads.end() ) - { - return nullptr; - } - return thread->second; - } - + { + if ( m_isInitialized ) + { + stop(); + } + } + + + unsigned DefaultTaskScheduler::GetHardwareThreadsCount() + { + return std::thread::hardware_concurrency() / 2; + } + + + const WorkerThread* DefaultTaskScheduler::getWorkerThread(const std::thread::id id) + { + auto thread =_threads.find(id); + if (thread == _threads.end() ) + { + return nullptr; + } + return thread->second; + } + Task::Allocator* DefaultTaskScheduler::getTaskAllocator() { return &defaultTaskAllocator; } - + void DefaultTaskScheduler::init(const unsigned int NbThread ) { if ( m_isInitialized ) @@ -103,14 +103,14 @@ namespace sofa start(NbThread); } - void DefaultTaskScheduler::start(const unsigned int NbThread ) - { - stop(); - + void DefaultTaskScheduler::start(const unsigned int NbThread ) + { + stop(); + m_isClosing = false; m_workerThreadsIdle = true; m_mainTaskStatus = nullptr; - + // default number of thread: only physicsal cores. no advantage from hyperthreading. m_threadCount = GetHardwareThreadsCount(); @@ -118,155 +118,155 @@ namespace sofa { m_threadCount = NbThread; } - + /* start worker threads */ for( unsigned int i=1; icreate_and_attach(this); - _threads[thread->getId()] = thread; - thread->start(this); + thread->create_and_attach(this); + _threads[thread->getId()] = thread; + thread->start(this); } m_workerThreadCount = m_threadCount; m_isInitialized = true; return; - } - - - - void DefaultTaskScheduler::stop() - { - m_isClosing = true; - - if ( m_isInitialized ) - { - // wait for all - WaitForWorkersToBeReady(); - wakeUpWorkers(); + } + + + + void DefaultTaskScheduler::stop() + { + m_isClosing = true; + + if ( m_isInitialized ) + { + // wait for all + WaitForWorkersToBeReady(); + wakeUpWorkers(); m_isInitialized = false; - for (auto it : _threads) - { - // if this is the main thread continue - if (std::this_thread::get_id() == it.first) - { - continue; - } - - // cpu busy wait - while (!it.second->isFinished()) - { - std::this_thread::yield(); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - - // free memory - // cpu busy wait: thread.joint call - delete it.second; - it.second = nullptr; - } - + for (auto it : _threads) + { + // if this is the main thread continue + if (std::this_thread::get_id() == it.first) + { + continue; + } + + // cpu busy wait + while (!it.second->isFinished()) + { + std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + // free memory + // cpu busy wait: thread.joint call + delete it.second; + it.second = nullptr; + } + m_threadCount = 1; - m_workerThreadCount = 1; - - auto mainThreadIt = _threads.find(std::this_thread::get_id()); - WorkerThread* mainThread = mainThreadIt->second; - _threads.clear(); - _threads[std::this_thread::get_id()] = mainThread; - } - - return; - } - + m_workerThreadCount = 1; + + auto mainThreadIt = _threads.find(std::this_thread::get_id()); + WorkerThread* mainThread = mainThreadIt->second; + _threads.clear(); + _threads[std::this_thread::get_id()] = mainThread; + } + + return; + } + const char* DefaultTaskScheduler::getCurrentThreadName() { WorkerThread* thread = WorkerThread::getCurrent(); return thread->getName(); } - + int DefaultTaskScheduler::getCurrentThreadType() { WorkerThread* thread = WorkerThread::getCurrent(); return thread->getType(); } - + bool DefaultTaskScheduler::addTask(Task* task) { WorkerThread* thread = WorkerThread::getCurrent(); return thread->addTask(task); } - + void DefaultTaskScheduler::workUntilDone(Task::Status* status) { WorkerThread* thread = WorkerThread::getCurrent(); thread->workUntilDone(status); } - - void DefaultTaskScheduler::wakeUpWorkers() - { - { - std::lock_guard guard(m_wakeUpMutex); - m_workerThreadsIdle = false; - } - m_wakeUpEvent.notify_all(); - } - - void DefaultTaskScheduler::WaitForWorkersToBeReady() - { - m_workerThreadsIdle = true; - } - - - //unsigned TaskSchedulerDefault::size() const - //{ - // return _workerThreadCount; - //} - - - + + void DefaultTaskScheduler::wakeUpWorkers() + { + { + std::lock_guard guard(m_wakeUpMutex); + m_workerThreadsIdle = false; + } + m_wakeUpEvent.notify_all(); + } + + void DefaultTaskScheduler::WaitForWorkersToBeReady() + { + m_workerThreadsIdle = true; + } + + + //unsigned TaskSchedulerDefault::size() const + //{ + // return _workerThreadCount; + //} + + + WorkerThread::WorkerThread(DefaultTaskScheduler* const& pScheduler, const int index, const std::string& name) - : m_type(0) - , m_name(name + std::to_string(index)) - , m_tasks() - , m_taskScheduler(pScheduler) - { - assert(pScheduler); - m_finished.store(false, std::memory_order_relaxed); + : m_type(0) + , m_name(name + std::to_string(index)) + , m_tasks() + , m_taskScheduler(pScheduler) + { + assert(pScheduler); + m_finished.store(false, std::memory_order_relaxed); m_currentStatus = nullptr; - } - - - WorkerThread::~WorkerThread() - { + } + + + WorkerThread::~WorkerThread() + { if (m_stdThread.joinable()) { m_stdThread.join(); } m_finished.store(true, std::memory_order_relaxed); - } - + } + bool WorkerThread::isFinished() { return m_finished.load(std::memory_order_relaxed);; } - - bool WorkerThread::start(DefaultTaskScheduler* const& taskScheduler) - { - assert(taskScheduler); - m_taskScheduler = taskScheduler; - m_currentStatus = nullptr; - - return true; - } - + + bool WorkerThread::start(DefaultTaskScheduler* const& taskScheduler) + { + assert(taskScheduler); + m_taskScheduler = taskScheduler; + m_currentStatus = nullptr; + + return true; + } + std::thread* WorkerThread::create_and_attach(DefaultTaskScheduler* const & taskScheduler) { SOFA_UNUSED(taskScheduler); m_stdThread = std::thread(std::bind(&WorkerThread::run, this)); return &m_stdThread; } - + WorkerThread* WorkerThread::getCurrent() { //return workerThreadIndex; @@ -277,93 +277,93 @@ namespace sofa } return thread->second; } - - void WorkerThread::run(void) - { + + void WorkerThread::run(void) + { //workerThreadIndex = this; //TaskSchedulerDefault::_threads[std::this_thread::get_id()] = this; - - // main loop + + // main loop while ( !m_taskScheduler->isClosing() ) - { - Idle(); + { + Idle(); while ( m_taskScheduler->m_mainTaskStatus != nullptr) - { - - doWork(nullptr); - - - if (m_taskScheduler->isClosing() ) + { + + doWork(nullptr); + + + if (m_taskScheduler->isClosing() ) { break; } - } - } - + } + } + m_finished.store(true, std::memory_order_relaxed); - return; - } - + return; + } + const std::thread::id WorkerThread::getId() { return m_stdThread.get_id(); } - + void WorkerThread::Idle() { { std::unique_lock lock( m_taskScheduler->m_wakeUpMutex ); - //if (!_taskScheduler->_workerThreadsIdle) - //{ - // return; - //} + //if (!_taskScheduler->_workerThreadsIdle) + //{ + // return; + //} // cpu free wait m_taskScheduler->m_wakeUpEvent.wait(lock, [&] {return !m_taskScheduler->m_workerThreadsIdle; }); } return; } - - void WorkerThread::doWork(Task::Status* status) - { - + + void WorkerThread::doWork(Task::Status* status) + { + for (;;)// do { Task* task; - + while (popTask(&task)) { // run task in the queue runTask(task); - - + + if (status && !status->isBusy()) return; } - + // check if main work is finished if (m_taskScheduler->m_mainTaskStatus == nullptr) return; - + if (!stealTask(&task)) return; - + // run the stolen task runTask(task); - + } //;;while (stealTasks()); - - - return; - - } - + + + return; + + } + void WorkerThread::runTask(Task* task) { Task::Status* prevStatus = m_currentStatus; m_currentStatus = task->getStatus(); - + { if (task->run() & Task::MemoryAlloc::Dynamic) { @@ -373,29 +373,29 @@ namespace sofa //delete task; } } - + m_currentStatus->setBusy(false); m_currentStatus = prevStatus; } - - void WorkerThread::workUntilDone(Task::Status* status) - { - while (status->isBusy()) - { - doWork(status); - } - - if (m_taskScheduler->m_mainTaskStatus == status) - { - m_taskScheduler->m_mainTaskStatus = nullptr; - } - } - - - bool WorkerThread::popTask(Task** task) - { + + void WorkerThread::workUntilDone(Task::Status* status) + { + while (status->isBusy()) + { + doWork(status); + } + + if (m_taskScheduler->m_mainTaskStatus == status) + { + m_taskScheduler->m_mainTaskStatus = nullptr; + } + } + + + bool WorkerThread::popTask(Task** task) + { TASK_SCHEDULER_PROFILER(Pop); - + simulation::ScopedLock lock( m_taskMutex ); if (!m_tasks.empty() ) { @@ -405,11 +405,11 @@ namespace sofa } *task = nullptr; return false; - } - - - bool WorkerThread::pushTask(Task* task) - { + } + + + bool WorkerThread::pushTask(Task* task) + { // if we're single threaded return false if ( m_taskScheduler->getThreadCount()<2 ) { @@ -418,7 +418,7 @@ namespace sofa { TASK_SCHEDULER_PROFILER(Push); - + simulation::ScopedLock lock(m_taskMutex); int taskId = task->getStatus()->setBusy(true); task->m_id = taskId; @@ -433,26 +433,26 @@ namespace sofa } return true; - } - - bool WorkerThread::addTask(Task* task) - { - if (pushTask(task)) + } + + bool WorkerThread::addTask(Task* task) + { + if (pushTask(task)) { return true; } - + // we are single thread: run the task runTask(task); - - return false; - } - + + return false; + } + bool WorkerThread::stealTask(Task** task) { { //TASK_SCHEDULER_PROFILER(StealTask); - + for (auto it : m_taskScheduler->_threads) { // if this is the main thread continue @@ -460,12 +460,12 @@ namespace sofa { continue; } - + WorkerThread* otherThread = it.second; - + { TASK_SCHEDULER_PROFILER(Steal); - + simulation::ScopedLock lock(otherThread->m_taskMutex); if (!otherThread->m_tasks.empty()) { @@ -474,13 +474,13 @@ namespace sofa return true; } } - + } } - + return false; } - + } // namespace simulation diff --git a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h index cc106979c27..4760180b541 100644 --- a/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h +++ b/SofaKernel/framework/sofa/simulation/DefaultTaskScheduler.h @@ -63,102 +63,102 @@ namespace sofa { #define TASK_SCHEDULER_PROFILER(name) #endif - - + + class DefaultTaskScheduler; class WorkerThread; - - + + class SOFA_SIMULATION_CORE_API WorkerThread { public: - + WorkerThread(DefaultTaskScheduler* const& taskScheduler, const int index, const std::string& name = "Worker"); - + ~WorkerThread(); - + static WorkerThread* getCurrent(); - + // queue task if there is space, and run it otherwise bool addTask(Task* pTask); - + void workUntilDone(Task::Status* status); - + const Task::Status* getCurrentStatus() const { return m_currentStatus; } - + const char* getName() const { return m_name.c_str(); } - + int getType() const { return m_type; } - + const std::thread::id getId(); - + const std::deque* getTasksQueue() { return &m_tasks; } - + std::uint64_t getTaskCount() { return m_tasks.size(); } - + int GetWorkerIndex(); - + void* allocate(); - + void free(void* ptr); - - + + private: - + bool start(DefaultTaskScheduler* const& taskScheduler); - + std::thread* create_and_attach(DefaultTaskScheduler* const& taskScheduler); - + void runTask(Task* task); - + // queue task if there is space (or do nothing) bool pushTask(Task* pTask); - + // pop task from queue bool popTask(Task** ppTask); - - // steal and queue some task from another thread + + // steal and queue some task from another thread bool stealTask(Task** task); - + void doWork(Task::Status* status); - + // boost thread main loop void run(void); - + //void ThreadProc(void); void Idle(void); - + bool isFinished(); - + private: - + enum { Max_TasksPerThread = 256 }; - + const std::string m_name; - + const int m_type; - + simulation::SpinLock m_taskMutex; - + std::deque m_tasks; - + std::thread m_stdThread; - + Task::Status* m_currentStatus; - + DefaultTaskScheduler* m_taskScheduler; - + // The following members may be accessed by _multiple_ threads at the same time: std::atomic m_finished; - + friend class DefaultTaskScheduler; }; - - - + + + class SOFA_SIMULATION_CORE_API DefaultTaskScheduler : public TaskScheduler { enum @@ -166,11 +166,11 @@ namespace sofa { MAX_THREADS = 16, STACKSIZE = 64 * 1024 /* 64K */, }; - + public: - + // interface - + virtual void init(const unsigned int nbThread = 0) final; virtual void stop(void) final; virtual unsigned int getThreadCount(void) const final { return m_threadCount; } @@ -181,68 +181,68 @@ namespace sofa { bool addTask(Task* task) override final; void workUntilDone(Task::Status* status) override final; Task::Allocator* getTaskAllocator() override final; - + public: - + // factory methods: name, creator function static const char* name() { return "_default"; } - + static DefaultTaskScheduler* create(); - + static const bool isRegistered; - + private: - + bool isInitialized() { return m_isInitialized; } - + bool isClosing(void) const { return m_isClosing; } - + void WaitForWorkersToBeReady(); - + void wakeUpWorkers(); - + static unsigned GetHardwareThreadsCount(); - + WorkerThread* getCurrentThread(); - + const WorkerThread* getWorkerThread(const std::thread::id id); - - + + private: - + static const std::string _name; - + // TO DO: replace with thread_specific_ptr. clang 3.5 doesn't support C++ 11 thread_local vars on Mac //static thread_local WorkerThread* _workerThreadIndex; static std::map< std::thread::id, WorkerThread*> _threads; - + const Task::Status* m_mainTaskStatus; - + std::mutex m_wakeUpMutex; - + std::condition_variable m_wakeUpEvent; - + private: - + DefaultTaskScheduler(); - + DefaultTaskScheduler(const DefaultTaskScheduler&) {} - + ~DefaultTaskScheduler() override; - + void start(unsigned int NbThread); - + bool m_isInitialized; - + unsigned m_workerThreadCount; - + bool m_workerThreadsIdle; - + bool m_isClosing; - + unsigned m_threadCount; - - + + friend class WorkerThread; }; From 7d83586b3f5ad20f923df4ea8ff20fb58789b117 Mon Sep 17 00:00:00 2001 From: fspadoni Date: Wed, 27 Mar 2019 12:43:43 +0100 Subject: [PATCH 09/10] [TaskScheduler] Re-Indent files --- SofaKernel/framework/sofa/simulation/Task.cpp | 46 +- SofaKernel/framework/sofa/simulation/Task.h | 56 +- .../MultiThreading/src/BeamLinearMapping_mt.h | 24 - .../src/BeamLinearMapping_mt.inl | 552 +++++++++--------- .../src/BeamLinearMapping_tasks.inl | 310 +++++----- 5 files changed, 467 insertions(+), 521 deletions(-) diff --git a/SofaKernel/framework/sofa/simulation/Task.cpp b/SofaKernel/framework/sofa/simulation/Task.cpp index 108700d88ea..6a431947be4 100644 --- a/SofaKernel/framework/sofa/simulation/Task.cpp +++ b/SofaKernel/framework/sofa/simulation/Task.cpp @@ -9,24 +9,24 @@ namespace sofa namespace simulation { - + Task::Allocator* Task::_allocator = nullptr; - - - Task::Task(int scheduledThread) - : m_scheduledThread(scheduledThread) - , m_id(0) - { - } - - Task::~Task() - { - } + + + Task::Task(int scheduledThread) + : m_scheduledThread(scheduledThread) + , m_id(0) + { + } + + Task::~Task() + { + } CpuTask::CpuTask(CpuTask::Status* status, int scheduledThread) - : Task(scheduledThread) - , m_status(status) + : Task(scheduledThread) + , m_status(status) { } @@ -38,27 +38,27 @@ namespace sofa ThreadSpecificTask::ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, CpuTask::Status* status ) - : CpuTask(status) - , m_atomicCounter(atomicCounter) - , m_threadSpecificMutex(mutex) + : CpuTask(status) + , m_atomicCounter(atomicCounter) + , m_threadSpecificMutex(mutex) {} - + ThreadSpecificTask::~ThreadSpecificTask() { } - + Task::MemoryAlloc ThreadSpecificTask::run() { - + runThreadSpecific(); - + { std::lock_guard lock(*m_threadSpecificMutex); runCriticalThreadSpecific(); } - + m_atomicCounter->fetch_sub(1, std::memory_order_acq_rel); - + while(m_atomicCounter->load(std::memory_order_relaxed) > 0) { // yield while waiting diff --git a/SofaKernel/framework/sofa/simulation/Task.h b/SofaKernel/framework/sofa/simulation/Task.h index 3be4ac11c17..246311a4b22 100644 --- a/SofaKernel/framework/sofa/simulation/Task.h +++ b/SofaKernel/framework/sofa/simulation/Task.h @@ -32,8 +32,8 @@ namespace sofa { namespace simulation { - - + + /** Task class interface */ class SOFA_SIMULATION_CORE_API Task { @@ -111,7 +111,7 @@ namespace sofa protected: -// Task::Status* m_status; + // Task::Status* m_status; int m_scheduledThread; @@ -124,26 +124,26 @@ namespace sofa }; - + /** Base class to implement a CPU task * all the tasks running on the CPU should inherits from this class */ class SOFA_SIMULATION_CORE_API CpuTask : public Task { public: - + /** CPU Task Status class definition: * used to synchronize CPU tasks */ class Status : public Task::Status { public: Status() : m_busy(0) {} - + virtual bool isBusy() const override final { return (m_busy.load(std::memory_order_relaxed) > 0); } - + virtual int setBusy(bool busy) override final { if (busy) @@ -155,49 +155,49 @@ namespace sofa return m_busy.fetch_sub(1, std::memory_order_relaxed); } } - + private: std::atomic m_busy; }; - - + + virtual CpuTask::Status* getStatus(void) const override final { return m_status; } - - + + public: CpuTask(CpuTask::Status* status, int scheduledThread = -1); - + virtual ~CpuTask(); - + private: CpuTask::Status* m_status; }; - - - - + + + + // This task is called once by each thread used by the TasScheduler // this is useful to initialize the thread specific variables class SOFA_SIMULATION_CORE_API ThreadSpecificTask : public CpuTask { - + public: - + ThreadSpecificTask(std::atomic* atomicCounter, std::mutex* mutex, CpuTask::Status* status); - + ~ThreadSpecificTask() override; - + MemoryAlloc run() final; - - + + private: - + virtual bool runThreadSpecific() { return true; } - + virtual bool runCriticalThreadSpecific() { return true; } - - + + std::atomic* m_atomicCounter; std::mutex* m_threadSpecificMutex; }; diff --git a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h index a01ace5fb09..f67c314bbaa 100644 --- a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h +++ b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h @@ -182,33 +182,9 @@ class BeamLinearMapping_mt : public BeamLinearMapping }; - //class applyJTconstrTask : public simulation::CpuTask - //{ - //public: - // applyJTconstrTask( const simulation::CpuTask::Status* status ); - - // virtual bool run( simulation::WorkerThread* ); - - //private: - - // BeamLinearMapping_mt* _mapping; - - // helper::WriteAccessor< Data< typename In::MatrixDeriv > >* _out; - // const helper::ReadAccessor< Data< typename Out::MatrixDeriv > >* _in; - - // size_t _firstPoint; - // size_t _lastPoint; - - // friend class BeamLinearMapping_mt; - //}; - - friend class applyTask; friend class applyJTask; friend class applyJTmechTask; - //friend class applyJTconstrTask; - - }; } // namespace mapping diff --git a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl index a40a95c3cb7..cd00825f79a 100644 --- a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl +++ b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl @@ -36,312 +36,312 @@ namespace component namespace mapping { - using namespace sofa::defaulttype; - - - - - template - BeamLinearMapping_mt< TIn, TOut>::BeamLinearMapping_mt() - : mGrainSize(initData(&mGrainSize, (unsigned int)32,"granularity", "minimum number of Beam points for task creation" )) - { - } - - - template - BeamLinearMapping_mt< TIn, TOut>::~BeamLinearMapping_mt() - { - } - - - template - void BeamLinearMapping_mt< TIn, TOut>::init() - { + using namespace sofa::defaulttype; + + + + + template + BeamLinearMapping_mt< TIn, TOut>::BeamLinearMapping_mt() + : mGrainSize(initData(&mGrainSize, (unsigned int)32,"granularity", "minimum number of Beam points for task creation" )) + { + } + + + template + BeamLinearMapping_mt< TIn, TOut>::~BeamLinearMapping_mt() + { + } + + + template + void BeamLinearMapping_mt< TIn, TOut>::init() + { simulation::TaskScheduler::getInstance()->init(); - - BeamLinearMapping< TIn, TOut>::init(); - } - - template - void BeamLinearMapping_mt< TIn, TOut>::bwdInit() - { - BeamLinearMapping< TIn, TOut>::bwdInit(); - } - - - template + + BeamLinearMapping< TIn, TOut>::init(); + } + + template + void BeamLinearMapping_mt< TIn, TOut>::bwdInit() + { + BeamLinearMapping< TIn, TOut>::bwdInit(); + } + + + template void BeamLinearMapping_mt< TIn, TOut>::apply(const core::MechanicalParams* mparams /* PARAMS FIRST */, Data& _out, const Data& _in) - { - - //Inherit::apply(mparams, dOut, dIn); - //boost::pool<> task_pool(sizeof(BeamLinearMapping_mt< TIn, TOut>::applyTask)); - + { + + //Inherit::apply(mparams, dOut, dIn); + //boost::pool<> task_pool(sizeof(BeamLinearMapping_mt< TIn, TOut>::applyTask)); + unsigned int numPoints = this->points.size(); - - if ( numPoints > 2*mGrainSize.getValue() ) - { - helper::WriteAccessor< Data< typename Out::VecCoord > > out = _out; - helper::ReadAccessor< Data< typename In::VecCoord > > in = _in; - - //const InVecCoord& in= _in.getValue(); - //VecCoord& out = *_out.beginEdit(); - + + if ( numPoints > 2*mGrainSize.getValue() ) + { + helper::WriteAccessor< Data< typename Out::VecCoord > > out = _out; + helper::ReadAccessor< Data< typename In::VecCoord > > in = _in; + + //const InVecCoord& in= _in.getValue(); + //VecCoord& out = *_out.beginEdit(); + this->rotatedPoints0.resize(this->points.size()); this->rotatedPoints1.resize(this->points.size()); out.resize(this->points.size()); - - - // create tasks + + + // create tasks simulation::CpuTask::Status status; simulation::TaskScheduler* scheduler = simulation::TaskScheduler::getInstance(); - - const int taskSize = 2*mGrainSize.getValue(); - - int nbTasks = numPoints / taskSize; - int pointsLeft = numPoints % taskSize; - - for ( int i=0; i::applyTask* task = - new typename BeamLinearMapping_mt< TIn, TOut>::applyTask( &status ); - - task->_mapping = this; - //task->_mparams = mparams; - task->_in = ∈ - task->_out = &out; - task->_firstPoint = i*taskSize; - task->_lastPoint = i*taskSize + mGrainSize.getValue(); - + + const int taskSize = 2*mGrainSize.getValue(); + + int nbTasks = numPoints / taskSize; + int pointsLeft = numPoints % taskSize; + + for ( int i=0; i::applyTask* task = + new typename BeamLinearMapping_mt< TIn, TOut>::applyTask( &status ); + + task->_mapping = this; + //task->_mparams = mparams; + task->_in = ∈ + task->_out = &out; + task->_firstPoint = i*taskSize; + task->_lastPoint = i*taskSize + mGrainSize.getValue(); + scheduler->addTask( task ); - - } - if ( pointsLeft > 0) - { - typename BeamLinearMapping_mt< TIn, TOut>::applyTask* task = - new typename BeamLinearMapping_mt< TIn, TOut>::applyTask( &status ); - - task->_mapping = this; - //task->_mparams = mparams; - task->_in = ∈ - task->_out = &out; - task->_firstPoint = nbTasks*taskSize; - task->_lastPoint = nbTasks*taskSize + pointsLeft; - + + } + if ( pointsLeft > 0) + { + typename BeamLinearMapping_mt< TIn, TOut>::applyTask* task = + new typename BeamLinearMapping_mt< TIn, TOut>::applyTask( &status ); + + task->_mapping = this; + //task->_mparams = mparams; + task->_in = ∈ + task->_out = &out; + task->_firstPoint = nbTasks*taskSize; + task->_lastPoint = nbTasks*taskSize + pointsLeft; + scheduler->addTask( task ); - - } - + + } + scheduler->workUntilDone(&status); - - - for ( int i=0; i::applyTask* task = - new typename BeamLinearMapping_mt< TIn, TOut>::applyTask( &status ); - - task->_mapping = this; - //task->_mparams = mparams; - task->_in = ∈ - task->_out = &out; - task->_firstPoint = i*taskSize + mGrainSize.getValue(); - task->_lastPoint = i*taskSize + taskSize; - + + + for ( int i=0; i::applyTask* task = + new typename BeamLinearMapping_mt< TIn, TOut>::applyTask( &status ); + + task->_mapping = this; + //task->_mparams = mparams; + task->_in = ∈ + task->_out = &out; + task->_firstPoint = i*taskSize + mGrainSize.getValue(); + task->_lastPoint = i*taskSize + taskSize; + scheduler->addTask( task ); - - } - + + } + scheduler->workUntilDone(&status); - - } - else - { - - BeamLinearMapping::apply( mparams, _out, _in ); - - } - - // it doesn't call the destructor - //task_pool.purge_memory(); - - } - - - - template - //void AdaptiveBeamMapping< TIn, TOut>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in ) - void BeamLinearMapping_mt< TIn, TOut>::applyJ(const core::MechanicalParams * params /* PARAMS FIRST */, Data< typename Out::VecDeriv >& _out, const Data< typename In::VecDeriv >& _in) - { - - //boost::pool<> task_pool(sizeof(BeamLinearMapping_mt< TIn, TOut>::applyJTask)); + + } + else + { + + BeamLinearMapping::apply( mparams, _out, _in ); + + } + + // it doesn't call the destructor + //task_pool.purge_memory(); + + } + + + + template + //void AdaptiveBeamMapping< TIn, TOut>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in ) + void BeamLinearMapping_mt< TIn, TOut>::applyJ(const core::MechanicalParams * params /* PARAMS FIRST */, Data< typename Out::VecDeriv >& _out, const Data< typename In::VecDeriv >& _in) + { + + //boost::pool<> task_pool(sizeof(BeamLinearMapping_mt< TIn, TOut>::applyJTask)); unsigned int numPoints = this->points.size(); - - if ( numPoints > 2*mGrainSize.getValue() ) - { - helper::WriteAccessor< Data< typename Out::VecDeriv > > out = _out; - helper::ReadAccessor< Data< typename In::VecDeriv > > in = _in; - - //const InVecDeriv& in= dIn.getValue(); - //VecDeriv& out = *dOut.beginEdit(); - - + + if ( numPoints > 2*mGrainSize.getValue() ) + { + helper::WriteAccessor< Data< typename Out::VecDeriv > > out = _out; + helper::ReadAccessor< Data< typename In::VecDeriv > > in = _in; + + //const InVecDeriv& in= dIn.getValue(); + //VecDeriv& out = *dOut.beginEdit(); + + out.resize(this->points.size()); - + simulation::CpuTask::Status status; simulation::TaskScheduler* scheduler = simulation::TaskScheduler::getInstance(); - - const int taskSize = 2*mGrainSize.getValue(); - - int nbTasks = numPoints / taskSize; - int pointsLeft = numPoints % taskSize; - - for ( int i=0; i::applyJTask* task = - new typename BeamLinearMapping_mt< TIn, TOut>::applyJTask( &status ); - - task->_mapping = this; - task->_in = ∈ - task->_out = &out; - task->_firstPoint = i*taskSize; - task->_lastPoint = i*taskSize + mGrainSize.getValue(); - + + const int taskSize = 2*mGrainSize.getValue(); + + int nbTasks = numPoints / taskSize; + int pointsLeft = numPoints % taskSize; + + for ( int i=0; i::applyJTask* task = + new typename BeamLinearMapping_mt< TIn, TOut>::applyJTask( &status ); + + task->_mapping = this; + task->_in = ∈ + task->_out = &out; + task->_firstPoint = i*taskSize; + task->_lastPoint = i*taskSize + mGrainSize.getValue(); + scheduler->addTask( task ); - - } - if ( pointsLeft > 0) - { - typename BeamLinearMapping_mt< TIn, TOut>::applyJTask* task = - new typename BeamLinearMapping_mt< TIn, TOut>::applyJTask( &status ); - - task->_mapping = this; - task->_in = ∈ - task->_out = &out; - task->_firstPoint = nbTasks*taskSize; - task->_lastPoint = nbTasks*taskSize + pointsLeft; - + + } + if ( pointsLeft > 0) + { + typename BeamLinearMapping_mt< TIn, TOut>::applyJTask* task = + new typename BeamLinearMapping_mt< TIn, TOut>::applyJTask( &status ); + + task->_mapping = this; + task->_in = ∈ + task->_out = &out; + task->_firstPoint = nbTasks*taskSize; + task->_lastPoint = nbTasks*taskSize + pointsLeft; + scheduler->addTask( task ); - - } - + + } + scheduler->workUntilDone(&status); - - - for ( int i=0; i::applyJTask* task = - new typename BeamLinearMapping_mt< TIn, TOut>::applyJTask( &status ); - - task->_mapping = this; - task->_in = ∈ - task->_out = &out; - task->_firstPoint = i*taskSize + mGrainSize.getValue(); - task->_lastPoint = i*taskSize + taskSize; - + + + for ( int i=0; i::applyJTask* task = + new typename BeamLinearMapping_mt< TIn, TOut>::applyJTask( &status ); + + task->_mapping = this; + task->_in = ∈ + task->_out = &out; + task->_firstPoint = i*taskSize + mGrainSize.getValue(); + task->_lastPoint = i*taskSize + taskSize; + scheduler->addTask( task ); - - } - + + } + scheduler->workUntilDone(&status); - - } - else - { - - BeamLinearMapping::applyJ( params, _out, _in ); - - } - - // it doesn't call the destructor - //task_pool.purge_memory(); - - } - - - - - template - void BeamLinearMapping_mt::applyJT(const core::MechanicalParams * mparams /* PARAMS FIRST */, Data< typename In::VecDeriv >& _out, const Data< typename Out::VecDeriv >& _in) - { - - //boost::pool<> task_pool(sizeof(BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask)); - + + } + else + { + + BeamLinearMapping::applyJ( params, _out, _in ); + + } + + // it doesn't call the destructor + //task_pool.purge_memory(); + + } + + + + + template + void BeamLinearMapping_mt::applyJT(const core::MechanicalParams * mparams /* PARAMS FIRST */, Data< typename In::VecDeriv >& _out, const Data< typename Out::VecDeriv >& _in) + { + + //boost::pool<> task_pool(sizeof(BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask)); + unsigned int numPoints = this->points.size(); - - if ( numPoints > 2*mGrainSize.getValue() ) - { - helper::WriteAccessor< Data< typename In::VecDeriv > > out = _out; - helper::ReadAccessor< Data< typename Out::VecDeriv > > in = _in; - - + + if ( numPoints > 2*mGrainSize.getValue() ) + { + helper::WriteAccessor< Data< typename In::VecDeriv > > out = _out; + helper::ReadAccessor< Data< typename Out::VecDeriv > > in = _in; + + simulation::CpuTask::Status status; simulation::TaskScheduler* scheduler = simulation::TaskScheduler::getInstance(); - - const int taskSize = 2*mGrainSize.getValue(); - - int nbTasks = numPoints / taskSize; - int pointsLeft = numPoints % taskSize; - - for ( int i=0; i::applyJTmechTask* task = - new typename BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask( &status ); - - task->_mapping = this; - task->_in = ∈ - task->_out = &out; - task->_firstPoint = i*taskSize; - task->_lastPoint = i*taskSize + mGrainSize.getValue(); - + + const int taskSize = 2*mGrainSize.getValue(); + + int nbTasks = numPoints / taskSize; + int pointsLeft = numPoints % taskSize; + + for ( int i=0; i::applyJTmechTask* task = + new typename BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask( &status ); + + task->_mapping = this; + task->_in = ∈ + task->_out = &out; + task->_firstPoint = i*taskSize; + task->_lastPoint = i*taskSize + mGrainSize.getValue(); + scheduler->addTask( task ); - - } - if ( pointsLeft > 0) - { - typename BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask* task = - new typename BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask( &status ); - - task->_mapping = this; - task->_in = ∈ - task->_out = &out; - task->_firstPoint = nbTasks*taskSize; - task->_lastPoint = nbTasks*taskSize + pointsLeft; - + + } + if ( pointsLeft > 0) + { + typename BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask* task = + new typename BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask( &status ); + + task->_mapping = this; + task->_in = ∈ + task->_out = &out; + task->_firstPoint = nbTasks*taskSize; + task->_lastPoint = nbTasks*taskSize + pointsLeft; + scheduler->addTask( task ); - - } - + + } + scheduler->workUntilDone(&status); - - - for ( int i=0; i::applyJTmechTask* task = - new typename BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask( &status ); - - task->_mapping = this; - task->_in = ∈ - task->_out = &out; - task->_firstPoint = i*taskSize + mGrainSize.getValue(); - task->_lastPoint = i*taskSize + taskSize; - + + + for ( int i=0; i::applyJTmechTask* task = + new typename BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask( &status ); + + task->_mapping = this; + task->_in = ∈ + task->_out = &out; + task->_firstPoint = i*taskSize + mGrainSize.getValue(); + task->_lastPoint = i*taskSize + taskSize; + scheduler->addTask( task ); - - } - + + } + scheduler->workUntilDone(&status); - - } - else - { - - BeamLinearMapping::applyJT( mparams, _out, _in ); - - } - - // it doesn't call the destructor - //task_pool.purge_memory(); - - } + + } + else + { + + BeamLinearMapping::applyJT( mparams, _out, _in ); + + } + + // it doesn't call the destructor + //task_pool.purge_memory(); + + } //// BeamLinearMapping::applyJT( typename In::MatrixDeriv& out, const typename Out::MatrixDeriv& in ) // diff --git a/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl b/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl index b51ee0146b4..e5a0df4a392 100644 --- a/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl +++ b/applications/plugins/MultiThreading/src/BeamLinearMapping_tasks.inl @@ -34,187 +34,157 @@ namespace component namespace mapping { - using namespace sofa::defaulttype; - - + using namespace sofa::defaulttype; + + + template + BeamLinearMapping_mt< TIn, TOut>::applyTask::applyTask( simulation::CpuTask::Status* status ) + : CpuTask( status ) + , _mapping(0) + , _in(0) + , _out(0) + , _firstPoint(0) + , _lastPoint(0) + + { + } + + template - BeamLinearMapping_mt< TIn, TOut>::applyTask::applyTask( simulation::CpuTask::Status* status ) - : CpuTask( status ) - , _mapping(0) - , _in(0) - , _out(0) - , _firstPoint(0) - , _lastPoint(0) - - { - } - - - template simulation::Task::MemoryAlloc BeamLinearMapping_mt< TIn, TOut>::applyTask::run() - { - for (size_t i = _firstPoint; i < _lastPoint; ++i ) - { - Coord inpos = _mapping->points[i]; - int in0 = helper::rfloor(inpos[0]); - if (in0<0) - in0 = 0; - else if (in0 > (int)_in->size()-2) - in0 = _in->size()-2; - inpos[0] -= in0; - + { + for (size_t i = _firstPoint; i < _lastPoint; ++i ) + { + Coord inpos = _mapping->points[i]; + int in0 = helper::rfloor(inpos[0]); + if (in0<0) + in0 = 0; + else if (in0 > (int)_in->size()-2) + in0 = _in->size()-2; + inpos[0] -= in0; + const typename In::Coord _in0 = (*_in)[in0]; const typename In::Coord _in1 = (*_in)[in0+1]; - Real beamLengh = _mapping->beamLength[in0]; - Coord& rotatedPoint0 = _mapping->rotatedPoints0[i]; - Coord& rotatedPoint1 = _mapping->rotatedPoints1[i]; - - rotatedPoint0 = _in0.getOrientation().rotate(inpos) * beamLengh; - Coord out0 = _in0.getCenter() + rotatedPoint0; - Coord inpos1 = inpos; inpos1[0] -= 1; - rotatedPoint1 = _in1.getOrientation().rotate(inpos1) * beamLengh; - Coord out1 = _in1.getCenter() + rotatedPoint1; - - Real fact = (Real)inpos[0]; - fact = 3*(fact*fact)-2*(fact*fact*fact); - (*_out)[i] = out0 * (1-fact) + out1 * (fact); - } - return MemoryAlloc::Stack; - } - - - template - BeamLinearMapping_mt< TIn, TOut>::applyJTask::applyJTask( simulation::CpuTask::Status* status ) - : CpuTask( status ) - , _mapping(0) - , _in(0) - , _out(0) - , _firstPoint(0) - , _lastPoint(0) - - { - } - - - template + Real beamLengh = _mapping->beamLength[in0]; + Coord& rotatedPoint0 = _mapping->rotatedPoints0[i]; + Coord& rotatedPoint1 = _mapping->rotatedPoints1[i]; + + rotatedPoint0 = _in0.getOrientation().rotate(inpos) * beamLengh; + Coord out0 = _in0.getCenter() + rotatedPoint0; + Coord inpos1 = inpos; inpos1[0] -= 1; + rotatedPoint1 = _in1.getOrientation().rotate(inpos1) * beamLengh; + Coord out1 = _in1.getCenter() + rotatedPoint1; + + Real fact = (Real)inpos[0]; + fact = 3*(fact*fact)-2*(fact*fact*fact); + (*_out)[i] = out0 * (1-fact) + out1 * (fact); + } + return MemoryAlloc::Stack; + } + + + template + BeamLinearMapping_mt< TIn, TOut>::applyJTask::applyJTask( simulation::CpuTask::Status* status ) + : CpuTask( status ) + , _mapping(0) + , _in(0) + , _out(0) + , _firstPoint(0) + , _lastPoint(0) + + { + } + + + template simulation::Task::MemoryAlloc BeamLinearMapping_mt< TIn, TOut>::applyJTask::run() - { - for (size_t i = _firstPoint; i < _lastPoint; ++i ) - { - - // out = J in - // J = [ I -OM^ ] - //out[i] = v - cross(rotatedPoints[i],omega); - + { + for (size_t i = _firstPoint; i < _lastPoint; ++i ) + { + + // out = J in + // J = [ I -OM^ ] + //out[i] = v - cross(rotatedPoints[i],omega); + defaulttype::Vec inpos = _mapping->points[i]; - int in0 = helper::rfloor(inpos[0]); - if (in0<0) - in0 = 0; - else if (in0 > (int)_in->size()-2) - in0 = _in->size()-2; - inpos[0] -= in0; - + int in0 = helper::rfloor(inpos[0]); + if (in0<0) + in0 = 0; + else if (in0 > (int)_in->size()-2) + in0 = _in->size()-2; + inpos[0] -= in0; + const typename In::Deriv _in0 = (*_in)[in0]; const typename In::Deriv _in1 = (*_in)[in0+1]; - Coord& rotatedPoint0 = _mapping->rotatedPoints0[i]; - Coord& rotatedPoint1 = _mapping->rotatedPoints1[i]; - - Deriv omega0 = getVOrientation( _in0 ); - Deriv out0 = getVCenter( _in0 ) - cross( rotatedPoint0, omega0); - Deriv omega1 = getVOrientation( _in1 ); - Deriv out1 = getVCenter( _in1 ) - cross( rotatedPoint1, omega1); - Real fact = (Real)inpos[0]; - fact = 3*(fact*fact)-2*(fact*fact*fact); - - (*_out)[i] = out0 * (1-fact) + out1 * (fact); - } - return MemoryAlloc::Stack; - } - - - template - BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask::applyJTmechTask( simulation::CpuTask::Status* status ) - : CpuTask( status ) - , _mapping(0) - , _in(0) - , _out(0) - , _firstPoint(0) - , _lastPoint(0) - - { - } - - - template + Coord& rotatedPoint0 = _mapping->rotatedPoints0[i]; + Coord& rotatedPoint1 = _mapping->rotatedPoints1[i]; + + Deriv omega0 = getVOrientation( _in0 ); + Deriv out0 = getVCenter( _in0 ) - cross( rotatedPoint0, omega0); + Deriv omega1 = getVOrientation( _in1 ); + Deriv out1 = getVCenter( _in1 ) - cross( rotatedPoint1, omega1); + Real fact = (Real)inpos[0]; + fact = 3*(fact*fact)-2*(fact*fact*fact); + + (*_out)[i] = out0 * (1-fact) + out1 * (fact); + } + return MemoryAlloc::Stack; + } + + + template + BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask::applyJTmechTask( simulation::CpuTask::Status* status ) + : CpuTask( status ) + , _mapping(0) + , _in(0) + , _out(0) + , _firstPoint(0) + , _lastPoint(0) + + { + } + + + template simulation::Task::MemoryAlloc BeamLinearMapping_mt< TIn, TOut>::applyJTmechTask::run() - { - for (size_t i = _firstPoint; i < _lastPoint; ++i ) - { - - // out = Jt in - // Jt = [ I ] - // [ -OM^t ] - // -OM^t = OM^ - - //Deriv f = in[i]; - //v += f; - //omega += cross(rotatedPoints[i],f); - - defaulttype::Vec inpos = _mapping->points[i]; - int in0 = helper::rfloor(inpos[0]); - if (in0<0) - in0 = 0; - else if (in0 > (int)_out->size()-2) - in0 = _out->size()-2; - inpos[0] -= in0; - + { + for (size_t i = _firstPoint; i < _lastPoint; ++i ) + { + + // out = Jt in + // Jt = [ I ] + // [ -OM^t ] + // -OM^t = OM^ + + //Deriv f = in[i]; + //v += f; + //omega += cross(rotatedPoints[i],f); + + defaulttype::Vec inpos = _mapping->points[i]; + int in0 = helper::rfloor(inpos[0]); + if (in0<0) + in0 = 0; + else if (in0 > (int)_out->size()-2) + in0 = _out->size()-2; + inpos[0] -= in0; + typename In::Deriv& _out0 = (*_out)[in0]; typename In::Deriv& _out1 = (*_out)[in0+1]; - const Coord& rotatedPoint0 = _mapping->rotatedPoints0[i]; - const Coord& rotatedPoint1 = _mapping->rotatedPoints1[i]; - - Deriv f = (*_in)[i]; - Real fact = (Real)inpos[0]; - fact = 3*(fact*fact)-2*(fact*fact*fact); - - getVCenter(_out0) += f * (1-fact); - getVOrientation(_out0) += cross( rotatedPoint0, f) * (1-fact); - getVCenter(_out1) += f * (fact); - getVOrientation(_out1) += cross( rotatedPoint1, f) * (fact); - - } - return MemoryAlloc::Stack; - } - - - //template - //BeamLinearMapping_mt< TIn, TOut>::applyJTconstrTask::applyJTconstrTask( const simulation::Task::Status* status ) - // : CpuTask( status ) - // , _mapping(0) - // , _in(0) - // , _out(0) - // , _firstPoint(0) - // , _lastPoint(0) - - //{ - //} - - - //template - //bool BeamLinearMapping_mt< TIn, TOut>::applyJTconstrTask::run( simulation::WorkerThread* ) - //{ - // bool result = true; - - // for (size_t i = _firstPoint; i < _lastPoint; ++i ) - // { - - // } - - // return true; - //} - - - + const Coord& rotatedPoint0 = _mapping->rotatedPoints0[i]; + const Coord& rotatedPoint1 = _mapping->rotatedPoints1[i]; + + Deriv f = (*_in)[i]; + Real fact = (Real)inpos[0]; + fact = 3*(fact*fact)-2*(fact*fact*fact); + + getVCenter(_out0) += f * (1-fact); + getVOrientation(_out0) += cross( rotatedPoint0, f) * (1-fact); + getVCenter(_out1) += f * (fact); + getVOrientation(_out1) += cross( rotatedPoint1, f) * (fact); + + } + return MemoryAlloc::Stack; + } } // namespace mapping From 0acdde18ca72ce7ba2830a511874fd0083ae0d64 Mon Sep 17 00:00:00 2001 From: fspadoni Date: Wed, 27 Mar 2019 15:36:00 +0100 Subject: [PATCH 10/10] [TaskScheduler] Re-Indent again all modified files --- .../simulation/TaskSchedulerTestTasks.cpp | 98 +++--- .../simulation/TaskSchedulerTestTasks.h | 92 +++--- .../simulation/TaskSchedulerTests.cpp | 102 +++--- .../framework/sofa/simulation/InitTasks.cpp | 28 +- .../framework/sofa/simulation/InitTasks.h | 26 +- SofaKernel/framework/sofa/simulation/Task.h | 2 +- .../sofa/simulation/TaskScheduler.cpp | 26 +- .../framework/sofa/simulation/TaskScheduler.h | 46 +-- .../MultiThreading/src/BeamLinearMapping_mt.h | 292 +++++++++--------- .../src/BeamLinearMapping_mt.inl | 154 +-------- 10 files changed, 357 insertions(+), 509 deletions(-) diff --git a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.cpp b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.cpp index 85c3170e2b2..9c69f5b89ed 100644 --- a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.cpp +++ b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.cpp @@ -7,66 +7,66 @@ using sofa::simulation::Task; namespace sofa { - + Task::MemoryAlloc FibonacciTask::run() - { - if (_N < 2) - { - *_sum = _N; - return MemoryAlloc::Stack; - } - + { + if (_N < 2) + { + *_sum = _N; + return MemoryAlloc::Stack; + } + simulation::CpuTask::Status status; - - int64_t x, y; - + + int64_t x, y; + simulation::TaskScheduler* scheduler = simulation::TaskScheduler::getInstance(); - - FibonacciTask task0(_N - 1, &x, &status); - FibonacciTask task1(_N - 2, &y, &status); - + + FibonacciTask task0(_N - 1, &x, &status); + FibonacciTask task1(_N - 2, &y, &status); + scheduler->addTask(&task0); scheduler->addTask(&task1); scheduler->workUntilDone(&status); - - // Do the sum - *_sum = x + y; - - return MemoryAlloc::Stack; - } - - - + + // Do the sum + *_sum = x + y; + + return MemoryAlloc::Stack; + } + + + Task::MemoryAlloc IntSumTask::run() - { - const int64_t count = _last - _first; - if (count < 1) - { - *_sum = _first; - return MemoryAlloc::Stack; - } - - const int64_t mid = _first + (count / 2); - + { + const int64_t count = _last - _first; + if (count < 1) + { + *_sum = _first; + return MemoryAlloc::Stack; + } + + const int64_t mid = _first + (count / 2); + simulation::CpuTask::Status status; - - int64_t x, y; - + + int64_t x, y; + simulation::TaskScheduler* scheduler = simulation::TaskScheduler::getInstance(); - - IntSumTask task0(_first, mid, &x, &status); - IntSumTask task1(mid+1, _last, &y, &status); - + + IntSumTask task0(_first, mid, &x, &status); + IntSumTask task1(mid+1, _last, &y, &status); + scheduler->addTask(&task0); scheduler->addTask(&task1); scheduler->workUntilDone(&status); - - // Do the sum - *_sum = x + y; - - - return MemoryAlloc::Stack; - } - + + // Do the sum + *_sum = x + y; + + + return MemoryAlloc::Stack; + } + } // namespace sofa diff --git a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.h b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.h index 638bdf7e054..03d1dfe81e3 100644 --- a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.h +++ b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTestTasks.h @@ -4,50 +4,50 @@ namespace sofa { - // compute recursively the Fibonacci number for input N O(~1.6 exp(N)) - // this is implemented to test the task scheduler generating super lightweight tasks and not for performance - class FibonacciTask : public simulation::CpuTask - { - public: - FibonacciTask(const int64_t N, int64_t* const sum, simulation::CpuTask::Status* status) - : CpuTask(status) - , _N(N) - , _sum(sum) - {} - - ~FibonacciTask() override { } - - MemoryAlloc run() final; - - private: - - const int64_t _N; - int64_t* const _sum; - }; - - - // compute recursively the sum of integers from first to last - // this is implemented to test the task scheduler generating super lightweight tasks and not for performance - class IntSumTask : public simulation::CpuTask - { - public: - IntSumTask(const int64_t first, const int64_t last, int64_t* const sum, simulation::CpuTask::Status* status) - : CpuTask(status) - , _first(first) - , _last(last) - , _sum(sum) - {} - - ~IntSumTask() override {} - - MemoryAlloc run() final; - - - private: - - const int64_t _first; - const int64_t _last; - int64_t* const _sum; - - }; + // compute recursively the Fibonacci number for input N O(~1.6 exp(N)) + // this is implemented to test the task scheduler generating super lightweight tasks and not for performance + class FibonacciTask : public simulation::CpuTask + { + public: + FibonacciTask(const int64_t N, int64_t* const sum, simulation::CpuTask::Status* status) + : CpuTask(status) + , _N(N) + , _sum(sum) + {} + + ~FibonacciTask() override { } + + MemoryAlloc run() final; + + private: + + const int64_t _N; + int64_t* const _sum; + }; + + + // compute recursively the sum of integers from first to last + // this is implemented to test the task scheduler generating super lightweight tasks and not for performance + class IntSumTask : public simulation::CpuTask + { + public: + IntSumTask(const int64_t first, const int64_t last, int64_t* const sum, simulation::CpuTask::Status* status) + : CpuTask(status) + , _first(first) + , _last(last) + , _sum(sum) + {} + + ~IntSumTask() override {} + + MemoryAlloc run() final; + + + private: + + const int64_t _first; + const int64_t _last; + int64_t* const _sum; + + }; } // namespace sofa diff --git a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTests.cpp b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTests.cpp index e0dd61c04eb..bc0b0f6b827 100644 --- a/SofaKernel/framework/framework_test/simulation/TaskSchedulerTests.cpp +++ b/SofaKernel/framework/framework_test/simulation/TaskSchedulerTests.cpp @@ -7,46 +7,46 @@ namespace sofa { - // compute the Fibonacci number for input N - static int64_t Fibonacci(int64_t N, int nbThread = 0) - { + // compute the Fibonacci number for input N + static int64_t Fibonacci(int64_t N, int nbThread = 0) + { simulation::TaskScheduler* scheduler = simulation::TaskScheduler::create(simulation::DefaultTaskScheduler::name()); scheduler->init(nbThread); - + simulation::CpuTask::Status status; - int64_t result = 0; - - FibonacciTask task(N, &result, &status); + int64_t result = 0; + + FibonacciTask task(N, &result, &status); scheduler->addTask(&task); scheduler->workUntilDone(&status); - + scheduler->stop(); - return result; - } - - - // compute the sum of integers from 1 to N - static int64_t IntSum1ToN(const int64_t N, int nbThread = 0) - { + return result; + } + + + // compute the sum of integers from 1 to N + static int64_t IntSum1ToN(const int64_t N, int nbThread = 0) + { simulation::TaskScheduler* scheduler = simulation::TaskScheduler::create(simulation::DefaultTaskScheduler::name()); scheduler->init(nbThread); - + simulation::CpuTask::Status status; - int64_t result = 0; - - IntSumTask task(1, N, &result, &status); + int64_t result = 0; + + IntSumTask task(1, N, &result, &status); scheduler->addTask(&task); scheduler->workUntilDone(&status); - + scheduler->stop(); - return result; - } - - - - // compute the Fibonacci single thread - TEST(TaskSchedulerTests, FibonacciSingle ) - { + return result; + } + + + + // compute the Fibonacci single thread + TEST(TaskSchedulerTests, FibonacciSingle ) + { // tested with // 3 : 2 // 6 : 8 @@ -59,12 +59,12 @@ namespace sofa // 47 : 2971215073 const int64_t res = Fibonacci(27, 1); EXPECT_EQ(res, 196418); - return; - } - - // compute the Fibonacci multi thread - TEST(TaskSchedulerTests, FibonacciMulti) - { + return; + } + + // compute the Fibonacci multi thread + TEST(TaskSchedulerTests, FibonacciMulti) + { // tested with // 3 : 2 // 6 : 8 @@ -77,26 +77,26 @@ namespace sofa // 47 : 2971215073 const int64_t res = Fibonacci(27); EXPECT_EQ(res, 196418); - return; - } - - // compute the sum of integers from 1 to N single thread - TEST(TaskSchedulerTests, IntSumSingle) - { + return; + } + + // compute the sum of integers from 1 to N single thread + TEST(TaskSchedulerTests, IntSumSingle) + { const int64_t N = 1 << 20; int64_t res = IntSum1ToN(N, 1); - EXPECT_EQ(res, (N)*(N+1)/2); - return; - } - - // compute the sum of integers from 1 to N multi thread - TEST(TaskSchedulerTests, IntSumMulti) - { + EXPECT_EQ(res, (N)*(N+1)/2); + return; + } + + // compute the sum of integers from 1 to N multi thread + TEST(TaskSchedulerTests, IntSumMulti) + { const int64_t N = 1 << 20; int64_t res = IntSum1ToN(N); - EXPECT_EQ(res, (N)*(N + 1) / 2); - return; - } - + EXPECT_EQ(res, (N)*(N + 1) / 2); + return; + } + } // namespace sofa diff --git a/SofaKernel/framework/sofa/simulation/InitTasks.cpp b/SofaKernel/framework/sofa/simulation/InitTasks.cpp index 8570ac807ab..2e34df847fd 100644 --- a/SofaKernel/framework/sofa/simulation/InitTasks.cpp +++ b/SofaKernel/framework/sofa/simulation/InitTasks.cpp @@ -13,38 +13,38 @@ namespace sofa namespace simulation { - + InitPerThreadDataTask::InitPerThreadDataTask(std::atomic* atomicCounter, std::mutex* mutex, CpuTask::Status* status) - : CpuTask(status), IdFactorygetIDMutex(mutex), _atomicCounter(atomicCounter) + : CpuTask(status), IdFactorygetIDMutex(mutex), _atomicCounter(atomicCounter) {} - + InitPerThreadDataTask::~InitPerThreadDataTask() { } - + Task::MemoryAlloc InitPerThreadDataTask::run() { - + core::ExecParams::defaultInstance(); - + core::ConstraintParams::defaultInstance(); - + core::MechanicalParams::defaultInstance(); - + core::visual::VisualParams::defaultInstance(); - + { // to solve IdFactory::getID() problem in AdvancedTimer functions std::lock_guard lock(*IdFactorygetIDMutex); - + //spinMutexLock lock( IdFactorygetIDMutex ); - + helper::AdvancedTimer::begin("Animate"); helper::AdvancedTimer::end("Animate"); } - + _atomicCounter->fetch_sub(1, std::memory_order_acq_rel); - + while (_atomicCounter->load(std::memory_order_relaxed) > 0) { // yield while waiting @@ -52,7 +52,7 @@ namespace sofa } return Task::MemoryAlloc::Dynamic; } - + // temp remove this function to use the global one void initThreadLocalData() diff --git a/SofaKernel/framework/sofa/simulation/InitTasks.h b/SofaKernel/framework/sofa/simulation/InitTasks.h index e798eaee35b..d472e60fb92 100644 --- a/SofaKernel/framework/sofa/simulation/InitTasks.h +++ b/SofaKernel/framework/sofa/simulation/InitTasks.h @@ -28,33 +28,33 @@ namespace sofa { namespace simulation { - + using namespace sofa; - - - + + + class SOFA_SIMULATION_CORE_API InitPerThreadDataTask : public CpuTask { - + public: - + InitPerThreadDataTask(std::atomic* atomicCounter, std::mutex* mutex, CpuTask::Status* status); - + ~InitPerThreadDataTask() override; - + MemoryAlloc run() override; - + private: - + std::mutex* IdFactorygetIDMutex; std::atomic* _atomicCounter; }; - - + + // thread storage initialization SOFA_SIMULATION_CORE_API void initThreadLocalData(); - + } // namespace simulation diff --git a/SofaKernel/framework/sofa/simulation/Task.h b/SofaKernel/framework/sofa/simulation/Task.h index 246311a4b22..32157f26e7c 100644 --- a/SofaKernel/framework/sofa/simulation/Task.h +++ b/SofaKernel/framework/sofa/simulation/Task.h @@ -201,7 +201,7 @@ namespace sofa std::atomic* m_atomicCounter; std::mutex* m_threadSpecificMutex; }; - + } // namespace simulation diff --git a/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp b/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp index 48515a842f1..c9e5e259d83 100644 --- a/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp +++ b/SofaKernel/framework/sofa/simulation/TaskScheduler.cpp @@ -17,10 +17,10 @@ namespace sofa std::map > TaskScheduler::_schedulers; std::string TaskScheduler::_currentSchedulerName; TaskScheduler* TaskScheduler::_currentScheduler = nullptr; - + // register default task scheduler const bool DefaultTaskScheduler::isRegistered = TaskScheduler::registerScheduler(DefaultTaskScheduler::name(), &DefaultTaskScheduler::create); - + TaskScheduler* TaskScheduler::create(const char* name) { @@ -28,7 +28,7 @@ namespace sofa std::string nameStr(name); if (!nameStr.empty() && _currentSchedulerName == name) return _currentScheduler; - + auto iter = _schedulers.find(name); if (iter == _schedulers.end()) { @@ -37,29 +37,29 @@ namespace sofa iter = _schedulers.end(); --iter; } - + if (_currentScheduler != nullptr) { delete _currentScheduler; } - + TaskSchedulerCreatorFunction& creatorFunc = iter->second; _currentScheduler = creatorFunc(); _currentSchedulerName = iter->first; - + Task::setAllocator(_currentScheduler->getTaskAllocator()); - + return _currentScheduler; } - - + + bool TaskScheduler::registerScheduler(const char* name, std::function creatorFunc) { _schedulers[name] = creatorFunc; return true; } - + TaskScheduler* TaskScheduler::getInstance() { if (_currentScheduler == nullptr) @@ -67,11 +67,11 @@ namespace sofa TaskScheduler::create();// TaskSchedulerDefault::getName()); _currentScheduler->init(); } - + return _currentScheduler; } - - + + TaskScheduler::~TaskScheduler() { diff --git a/SofaKernel/framework/sofa/simulation/TaskScheduler.h b/SofaKernel/framework/sofa/simulation/TaskScheduler.h index 1f2c5e27e18..8c3fba26db8 100644 --- a/SofaKernel/framework/sofa/simulation/TaskScheduler.h +++ b/SofaKernel/framework/sofa/simulation/TaskScheduler.h @@ -42,56 +42,56 @@ namespace sofa namespace simulation { - + class SOFA_SIMULATION_CORE_API TaskScheduler { - + public: - - + + virtual ~TaskScheduler(); - + static TaskScheduler* create(const char* name = ""); - + typedef std::function TaskSchedulerCreatorFunction; - + static bool registerScheduler(const char* name, std::function creatorFunc); - + static TaskScheduler* getInstance(); - + static const std::string& getCurrentName() { return _currentSchedulerName; } - + // interface virtual void init(const unsigned int nbThread = 0) = 0; - + virtual void stop(void) = 0; - + virtual unsigned int getThreadCount(void) const = 0; - + virtual const char* getCurrentThreadName() = 0; - + virtual int getCurrentThreadType() = 0; - + // queue task if there is space, and run it otherwise virtual bool addTask(Task* task) = 0; - + virtual void workUntilDone(Task::Status* status) = 0; - + virtual Task::Allocator* getTaskAllocator() = 0; - - + + protected: - + // factory map: registered schedulers: name, creation function static std::map > _schedulers; - + // current instantiated scheduler static std::string _currentSchedulerName; static TaskScheduler * _currentScheduler; - + friend class Task; }; - + } // namespace simulation diff --git a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h index f67c314bbaa..63f00e0b86e 100644 --- a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h +++ b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.h @@ -39,153 +39,153 @@ namespace component namespace mapping { - -template -class BeamLinearMapping_mt : public BeamLinearMapping -{ -public: - SOFA_CLASS(SOFA_TEMPLATE2(BeamLinearMapping_mt,TIn,TOut), SOFA_TEMPLATE2(BeamLinearMapping,TIn,TOut) ); - - typedef core::Mapping Inherit; - typedef TIn In; - typedef TOut Out; - typedef Out OutDataTypes; - typedef typename Out::VecCoord VecCoord; - typedef typename Out::VecDeriv VecDeriv; - typedef typename Out::Coord Coord; - typedef typename Out::Deriv Deriv; - - typedef In InDataTypes; - typedef typename In::Deriv InDeriv; - - typedef typename Coord::value_type Real; - - typedef BeamLinearMapping BeamLinearMappingInOut; - enum { N = BeamLinearMappingInOut::N }; - enum { NIn = BeamLinearMappingInOut::NIn }; - enum { NOut = BeamLinearMappingInOut::NOut }; - - typedef defaulttype::Mat Mat; - typedef defaulttype::Vec Vector; - typedef defaulttype::Mat MBloc; - typedef sofa::component::linearsolver::CompressedRowSparseMatrix MatrixType; - - - BeamLinearMapping_mt(); - - virtual ~BeamLinearMapping_mt(); - - - virtual void apply(const core::MechanicalParams *mparams /* PARAMS FIRST */, Data< typename Out::VecCoord >& out, const Data< typename In::VecCoord >& in); - - virtual void applyJ(const core::MechanicalParams *mparams /* PARAMS FIRST */, Data< typename Out::VecDeriv >& out, const Data< typename In::VecDeriv >& in); - - virtual void applyJT(const core::MechanicalParams *mparams /* PARAMS FIRST */, Data< typename In::VecDeriv >& out, const Data< typename Out::VecDeriv >& in); - - //virtual void applyJT(const core::ConstraintParams *cparams /* PARAMS FIRST */, Data< typename In::MatrixDeriv >& out, const Data< typename Out::MatrixDeriv >& in); - - - virtual void init(); // get the interpolation - virtual void bwdInit(); // get the points - - - -public: - - // granularity - Data mGrainSize; ///< minimum number of Beam points for task creation - - - -private: - - - // all tasks here - - class applyTask : public simulation::CpuTask - { - - typedef typename BeamLinearMapping::Out::VecCoord VecCoord; - typedef typename BeamLinearMapping::In::VecCoord InVecCoord; - - public: - - MemoryAlloc run() final; - - protected: - - applyTask( simulation::CpuTask::Status* status ); - - private: - - BeamLinearMapping_mt* _mapping; - - const helper::ReadAccessor< Data< typename In::VecCoord > >* _in; - helper::WriteAccessor< Data< typename Out::VecCoord > >* _out; - - size_t _firstPoint; - size_t _lastPoint; - - friend class BeamLinearMapping_mt; - }; - - - class applyJTask : public simulation::CpuTask - { - - typedef typename BeamLinearMapping::Out::VecDeriv VecDeriv; - typedef typename BeamLinearMapping::In::VecDeriv InVecDeriv; - - public: - - applyJTask( simulation::CpuTask::Status* status ); - - MemoryAlloc run() final; - - private: - - BeamLinearMapping_mt* _mapping; - - const helper::ReadAccessor< Data< typename In::VecDeriv > >* _in; - helper::WriteAccessor< Data< typename Out::VecDeriv > >* _out; - - size_t _firstPoint; - size_t _lastPoint; - - friend class BeamLinearMapping_mt; - }; - - - class applyJTmechTask : public simulation::CpuTask - { - typedef typename BeamLinearMapping::Out::VecDeriv VecDeriv; - typedef typename BeamLinearMapping::In::VecDeriv InVecDeriv; - - public: - - applyJTmechTask( simulation::CpuTask::Status* status ); - - MemoryAlloc run() final; - - private: - - BeamLinearMapping_mt* _mapping; - - const helper::ReadAccessor< Data< typename Out::VecDeriv > >* _in; - helper::WriteAccessor< Data< typename In::VecDeriv > >* _out; - - size_t _firstPoint; - size_t _lastPoint; - - friend class BeamLinearMapping_mt; - }; - - - friend class applyTask; - friend class applyJTask; - friend class applyJTmechTask; -}; + template + class BeamLinearMapping_mt : public BeamLinearMapping + { + public: + SOFA_CLASS(SOFA_TEMPLATE2(BeamLinearMapping_mt,TIn,TOut), SOFA_TEMPLATE2(BeamLinearMapping,TIn,TOut) ); + + typedef core::Mapping Inherit; + typedef TIn In; + typedef TOut Out; + typedef Out OutDataTypes; + typedef typename Out::VecCoord VecCoord; + typedef typename Out::VecDeriv VecDeriv; + typedef typename Out::Coord Coord; + typedef typename Out::Deriv Deriv; + + typedef In InDataTypes; + typedef typename In::Deriv InDeriv; + + typedef typename Coord::value_type Real; + + typedef BeamLinearMapping BeamLinearMappingInOut; + enum { N = BeamLinearMappingInOut::N }; + enum { NIn = BeamLinearMappingInOut::NIn }; + enum { NOut = BeamLinearMappingInOut::NOut }; + + typedef defaulttype::Mat Mat; + typedef defaulttype::Vec Vector; + typedef defaulttype::Mat MBloc; + typedef sofa::component::linearsolver::CompressedRowSparseMatrix MatrixType; + + + BeamLinearMapping_mt(); + + virtual ~BeamLinearMapping_mt(); + + + virtual void apply(const core::MechanicalParams *mparams /* PARAMS FIRST */, Data< typename Out::VecCoord >& out, const Data< typename In::VecCoord >& in); + + virtual void applyJ(const core::MechanicalParams *mparams /* PARAMS FIRST */, Data< typename Out::VecDeriv >& out, const Data< typename In::VecDeriv >& in); + + virtual void applyJT(const core::MechanicalParams *mparams /* PARAMS FIRST */, Data< typename In::VecDeriv >& out, const Data< typename Out::VecDeriv >& in); + + //virtual void applyJT(const core::ConstraintParams *cparams /* PARAMS FIRST */, Data< typename In::MatrixDeriv >& out, const Data< typename Out::MatrixDeriv >& in); + + + virtual void init(); // get the interpolation + virtual void bwdInit(); // get the points + + + + + public: + + // granularity + Data mGrainSize; ///< minimum number of Beam points for task creation + + + + private: + + + // all tasks here + + class applyTask : public simulation::CpuTask + { + + typedef typename BeamLinearMapping::Out::VecCoord VecCoord; + typedef typename BeamLinearMapping::In::VecCoord InVecCoord; + + public: + + MemoryAlloc run() final; + + protected: + + applyTask( simulation::CpuTask::Status* status ); + + private: + + BeamLinearMapping_mt* _mapping; + + const helper::ReadAccessor< Data< typename In::VecCoord > >* _in; + helper::WriteAccessor< Data< typename Out::VecCoord > >* _out; + + size_t _firstPoint; + size_t _lastPoint; + + friend class BeamLinearMapping_mt; + }; + + + class applyJTask : public simulation::CpuTask + { + + typedef typename BeamLinearMapping::Out::VecDeriv VecDeriv; + typedef typename BeamLinearMapping::In::VecDeriv InVecDeriv; + + public: + + applyJTask( simulation::CpuTask::Status* status ); + + MemoryAlloc run() final; + + private: + + BeamLinearMapping_mt* _mapping; + + const helper::ReadAccessor< Data< typename In::VecDeriv > >* _in; + helper::WriteAccessor< Data< typename Out::VecDeriv > >* _out; + + size_t _firstPoint; + size_t _lastPoint; + + friend class BeamLinearMapping_mt; + }; + + + class applyJTmechTask : public simulation::CpuTask + { + typedef typename BeamLinearMapping::Out::VecDeriv VecDeriv; + typedef typename BeamLinearMapping::In::VecDeriv InVecDeriv; + + public: + + applyJTmechTask( simulation::CpuTask::Status* status ); + + MemoryAlloc run() final; + + private: + + BeamLinearMapping_mt* _mapping; + + const helper::ReadAccessor< Data< typename Out::VecDeriv > >* _in; + helper::WriteAccessor< Data< typename In::VecDeriv > >* _out; + + size_t _firstPoint; + size_t _lastPoint; + + friend class BeamLinearMapping_mt; + }; + + + friend class applyTask; + friend class applyJTask; + friend class applyJTmechTask; + }; } // namespace mapping diff --git a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl index cd00825f79a..b2f51559de0 100644 --- a/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl +++ b/applications/plugins/MultiThreading/src/BeamLinearMapping_mt.inl @@ -342,159 +342,7 @@ namespace mapping //task_pool.purge_memory(); } - - - //// BeamLinearMapping::applyJT( typename In::MatrixDeriv& out, const typename Out::MatrixDeriv& in ) // - //// this function propagate the constraint through the rigid mapping : - //// if one constraint along (vector n) with a value (v) is applied on the childModel (like collision model) - //// then this constraint is transformed by (Jt.n) with value (v) for the rigid model - //// There is a specificity of this propagateConstraint: we have to find the application point on the childModel - //// in order to compute the right constaint on the rigidModel. - //template - //void BeamLinearMapping_mt::applyJT(const core::ConstraintParams * cparams /* PARAMS FIRST */, Data< typename In::MatrixDeriv >& _out, const Data< typename Out::MatrixDeriv >& _in) - //{ - // typename In::MatrixDeriv* out = _out.beginEdit(); - // const typename Out::MatrixDeriv& in = _in.getValue(); - - // const typename In::VecCoord& x = *this->fromModel->getX(); - - // typename Out::MatrixDeriv::RowConstIterator rowItEnd = in.end(); - - // //for (typename Out::MatrixDeriv::RowConstIterator rowIt = in.begin(); rowIt != rowItEnd; ++rowIt) - // //{ - // // typename Out::MatrixDeriv::ColConstIterator colIt = rowIt.begin(); - // // typename Out::MatrixDeriv::ColConstIterator colItEnd = rowIt.end(); - - // // if (colIt != colItEnd) - // // { - // // typename In::MatrixDeriv::RowIterator o = out->writeLine(rowIt.index()); - - // // // computation of (Jt.n) - // // for (typename Out::MatrixDeriv::ColConstIterator colIt = rowIt.begin(); colIt != colItEnd; ++colIt) - // // { - // // unsigned int indexIn = colIt.index(); - // // Deriv data = (Deriv) colIt.val(); - - // // // interpolation - // // Coord inpos = points[indexIn]; - // // int in0 = helper::rfloor(inpos[0]); - // // if (in0<0) - // // in0 = 0; - // // else if (in0 > (int)x.size()-2) - // // in0 = x.size()-2; - // // inpos[0] -= in0; - // // Real fact = (Real)inpos[0]; - // // fact = (Real)3.0*(fact*fact) - (Real)2.0*(fact*fact*fact); - - // // // weighted value of the constraint direction - // // Deriv w_n = data; - - // // // Compute the mapped Constraint on the beam nodes - // // InDeriv direction0; - // // getVCenter(direction0) = w_n * (1-fact); - // // getVOrientation(direction0) = cross(rotatedPoints0[indexIn], w_n) * (1-fact); - // // InDeriv direction1; - // // getVCenter(direction1) = w_n * (fact); - // // getVOrientation(direction1) = cross(rotatedPoints1[indexIn], w_n) * (fact); - - // // o.addCol(in0, direction0); - // // o.addCol(in0+1, direction1); - // // } - // // } - // //} - - - - - // //static boost::pool<> task_pool(sizeof(BeamLinearMapping_mt< TIn, TOut>::applyJTconstrTask)); - - // //unsigned int numPoints = points.size(); - - // //if ( numPoints > 2*mGrainSize.getValue() ) - // //{ - // // helper::WriteAccessor< Data< typename In::VecDeriv > > out = _out; - // // helper::ReadAccessor< Data< typename Out::VecDeriv > > in = _in; - - // // //const InVecDeriv& in= dIn.getValue(); - // // //VecDeriv& out = *dOut.beginEdit(); - - - // // out.resize(points.size()); - - // // simulation::Task::Status status; - // // simulation::WorkerThread* thread = simulation::WorkerThread::getCurrent(); - - // // const int taskSize = 2*mGrainSize.getValue(); - - // // int nbTasks = numPoints / taskSize; - // // int pointsLeft = numPoints % taskSize; - - // // for ( int i=0; i::applyJTconstrTask* task = - // // new( task_pool.malloc()) BeamLinearMapping_mt< TIn, TOut>::applyJTconstrTask( &status ); - - // // task->_mapping = this; - // // task->_in = ∈ - // // task->_out = &out; - // // task->_firstPoint = i*taskSize; - // // task->_lastPoint = i*taskSize + mGrainSize.getValue(); - - // // thread->addTask( task ); - - // // } - // // if ( pointsLeft > 0) - // // { - // // BeamLinearMapping_mt< TIn, TOut>::applyJTconstrTask* task = - // // new( task_pool.malloc()) BeamLinearMapping_mt< TIn, TOut>::applyJTconstrTask( &status ); - - // // task->_mapping = this; - // // task->_in = ∈ - // // task->_out = &out; - // // task->_firstPoint = nbTasks*taskSize; - // // task->_lastPoint = nbTasks*taskSize + pointsLeft; - - // // thread->addTask( task ); - - // // } - - // // thread->workUntilDone(&status); - - - // // for ( int i=0; i::applyJTconstrTask* task = - // // new( task_pool.malloc()) BeamLinearMapping_mt< TIn, TOut>::applyJTconstrTask( &status ); - - // // task->_mapping = this; - // // task->_in = ∈ - // // task->_out = &out; - // // task->_firstPoint = i*taskSize + mGrainSize.getValue(); - // // task->_lastPoint = i*taskSize + taskSize; - - // // thread->addTask( task ); - - // // } - - // // thread->workUntilDone(&status); - - // //} - // //else - // { - - // BeamLinearMapping::applyJT( cparams, _out, _in ); - - // } - - // // it doesn't call the destructor - // //task_pool.purge_memory(); - - - //} - - - - + } // namespace mapping