Buckets:
| const uint num_threads = 256; | |
| layout (binding = 3, std430) buffer PartialBuf {float partial_sums[];}; | |
| layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in; | |
| // XXX TODO this could be sized based on number of subgroups, but that't not considered a constant | |
| shared FLOAT_TYPE sumsh[num_threads]; | |
| void main() { | |
| uint idx = get_idx(); | |
| uint orig_idx = idx; | |
| // num_threads * num_iter must equal 512, to match the wg_denoms and get_idx calculation | |
| const uint num_iter = 2; | |
| FLOAT_TYPE sum_sq = 0; | |
| [[unroll]] for (uint i = 0; i < num_iter; ++i) { | |
| if (idx >= p.ne) { | |
| continue; | |
| } | |
| uint i00, i01, i02, i03; | |
| get_indices(idx, i00, i01, i02, i03); | |
| FLOAT_TYPE sum = FLOAT_TYPE(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)]) + FLOAT_TYPE(data_b[get_boffset() + src1_idx(i00, i01, i02, i03)]); | |
| sum_sq += sum*sum; | |
| data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] = D_TYPE(sum); | |
| idx += num_threads; | |
| } | |
| if (p.param3 != 0) { | |
| // reduce the sum within each subgroup, then across subgroups | |
| const uint NumSubgroups = num_threads / gl_SubgroupSize; | |
| sum_sq = subgroupAdd(sum_sq); | |
| if (gl_SubgroupInvocationID == 0) { | |
| sumsh[gl_SubgroupID] = sum_sq; | |
| } | |
| barrier(); | |
| [[unroll]] for (uint s = NumSubgroups / 2; s > 0; s >>= 1) { | |
| if (gl_SubgroupID < s && gl_SubgroupInvocationID == 0) { | |
| sum_sq += sumsh[gl_SubgroupID + s]; | |
| sumsh[gl_SubgroupID] = sum_sq; | |
| } | |
| barrier(); | |
| } | |
| if (gl_SubgroupID == 0 && gl_SubgroupInvocationID == 0) { | |
| partial_sums[orig_idx / (num_iter * num_threads)] = sum_sq; | |
| } | |
| } | |
| } | |
Xet Storage Details
- Size:
- 2.06 kB
- Xet hash:
- 2883f57cdb154e9dc3421897c0b2415dadc9e4faa5195b819dabd0f5df4f3194
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.