| 190 | // This change was prompted by issue #2429 |
| 191 | template<typename T> |
| 192 | void philoxUniform(T *out, size_t elements, const uintl seed, uintl counter) { |
| 193 | uint hi = seed >> 32; |
| 194 | uint lo = seed; |
| 195 | uint hic = counter >> 32; |
| 196 | uint loc = counter; |
| 197 | |
| 198 | constexpr size_t RESET_CTR = MAX_RESET_CTR_VAL / sizeof(T); |
| 199 | constexpr size_t ELEMS_PER_ITER = |
| 200 | WRITE_STRIDE * 4 * sizeof(uint) / sizeof(T); |
| 201 | |
| 202 | int num_iters = divup(elements, ELEMS_PER_ITER); |
| 203 | size_t len = num_iters * ELEMS_PER_ITER; |
| 204 | |
| 205 | constexpr size_t NUM_WRITES = 16 / sizeof(T); |
| 206 | for (size_t iter = 0; iter < len; iter += ELEMS_PER_ITER) { |
| 207 | for (size_t i = 0; i < WRITE_STRIDE; i += RESET_CTR) { |
| 208 | for (size_t j = 0; j < RESET_CTR; ++j) { |
| 209 | // first_write_idx is the first of the 4 locations that will |
| 210 | // be written to |
| 211 | uintptr_t first_write_idx = iter + i + j; |
| 212 | if (first_write_idx >= elements) { break; } |
| 213 | |
| 214 | // Recalculate key and ctr to emulate how the CUDA backend |
| 215 | // calculates these per thread |
| 216 | uint key[2] = {lo, hi}; |
| 217 | uint ctr[4] = {loc + (uint)first_write_idx, 0, 0, 0}; |
| 218 | ctr[1] = hic + (ctr[0] < loc); |
| 219 | ctr[2] = (ctr[1] < hic); |
| 220 | philox(key, ctr); |
| 221 | |
| 222 | // Use the same ctr array for each of the 4 locations, |
| 223 | // but each of the location gets a different ctr value |
| 224 | for (uint buf_idx = 0; buf_idx < NUM_WRITES; ++buf_idx) { |
| 225 | size_t out_idx = iter + buf_idx * WRITE_STRIDE + i + j; |
| 226 | if (out_idx < elements) { |
| 227 | out[out_idx] = transform<T>(ctr, buf_idx); |
| 228 | } |
| 229 | } |
| 230 | } |
| 231 | } |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | #undef MAX_RESET_CTR_VAL |
| 236 | #undef WRITE_STRIDE |
no test coverage detected