diff --git a/mindspore/core/mindrt/src/actor/actormgr.cc b/mindspore/core/mindrt/src/actor/actormgr.cc index e9d1a53f20e..cd86713eff4 100644 --- a/mindspore/core/mindrt/src/actor/actormgr.cc +++ b/mindspore/core/mindrt/src/actor/actormgr.cc @@ -67,6 +67,10 @@ void ActorMgr::Initialize(bool use_inner_pool, size_t actor_thread_num, size_t m inner_pool_->DisableOccupiedActorThread(); inner_pool_->SetKernelThreadNum(max_thread_num - actor_thread_num); } + if (inner_pool_ != nullptr) { + inner_pool_->SetMaxSpinCount(kDefaultSpinCount); + inner_pool_->SetSpinCountMaxValue(); + } } } @@ -253,7 +257,6 @@ void ActorMgr::Terminate(const AID &id) { std::unique_ptr msg(new (std::nothrow) MessageBase("Terminate", MessageBase::Type::KTERMINATE)); MINDRT_OOM_EXIT(msg); (void)actor->EnqueMessage(std::move(msg)); - actor->SetRunningStatus(true); // Wait actor's thread to finish. actor->Await(); diff --git a/mindspore/core/mindrt/src/thread/actor_threadpool.cc b/mindspore/core/mindrt/src/thread/actor_threadpool.cc index 730971d99f3..b3aac2f12f7 100644 --- a/mindspore/core/mindrt/src/thread/actor_threadpool.cc +++ b/mindspore/core/mindrt/src/thread/actor_threadpool.cc @@ -41,7 +41,7 @@ void ActorWorker::RunWithSpin() { } else { YieldAndDeactive(); } - if (spin_count_ >= max_spin_count_) { + if (spin_count_ > max_spin_count_) { WaitUntilActive(); spin_count_ = 0; } @@ -58,11 +58,15 @@ bool ActorWorker::RunQueueActorTask() { return true; } -bool ActorWorker::Active() { +bool ActorWorker::ActorActive() { if (status_ != kThreadIdle) { return false; } - status_ = kThreadBusy; + { + std::lock_guard _l(mutex_); + active_num_++; + status_ = kThreadBusy; + } cond_var_.notify_one(); return true; } @@ -70,6 +74,7 @@ bool ActorWorker::Active() { ActorThreadPool::~ActorThreadPool() { // wait until actor queue is empty bool terminate = false; + int count = 0; do { { #ifdef USE_HQUEUE @@ -80,9 +85,12 @@ ActorThreadPool::~ActorThreadPool() { #endif } if (!terminate) { + for (auto &worker : workers_) { + worker->Active(); + } std::this_thread::yield(); } - } while (!terminate); + } while (!terminate && count++ < kMaxCount); for (auto &worker : workers_) { delete worker; worker = nullptr; @@ -124,7 +132,7 @@ void ActorThreadPool::PushActorToQueue(ActorBase *actor) { // active one idle actor thread if exist for (size_t i = 0; i < actor_thread_num_; ++i) { auto worker = reinterpret_cast(workers_[i]); - if (worker->Active()) { + if (worker->ActorActive()) { break; } } diff --git a/mindspore/core/mindrt/src/thread/actor_threadpool.h b/mindspore/core/mindrt/src/thread/actor_threadpool.h index 037440d3c02..b0995bda7f7 100644 --- a/mindspore/core/mindrt/src/thread/actor_threadpool.h +++ b/mindspore/core/mindrt/src/thread/actor_threadpool.h @@ -33,7 +33,7 @@ class ActorThreadPool; class ActorWorker : public Worker { public: void CreateThread(ActorThreadPool *pool); - bool Active(); + bool ActorActive(); private: void RunWithSpin(); diff --git a/mindspore/core/mindrt/src/thread/threadpool.cc b/mindspore/core/mindrt/src/thread/threadpool.cc index 07bea538891..fd28938d52b 100644 --- a/mindspore/core/mindrt/src/thread/threadpool.cc +++ b/mindspore/core/mindrt/src/thread/threadpool.cc @@ -66,7 +66,7 @@ void Worker::Run() { } else { YieldAndDeactive(); } - if (spin_count_ >= max_spin_count_) { + if (spin_count_ > max_spin_count_) { WaitUntilActive(); spin_count_ = 0; } @@ -96,7 +96,8 @@ void Worker::YieldAndDeactive() { void Worker::WaitUntilActive() { std::unique_lock _l(mutex_); - cond_var_.wait(_l, [&] { return status_ == kThreadBusy || !alive_; }); + cond_var_.wait(_l, [&] { return status_ == kThreadBusy || active_num_ > 0 || !alive_; }); + active_num_--; } void Worker::set_scale(float lhs_scale, float rhs_scale) { @@ -114,6 +115,15 @@ void Worker::Active(Task *task, int task_id) { cond_var_.notify_one(); } +void Worker::Active() { + { + std::lock_guard _l(mutex_); + active_num_++; + status_ = kThreadBusy; + } + cond_var_.notify_one(); +} + bool Worker::available() { int expected = kThreadIdle; return status_.compare_exchange_strong(expected, kThreadHeld); @@ -262,6 +272,12 @@ void ThreadPool::ActiveWorkers(const std::vector &workers, Task *task, } } +void ThreadPool::ActiveWorkers() const { + for (auto &worker : workers_) { + worker->Active(); + } +} + Worker *ThreadPool::CurrentWorker() const { for (const auto &worker : workers_) { if (worker->thread_id() == std::this_thread::get_id()) { @@ -332,6 +348,20 @@ void ThreadPool::SetSpinCountMinValue() { return; } +void ThreadPool::SetMaxSpinCount(int spin_count) { + if (spin_count <= 0) { + return; + } + max_spin_count_ = spin_count; +} + +void ThreadPool::SetMinSpinCount(int spin_count) { + if (spin_count <= 0) { + return; + } + min_spin_count_ = spin_count; +} + ThreadPool *ThreadPool::CreateThreadPool(size_t thread_num, const std::vector &core_list) { ThreadPool *pool = new (std::nothrow) ThreadPool(); if (pool == nullptr) { diff --git a/mindspore/core/mindrt/src/thread/threadpool.h b/mindspore/core/mindrt/src/thread/threadpool.h index 035cc9a0bbf..ffadb7b2b97 100644 --- a/mindspore/core/mindrt/src/thread/threadpool.h +++ b/mindspore/core/mindrt/src/thread/threadpool.h @@ -30,7 +30,8 @@ namespace mindspore { constexpr int kDefaultSpinCount = 300000; -constexpr int kMinSpinCount = 3000; +constexpr int kMaxCount = 30000; +constexpr int kMinSpinCount = 1; constexpr int kDefaultFrequency = 1; constexpr float kMaxScale = 1.; @@ -61,6 +62,8 @@ class Worker { void CreateThread(); // assign task and then activate thread void Active(Task *task, int task_id); + // activate thread + void Active(); // whether or not it is idle and marked as held bool available(); // assigns task first before running @@ -93,6 +96,7 @@ class Worker { cpu_set_t mask_; #endif std::atomic_int status_{kThreadBusy}; + std::atomic_int active_num_{0}; std::mutex mutex_; std::condition_variable cond_var_; @@ -103,7 +107,7 @@ class Worker { float rhs_scale_{kMaxScale}; int frequency_{kDefaultFrequency}; int spin_count_{0}; - int max_spin_count_{kDefaultSpinCount}; + int max_spin_count_{kMinSpinCount}; }; class ThreadPool { @@ -124,8 +128,9 @@ class ThreadPool { size_t GetKernelThreadNum() const { return kernel_thread_num_; } void SetSpinCountMaxValue(); void SetSpinCountMinValue(); - void SetMaxSpinCount(int spin_count) { max_spin_count_ = spin_count; } - void SetMinSpinCount(int spin_count) { min_spin_count_ = spin_count; } + void SetMaxSpinCount(int spin_count); + void SetMinSpinCount(int spin_count); + void ActiveWorkers() const; protected: ThreadPool() = default; diff --git a/mindspore/lite/test/config/models_onnx_fp16.cfg b/mindspore/lite/test/config/models_onnx_fp16.cfg index f09f337d7ad..7869abf3ffa 100644 --- a/mindspore/lite/test/config/models_onnx_fp16.cfg +++ b/mindspore/lite/test/config/models_onnx_fp16.cfg @@ -61,7 +61,7 @@ ml_ei_facedetection.onnx 2 #ml_video_edit_art_generate.onnx #mul operator overflows, not suitable for fp16 #ml_voice_detect.onnx #conv operator overflows, not suitable for fp16 #ml_location_lane_counter.onnx has very small values during op computation (<1e-6), which causes the precision variation -ml_location_lane_counter.onnx 7.5 +ml_location_lane_counter.onnx 8 ml_location_lane_counter0.onnx 1.0 #The encoder an decoder model are used in ml_asr scene, both have value overflow. Not suitable for fp16. #But added for guarding process.