| 63 | } |
| 64 | |
| 65 | void RunSharding(int64 block_size, int64 total, ThreadPool* threads) { |
| 66 | mutex mu; |
| 67 | int64 num_shards = 0; |
| 68 | int64 num_done_work = 0; |
| 69 | std::vector<std::atomic<bool>> work(total); |
| 70 | for (int i = 0; i < total; i++) { |
| 71 | work[i] = false; |
| 72 | } |
| 73 | threads->TransformRangeConcurrently( |
| 74 | block_size, total, |
| 75 | [=, &mu, &num_shards, &num_done_work, &work](int64 start, int64 end) { |
| 76 | VLOG(1) << "Shard [" << start << "," << end << ")"; |
| 77 | EXPECT_GE(start, 0); |
| 78 | EXPECT_LE(end, total); |
| 79 | mutex_lock l(mu); |
| 80 | ++num_shards; |
| 81 | for (; start < end; ++start) { |
| 82 | EXPECT_FALSE(work[start].exchange(true)); // No duplicate |
| 83 | ++num_done_work; |
| 84 | } |
| 85 | }); |
| 86 | LOG(INFO) << block_size << " " << total; |
| 87 | EXPECT_EQ(num_done_work, total); |
| 88 | for (int i = 0; i < total; i++) { |
| 89 | ASSERT_TRUE(work[i]); |
| 90 | } |
| 91 | const int64 num_workers = (total + block_size - 1) / block_size; |
| 92 | if (num_workers < threads->NumThreads()) { |
| 93 | // If the intention is to limit the parallelism explicitly, we'd |
| 94 | // better honor it. Ideally, even if per_thread_max_parallelism > |
| 95 | // num_workers, we should expect that Shard() implementation do |
| 96 | // not over-shard. Unfortunately, ThreadPoolDevice::parallelFor |
| 97 | // tends to over-shard. |
| 98 | EXPECT_LE(num_shards, 1 + num_workers); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | // Adapted from work_sharder_test.cc |
| 103 | TEST(SparseUtilsTest, TransformRangeConcurrently) { |
no test coverage detected