()
| 59 | } |
| 60 | |
| 61 | getUserCode(): string { |
| 62 | let indicesString = ''; |
| 63 | if (this.indicesRank === 1) { |
| 64 | indicesString = 'coords[0]'; |
| 65 | } else if (this.indicesRank === 2) { |
| 66 | indicesString = 'coords[0], j'; |
| 67 | } |
| 68 | const indicesSnippet = `getIndices(${indicesString})`; |
| 69 | |
| 70 | const strideString = this.sliceDimGreaterThanOne ? 'uniforms.strides[j]' : |
| 71 | 'uniforms.strides'; |
| 72 | |
| 73 | let outCoordsString = ''; |
| 74 | let getUpdatesCoordsFromFlatIndex = ''; |
| 75 | if (this.dispatchLayout.x.length === 1) { |
| 76 | outCoordsString = 'flattenedIndex'; |
| 77 | getUpdatesCoordsFromFlatIndex = ` |
| 78 | fn getUpdatesCoordsFromFlatIndex(index : i32) -> i32 { |
| 79 | return index; |
| 80 | } |
| 81 | `; |
| 82 | } else if (this.dispatchLayout.x.length === 2) { |
| 83 | outCoordsString = 'vec2<i32>(flattenedIndex, coords[1])'; |
| 84 | getUpdatesCoordsFromFlatIndex = ` |
| 85 | fn getUpdatesCoordsFromFlatIndex(index : i32) -> vec2<i32> { |
| 86 | // N.B. |updates| could be a scalar tensor, conceptually representing a |
| 87 | // 2D tensor with all values equal to that. By design, its size must be |
| 88 | // the same as |outShape[1]| in one dimension, and |indicesShape[0]| |
| 89 | // gives the other. |
| 90 | let sliceSize = uniforms.outShape[1]; |
| 91 | let d0 = index / sliceSize; |
| 92 | let d1 = index - d0 * sliceSize; |
| 93 | return vec2<i32>(d0, d1); |
| 94 | } |
| 95 | `; |
| 96 | } |
| 97 | const updatesString = |
| 98 | Array.from({length: this.updatesRank}, (_, idx) => `coords[${idx}]`); |
| 99 | const updatesSnippet = `getUpdates(${updatesString.join(', ')})`; |
| 100 | |
| 101 | const userCode = ` |
| 102 | ${getUpdatesCoordsFromFlatIndex} |
| 103 | ${main('index')} { |
| 104 | if (index < uniforms.updatesSize) { |
| 105 | let coords = getUpdatesCoordsFromFlatIndex(index); |
| 106 | var flattenedIndex = 0; |
| 107 | for (var j = 0; j < uniforms.sliceDim; j = j + 1) { |
| 108 | let indexInside = i32(round(${indicesSnippet})); |
| 109 | flattenedIndex = flattenedIndex + indexInside * ${strideString}; |
| 110 | } |
| 111 | let updateValue = |
| 112 | ${dataTypeToGPUType(this.type)}(${updatesSnippet}); |
| 113 | let flatIndex = getOutputIndexFromCoords(${outCoordsString}); |
| 114 | |
| 115 | ${ |
| 116 | this.sumDupeIndices ? |
| 117 | atomicAddSnippet( |
| 118 | '&result[flatIndex]', 'updateValue', |
nothing calls this directly
no test coverage detected