/* * Multi-core evaluation. Takes number of theads as an * optional argument. On a 4-core device, run with "1" and * again with "4". If the times are about the same, all * cores were used. If the 4-core run takes twice as long, * only two cores were used. * * The threshold at which the kernel migrates a thread to * a new core is system-specific. You can try to force it * with sched_getaffinity(). * * Not useful as a benchmark. * * desktop: gcc -g -Wall spinner.c -o spinner -lpthread */ #include #include #include #include #include #define _GNU_SOURCE #include #define ONE_MILLION 1000000LL // This needs to be long enough for the kernel to decide // that the thread should be on its own core. #define SPIN_COUNT 20000 void* spin(void* vtid) { int tid = (int)(uintptr_t) vtid; int reps = SPIN_COUNT + tid; int ret = 0; int i, j; for (i = 0; i < reps; i++) { for (j = 0; j < 100000; j++) { ret += i * j; } } // Print the number of the core we're currently on. // This isn't all that useful, because threads can // move between cores, so even if all 4 cores were // used you might not see all 4 represented in the // output. OTOH, if you do see 4 different core // numbers you know they were all used. printf("Thread %d done, was on core %d\n", tid, sched_getcpu()); return (void*)(uintptr_t) ret; } int main(int argc, char** argv) { int numThreads = 4; if (argc == 2) { numThreads = atoi(argv[1]); if (numThreads < 0 || numThreads > 256) { fprintf(stderr, "ERROR: invalid numThreads=%d\n", numThreads); return 2; } } printf("Starting %d threads\n", numThreads); struct timeval tv; gettimeofday(&tv, NULL); long long startWhen = (tv.tv_sec * ONE_MILLION) + tv.tv_usec; pthread_t threads[numThreads]; int i; for (i = 0; i < numThreads; i++) { int cc = pthread_create(&threads[i], NULL, spin, (void*)(uintptr_t) i); if (cc != 0) { fprintf(stderr, "ERROR: pthread_create %d failed: %d\n", i, cc); return 1; } } for (i = 0; i < numThreads; i++) { int cc = pthread_join(threads[i], NULL); if (cc != 0) { fprintf(stderr, "ERROR: pthread_join %d failed: %d\n", i, cc); return 1; } } gettimeofday(&tv, NULL); long long endWhen = (tv.tv_sec * ONE_MILLION) + tv.tv_usec; printf("All threads finished in %lldms\n", (endWhen - startWhen) / 1000); return 0; }