Split [0, total) into one chunk per thread. Chunk boundaries are rounded up to a multiple of `align` so each slice's AVX/scalar split lines up with the whole-tensor kernel's split -- otherwise an element could be computed by AVX (FMA) in one layout and the scalar tail (mul+add) in another, which differ in the last bit.
| 404 | // kernel's split -- otherwise an element could be computed by AVX (FMA) in one layout |
| 405 | // and the scalar tail (mul+add) in another, which differ in the last bit. |
| 406 | void parallel_for(size_t total, size_t align, std::function<void(size_t, size_t)> fn) |
| 407 | { |
| 408 | { |
| 409 | std::unique_lock<std::mutex> lk(m_); |
| 410 | fn_ = std::move(fn); |
| 411 | total_ = total; |
| 412 | align_ = std::max<size_t>(1, align); |
| 413 | done_count_ = 0; |
| 414 | ++gen_; |
| 415 | } |
| 416 | cv_start_.notify_all(); |
| 417 | std::unique_lock<std::mutex> lk(m_); |
| 418 | cv_done_.wait(lk, [this] { return done_count_ == n_; }); |
| 419 | } |
| 420 | |
| 421 | private: |
| 422 | void worker(size_t tid, int core) |
no test coverage detected