TaskManager :: TaskManager() { num_threads = GetMaxThreads(); // if (MyMPI_GetNTasks() > 1) num_threads = 1; #ifdef USE_NUMA numa_available(); num_nodes = numa_max_node() + 1; if (num_nodes > num_threads) num_nodes = num_threads; for (int j = 0; j < num_nodes; j++) { void * mem = numa_alloc_onnode (sizeof(NodeData), j); nodedata[j] = new (mem) NodeData; complete[j] = -1; workers_on_node[j] = 0; } #else num_nodes = 1; nodedata[0] = new NodeData; complete[0] = -1; workers_on_node[0] = 0; #endif jobnr = 0; done = 0; sleep = false; sleep_usecs = 1000; active_workers = 0; static int cnt = 0; char buf[100]; if (use_paje_trace) { #ifdef PARALLEL sprintf(buf, "ng%d_rank%d.trace", cnt++, MyMPI_GetId()); #else sprintf(buf, "ng%d.trace", cnt++); #endif } else buf[0] = 0; //sprintf(buf, ""); trace = new PajeTrace(num_threads, buf); }
CTimeSpan CThreadPool_Controller_PID::GetSafeSleepTime(void) const { double last_err = 0, integr_err = 0; CThreadPool* pool = GetPool(); if (!pool) { return CTimeSpan(0, 0); } {{ CMutexGuard guard(GetMainPoolMutex(pool)); if (m_ErrHistory.size() == 0) { return CThreadPool_Controller::GetSafeSleepTime(); } last_err = m_ErrHistory.back().err; integr_err = m_IntegrErr; }} unsigned int threads_cnt = pool->GetThreadsCount(); if (last_err == 0 || (last_err > 0 && threads_cnt == GetMaxThreads()) || (last_err < 0 && threads_cnt == GetMinThreads())) { return CThreadPool_Controller::GetSafeSleepTime(); } double sleep_time = 0; if (last_err > 0) { sleep_time = (m_Threshold - last_err - integr_err) * m_IntegrCoeff / last_err; } else { sleep_time = (-m_Threshold - last_err - integr_err) * m_IntegrCoeff / last_err; } if (sleep_time < 0) sleep_time = 0; return CTimeSpan(sleep_time); }
void CThreadPool_Controller_PID::OnEvent(EEvent event) { if (event == eSuspend) { return; } // All reads below are atomic reads of one variable, thus they cannot // return bad results. They can be a little bit inconsistent with each // other because of races with other threads but that's okay for the // purposes of this controller. unsigned int threads_count = GetPool()->GetThreadsCount(); unsigned int queued_tasks = GetPool()->GetQueuedTasksCount(); unsigned int run_tasks = GetPool()->GetExecutingTasksCount(); if (threads_count == 0) { EnsureLimits(); threads_count = GetMinThreads(); // Special case when MinThreads == 0 if (threads_count == 0) { if (queued_tasks == 0) { return; } threads_count = 1; SetThreadsCount(threads_count); } } double now_err = (double(queued_tasks + run_tasks) - threads_count) / threads_count; double now_time = m_Timer.Elapsed(); if (event == eResume) { // When we resuming we need to avoid panic because of big changes in // error value. So we will assume that current error value was began // long time ago and didn't change afterwards. m_ErrHistory.clear(); m_ErrHistory.push_back(SThreadPool_PID_ErrInfo(now_time - m_DerivTime, now_err)); } double period = now_time - m_ErrHistory.back().call_time; if (now_err < 0 && threads_count == GetMinThreads() && m_IntegrErr <= 0) { now_err = 0; } double integr_err = m_IntegrErr + (now_err + m_ErrHistory.back().err) / 2 * period / m_IntegrCoeff; while (m_ErrHistory.size() > 1 && now_time - m_ErrHistory[1].call_time >= m_DerivTime) { m_ErrHistory.pop_front(); } if (now_time - m_ErrHistory.back().call_time >= m_DerivTime / 10) { m_ErrHistory.push_back(SThreadPool_PID_ErrInfo(now_time, now_err)); if (threads_count == GetMaxThreads() && integr_err > m_Threshold) { m_IntegrErr = m_Threshold; } else if (threads_count == GetMinThreads() && integr_err < -m_Threshold) { m_IntegrErr = -m_Threshold; } else { m_IntegrErr = integr_err; } } double deriv_err = (now_err - m_ErrHistory[0].err) / m_DerivTime * m_DerivCoeff; double final_val = (now_err + integr_err + deriv_err) / m_Threshold; /* LOG_POST(CTime(CTime::eCurrent).AsString("M/D/Y h:m:s.l").c_str() << " count=" << threads_count << ", queued=" << queued_tasks << ", run=" << run_tasks << ", err=" << now_err << ", time=" << now_time << ", intErr=" << m_IntegrErr << ", derivErr=" << deriv_err << ", final=" << final_val << ", hist_size=" << m_ErrHistory.size()); */ if (final_val >= 1 || final_val <= -1) { if (final_val < 0 && -final_val > threads_count) SetThreadsCount(GetMinThreads()); else SetThreadsCount(threads_count + int(final_val)); } else { EnsureLimits(); } }