void Add (int blocknr, IntRange range) { switch (mode) { case 1: if (blocknr+1 > nd) nd = blocknr+1; break; case 2: cnt[blocknr]+=range.Size(); break; case 3: for (int j = 0; j < range.Size(); j++) (*table)[blocknr][cnt[blocknr]+j] = range.First()+j; cnt[blocknr]+=range.Size(); /* for (int j = 0; j < range.Size(); j++) table->Data()[cnt[blocknr]+j] = range.First()+j; cnt[blocknr]+=range.Size(); */ break; } }
void TaskManager :: Loop(int thd) { /* static Timer tADD("add entry counter"); static Timer tCASready1("spin-CAS ready tick1"); static Timer tCASready2("spin-CAS ready tick2"); static Timer tCASyield("spin-CAS yield"); static Timer tCAS1("spin-CAS wait"); static Timer texit("exit zone"); static Timer tdec("decrement"); */ thread_id = thd; int thds = GetNumThreads(); int mynode = num_nodes * thd/thds; NodeData & mynode_data = *(nodedata[mynode]); TaskInfo ti; ti.nthreads = thds; ti.thread_nr = thd; // ti.nnodes = num_nodes; // ti.node_nr = mynode; #ifdef USE_NUMA numa_run_on_node (mynode); #endif active_workers++; workers_on_node[mynode]++; int jobdone = 0; #ifdef USE_MKL auto mkl_max = mkl_get_max_threads(); mkl_set_num_threads_local(1); #endif while (!done) { if (complete[mynode] > jobdone) jobdone = complete[mynode]; if (jobnr == jobdone) { // RegionTracer t(ti.thread_nr, tCASyield, ti.task_nr); if(sleep) this_thread::sleep_for(chrono::microseconds(sleep_usecs)); else { #ifdef WIN32 this_thread::yield(); #else // WIN32 sched_yield(); #endif // WIN32 } continue; } { // RegionTracer t(ti.thread_nr, tADD, ti.task_nr); // non-atomic fast check ... if ( (mynode_data.participate & 1) == 0) continue; int oldval = mynode_data.participate += 2; if ( (oldval & 1) == 0) { // job not active, going out again mynode_data.participate -= 2; continue; } } if (startup_function) (*startup_function)(); IntRange mytasks = Range(int(ntasks)).Split (mynode, num_nodes); try { while (1) { if (mynode_data.start_cnt >= mytasks.Size()) break; int mytask = mynode_data.start_cnt.fetch_add(1, memory_order_relaxed); if (mytask >= mytasks.Size()) break; ti.task_nr = mytasks.First()+mytask; ti.ntasks = ntasks; { RegionTracer t(ti.thread_nr, jobnr, RegionTracer::ID_JOB, ti.task_nr); (*func)(ti); } } } catch (Exception e) { { // cout << "got exception in TM" << endl; lock_guard<mutex> guard(copyex_mutex); delete ex; ex = new Exception (e); mynode_data.start_cnt = mytasks.Size(); } } #ifndef __MIC__ atomic_thread_fence (memory_order_release); #endif // __MIC__ if (cleanup_function) (*cleanup_function)(); jobdone = jobnr; mynode_data.participate-=2; { int oldpart = 1; if (mynode_data.participate.compare_exchange_strong (oldpart, 0)) { if (jobdone < jobnr.load()) { // reopen gate mynode_data.participate |= 1; } else { if (mynode != 0) mynode_data.start_cnt = 0; complete[mynode] = jobnr.load(); } } } } #ifdef USE_MKL mkl_set_num_threads_local(mkl_max); #endif workers_on_node[mynode]--; active_workers--; }
void TaskManager :: CreateJob (const function<void(TaskInfo&)> & afunc, int antasks) { if (num_threads == 1 || !task_manager || func) { if (startup_function) (*startup_function)(); TaskInfo ti; ti.ntasks = antasks; ti.thread_nr = 0; ti.nthreads = 1; // ti.node_nr = 0; ti.nnodes = 1; for (ti.task_nr = 0; ti.task_nr < antasks; ti.task_nr++) afunc(ti); if (cleanup_function) (*cleanup_function)(); return; } trace->StartJob(jobnr, afunc.target_type()); func = &afunc; ntasks.store (antasks); // , memory_order_relaxed); ex = nullptr; nodedata[0]->start_cnt.store (0, memory_order_relaxed); jobnr++; for (int j = 0; j < num_nodes; j++) nodedata[j]->participate |= 1; if (startup_function) (*startup_function)(); int thd = 0; int thds = GetNumThreads(); int mynode = num_nodes * thd/thds; IntRange mytasks = Range(int(ntasks)).Split (mynode, num_nodes); NodeData & mynode_data = *(nodedata[mynode]); TaskInfo ti; ti.nthreads = thds; ti.thread_nr = thd; // ti.nnodes = num_nodes; // ti.node_nr = mynode; try { while (1) { int mytask = mynode_data.start_cnt++; if (mytask >= mytasks.Size()) break; ti.task_nr = mytasks.First()+mytask; ti.ntasks = ntasks; { RegionTracer t(ti.thread_nr, jobnr, RegionTracer::ID_JOB, ti.task_nr); (*func)(ti); } } } catch (Exception e) { { lock_guard<mutex> guard(copyex_mutex); delete ex; ex = new Exception (e); mynode_data.start_cnt = mytasks.Size(); } } if (cleanup_function) (*cleanup_function)(); for (int j = 0; j < num_nodes; j++) if (workers_on_node[j]) { while (complete[j] != jobnr) _mm_pause(); } func = nullptr; if (ex) throw Exception (*ex); trace->StopJob(); }