Esempio n. 1
0
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();
}