1616#include < nanovdb/HostBuffer.h>
1717#include < nanovdb/tools/cuda/PointsToGrid.cuh>
1818#include < nanovdb/tools/VoxelBlockManager.h>
19+ #include < nanovdb/util/ForEach.h>
1920#include < nanovdb/util/Timer.h>
2021#include < nanovdb/util/cuda/Timer.h>
2122#include < nanovdb/util/cuda/Util.h>
2223
2324#include < thrust/universal_vector.h>
2425
2526#include < immintrin.h>
26- #ifdef _OPENMP
27- #include < omp.h>
28- #else
29- inline int omp_get_max_threads () { return 1 ; }
30- #endif
3127
3228#include < algorithm>
29+ #include < atomic>
3330#include < vector>
3431#include < iostream>
3532
@@ -38,13 +35,6 @@ namespace {
3835static constexpr int Log2BlockWidth = 7 ;
3936static constexpr int BlockWidth = 1 << Log2BlockWidth; // 128
4037
41- // Thread-private scratch arrays for CPU decodeInverseMaps benchmarks.
42- // Declared at namespace scope with static storage so threadprivate is valid;
43- // aligned to a cache line to avoid false sharing between threads.
44- alignas (64 ) static uint32_t g_scratchLeafIndex[BlockWidth];
45- alignas (64 ) static uint16_t g_scratchVoxelOffset[BlockWidth];
46- #pragma omp threadprivate(g_scratchLeafIndex, g_scratchVoxelOffset)
47-
4838using VBM = nanovdb::tools::cuda::VoxelBlockManager<Log2BlockWidth>;
4939using CPUVBM = nanovdb::tools::VoxelBlockManager<Log2BlockWidth>;
5040
@@ -381,23 +371,19 @@ void runVBMCudaTest(const std::vector<nanovdb::Coord>& coords)
381371 static constexpr int nPerfRuns = 20 ;
382372
383373 // --- Sanity check: countOn + std::fill only, no tree access ---
384- // If OpenMP parallelism is working, this should scale near-linearly.
385374 {
386- std::cout << " \n CPU decodeInverseMaps sanity (countOn only, "
387- << omp_get_max_threads () << " OMP threads):\n " ;
375+ std::cout << " \n CPU decodeInverseMaps sanity (countOn only):\n " ;
388376
389- // Never true: nExtraLeaves <= JumpMapLength*64, so == JumpMapLength*64+1 is impossible.
390- // Used only to prevent dead code elimination without a reduction.
377+ // Never true: used only to prevent dead code elimination.
391378 volatile uint32_t dummy = 0 ;
392379
393380 for (int run = 0 ; run < nPerfRuns; ++run) {
394381 nanovdb::util::Timer timer;
395382 timer.start (" " );
396383
397- #pragma omp parallel
398- {
399- #pragma omp for schedule(static)
400- for (uint32_t bID = 0 ; bID < nBlocks; ++bID) {
384+ nanovdb::util::forEach (0 , nBlocks, 1 ,
385+ [&](const nanovdb::util::Range1D& range) {
386+ for (auto bID = range.begin (); bID < range.end (); ++bID) {
401387 int nExtraLeaves = 0 ;
402388 for (int i = 0 ; i < CPUVBM ::JumpMapLength; i++)
403389 nExtraLeaves += nanovdb::util::countOn (
@@ -443,28 +429,28 @@ void runVBMCudaTest(const std::vector<nanovdb::Coord>& coords)
443429 if (prefixCountRealigned[31 ][15 ] == 513u )
444430 dummy = prefixCountRealigned[31 ][15 ];
445431 }
446- }
432+ });
447433
448434 const float ms =
449435 (float )timer.elapsed <std::chrono::microseconds>() / 1000 .0f ;
450436 std::cout << " run " << run << " : " << ms << " ms\n " ;
451437 }
452438 }
453439
454- uint32_t dummy = 0 ;
440+ std::atomic< uint32_t > dummy{ 0 } ;
455441
456442 std::cout << " \n CPU decodeInverseMaps performance ("
457- << nBlocks << " blocks, " << nVoxels << " voxels"
458- << " , " << omp_get_max_threads () << " OMP threads):\n " ;
443+ << nBlocks << " blocks, " << nVoxels << " voxels):\n " ;
459444
460445 for (int run = 0 ; run < nPerfRuns; ++run) {
461446 nanovdb::util::Timer timer;
462447 timer.start (" " );
463448
464- #pragma omp parallel reduction(+:dummy)
465- {
466- #pragma omp for schedule(static)
467- for (uint32_t bID = 0 ; bID < nBlocks; ++bID) {
449+ nanovdb::util::forEach (0 , nBlocks, 1 ,
450+ [&](const nanovdb::util::Range1D& range) {
451+ alignas (64 ) uint32_t scratchLeafIndex[BlockWidth];
452+ alignas (64 ) uint16_t scratchVoxelOffset[BlockWidth];
453+ for (auto bID = range.begin (); bID < range.end (); ++bID) {
468454 const uint64_t blockFirstOffset =
469455 cpuHandle.firstOffset () + (uint64_t )bID * BlockWidth;
470456
@@ -473,18 +459,18 @@ void runVBMCudaTest(const std::vector<nanovdb::Coord>& coords)
473459 firstLeafIDPtr[bID],
474460 &jumpMapPtr[(uint64_t )bID * CPUVBM ::JumpMapLength],
475461 blockFirstOffset,
476- g_scratchLeafIndex ,
477- g_scratchVoxelOffset );
462+ scratchLeafIndex ,
463+ scratchVoxelOffset );
478464
479- dummy += (g_scratchLeafIndex [0 ] != CPUVBM ::UnusedLeafIndex) ? 1u : 0u ;
480- dummy += (g_scratchVoxelOffset [0 ] != CPUVBM ::UnusedVoxelOffset) ? 1u : 0u ;
465+ dummy += (scratchLeafIndex [0 ] != CPUVBM ::UnusedLeafIndex) ? 1u : 0u ;
466+ dummy += (scratchVoxelOffset [0 ] != CPUVBM ::UnusedVoxelOffset) ? 1u : 0u ;
481467 }
482- }
468+ });
483469
484470 const float ms =
485471 (float )timer.elapsed <std::chrono::microseconds>() / 1000 .0f ;
486472 std::cout << " run " << run << " : " << ms << " ms\n " ;
487473 }
488- std::cout << " (dummy=" << dummy << " )\n " ;
474+ std::cout << " (dummy=" << dummy. load () << " )\n " ;
489475 }
490476}
0 commit comments