@imaduddin/fastbrain 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/index.js +20 -0
  2. package/package.json +29 -6
  3. package/readme.md +959 -0
  4. package/src/Embedding/index.d.ts +21 -0
  5. package/src/Embedding/index.js +141 -0
  6. package/src/FFN/index.d.ts +23 -0
  7. package/src/FFN/index.js +45 -0
  8. package/src/Linear/index.d.ts +31 -0
  9. package/src/Linear/index.js +198 -0
  10. package/src/OperationManager.js +169 -0
  11. package/src/PositionEmbedding/index.d.ts +30 -0
  12. package/src/PositionEmbedding/index.js +65 -0
  13. package/src/RMSNorm/index.d.ts +30 -0
  14. package/src/RMSNorm/index.js +96 -0
  15. package/src/Relu/index.d.ts +25 -0
  16. package/src/Relu/index.js +110 -0
  17. package/src/SelfAttention/index.d.ts +28 -0
  18. package/src/SelfAttention/index.js +138 -0
  19. package/src/Softmax/index.d.ts +26 -0
  20. package/src/Softmax/index.js +225 -0
  21. package/src/Tokenizer/index.d.ts +12 -0
  22. package/src/Tokenizer/index.js +164 -0
  23. package/src/Tokenizer/vocabs.json +19618 -0
  24. package/src/TransformerBlock/index.d.ts +28 -0
  25. package/src/TransformerBlock/index.js +78 -0
  26. package/src/getVec.js +30 -0
  27. package/src/gpu.js +0 -0
  28. package/src/residualConnection/index.js +32 -0
  29. package/src/shaders/CalculateAcc.wgsl +50 -0
  30. package/src/shaders/CalculateLoss.wgsl +30 -0
  31. package/src/shaders/ComputeDInput.wgsl +32 -0
  32. package/src/shaders/EB.wgsl +33 -0
  33. package/src/shaders/EF.wgsl +25 -0
  34. package/src/shaders/LB.wgsl +75 -0
  35. package/src/shaders/LF.wgsl +60 -0
  36. package/src/shaders/Norm/rmsBackward.wgsl +65 -0
  37. package/src/shaders/Norm/rmsForward.wgsl +30 -0
  38. package/src/shaders/Norm/sumSquare.wgsl +38 -0
  39. package/src/shaders/Norm/updateGamma.wgsl +52 -0
  40. package/src/shaders/PB.wgsl +25 -0
  41. package/src/shaders/PF.wgsl +19 -0
  42. package/src/shaders/RB.wgsl +37 -0
  43. package/src/shaders/RF.wgsl +33 -0
  44. package/src/shaders/ReductionFunction.wgsl +28 -0
  45. package/src/shaders/SB.wgsl +36 -0
  46. package/src/shaders/SF.wgsl +75 -0
  47. package/src/shaders/SoftmaxBackward.wgsl +31 -0
  48. package/src/shaders/add.wgsl +30 -0
  49. package/src/shaders/attentionShader/CompueFinalForwardOutput.wgsl +29 -0
  50. package/src/shaders/attentionShader/ComputeDA.wgsl +30 -0
  51. package/src/shaders/attentionShader/ComputeDV.wgsl +37 -0
  52. package/src/shaders/attentionShader/ComputeK.wgsl +30 -0
  53. package/src/shaders/attentionShader/ComputedQ.wgsl +31 -0
  54. package/src/shaders/attentionShader/attentionSocres.wgsl +40 -0
  55. package/src/shaders/attentionShader/sumGradient.wgsl +24 -0
  56. package/src/shaders/calculateTotal.wgsl +26 -0
  57. package/README.md +0 -3
@@ -0,0 +1,28 @@
1
+ export class TransformerBlock{
2
+ constructor(device: GPUAdapter, embeddingSize: number, configs: {
3
+ dirname: string
4
+ })
5
+ async forward(input : {
6
+ read: function(): Promise<Float32Array>,
7
+ mainBuffer: GPUBuffer,
8
+ isDestroyed: function(): Boolean,
9
+ destroy: function(): void
10
+ }) : Promise<{
11
+ read: function(): Promise<Float32Array>,
12
+ mainBuffer: GPUBuffer,
13
+ isDestroyed: function(): Boolean,
14
+ destroy: function(): void
15
+ }>
16
+ async backward(outInput : {
17
+ read: function(): Promise<Float32Array>,
18
+ mainBuffer: GPUBuffer,
19
+ isDestroyed: function(): Boolean,
20
+ destroy: function(): void
21
+ }, lr : number) : Promise<{
22
+ read: function(): Promise<Float32Array>,
23
+ mainBuffer: GPUBuffer,
24
+ isDestroyed: function(): Boolean,
25
+ destroy: function(): void
26
+ }>
27
+ async Save() : Promise<void>
28
+ }
@@ -0,0 +1,78 @@
1
+
2
+ import { SelfAttention } from '../SelfAttention/index.js';
3
+ import { FFN } from '../FFN/index.js';
4
+ import { existsSync, mkdirSync } from 'fs';
5
+ import { RMSNorm } from '../../index.js';
6
+ import { OperationManager } from '../OperationManager.js';
7
+ import path, { join } from 'path';
8
+ import { residualConnection } from '../residualConnection/index.js'
9
+
10
+ export class TransformerBlock {
11
+ attention;
12
+ ffn;
13
+ gpu;
14
+ size;
15
+ rmsnorm;
16
+ rmsnorm2;
17
+
18
+ constructor(device, embeddingSize, configs) {
19
+ this.size = embeddingSize;
20
+ if (!existsSync(configs.dirname)) {
21
+ mkdirSync(configs.dirname, { recursive: true });
22
+ }
23
+ this.rmsnorm = new RMSNorm(device, embeddingSize, {
24
+ save: {
25
+ filename: join(configs.dirname, "LAYERNORM-1.bin")
26
+ }
27
+ });
28
+ this.rmsnorm2 = new RMSNorm(device, embeddingSize, {
29
+ save: {
30
+ filename: join(configs.dirname, "LAYERNORM-2.bin")
31
+ }
32
+ });
33
+
34
+
35
+ this.attention = new SelfAttention(
36
+ device, embeddingSize, configs
37
+ );
38
+ this.rFor1 = new residualConnection(device)
39
+ this.rFor2 = new residualConnection(device)
40
+ this.rback1 = new residualConnection(device)
41
+ this.rback2 = new residualConnection(device)
42
+ this.ffn = new FFN(device, embeddingSize, configs);
43
+ this.gpu = new OperationManager(device);
44
+ }
45
+
46
+ async forward(input, encoderMain) {
47
+ const count = input.size / 4;
48
+ const norm1 = await this.rmsnorm.forward(input);
49
+ const att = await this.attention.forward(norm1, encoderMain)
50
+ const residual1 = await this.rFor1.add(att, input, encoderMain)
51
+ const norm2 = await this.rmsnorm2.forward(residual1)
52
+ const f = await this.ffn.forward(norm2, encoderMain)
53
+ const residual2 = await this.rFor2.add(f, residual1, encoderMain)
54
+ return residual2;
55
+ }
56
+
57
+ async backward(outGradient, lr, encoderMain) {
58
+ const dAtt = await this.ffn.backward(outGradient, lr, encoderMain);
59
+ const dNorm2 = await this.rmsnorm2.backward(dAtt, lr)
60
+ const dResidual1 = await this.rback2.add(outGradient, dNorm2, encoderMain)
61
+ const dFF = await this.attention.backward(dResidual1, lr, encoderMain)
62
+ const dNorm = await this.rmsnorm.backward(dFF, lr)
63
+ const dResidual2 = await this.rback1.add(dNorm, dResidual1, encoderMain)
64
+ return dResidual2;
65
+ }
66
+
67
+ async ClearInputCache() {
68
+ await this.ffn.ClearInputCache();
69
+ await this.attention.ClearInputCache();
70
+ }
71
+
72
+ async Save() {
73
+ await this.ffn.Save();
74
+ await this.attention.Save();
75
+ await this.rmsnorm.Save()
76
+ await this.rmsnorm2.Save()
77
+ }
78
+ }
package/src/getVec.js ADDED
@@ -0,0 +1,30 @@
1
+ import fs from 'fs'
2
+
3
+
4
+ export function getVector(filename, size, bias) {
5
+ if (!fs.existsSync(filename)) {
6
+ return null;
7
+ }
8
+ const buffer = fs.readFileSync(filename);
9
+ const r = new Float32Array(
10
+ buffer.buffer,
11
+ buffer.byteOffset,
12
+ buffer.byteLength / 4
13
+ );
14
+ if (r.length >= size) {
15
+ return r;
16
+ }
17
+ const output = new Float32Array(size);
18
+ output.set(r);
19
+ if (!bias) {
20
+ for (let i = r.length; i < size; i++) {
21
+ output[i] = (Math.random() * 2 - 1) * 0.02;
22
+ }
23
+ }
24
+ return output;
25
+ }
26
+
27
+ export function SaveVector(filename, vectors) {
28
+ const buffer = Buffer.from(vectors.buffer)
29
+ fs.writeFileSync(filename, buffer)
30
+ }
package/src/gpu.js ADDED
File without changes
@@ -0,0 +1,32 @@
1
+ import { OperationManager } from "../OperationManager.js";
2
+
3
+ export class residualConnection {
4
+ gpu;
5
+ addShader;
6
+ a;
7
+ b;
8
+ output;
9
+ constructor(device) {
10
+ this.gpu = new OperationManager(device)
11
+ this.addShader = this.gpu.getShaderPipline("./src/shaders/add.wgsl")
12
+ }
13
+ async add(a, b, encoderMain) {
14
+ if (!this.params) {
15
+ this.params = await this.gpu.createUniFormBuffer(4 * 4)
16
+ }
17
+ const encoder = encoderMain ? encoderMain : await this.gpu.CreateEncoder()
18
+ if (!this.output) {
19
+ this.output = await this.gpu.ManageBuffer(a.size);
20
+ }
21
+ if (this.output.size !== a.size || this.output.size == 0 || this.output.isDestroyed()) {
22
+ this.output.destroy()
23
+ this.output = await this.gpu.ManageBuffer(a.size);
24
+ }
25
+ await this.output.count()
26
+ const bind = await this.gpu.createBindGroup(this.addShader, 0, [a.mainBuffer, b.mainBuffer, this.output.mainBuffer, this.params]);
27
+ await this.gpu.WriteBuffer(this.params, new Uint32Array([(a.size / 4), 0]))
28
+ await this.gpu.RunPipline(encoder, this.addShader, bind, Math.ceil((a.size / 4) / 64));
29
+ if(!encoderMain) await this.gpu.submitQueue(encoder)
30
+ return this.output
31
+ }
32
+ }
@@ -0,0 +1,50 @@
1
+ struct Params{
2
+ vocabSize: u32,
3
+ tokenCount: u32
4
+ }
5
+
6
+ @group(0) @binding(0)
7
+
8
+ var <uniform> params : Params;
9
+
10
+
11
+ @group(0) @binding(1)
12
+
13
+ var <storage, read_write> probs : array<f32>;
14
+
15
+ @group(0) @binding(3)
16
+
17
+ var <storage, read_write> tToken : array<u32>;
18
+
19
+ @group(0) @binding(2)
20
+
21
+
22
+ var <storage, read_write> result : array<f32>;
23
+
24
+
25
+ @compute @workgroup_size(1)
26
+
27
+ fn main(@builtin(global_invocation_id) id : vec3<u32>){
28
+ let x = id.x;
29
+
30
+ var correct = 0.0;
31
+ for(var a = 0u; a < params.tokenCount; a++){
32
+ var bestVal = - 3.402823e38;
33
+ var maxToken = 0u;
34
+ var start = a * params.vocabSize;
35
+ let end = start + params.vocabSize;
36
+ for(var t = start; t < end; t++){
37
+ let val = probs[t];
38
+ if(bestVal < val){
39
+ bestVal = val;
40
+ maxToken = t - start;
41
+ }
42
+ }
43
+ if(maxToken == tToken[a]){
44
+ correct += 1.0;
45
+ }
46
+
47
+ }
48
+ correct /= f32(params.tokenCount);
49
+ result[x] = correct;
50
+ }
@@ -0,0 +1,30 @@
1
+ struct Params {
2
+ vocabSize: u32,
3
+ tokenCount: u32,
4
+ }
5
+
6
+ @group(0) @binding(0)
7
+
8
+ var <storage, read> probs : array<f32>;
9
+
10
+ @group(0) @binding(1)
11
+
12
+ var <storage, read> targetToken : array<u32>;
13
+
14
+ @group(0) @binding(2)
15
+
16
+ var <storage, read_write> loss : array<f32>;
17
+
18
+ @group(0) @binding(3)
19
+
20
+ var <uniform> params: Params;
21
+
22
+
23
+ @compute @workgroup_size(4)
24
+
25
+ fn main(@builtin(global_invocation_id) id : vec3<u32>) {
26
+ let index = id.x;
27
+ var targetIndex = targetToken[index];
28
+ let probalitils = probs[index * params.vocabSize + u32(targetIndex)];
29
+ loss[index] = -log(probalitils + 1e-15);
30
+ }
@@ -0,0 +1,32 @@
1
+ struct Params {
2
+ vocabSize: u32,
3
+ tokenCount: u32,
4
+ lr: f32,
5
+ inputSize: u32,
6
+ }
7
+
8
+ @group(0) @binding(0)
9
+ var<storage, read_write> weight: array<f32>;
10
+ @group(0) @binding(1)
11
+ var<storage, read> outGradient: array<f32>;
12
+ @group(0) @binding(3)
13
+ var<uniform> params: Params;
14
+ @group(0) @binding(4)
15
+ var<storage, read_write> dInput: array<f32>;
16
+ @compute @workgroup_size(256)
17
+ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
18
+ let index = id.x;
19
+ let total = params.tokenCount * params.inputSize;
20
+ if (index >= u32(total)) {
21
+ return;
22
+ }
23
+ let token =index / u32(params.inputSize);
24
+ let inputIndex = index % u32(params.inputSize);
25
+ var gradInput = 0.0;
26
+ for (var i = 0u; i < u32(params.vocabSize); i++) {
27
+ let w = weight[i * u32(params.inputSize) + inputIndex];
28
+ let grad = outGradient[token * u32(params.vocabSize) + i];
29
+ gradInput += grad * w;
30
+ }
31
+ dInput[index] = gradInput;
32
+ }
@@ -0,0 +1,33 @@
1
+ struct Params {
2
+ lr: f32
3
+ }
4
+
5
+ @group(0) @binding(0)
6
+
7
+ var<storage, read_write> embeddings: array<f32>;
8
+
9
+ @group(0) @binding(1)
10
+
11
+ var<storage, read_write> outputGradient: array<f32>;
12
+
13
+ @group(0) @binding(2)
14
+
15
+ var<storage, read_write> tokens: array<u32>;
16
+
17
+ @group(0) @binding(3)
18
+ var<uniform> params: Params;
19
+
20
+ const embeddingSize = %embeddingSize%u;
21
+
22
+ @compute @workgroup_size(256)
23
+
24
+ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
25
+ let dim = id.x % embeddingSize;
26
+ if (id.x >= arrayLength(&outputGradient)) {
27
+ return;
28
+ }
29
+ let tokenIndex = id.x / embeddingSize;
30
+ let tokenID = tokens[tokenIndex];
31
+ let embeddingIDx = tokenID * embeddingSize + dim;
32
+ embeddings[embeddingIDx] -= params.lr * outputGradient[id.x];
33
+ }
@@ -0,0 +1,25 @@
1
+ @group(0) @binding(0)
2
+
3
+ var <storage, read_write> embeddings: array<f32>;
4
+
5
+ @group(0) @binding(1)
6
+
7
+ var <storage, read_write> output: array<f32>;
8
+
9
+ @group(0) @binding(2)
10
+
11
+ var <storage, read_write> tokens: array<u32>;
12
+
13
+ const embeddingSize = %embeddingSize%u;
14
+
15
+ @compute @workgroup_size(256)
16
+
17
+ fn main(@builtin(global_invocation_id) id : vec3<u32>){
18
+ let dim = id.x % embeddingSize;
19
+ let tokenIndex = id.x / embeddingSize;
20
+
21
+ let tokenID = tokens[tokenIndex];
22
+
23
+ let embeddingIDx = tokenID * embeddingSize + dim;
24
+ output[id.x] = embeddings[embeddingIDx];
25
+ }
@@ -0,0 +1,75 @@
1
+ struct Params {
2
+ vocabSize: u32,
3
+ tokenCount: u32,
4
+ lr: f32,
5
+ inputSize: u32,
6
+ }
7
+
8
+ @group(0) @binding(0)
9
+ var<storage, read_write> bias: array<f32>;
10
+
11
+ @group(0) @binding(1)
12
+ var<storage, read_write> weight: array<f32>;
13
+
14
+ @group(0) @binding(2)
15
+ var<storage, read> outGradient: array<f32>;
16
+
17
+ @group(0) @binding(3)
18
+ var<storage, read> input: array<f32>;
19
+
20
+ @group(0) @binding(4)
21
+ var<uniform> params: Params;
22
+
23
+ var<workgroup> sharedBias: array<f32, 256>;
24
+
25
+ @compute @workgroup_size(256)
26
+ fn main(
27
+ @builtin(workgroup_id) wid: vec3<u32>,
28
+ @builtin(local_invocation_id) lid: vec3<u32>
29
+ ) {
30
+ let outputIndex = wid.x;
31
+ let tid = lid.x;
32
+
33
+ let vocab = params.vocabSize;
34
+ let tokens = params.tokenCount;
35
+ let inputSize = params.inputSize;
36
+
37
+ for (
38
+ var inputIndex = tid;
39
+ inputIndex < inputSize;
40
+ inputIndex += 256u
41
+ ) {
42
+ var grad = 0.0;
43
+
44
+ for (var t = 0u; t < tokens; t++) {
45
+ grad += input[t * inputSize + inputIndex]
46
+ * outGradient[t * vocab + outputIndex];
47
+ }
48
+
49
+ if (tokens > 0u) {
50
+ weight[outputIndex * inputSize + inputIndex] -=
51
+ params.lr * grad / f32(tokens);
52
+ }
53
+ }
54
+
55
+ var biasGrad = 0.0;
56
+
57
+ for (var t = tid; t < tokens; t += 256u) {
58
+ biasGrad += outGradient[t * vocab + outputIndex];
59
+ }
60
+
61
+ sharedBias[tid] = biasGrad;
62
+ workgroupBarrier();
63
+
64
+ for (var stride = 128u; stride > 0u; stride >>= 1u) {
65
+ if (tid < stride) {
66
+ sharedBias[tid] += sharedBias[tid + stride];
67
+ }
68
+ workgroupBarrier();
69
+ }
70
+
71
+ if (tid == 0u && tokens > 0u) {
72
+ bias[outputIndex] -=
73
+ params.lr * sharedBias[0] / f32(tokens);
74
+ }
75
+ }
@@ -0,0 +1,60 @@
1
+
2
+ struct Params {
3
+ inputSize: u32,
4
+ outputSize: u32,
5
+ tokenCount: u32,
6
+ }
7
+
8
+ @group(0) @binding(0)
9
+ var<storage, read> weights: array<f32>;
10
+
11
+ @group(0) @binding(1)
12
+ var<storage, read_write> output: array<f32>;
13
+
14
+ @group(0) @binding(2)
15
+ var<storage, read> input: array<f32>;
16
+
17
+ @group(0) @binding(3)
18
+ var<storage, read> bias: array<f32>;
19
+
20
+ @group(0) @binding(4)
21
+ var<uniform> params: Params;
22
+
23
+ const TILE_OUT: u32 = 16u;
24
+ const TILE_TOKEN: u32 = 4u;
25
+ const TILE_K: u32 = 16u;
26
+
27
+ var<workgroup> tileInput: array<f32, 64>;
28
+ var<workgroup> tileWeights: array<f32, 256>;
29
+
30
+ @compute @workgroup_size(64)
31
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
32
+ let outFeature = wid.x * TILE_OUT + lid.x % TILE_OUT;
33
+ let token = wid.y * TILE_TOKEN + lid.x / TILE_OUT;
34
+ let localOut = lid.x % TILE_OUT;
35
+ let localToken = lid.x / TILE_OUT;
36
+ var sum = 0.0;
37
+ for (var baseK = 0u; baseK < params.inputSize; baseK += TILE_K) {
38
+ let loadIndex = lid.x;
39
+ let inputToken = wid.y * TILE_TOKEN + loadIndex / TILE_K;
40
+ let inputK = baseK + loadIndex % TILE_K;
41
+ if (loadIndex < TILE_TOKEN * TILE_K && inputToken < params.tokenCount && inputK < params.inputSize) {
42
+ tileInput[loadIndex] = input[inputToken * params.inputSize + inputK];
43
+ }
44
+ let weightFeature = wid.x * TILE_OUT + loadIndex / TILE_K;
45
+ let weightK = baseK + loadIndex % TILE_K;
46
+ if (loadIndex < TILE_OUT * TILE_K && weightFeature < params.outputSize && weightK < params.inputSize) {
47
+ tileWeights[loadIndex] = weights[weightFeature * params.inputSize + weightK];
48
+ }
49
+ workgroupBarrier();
50
+ for (var k = 0u; k < TILE_K; k++) {
51
+ let a = tileInput[localToken * TILE_K + k];
52
+ let b = tileWeights[localOut * TILE_K + k];
53
+ sum += a * b;
54
+ }
55
+ workgroupBarrier();
56
+ }
57
+ if (token < params.tokenCount && outFeature < params.outputSize) {
58
+ output[token * params.outputSize + outFeature] = sum + bias[outFeature];
59
+ }
60
+ }
@@ -0,0 +1,65 @@
1
+
2
+ @group(0) @binding(0)
3
+ var<storage, read> input: array<f32>;
4
+
5
+ @group(0) @binding(1)
6
+ var<storage, read> gradOutput: array<f32>;
7
+ @group(0) @binding(2)
8
+ var<storage, read> sumSquares: array<f32>;
9
+
10
+ @group(0) @binding(3)
11
+ var<storage, read> gamma: array<f32>;
12
+
13
+ @group(0) @binding(4)
14
+ var<storage, read_write> gradInput: array<f32>;
15
+
16
+ var<workgroup> partial: array<f32, 64>;
17
+
18
+ const D: u32 = %embeddingSize%u;
19
+ const EPSILON: f32 = 1e-6;
20
+ @compute @workgroup_size(64)
21
+ fn main(@builtin(local_invocation_index) lid: u32, @builtin(workgroup_id) wid: vec3<u32>) {
22
+ let token = wid.x;
23
+ if (token >= arrayLength(&sumSquares)) {
24
+ return;
25
+ }
26
+ let base = token * D;
27
+ let r = sqrt(sumSquares[token] / f32(D) + EPSILON);
28
+ var localSum = 0.0;
29
+ var d = lid;
30
+ while (d < D) {
31
+ let idx = base + d;
32
+ localSum += gradOutput[idx] * gamma[d] * input[idx];
33
+ d += 64u;
34
+ }
35
+
36
+ partial[lid] = localSum;
37
+ workgroupBarrier();
38
+ var stride = 32u;
39
+ loop {
40
+ if (stride == 0u) {
41
+ break;
42
+ }
43
+
44
+ if (lid < stride) {
45
+ partial[lid] += partial[lid + stride];
46
+ }
47
+
48
+ workgroupBarrier();
49
+ stride /= 2u;
50
+ }
51
+ let dot = partial[0];
52
+ d = lid;
53
+ while (d < D) {
54
+ let idx = base + d;
55
+ let x = input[idx];
56
+ let dy = gradOutput[idx];
57
+ let g = gamma[d];
58
+
59
+ gradInput[idx] =
60
+ (dy * g) / r
61
+ - (x * dot) / (f32(D) * r * r * r);
62
+
63
+ d += 64u;
64
+ }
65
+ }
@@ -0,0 +1,30 @@
1
+ @group(0) @binding(0)
2
+ var<storage, read> reduce: array<f32>;
3
+
4
+ @group(0) @binding(1)
5
+ var<storage, read> vector: array<f32>;
6
+
7
+ @group(0) @binding(2)
8
+ var<storage, read_write> output: array<f32>;
9
+
10
+ @group(0) @binding(3)
11
+ var<storage, read> gamma: array<f32>;
12
+
13
+ @compute @workgroup_size(64)
14
+ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
15
+ let x = id.x;
16
+
17
+ if (x >= arrayLength(&vector)) {
18
+ return;
19
+ }
20
+
21
+ let dim = %embeddingSize%u;
22
+ let token = x / dim;
23
+ let d = x % dim;
24
+
25
+ let rms = sqrt(
26
+ reduce[token] / f32(dim) + 1e-6
27
+ );
28
+
29
+ output[x] = (vector[x] / rms) * gamma[d];
30
+ }
@@ -0,0 +1,38 @@
1
+
2
+ @group(0) @binding(0)
3
+ var<storage, read> input: array<f32>;
4
+
5
+ @group(0) @binding(1)
6
+ var<storage, read_write> out: array<f32>;
7
+
8
+ var<workgroup> partial: array<f32, 64>;
9
+ const D: u32 = %embeddingSize%u;
10
+ @compute @workgroup_size(64)
11
+ fn main(@builtin(local_invocation_index) lid: u32, @builtin(workgroup_id) wid: vec3<u32>) {
12
+ let base = wid.x * D;
13
+ var sum = 0.0;
14
+ var d = lid;
15
+ while (d < D) {
16
+ let idx = base + d;
17
+ if (idx < arrayLength(&input)) {
18
+ sum += input[idx] * input[idx];
19
+ }
20
+ d += 64u;
21
+ }
22
+ partial[lid] = sum;
23
+ workgroupBarrier();
24
+ var stride = 32u;
25
+ loop {
26
+ if (stride == 0u) {
27
+ break;
28
+ }
29
+ if (lid < stride) {
30
+ partial[lid] += partial[lid + stride];
31
+ }
32
+ workgroupBarrier();
33
+ stride /= 2u;
34
+ }
35
+ if (lid == 0u) {
36
+ out[wid.x] = partial[0];
37
+ }
38
+ }
@@ -0,0 +1,52 @@
1
+
2
+ @group(0) @binding(0)
3
+ var<storage, read> input: array<f32>;
4
+
5
+ @group(0) @binding(1)
6
+ var<storage, read> gradOutput: array<f32>;
7
+
8
+ @group(0) @binding(2)
9
+ var<storage, read> sumSquares: array<f32>;
10
+
11
+ @group(0) @binding(3)
12
+ var<storage, read_write> gamma: array<f32>;
13
+
14
+ @group(0) @binding(4)
15
+ var<storage, read> params: array<f32>;
16
+
17
+ var<workgroup> partial: array<f32, 64>;
18
+
19
+ const D: u32 = %embeddingSize%u;
20
+ const EPSILON: f32 = 1e-6;
21
+
22
+ @compute @workgroup_size(64)
23
+ fn main(@builtin(local_invocation_index) lid: u32, @builtin(workgroup_id) wid: vec3<u32>) {
24
+ let dim = wid.x;
25
+ let T = arrayLength(&sumSquares);
26
+ var sum = 0.0;
27
+ if (dim < D) {
28
+ var token = lid;
29
+ while (token < T) {
30
+ let idx = token * D + dim;
31
+ let rms = sqrt(sumSquares[token] / f32(D) + EPSILON);
32
+ sum += gradOutput[idx] * input[idx] / rms;
33
+ token += 64u;
34
+ }
35
+ }
36
+ partial[lid] = sum;
37
+ workgroupBarrier();
38
+ var stride = 32u;
39
+ loop {
40
+ if (stride == 0u) {
41
+ break;
42
+ }
43
+ if (lid < stride) {
44
+ partial[lid] += partial[lid + stride];
45
+ }
46
+ workgroupBarrier();
47
+ stride /= 2u;
48
+ }
49
+ if (lid == 0u && dim < D) {
50
+ gamma[dim] -= params[0] * partial[0];
51
+ }
52
+ }
@@ -0,0 +1,25 @@
1
+ struct Params{
2
+ lr : f32
3
+ }
4
+
5
+ @group(0) @binding(0)
6
+ var <storage, read_write> posVec: array<f32>;
7
+
8
+ @group(0) @binding(1)
9
+
10
+ var <storage, read> outputGradient : array<f32>;
11
+
12
+
13
+ @group(0) @binding(2)
14
+
15
+ var <uniform> params: Params;
16
+
17
+ @compute @workgroup_size(64)
18
+
19
+ fn main(@builtin(global_invocation_id) id : vec3<u32>){
20
+ let x = id.x;
21
+ if(x >= arrayLength(&outputGradient)){
22
+ return;
23
+ }
24
+ posVec[x] -= params.lr * outputGradient[x];
25
+ }