| 262 | } |
| 263 | |
| 264 | void mem_bench2() { |
| 265 | constexpr size_t N_THREADS = 64; |
| 266 | constexpr size_t MB_PER_THREAD = 2048; |
| 267 | constexpr size_t ELS_PER_THREAD = (MB_PER_THREAD * 1024 * 1024) / sizeof(uint32_t); |
| 268 | constexpr size_t N = N_THREADS * ELS_PER_THREAD; |
| 269 | |
| 270 | std::cout << "Using " << N_THREADS << " threads" << std::endl; |
| 271 | std::cout << "Allocating " << N_THREADS * MB_PER_THREAD << " MB (" << N << " uint32_t)" << std::endl; |
| 272 | uint32_t* data = new uint32_t[N]; |
| 273 | |
| 274 | std::cout << "Filling data..." << std::endl; |
| 275 | #pragma omp parallel for num_threads(N_THREADS) |
| 276 | for (size_t i = 0; i < N_THREADS; i++) { |
| 277 | for (size_t j = 0; j < ELS_PER_THREAD; j++) { |
| 278 | data[i * ELS_PER_THREAD + j] = i + j; |
| 279 | } |
| 280 | } |
| 281 | std::cout << "Running memory bandwidth test..." << std::endl; |
| 282 | |
| 283 | // Allocate cache-line aligned sinks for each thread |
| 284 | std::vector<ThreadData> thread_sinks(N_THREADS); |
| 285 | |
| 286 | uint64_t start = get_timestamp_ms(); |
| 287 | std::vector<std::thread> threads; |
| 288 | |
| 289 | // Launch threads |
| 290 | for (size_t i = 0; i < N_THREADS; i++) { |
| 291 | threads.emplace_back(mem_bench2_thread, |
| 292 | data, |
| 293 | i * ELS_PER_THREAD, |
| 294 | ELS_PER_THREAD, |
| 295 | &thread_sinks[i] |
| 296 | ); |
| 297 | } |
| 298 | |
| 299 | // Wait for all threads to complete |
| 300 | for (auto& thread : threads) { |
| 301 | thread.join(); |
| 302 | } |
| 303 | |
| 304 | uint64_t end = get_timestamp_ms(); |
| 305 | float elapsed_s = (end - start) / 1000.0; |
| 306 | float mb_per_s = N_THREADS * MB_PER_THREAD / elapsed_s; |
| 307 | |
| 308 | std::cout << "Elapsed time: " << elapsed_s << " s" << std::endl; |
| 309 | std::cout << "Memory bandwidth: " << mb_per_s << " MB/s" << std::endl; |
| 310 | } |
| 311 | |
| 312 | int main(int argc, char* argv[]) { |
| 313 | if (argc == 2 && std::string(argv[1]) == "-b") { |
no test coverage detected