void TestLocalAllocations( int nthread ) { ASSERT(nthread > 0, "nthread must be positive"); #define NITERATIONS 1000 Body myBody(nthread, NITERATIONS); tbb::combinable<int> myCombinable; myBody.locals = &myCombinable; NativeParallelFor( nthread, myBody ); int mySum = 0; int mySlots = 0; CombineEachHelperCnt<int> myCountCombine(mySum, mySlots); myCombinable.combine_each(myCountCombine); ASSERT(nthread == mySlots, "Incorrect number of slots"); ASSERT(mySum == (nthread - 1) * nthread / 2, "Incorrect values in result"); }
void RunOneCriticalSectionTest(int nThreads, int csWorkRatio, bool test_throw) { tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred); tbb::enumerable_thread_specific<double> test_locals; int myCount = 0; BusyBody myBody(nThreads, csWorkRatio, test_locals, myCount, test_throw); BusyBodyScoped myScopedBody(nThreads, csWorkRatio, test_locals, myCount, test_throw); init.initialize(nThreads); tbb::tick_count t0; { t0 = tbb::tick_count::now(); myCount = 0; NativeParallelFor(nThreads, myBody); ASSERT(myCount == (MAX_WORK - (MAX_WORK % nThreads)), NULL); REMARK("%d threads, work ratio %d per cent, time %g", nThreads, csWorkRatio, (tbb::tick_count::now() - t0).seconds()); if (nThreads > 1) { double etsSum = 0; double etsMax = 0; double etsMin = 0; double etsSigmaSq = 0; double etsSigma = 0; for(tbb::enumerable_thread_specific<double>::const_iterator ci = test_locals.begin(); ci != test_locals.end(); ci++) { etsSum += *ci; if(etsMax==0.0) { etsMin = *ci; } else { if(etsMin > *ci) etsMin = *ci; } if(etsMax < *ci) etsMax = *ci; } double etsAvg = etsSum / (double)nThreads; for(tbb::enumerable_thread_specific<double>::const_iterator ci = test_locals.begin(); ci != test_locals.end(); ci++) { etsSigma = etsAvg - *ci; etsSigmaSq += etsSigma * etsSigma; } // an attempt to gauge the "fairness" of the scheduling of the threads. We figure // the standard deviation, and compare it with the maximum deviation from the // average time. If the difference is 0 that means all threads finished in the same // amount of time. If non-zero, the difference is divided by the time, and the // negative log is taken. If > 2, then the difference is on the order of 0.01*t // where T is the average time. We aritrarily define this as "fair." etsSigma = sqrt(etsSigmaSq/double(nThreads)); etsMax -= etsAvg; // max - a == delta1 etsMin = etsAvg - etsMin; // a - min == delta2 if(etsMax < etsMin) etsMax = etsMin; etsMax -= etsSigma; // ASSERT(etsMax >= 0, NULL); // shouldn't the maximum difference from the mean be > the stddev? etsMax = (etsMax > 0.0) ? etsMax : 0.0; // possible rounding error double fairness = etsMax / etsAvg; if(fairness == 0.0) { fairness = 100.0; } else fairness = - log10(fairness); if(fairness > 2.0 ) { REMARK(" Fair (%g)\n", fairness); } else { REMARK(" Unfair (%g)\n", fairness); } } myCount = 0; NativeParallelFor(nThreads, myScopedBody); ASSERT(myCount == (MAX_WORK - (MAX_WORK % nThreads)), NULL); } init.terminate(); }