#include #include #include #include #include #include static uint32_t *workerID; static uint32_t numWorkers; static uint32_t m_cost; // Memory to be hashed static uint32_t *mem; static uint32_t *hash; // Do L3-cache intensive work in a regular manner, not SSE enabled. static void *doWork(void *workerIDPtr) { uint32_t workerID = *(uint32_t *)workerIDPtr; uint64_t len = (1024ull << m_cost)/(sizeof(uint32_t)*numWorkers); printf("Hashing %lu memory on thread %u\n", len*sizeof(uint32_t), workerID); uint32_t *p = mem + len*workerID; p[0] = 2*workerID + 1; // Always odd uint64_t randAddr = 0; for(uint64_t i = 1; i < len; i++) { p[i] = p[randAddr] * (randAddr | 1) + 1234; // Always odd randAddr ^= p[i] >> 8; } hash[workerID] = randAddr; pthread_exit(NULL); } // Start numWorker worker threads that do regular speed cache thrashing. static void startWorkers(pthread_t *workerThreads, uint32_t numWorkers) { for(uint32_t i = 0; i < numWorkers; i++) { workerID[i] = i; pthread_create(&workerThreads[i], NULL, doWork, workerID + i); } } // Join numWorker worker threads. static void joinWorkers(pthread_t *workerThreads, uint32_t numWorkers) { for(uint32_t i = 0; i < numWorkers; i++) { pthread_join(workerThreads[i], NULL); } } int main(int argc, char **argv) { if(argc != 3) { printf("Usage: %s numWorkers m_cost\n", argv[0]); return 1; } numWorkers = atoi(argv[1]); m_cost = atoi(argv[2]); bool hashMemory = atoi(argv[4]); workerID = calloc(numWorkers, sizeof(uint32_t)); hash = calloc(numWorkers, sizeof(uint32_t)); mem = malloc(1024llu << m_cost); printf("Allocated %llu memory\n", 1024ll << m_cost); pthread_t workerThreads[numWorkers]; startWorkers(workerThreads, numWorkers); joinWorkers(workerThreads, numWorkers); uint32_t result = 0; for(uint32_t i = 0; i < numWorkers; i++) { result += hash[i]; } printf("Result: %u\n", result); return 0; }