@mineproness/tensorloop 2.1.81 → 2.2.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mineproness/tensorloop",
3
- "version": "2.1.81",
3
+ "version": "2.2.1",
4
4
  "description": "Raw-JAVASCRIPT Based Matirx and AI LLM Package called Tensorloop.",
5
5
  "keywords": [
6
6
  "ai",
@@ -1,11 +1,21 @@
1
- export class Embedding{
2
- constructor(device: GPUBuffer ,embedding : number, vocabSize: number, config:{
1
+ export class Embedding {
2
+ constructor(device: GPUBuffer, embedding: number, vocabSize: number, config: {
3
3
  cpuReadBack: boolean,
4
4
  save: {
5
5
  filename: string
6
6
  }
7
7
  })
8
- async forward(tokens: number[]) : Promise<GPUBuffer>
9
- async Save() : void
10
- async backward(tokens: number[], inputGradient: GPUBuffer, lr: number) : Promise<void>
8
+ async forward(tokens: number[]): Promise<{
9
+ read: function(): Promise<Float32Array>,
10
+ mainBuffer: GPUBuffer,
11
+ isDestroyed: function(): Boolean,
12
+ destroy: function(): void
13
+ }>
14
+ async Save(): void
15
+ async backward(inputGradient: {
16
+ read: function(): Promise<Float32Array>,
17
+ mainBuffer: GPUBuffer,
18
+ isDestroyed: function(): Boolean,
19
+ destroy: function(): void
20
+ }, lr: number): Promise<void>
11
21
  }
@@ -51,9 +51,18 @@ export class Embedding {
51
51
  this.vectorsBuffer = await this.gpu.createBuffer(Float32Array.BYTES_PER_ELEMENT * this.vocabSize * this.embeddingSize);
52
52
  await this.gpu.WriteBuffer(this.vectorsBuffer, this.vectors)
53
53
  }
54
- const tokenBuffer = await this.gpu.createBuffer(Uint32Array.BYTES_PER_ELEMENT * input.length);
55
- await this.gpu.WriteBuffer(tokenBuffer, new Uint32Array(input))
56
- const outputBuffer = await this.gpu.createBuffer(Float32Array.BYTES_PER_ELEMENT * this.embeddingSize * input.length);
54
+ if (!this.tokenBuffer) this.tokenBuffer = await this.gpu.createBuffer(Uint32Array.BYTES_PER_ELEMENT * input.length);
55
+ if (this.tokenBuffer.size !== Uint32Array.BYTES_PER_ELEMENT * input.length) {
56
+ this.tokenBuffer.destroy()
57
+ this.tokenBuffer = await this.gpu.createBuffer(Uint32Array.BYTES_PER_ELEMENT * input.length);
58
+ }
59
+
60
+ await this.gpu.WriteBuffer(this.tokenBuffer, new Uint32Array(input))
61
+ if (!this.outputBuffer) this.outputBuffer = await this.gpu.ManageBuffer(Float32Array.BYTES_PER_ELEMENT * this.embeddingSize * input.length)
62
+ if (this.outputBuffer.mainBuffer.size !== Float32Array.BYTES_PER_ELEMENT * this.embeddingSize * input.length || this.outputBuffer.isDestroyed()) {
63
+ this.outputBuffer.destroy()
64
+ this.outputBuffer = await this.gpu.ManageBuffer(Float32Array.BYTES_PER_ELEMENT * this.embeddingSize * input.length);
65
+ }
57
66
  const bind = await this.device.createBindGroup({
58
67
  layout: await this.forwardPipline.getBindGroupLayout(0),
59
68
  entries: [
@@ -66,37 +75,30 @@ export class Embedding {
66
75
  {
67
76
  binding: 1,
68
77
  resource: {
69
- buffer: outputBuffer
78
+ buffer: this.outputBuffer.mainBuffer
70
79
  }
71
80
  }, {
72
81
  binding: 2,
73
82
  resource: {
74
- buffer: tokenBuffer
83
+ buffer: this.tokenBuffer
75
84
  }
76
85
  }
77
86
  ]
78
87
  })
79
- await this.gpu.RunPipline(encoder,this.forwardPipline, bind, Math.ceil((this.embeddingSize * input.length) / 256))
88
+ await this.gpu.RunPipline(encoder, this.forwardPipline, bind, Math.ceil((this.embeddingSize * input.length) / 256))
80
89
  this.device.queue.submit([encoder.finish()])
81
- tokenBuffer.destroy()
82
- if (this.configs.cpuReadBack) {
83
- const output = await this.gpu.readBuffer(Float32Array.BYTES_PER_ELEMENT * this.embeddingSize * input.length, outputBuffer);
84
- outputBuffer.destroy()
85
- return output
86
- }
87
- return outputBuffer
90
+ return this.outputBuffer
88
91
 
89
92
  }
90
93
  async Save() {
91
94
  const vec = await this.gpu.readBuffer(Float32Array.BYTES_PER_ELEMENT * this.vocabSize * this.embeddingSize, this.vectorsBuffer)
92
95
  SaveVector(this.configs.save.filename, vec)
93
96
  }
94
- async backward(token, inputGradient, lr) {
97
+ async backward(inputGradient, lr) {
95
98
  const encoder = this.device.createCommandEncoder()
96
99
  if (!this.oldParam) {
97
100
  this.oldParam = new Float32Array([0, 0]);
98
101
  this.param = await this.gpu.createUniFormBuffer(this.oldParam.byteLength);
99
- this.tokenBuffer = await this.gpu.createBuffer(4 * token.length)
100
102
  }
101
103
  if (this.oldParam[0] !== lr) {
102
104
  this.oldParam = new Float32Array([lr, 0]);
@@ -114,7 +116,7 @@ export class Embedding {
114
116
  {
115
117
  binding: 1,
116
118
  resource: {
117
- buffer: inputGradient
119
+ buffer: inputGradient.mainBuffer
118
120
  }
119
121
  }, {
120
122
  binding: 2,
@@ -131,10 +133,18 @@ export class Embedding {
131
133
  }
132
134
  ]
133
135
  })
134
- await this.gpu.WriteBuffer(this.tokenBuffer, new Uint32Array(token));
135
- await this.gpu.RunPipline(encoder, this.backwardPipline, bind, Math.ceil((this.embeddingSize * token.length) / 256))
136
+ await this.gpu.RunPipline(encoder, this.backwardPipline, bind, Math.ceil((this.embeddingSize * (this.tokenBuffer.size / 4)) / 256))
136
137
  this.device.queue.submit([encoder.finish()])
137
- if(this.prevGra) this.prevGra.destroy()
138
- this.prevGra = inputGradient;
138
+ }
139
+ destroy() {
140
+ this.vectorsBuffer?.destroy();
141
+ this.tokenBuffer?.destroy();
142
+ this.outputBuffer?.destroy();
143
+ this.param?.destroy();
144
+
145
+ this.vectorsBuffer = null;
146
+ this.tokenBuffer = null;
147
+ this.outputBuffer = null;
148
+ this.param = null;
139
149
  }
140
150
  }
package/src/FFN/index.js CHANGED
@@ -29,8 +29,6 @@ export class FFN {
29
29
  return final
30
30
  }
31
31
  async backward(inputGradient, lr) {
32
- if(this.prevOUTGR) await this.prevOUTGR.destroy()
33
- this.prevOUTGR = inputGradient;
34
32
  const logit2 = await this.linear2.backward(inputGradient, lr)
35
33
  const hidden = await this.hiddenLayer.backward(logit2)
36
34
  const final = await this.linear1.backward(hidden, lr)
@@ -1,12 +1,31 @@
1
1
  export class Linear {
2
2
  constructor(device: GPUAdapter, embeddingSize: number, vocabSize: number, configs: {
3
- cpuReadBack: boolean,
4
3
  save: {
5
4
  filename: string[]
6
5
  }
7
6
  })
8
- async forward(vec: GPUBuffer): Promise<GPUBuffer | Float32Array>
9
- async backward(dOutput: GPUBuffer, lr: number): Promise<GPUBuffer>
7
+ async forward(vec: {
8
+ read: function(): Promise<Float32Array>,
9
+ mainBuffer: GPUBuffer,
10
+ isDestroyed: function(): Boolean,
11
+ destroy: function(): void
12
+ }): Promise<{
13
+ read: function(): Promise<Float32Array>,
14
+ mainBuffer: GPUBuffer,
15
+ isDestroyed: function(): Boolean,
16
+ destroy: function(): void
17
+ }>
18
+ async backward(dOutput: {
19
+ read: function(): Promise<Float32Array>,
20
+ mainBuffer: GPUBuffer,
21
+ isDestroyed: function(): Boolean,
22
+ destroy: function(): void
23
+ }, lr: number): Promise<{
24
+ read: function(): Promise<Float32Array>,
25
+ mainBuffer: GPUBuffer,
26
+ isDestroyed: function(): Boolean,
27
+ destroy: function(): void
28
+ }>
10
29
  async Save(): Promise<void>
11
- async ClearInputCache() : Promise<void>
30
+ async ClearInputCache(): Promise<void>
12
31
  }
@@ -63,7 +63,7 @@ export class Linear {
63
63
  }
64
64
  async forward(vec) {
65
65
  const encoder = this.device.createCommandEncoder()
66
- const tokenCount = vec.size / (this.embeddingSize * 4)
66
+ const tokenCount = vec.mainBuffer.size / (this.embeddingSize * 4)
67
67
  if (!this.wBuffer) {
68
68
 
69
69
  this.wBuffer = await this.gpu.createBuffer(this.embeddingSize * this.vocabSize * 4)
@@ -80,7 +80,12 @@ export class Linear {
80
80
  await this.gpu.WriteBuffer(this.paramForward, new Uint32Array([this.embeddingSize, this.vocabSize, tokenCount, 0]))
81
81
  this.oldParam = new Uint32Array([this.embeddingSize, this.vocabSize, tokenCount, 0]);
82
82
  }
83
- const outputBuffer = await this.gpu.createBuffer(4 * this.vocabSize * tokenCount)
83
+ if (!this.outputBuffer) this.outputBuffer = await this.gpu.ManageBuffer(4 * this.vocabSize * tokenCount)
84
+ if (this.outputBuffer.mainBuffer.size !== 4 * this.vocabSize * tokenCount || this.outputBuffer.isDestroyed()) {
85
+ this.outputBuffer.destroy()
86
+ this.outputBuffer = await this.gpu.ManageBuffer(4 * this.vocabSize * tokenCount)
87
+ }
88
+
84
89
  const bind = await this.device.createBindGroup({
85
90
  layout: await this.forwardPipline.getBindGroupLayout(0),
86
91
  entries: [
@@ -90,11 +95,11 @@ export class Linear {
90
95
  },
91
96
  {
92
97
  binding: 1,
93
- resource: outputBuffer
98
+ resource: this.outputBuffer.mainBuffer
94
99
  },
95
100
  {
96
101
  binding: 2,
97
- resource: vec
102
+ resource: vec.mainBuffer
98
103
  },
99
104
  {
100
105
  binding: 3,
@@ -107,14 +112,12 @@ export class Linear {
107
112
  ]
108
113
  })
109
114
  await this.gpu.RunPipline(encoder, this.forwardPipline, bind, Math.ceil((this.vocabSize * tokenCount) / 256))
110
- if (this.input) this.input.destroy()
111
- this.input = await this.gpu.MakeACopyBuffer(encoder, vec);
115
+
112
116
  this.device.queue.submit([encoder.finish()])
113
- return outputBuffer
117
+ this.input = vec;
118
+ return this.outputBuffer
114
119
  }
115
120
  async backward(dOutput, learningRate) {
116
- if(this.pdOutput) await this.pdOutput.destroy();
117
- this.pdOutput = dOutput
118
121
  const encoder = this.device.createCommandEncoder()
119
122
  const tokenCount = dOutput.size / (this.vocabSize * 4)
120
123
  if (!this.oldParamb) {
@@ -124,7 +127,12 @@ export class Linear {
124
127
  await this.gpu.WriteBuffer(this.paramBackward, new Float32Array([this.vocabSize, tokenCount, learningRate, this.embeddingSize, 0]));
125
128
  this.oldParamb = new Float32Array([this.vocabSize, tokenCount, learningRate, this.embeddingSize, 0]);
126
129
  }
127
- const outputBuffer = await this.gpu.createBuffer(this.embeddingSize * tokenCount * 4);
130
+ if(!this.gradientBuffer) this.gradientBuffer = await this.gpu.ManageBuffer(this.embeddingSize * tokenCount * 4);
131
+ if(this.gradientBuffer.size !== 4 * this.embeddingSize * tokenCount || this.gradientBuffer.isDestroyed()){
132
+ this.gradientBuffer.destroy()
133
+ this.gradientBuffer = await this.gpu.ManageBuffer(this.embeddingSize * tokenCount * 4)
134
+
135
+ }
128
136
  const bind = await this.device.createBindGroup({
129
137
  layout: await this.backwardPipline.getBindGroupLayout(0),
130
138
  entries: [
@@ -138,11 +146,11 @@ export class Linear {
138
146
  },
139
147
  {
140
148
  binding: 2,
141
- resource: dOutput
149
+ resource: dOutput.mainBuffer
142
150
  },
143
151
  {
144
152
  binding: 3,
145
- resource: this.input
153
+ resource: this.input.mainBuffer
146
154
  },
147
155
  {
148
156
  binding: 4,
@@ -159,7 +167,7 @@ export class Linear {
159
167
  },
160
168
  {
161
169
  binding: 1,
162
- resource: dOutput
170
+ resource: dOutput.mainBuffer
163
171
  },
164
172
  {
165
173
  binding: 3,
@@ -167,7 +175,7 @@ export class Linear {
167
175
  },
168
176
  {
169
177
  binding: 4,
170
- resource: outputBuffer
178
+ resource: this.gradientBuffer.mainBuffer
171
179
  }
172
180
  ]
173
181
  })
@@ -175,8 +183,7 @@ export class Linear {
175
183
  await this.gpu.RunPipline(encoder, this.dInputBackward, bind2, Math.ceil((this.embeddingSize * tokenCount) / 256));
176
184
  await this.gpu.RunPipline(encoder, this.backwardPipline, bind, Math.ceil((this.vocabSize * tokenCount) / 256));
177
185
  await this.device.queue.submit([encoder.finish()])
178
- this.input.destroy()
179
- return outputBuffer
186
+ return this.gradientBuffer
180
187
 
181
188
  }
182
189
  async Save() {
@@ -186,7 +193,7 @@ export class Linear {
186
193
  SaveVector(this.configs.save.filename[1], b)
187
194
  }
188
195
  async ClearInputCache() {
189
- if (this.input) await this.input.destroy();
196
+
190
197
  }
191
198
 
192
199
  }
@@ -15,7 +15,7 @@ export class OperationManager {
15
15
  }
16
16
  async createBuffer(size) {
17
17
  return this.device.createBuffer({
18
- size,
18
+ size: size,
19
19
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE
20
20
  })
21
21
  }
@@ -106,8 +106,8 @@ export class OperationManager {
106
106
 
107
107
  }
108
108
  const encoder = await this.CreateEncoder()
109
- const output = await this.createBuffer(a.size);
110
- const bind = await this.createBindGroup(this.addShader, 0, [a, b, output, this.params]);
109
+ const output = await this.ManageBuffer(a.size);
110
+ const bind = await this.createBindGroup(this.addShader, 0, [a, b, output.mainBuffer, this.params]);
111
111
  await this.WriteBuffer(this.params, new Uint32Array([size, 0]))
112
112
  await this.RunPipline(encoder, this.addShader, bind, Math.ceil(size / 64));
113
113
  await this.submitQueue(encoder)
@@ -115,5 +115,27 @@ export class OperationManager {
115
115
  // b.destroy()
116
116
  return output
117
117
  }
118
+ async ManageBuffer(size){
119
+ const buffer = await this.device.createBuffer({
120
+ size,
121
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE
122
+ })
123
+ let isDestroy = false;
124
+ return {
125
+ mainBuffer: buffer,
126
+ destroy: function(){
127
+ isDestroy = true
128
+ this.mainBuffer.destroy()
129
+ },
130
+ isDestroyed: function(){
131
+ return isDestroy
132
+ },
133
+ read: async ()=>{
134
+ return await this.readBuffer(buffer.size, buffer)
135
+ },
136
+ size: size
137
+
138
+ }
139
+ }
118
140
 
119
141
  }
@@ -1,10 +1,30 @@
1
- export class PositionEmbedding{
2
- constructor(device: GPUBuffer ,embedding : number, contextSize: number, config:{
1
+ export class PositionEmbedding {
2
+ constructor(device: GPUBuffer, embedding: number, contextSize: number, config: {
3
3
  save: {
4
4
  filename: string
5
5
  }
6
6
  });
7
- async forward(input: GPUBuffer) : Promise<GPUBuffer>
8
- async Save() : Promise<GPUBuffer>
9
- async backward(inputGradient: GPUBuffer, lr: number) : Promise<void>
7
+ async forward(input: {
8
+ read: function(): Promise<Float32Array>,
9
+ mainBuffer: GPUBuffer,
10
+ isDestroyed: function(): Boolean,
11
+ destroy: function(): void
12
+ }): Promise<{
13
+ read: function(): Promise<Float32Array>,
14
+ mainBuffer: GPUBuffer,
15
+ isDestroyed: function(): Boolean,
16
+ destroy: function(): void
17
+ }>
18
+ async Save(): Promise<void>
19
+ async backward(inputGradient: {
20
+ read: function(): Promise<Float32Array>,
21
+ mainBuffer: GPUBuffer,
22
+ isDestroyed: function(): Boolean,
23
+ destroy: function(): void
24
+ }, lr: number): Promise<{
25
+ read: function(): Promise<Float32Array>,
26
+ mainBuffer: GPUBuffer,
27
+ isDestroyed: function(): Boolean,
28
+ destroy: function(): void
29
+ }>
10
30
  }
@@ -45,21 +45,16 @@ export class PositionEmbedding {
45
45
  this.vecBuffer = await this.gpu.createBuffer(Float32Array.BYTES_PER_ELEMENT * this.contextSize * this.embeddingSize);
46
46
  await this.gpu.WriteBuffer(this.vecBuffer, this.vectors)
47
47
  }
48
- const output = await this.gpu.createBuffer(input.size);
49
48
  const size = Math.ceil((input.size / 4) / 64);
50
- const bindGroup = await this.gpu.createBindGroup(this.forwardShader, 0, [this.vecBuffer, input, output])
51
- if (this.prevVec) this.prevVec.destroy();
52
- this.prevVec = input;
49
+ const bindGroup = await this.gpu.createBindGroup(this.forwardShader, 0, [this.vecBuffer, input.mainBuffer])
53
50
  await this.gpu.RunPipline(encoder, this.forwardShader, bindGroup, size);
54
51
  await this.gpu.submitQueue(encoder);
55
- return output
52
+ return input
56
53
  }
57
54
  async backward(outputGradient, lr){
58
55
  const encoder = await this.gpu.CreateEncoder()
59
56
  await this.gpu.WriteBuffer(this.params, new Float32Array([lr,0]))
60
- const bindGroup = await this.gpu.createBindGroup(this.backwardShader, 0, [this.vecBuffer, outputGradient, this.params])
61
- if(this.prevGradient) await this.prevGradient.destroy()
62
- this.prevGradient = outputGradient;
57
+ const bindGroup = await this.gpu.createBindGroup(this.backwardShader, 0, [this.vecBuffer, outputGradient.mainBuffer, this.params])
63
58
  await this.gpu.RunPipline(encoder, this.backwardShader, bindGroup, Math.ceil((outputGradient.size / 4) / 64))
64
59
  await this.gpu.submitQueue(encoder);
65
60
  }
@@ -1,10 +1,30 @@
1
- export class RMSNorm{
2
- constructor(device : GPUAdapter, embeddingSize : number , {
3
- save:{
1
+ export class RMSNorm {
2
+ constructor(device: GPUAdapter, embeddingSize: number, {
3
+ save: {
4
4
  filename: string
5
5
  }
6
6
  });
7
- async forward(input : GPUBuffer) : Promise<GPUBuffer>
8
- async backward(outputGradient : GPUBuffer) : Promise<GPUBuffer>
9
- async Save() : Promise<void>
7
+ async forward(input: {
8
+ read: function(): Promise<Float32Array>,
9
+ mainBuffer: GPUBuffer,
10
+ isDestroyed: function(): Boolean,
11
+ destroy: function(): void
12
+ }): Promise<{
13
+ read: function(): Promise<Float32Array>,
14
+ mainBuffer: GPUBuffer,
15
+ isDestroyed: function(): Boolean,
16
+ destroy: function(): void
17
+ }>
18
+ async backward(outputGradient: {
19
+ read: function(): Promise<Float32Array>,
20
+ mainBuffer: GPUBuffer,
21
+ isDestroyed: function(): Boolean,
22
+ destroy: function(): void
23
+ }): Promise<{
24
+ read: function(): Promise<Float32Array>,
25
+ mainBuffer: GPUBuffer,
26
+ isDestroyed: function(): Boolean,
27
+ destroy: function(): void
28
+ }>
29
+ async Save(): Promise<void>
10
30
  }
@@ -40,43 +40,47 @@ export class RMSNorm {
40
40
  }
41
41
  }
42
42
  async forward(input) {
43
+ this.input = input;
43
44
  if (!this.gammabuffer) {
44
45
  this.gammabuffer = await this.op.createBuffer(4 * this.embeddingSize);
45
46
  await this.op.WriteBuffer(this.gammabuffer, this.gamma);
46
47
  }
47
48
  let context = input.size / (this.embeddingSize * 4)
48
- const outputReduce = await this.op.createBuffer(4 * context);
49
- const output = await this.op.createBuffer(input.size);
50
- const bindGroup = await this.op.createBindGroup(this.reductionShader, 0, [input, outputReduce])
49
+ if (!this.rms) this.rms = await this.op.createBuffer(4 * context);
50
+ if (this.rms.size !== 4 * context * this.embeddingSize) {
51
+ this.rms.destroy()
52
+ this.rms = await this.op.createBuffer(4 * context);
53
+ }
54
+ if (!this.output) this.output = await this.op.ManageBuffer(input.size);
55
+ if (this.output.size !== 4 * context || this.output.isDestroyed()) {
56
+ this.output.destroy()
57
+ this.output = await this.op.ManageBuffer(input.size)
58
+ }
59
+ const bindGroup = await this.op.createBindGroup(this.reductionShader, 0, [input.mainBuffer, this.rms])
51
60
  const encoder = await this.op.CreateEncoder()
52
61
  await this.op.RunPipline(encoder, this.reductionShader, bindGroup, context)
53
- const bindGroup1 = await this.op.createBindGroup(this.forwardShader, 0, [outputReduce, input, output, this.gammabuffer])
62
+ const bindGroup1 = await this.op.createBindGroup(this.forwardShader, 0, [this.rms, input.mainBuffer, this.output.mainBuffer, this.gammabuffer])
54
63
  await this.op.RunPipline(encoder, this.forwardShader, bindGroup1, Math.ceil((input.size / 4) / 64));
55
64
  await this.op.submitQueue(encoder);
56
- if (this.rms) this.rms.destroy()
57
- this.rms = outputReduce
58
- if (this.input) this.input.destroy()
59
- this.input = input;
60
- if (this.outputPre) this.outputPre.destroy()
61
- this.outputPre = output
62
- return output
65
+ return this.output
63
66
  }
64
67
  async backward(outputGradient, lr) {
65
- const output = await this.op.createBuffer(outputGradient.size);
66
- let params = await this.op.createBuffer(4 * 2)
67
- await this.op.WriteBuffer(params, new Float32Array([lr, 0]))
68
- const bindGroup = await this.op.createBindGroup(this.backwardShader, 0, [this.input, outputGradient, this.rms, this.gammabuffer, output]);
69
- const bindGroup2 = await this.op.createBindGroup(this.updateGamma, 0, [this.input, outputGradient, this.rms, this.gammabuffer, params]);
68
+ if(!this.gradOut) this.gradOut = await this.op.ManageBuffer(outputGradient.size);
69
+ if(this.gradOut.size !== outputGradient.size || this.gradOut.isDestroyed()){
70
+ this.gradOut.destroy()
71
+ this.gradOut = await this.op.ManageBuffer(outputGradient.size)
72
+ }
73
+ if(!this.params) this.params = await this.op.createBuffer(4 * 2)
74
+ await this.op.WriteBuffer(this.params, new Float32Array([lr, 0]))
75
+ const bindGroup = await this.op.createBindGroup(this.backwardShader, 0, [this.input.mainBuffer, outputGradient.mainBuffer, this.rms, this.gammabuffer, this.gradOut.mainBuffer]);
76
+ const bindGroup2 = await this.op.createBindGroup(this.updateGamma, 0, [this.input.mainBuffer, outputGradient.mainBuffer, this.rms, this.gammabuffer, this.params]);
70
77
  const encoder = await this.op.CreateEncoder()
71
78
  await this.op.RunPipline(encoder, this.backwardShader, bindGroup, Math.ceil((this.input.size) / (this.embeddingSize * 4)))
72
79
  await this.op.RunPipline(encoder, this.updateGamma, bindGroup2, Math.ceil(this.embeddingSize))
73
80
  await this.op.submitQueue(encoder)
74
- if (this.prevOut) this.prevOut.destroy()
75
- this.prevOut = outputGradient
76
- params.destroy()
77
- return output
81
+ return this.gradOut
78
82
  }
79
- async Save(){
83
+ async Save() {
80
84
  const read = await this.op.readBuffer(4 * this.embeddingSize, this.gammabuffer);
81
85
  SaveVector(this.configs.save.filename, read)
82
86
  }
@@ -1,5 +1,25 @@
1
- export class Relu{
2
- constructor(device : GPUAdapter, embeddingSize : number);
3
- async forward(input: GPUBuffer) : Promise<GPUBuffer>
4
- async backward(outGradinet: GPUBuffer) : Promise<GPUBuffer>
1
+ export class Relu {
2
+ constructor(device: GPUAdapter, embeddingSize: number);
3
+ async forward(input: {
4
+ read: function(): Promise<Float32Array>,
5
+ mainBuffer: GPUBuffer,
6
+ isDestroyed: function(): Boolean,
7
+ destroy: function(): void
8
+ }): Promise<{
9
+ read: function(): Promise<Float32Array>,
10
+ mainBuffer: GPUBuffer,
11
+ isDestroyed: function(): Boolean,
12
+ destroy: function(): void
13
+ }>
14
+ async backward(outGradinet: {
15
+ read: function(): Promise<Float32Array>,
16
+ mainBuffer: GPUBuffer,
17
+ isDestroyed: function(): Boolean,
18
+ destroy: function(): void
19
+ }): Promise<{
20
+ read: function(): Promise<Float32Array>,
21
+ mainBuffer: GPUBuffer,
22
+ isDestroyed: function(): Boolean,
23
+ destroy: function(): void
24
+ }>
5
25
  }
package/src/Relu/index.js CHANGED
@@ -17,12 +17,16 @@ export class Relu {
17
17
  }
18
18
  async forward(input) {
19
19
  const encoder = this.device.createCommandEncoder()
20
- const tokenCount = input.size / (this.embeddingSize * 4)
20
+ const tokenCount = input.mainBuffer.size / (this.embeddingSize * 4)
21
21
  if (!this.oldParam) {
22
22
  this.oldParam = new Uint32Array([0, 0, 0]);
23
23
  this.paramBuffer = await this.gpu.createUniFormBuffer(4 * 3);
24
24
  }
25
- const output = await this.gpu.createBuffer(input.size)
25
+ if (!this.output) this.output = await this.gpu.ManageBuffer(input.mainBuffer.size);
26
+ if (this.output.mainBuffer.size !== input.mainBuffer.size || this.output.isDestroyed()) {
27
+ this.output.destroy()
28
+ this.output = await this.gpu.ManageBuffer(input.mainBuffer.size);
29
+ }
26
30
  if (this.oldParam[1] !== tokenCount) {
27
31
  this.oldParam = new Uint32Array([this.embeddingSize, tokenCount, 0])
28
32
  await this.gpu.WriteBuffer(this.paramBuffer, this.oldParam)
@@ -33,7 +37,7 @@ export class Relu {
33
37
  {
34
38
  binding: 0,
35
39
  resource: {
36
- buffer: input
40
+ buffer: input.mainBuffer
37
41
  }
38
42
  },
39
43
  {
@@ -44,16 +48,15 @@ export class Relu {
44
48
  }, {
45
49
  binding: 2,
46
50
  resource: {
47
- buffer: output
51
+ buffer: this.output.mainBuffer
48
52
  }
49
53
  }
50
54
  ]
51
55
  })
52
56
  await this.gpu.RunPipline(encoder, this.forwardPipline, bind, Math.ceil((tokenCount * this.embeddingSize) / 256))
53
57
  this.device.queue.submit([encoder.finish()])
54
- if(this.input) this.input.destroy()
55
58
  this.input = input
56
- return output
59
+ return this.output
57
60
  }
58
61
  async backward(inputGradient) {
59
62
  const encoder = this.device.createCommandEncoder()
@@ -62,7 +65,11 @@ export class Relu {
62
65
  this.oldParam = new Uint32Array([0, 0, 0]);
63
66
  this.paramBuffer = await this.gpu.createUniFormBuffer(4 * 3);
64
67
  }
65
- const output = await this.gpu.createBuffer(inputGradient.size)
68
+ if(!this.gradOut) this.gradOut = await this.gpu.ManageBuffer(inputGradient.size);
69
+ if(this.gradOut.size !== inputGradient.size || this.gradOut.isDestroyed()){
70
+ this.gradOut.destroy();
71
+ this.gradOut = await this.gpu.ManageBuffer(inputGradient.size)
72
+ }
66
73
  if (this.oldParam[1] !== tokenCount) {
67
74
  this.oldParam = new Uint32Array([this.embeddingSize, tokenCount, 0])
68
75
  await this.gpu.WriteBuffer(this.paramBuffer, this.oldParam)
@@ -73,7 +80,7 @@ export class Relu {
73
80
  {
74
81
  binding: 0,
75
82
  resource: {
76
- buffer: this.input
83
+ buffer: this.input.mainBuffer
77
84
  }
78
85
  },
79
86
  {
@@ -84,20 +91,18 @@ export class Relu {
84
91
  }, {
85
92
  binding: 2,
86
93
  resource: {
87
- buffer: output
94
+ buffer: this.gradOut.mainBuffer
88
95
  }
89
96
  }, {
90
97
  binding: 3,
91
98
  resource: {
92
- buffer: inputGradient
99
+ buffer: inputGradient.mainBuffer
93
100
  }
94
101
  }
95
102
  ]
96
103
  })
97
104
  await this.gpu.RunPipline(encoder, this.backwardPipline, bind, Math.ceil((tokenCount * this.embeddingSize) / 256))
98
105
  await this.device.queue.submit([encoder.finish()])
99
- this.input.destroy()
100
- inputGradient.destroy()
101
- return output
106
+ return this.gradOut
102
107
  }
103
108
  }
@@ -1,9 +1,14 @@
1
- export class SelfAttention{
2
- constructor(device : GPUAdapter,embeddingSize: number, configs : {
1
+ export class SelfAttention {
2
+ constructor(device: GPUAdapter, embeddingSize: number, configs: {
3
3
  dirname: string
4
4
  })
5
- async forward(vec : GPUBuffer) : Promise<GPUBuffer>
6
- async backward(dO : GPUBuffer, lr : number) : Promise<GPUBuffer>
7
- async ClearInputCache() : Promise<void>
8
- async Save() : Promise<void>
5
+ async forward(vec: GPUBuffer): Promise<{
6
+ read: function(): Promise<Float32Array>,
7
+ mainBuffer: GPUBuffer,
8
+ isDestroyed: function(): Boolean,
9
+ destroy: function(): void
10
+ }>
11
+ async backward(dO: GPUBuffer, lr: number): Promise<GPUBuffer>
12
+ async ClearInputCache(): Promise<void>
13
+ async Save(): Promise<void>
9
14
  }
@@ -39,82 +39,102 @@ export class SelfAttention {
39
39
  this.sumShader = this.gpu.getShaderPipline("./src/shaders/attentionShader/sumGradient.wgsl")
40
40
  }
41
41
  async forward(vec) {
42
- if (this.input) await this.input.destroy()
43
- this.input = vec;
44
- const tokenCount = vec.size / (this.embeddingSize * 4)
42
+ this.input = vec.mainBuffer;
43
+ const tokenCount = vec.mainBuffer.size / (this.embeddingSize * 4)
45
44
  if (!this.asParams) this.asParams = await this.gpu.createUniFormBuffer(4 * 3);
46
45
  if (!this.softmaxParams) this.softmaxParams = await this.gpu.createUniFormBuffer(4 * 3);
47
46
  const encoder = await this.gpu.CreateEncoder()
48
- const scroes = await this.gpu.createBuffer(tokenCount * tokenCount * 4)
47
+ if (!this.scroes) {
48
+ this.scroes = await this.gpu.createBuffer(tokenCount * tokenCount * 4)
49
+ }
50
+ if (this.scroes.size !== tokenCount * tokenCount * 4) {
51
+ this.scroes.destroy()
52
+ this.scroes = await this.gpu.createBuffer(tokenCount * tokenCount * 4)
53
+ }
49
54
  await this.gpu.WriteBuffer(this.asParams, new Uint32Array([tokenCount, this.embeddingSize, 0]))
50
55
  await this.gpu.WriteBuffer(this.softmaxParams, new Uint32Array([tokenCount, tokenCount, 0]))
51
- if (this.query) this.query.destroy()
52
- if (this.key) this.key.destroy()
53
- if (this.value) this.value.destroy()
54
56
  this.query = await this.q.forward(vec)
55
57
  this.key = await this.k.forward(vec)
56
58
  this.value = await this.v.forward(vec)
57
- const bindAttention = await this.gpu.createBindGroup(this.attentionscoresShader, 0, [this.query, this.key, scroes, this.asParams])
59
+ const bindAttention = await this.gpu.createBindGroup(this.attentionscoresShader, 0, [this.query.mainBuffer, this.key.mainBuffer, this.scroes, this.asParams])
58
60
  await this.gpu.RunPipline(encoder, this.attentionscoresShader, bindAttention, Math.ceil(tokenCount / 16), Math.ceil(tokenCount / 16))
59
61
  if (this.weights) this.weights.destroy()
60
62
  this.weights = await this.gpu.createBuffer(tokenCount * tokenCount * 4)
61
- const bindSF = await this.gpu.createBindGroup(this.softmaxForward, 0, [scroes, this.weights, this.softmaxParams]);
63
+ const bindSF = await this.gpu.createBindGroup(this.softmaxForward, 0, [this.scroes, this.weights, this.softmaxParams]);
62
64
  await this.gpu.RunPipline(encoder, this.softmaxForward, bindSF, tokenCount)
63
- const finalOutput = await this.gpu.createBuffer(tokenCount * this.embeddingSize * 4)
64
- const outputBind = await this.gpu.createBindGroup(this.outputForward, 0, [this.weights, this.value, finalOutput, this.asParams]);
65
+ if (!this.finalOutput) {
66
+ this.finalOutput = await this.gpu.ManageBuffer(tokenCount * this.embeddingSize * 4)
67
+ }
68
+ if (this.finalOutput.mainBuffer.size !== tokenCount * this.embeddingSize * 4 || this.finalOutput.isDestroyed()) {
69
+ this.finalOutput = await this.gpu.ManageBuffer(tokenCount * this.embeddingSize * 4)
70
+ }
71
+ const outputBind = await this.gpu.createBindGroup(this.outputForward, 0, [this.weights, this.value.mainBuffer, this.finalOutput.mainBuffer, this.asParams]);
65
72
  await this.gpu.RunPipline(encoder, this.outputForward, outputBind, Math.ceil((tokenCount * this.embeddingSize) / 256))
66
73
  await this.gpu.submitQueue(encoder)
67
- scroes.destroy()
68
- return finalOutput
74
+ return this.finalOutput
69
75
  }
70
76
  async backward(dO, lr) {
71
77
  const tokenCount = dO.size / (this.embeddingSize * 4);
72
78
  const encoder = await this.gpu.CreateEncoder();
73
- const dV = await this.gpu.createBuffer(dO.size);
74
- const DvBind = await this.gpu.createBindGroup(this.dVShader, 0, [this.weights, dO, dV, this.asParams]);
79
+ if (!this.dV) this.dV = await this.gpu.createBuffer(dO.size);
80
+ if (!this.dA) this.dA = await this.gpu.createBuffer(tokenCount * tokenCount * 4);
81
+ if (!this.dS) this.dS = await this.gpu.createBuffer(tokenCount * tokenCount * 4);
82
+ if (!this.dQ) this.dQ = await this.gpu.createBuffer(tokenCount * this.embeddingSize * 4);
83
+ if (!this.dK) this.dK = await this.gpu.createBuffer(this.embeddingSize * tokenCount * 4)
84
+ if (this.dV.size !== dO.size) {
85
+ this.dV.destroy()
86
+ this.dV = await this.gpu.createBuffer(dO.size);
87
+ }
88
+ if (this.dA.size !== tokenCount * tokenCount * 4) {
89
+ this.dA.destroy()
90
+ this.dA = await this.gpu.createBuffer(tokenCount * tokenCount * 4);
91
+ }
92
+ if (this.dS.size !== tokenCount * tokenCount * 4) {
93
+ this.dS.destroy()
94
+ this.dS = await this.gpu.createBuffer(tokenCount * tokenCount * 4);
95
+ }
96
+ if (this.dQ.size !== tokenCount * this.embeddingSize * 4) {
97
+ this.dQ.destroy()
98
+ this.dQ = await this.gpu.createBuffer(tokenCount * this.embeddingSize * 4);
99
+ }
100
+ if (this.dK.size !== tokenCount * this.embeddingSize * 4) {
101
+ this.dK.destroy()
102
+ this.dK = await this.gpu.createBuffer(tokenCount * this.embeddingSize * 4);
103
+ }
104
+ const DvBind = await this.gpu.createBindGroup(this.dVShader, 0, [this.weights, dO.mainBuffer, this.dV, this.asParams]);
75
105
  await this.gpu.RunPipline(encoder, this.dVShader, DvBind, Math.ceil(tokenCount / 16), Math.ceil(this.embeddingSize / 16));
76
- const dA = await this.gpu.createBuffer(tokenCount * tokenCount * 4)
77
- const DaBind = await this.gpu.createBindGroup(this.dAshader, 0, [dO, this.value, dA, this.asParams]);
106
+ const DaBind = await this.gpu.createBindGroup(this.dAshader, 0, [dO.mainBuffer, this.value.mainBuffer, this.dA, this.asParams]);
78
107
  await this.gpu.RunPipline(encoder, this.dAshader, DaBind, Math.ceil(tokenCount / 16), Math.ceil(tokenCount / 16))
79
- const dS = await this.gpu.createBuffer(tokenCount * tokenCount * 4);
80
- const dSBind = await this.gpu.createBindGroup(this.softmaxBackward, 0, [this.weights, dA, dS, this.asParams])
108
+ const dSBind = await this.gpu.createBindGroup(this.softmaxBackward, 0, [this.weights, this.dA, this.dS, this.asParams])
81
109
  await this.gpu.RunPipline(encoder, this.softmaxBackward, dSBind, Math.ceil((tokenCount * tokenCount) / 256))
82
- const dQ = await this.gpu.createBuffer(tokenCount * this.embeddingSize * 4);
83
- const dQbind = await this.gpu.createBindGroup(this.dQshader, 0, [dS, this.key, dQ, this.asParams]);
110
+ const dQbind = await this.gpu.createBindGroup(this.dQshader, 0, [this.dS, this.key.mainBuffer, this.dQ, this.asParams]);
84
111
  await this.gpu.RunPipline(encoder, this.dQshader, dQbind, Math.ceil(tokenCount / 16), Math.ceil(this.embeddingSize / 16))
85
- const dK = await this.gpu.createBuffer(this.embeddingSize * tokenCount * 4)
86
- const dKbind = await this.gpu.createBindGroup(this.dKShader, 0, [dS, this.query, dK, this.asParams]);
112
+ const dKbind = await this.gpu.createBindGroup(this.dKShader, 0, [this.dS, this.query.mainBuffer, this.dK, this.asParams]);
87
113
  await this.gpu.RunPipline(encoder, this.dKShader, dKbind, Math.ceil(tokenCount / 16), Math.ceil(this.embeddingSize / 16))
88
114
  await this.gpu.submitQueue(encoder);
89
- const dq = await this.q.backward(dQ, lr)
90
- const dk = await this.k.backward(dK, lr)
91
- const dv = await this.v.backward(dV, lr)
92
- const output = await this.gpu.createBuffer(this.embeddingSize * tokenCount * 4);
115
+ const dq = await this.q.backward({ mainBuffer: this.dQ, size: this.dQ.size}, lr)
116
+ const dk = await this.k.backward({ mainBuffer: this.dK, size: this.dK.size}, lr)
117
+ const dv = await this.v.backward({ mainBuffer: this.dV, size: this.dV.size}, lr)
118
+ if(!this.gradOut) this.gradOut = await this.gpu.ManageBuffer(tokenCount * this.embeddingSize * 4)
119
+ if(this.gradOut.size !== tokenCount * 4 * this.embeddingSize || this.gradOut.isDestroyed()){
120
+ this.gradOut.destroy()
121
+ this.gradOut = this.gpu.ManageBuffer(tokenCount * 4 * this.embeddingSize)
122
+ }
93
123
  const encode = this.gpu.CreateEncoder()
94
- const outputBind = await this.gpu.createBindGroup(this.sumShader, 0 , [dq, dk, dv, output, this.asParams]);
124
+ const outputBind = await this.gpu.createBindGroup(this.sumShader, 0, [dq.mainBuffer, dk.mainBuffer, dv.mainBuffer, this.gradOut.mainBuffer, this.asParams]);
95
125
  await this.gpu.RunPipline(encode, this.sumShader, outputBind, Math.ceil((tokenCount * this.embeddingSize / 256)));
96
126
  await this.gpu.submitQueue(encode)
97
- dS.destroy()
98
- dA.destroy()
99
- dq.destroy()
100
- dk.destroy()
101
- dv.destroy()
102
- dK.destroy()
103
- dQ.destroy()
104
- dV.destroy()
105
- if(this.prevdO) await this.prevdO.destroy()
106
- this.prevdO = dO
107
- return output
108
-
127
+ return this.gradOut
128
+
109
129
  }
110
- async ClearInputCache(){
111
- await this.q.ClearInputCache()
112
- await this.k.ClearInputCache()
113
- await this.v.ClearInputCache()
130
+ async ClearInputCache() {
131
+ await this.q.ClearInputCache()
132
+ await this.k.ClearInputCache()
133
+ await this.v.ClearInputCache()
114
134
  }
115
- async Save(){
116
- await this.q.Save()
117
- await this.k.Save()
118
- await this.v.Save()
135
+ async Save() {
136
+ await this.q.Save()
137
+ await this.k.Save()
138
+ await this.v.Save()
119
139
  }
120
140
  }
@@ -1,6 +1,26 @@
1
- export class Softmax{
1
+ export class Softmax {
2
2
  constructor(device: GPUAdapter, embeddingSize: number, vocabSize: number);
3
- async forward(logit: GPUBuffer, isCpuReadBack) : Promise<Float32Array | GPUBuffer>;
4
- async backward(probs : GPUBuffer, target : number[]) : Promise<GPUBuffer>
5
- async crossEntropy(probs: GPUBuffer, target: number[]) : Promise<{loss: Float32Array, acc: Float32Array}>
3
+ async forward(logit: {
4
+ read: function(): Promise<Float32Array>,
5
+ mainBuffer: GPUBuffer,
6
+ isDestroyed: function(): Boolean,
7
+ destroy: function(): void
8
+ }, isCpuReadBack): Promise<{
9
+ read: function(): Promise<Float32Array>,
10
+ mainBuffer: GPUBuffer,
11
+ isDestroyed: function(): Boolean,
12
+ destroy: function(): void
13
+ }>;
14
+ async backward(probs: {
15
+ read: function(): Promise<Float32Array>,
16
+ mainBuffer: GPUBuffer,
17
+ isDestroyed: function(): Boolean,
18
+ destroy: function(): void
19
+ }, target: number[]): Promise<{
20
+ read: function(): Promise<Float32Array>,
21
+ mainBuffer: GPUBuffer,
22
+ isDestroyed: function(): Boolean,
23
+ destroy: function(): void
24
+ }>
25
+ async crossEntropy(probs: GPUBuffer, target: number[]): Promise<{ loss: Float32Array, acc: Float32Array }>
6
26
  }
@@ -33,20 +33,24 @@ export class Softmax {
33
33
  }
34
34
 
35
35
  if (this.oldParam[1] !== tokenCount) { await this.gpu.WriteBuffer(this.paramsForward, new Uint32Array([this.vocabSize, tokenCount, 0])); this.oldParam = new Uint32Array([this.vocabSize, tokenCount, 0]); }
36
- const output = await this.gpu.createBuffer(logits.size);
36
+ if (!this.output) this.output = await this.gpu.ManageBuffer(logits.size);
37
+ if (this.output.size !== 4 * tokenCount * this.vocabSize || this.output.isDestroyed()) {
38
+ this.output.destroy()
39
+ this.output = await this.gpu.ManageBuffer(logits.size)
40
+ }
37
41
  const bind = await this.device.createBindGroup({
38
42
  layout: await this.forwardPipline.getBindGroupLayout(0),
39
43
  entries: [
40
44
  {
41
45
  binding: 0,
42
46
  resource: {
43
- buffer: logits
47
+ buffer: logits.mainBuffer
44
48
  }
45
49
  },
46
50
  {
47
51
  binding: 1,
48
52
  resource: {
49
- buffer: output
53
+ buffer: this.output.mainBuffer
50
54
  }
51
55
  }, {
52
56
  binding: 2,
@@ -61,12 +65,7 @@ export class Softmax {
61
65
  await this.device.queue.submit([encoder.finish()])
62
66
  logits.destroy()
63
67
  }
64
- if (cpuReadBack) {
65
- const outputCPU = await this.gpu.readBuffer(output.size, output);
66
- logits.destroy()
67
- return outputCPU
68
- }
69
- return output
68
+ return this.output
70
69
  }
71
70
  async backward(probs, target) {
72
71
  const encoder = this.device.createCommandEncoder()
@@ -81,27 +80,24 @@ export class Softmax {
81
80
  await this.gpu.WriteBuffer(this.paramsForward, new Uint32Array([this.vocabSize, tokenCount, 0]));
82
81
  this.oldParam = new Uint32Array([this.vocabSize, tokenCount, 0]);
83
82
  }
84
- const targetBuffer = await this.gpu.createBuffer(target.length * Float32Array.BYTES_PER_ELEMENT)
85
- await this.gpu.WriteBuffer(targetBuffer, new Float32Array(target))
86
- const output = await this.gpu.createBuffer(probs.size)
83
+ if (!this.targetBuffer) this.targetBuffer = await this.gpu.createBuffer(target.length * Float32Array.BYTES_PER_ELEMENT);
84
+ if (this.targetBuffer.size !== target.length * 4) {
85
+ this.targetBuffer.destroy()
86
+ this.targetBuffer = await this.gpu.createBuffer(target.length * Float32Array.BYTES_PER_ELEMENT)
87
+ }
88
+ await this.gpu.WriteBuffer(this.targetBuffer, new Float32Array(target))
87
89
  const bind = await this.device.createBindGroup({
88
90
  layout: await this.backwardPipline.getBindGroupLayout(0),
89
91
  entries: [
90
92
  {
91
93
  binding: 0,
92
94
  resource: {
93
- buffer: probs
94
- }
95
- },
96
- {
97
- binding: 1,
98
- resource: {
99
- buffer: output
95
+ buffer: probs.mainBuffer
100
96
  }
101
97
  }, {
102
98
  binding: 2,
103
99
  resource: {
104
- buffer: targetBuffer
100
+ buffer: this.targetBuffer
105
101
  }
106
102
  }, {
107
103
  binding: 3,
@@ -113,9 +109,7 @@ export class Softmax {
113
109
  })
114
110
  await this.gpu.RunPipline(encoder, this.backwardPipline, bind, tokenCount)
115
111
  this.device.queue.submit([encoder.finish()])
116
- probs.destroy()
117
- targetBuffer.destroy()
118
- return output
112
+ return probs
119
113
  }
120
114
  async crossEntropy(probs, target) {
121
115
  const encoder = this.device.createCommandEncoder()
@@ -131,7 +125,7 @@ export class Softmax {
131
125
  {
132
126
  binding: 0,
133
127
  resource: {
134
- buffer: probs
128
+ buffer: probs.mainBuffer
135
129
  }
136
130
  },
137
131
  {
@@ -169,7 +163,7 @@ export class Softmax {
169
163
  {
170
164
  binding: 1,
171
165
  resource: {
172
- buffer: probs
166
+ buffer: probs.mainBuffer
173
167
  }
174
168
  }, {
175
169
  binding: 3,
@@ -192,6 +186,7 @@ export class Softmax {
192
186
  const lossCpu = await this.gpu.readBuffer(outputLoss.size, outputLoss)
193
187
  const accCPU = await this.gpu.readBuffer(acc.size, acc)
194
188
  acc.destroy()
189
+ outputLoss.destroy()
195
190
  return { loss: lossCpu[0], acc: accCPU[0] }
196
191
  }
197
192
 
@@ -43,32 +43,18 @@ export class TransformerBlock {
43
43
  async forward(input) {
44
44
  const count = input.size / 4;
45
45
  const norm1 = await this.rmsnorm.forward(input);
46
- const att = await this.attention.forward(norm1);
47
- const h = await this.gpu.add(input, att, count);
48
- const norm2 = await this.rmsnorm2.forward(h);
49
- const f = await this.ffn.forward(norm2);
50
- const y = await this.gpu.add(h, f, count);
51
- norm1.destroy();
52
- att.destroy();
53
- f.destroy();
54
- return y;
46
+ const att = await this.attention.forward(norm1)
47
+ const f = await this.ffn.forward(att)
48
+ const norm2 = await this.rmsnorm2.forward(f)
49
+ return norm2;
55
50
  }
56
51
 
57
52
  async backward(outGradient, lr) {
58
- const count = outGradient.size / 4;
59
- const dNorm2 = await this.ffn.backward(outGradient, lr);
60
- const dHFromFFN = await this.rmsnorm2.backward(dNorm2 , lr);
61
- const dH = await this.gpu.add(outGradient, dHFromFFN, count);
62
- const dNorm1 = await this.attention.backward(dH, lr);
63
- const dInputFromAttention = await this.rmsnorm.backward(dNorm1, lr);
64
- const dInput = await this.gpu.add(dH, dInputFromAttention, count);
65
- dNorm2.destroy();
66
- dHFromFFN.destroy();
67
- dH.destroy();
68
- dNorm1.destroy();
69
- dInputFromAttention.destroy();
70
- dInputFromAttention.destroy();
71
- return dInput;
53
+ const dNorm2 = await this.rmsnorm2.backward(outGradient, lr)
54
+ const dAtt = await this.ffn.backward(dNorm2, lr);
55
+ const dFF = await this.attention.backward(dAtt, lr)
56
+ const dNorm = await this.rmsnorm.backward(dFF, lr)
57
+ return dNorm;
72
58
  }
73
59
 
74
60
  async ClearInputCache() {
@@ -44,14 +44,14 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
44
44
  let dW = inputValue * gradient;
45
45
  dWeights += dW;
46
46
  }
47
- let vClap = weight[index] - params.lr * clamp(dWeights, -20.0, 20.0);
47
+ let vClap = weight[index] - params.lr * clamp(dWeights, -8.0, 8.0);
48
48
  weight[index] = vClap;
49
49
  if (inputIndex == 0u) {
50
50
  var dBias = 0.0;
51
51
  for (var token = 0u; token < u32(params.tokenCount); token++) {
52
52
  dBias += outGradient[token * u32(params.vocabSize) + outputIndex];
53
53
  }
54
- bias[outputIndex] = bias[outputIndex] - params.lr * clamp(dBias, -20.0, 20.0);
54
+ bias[outputIndex] = bias[outputIndex] - params.lr * clamp(dBias, -8.0, 8.0);
55
55
 
56
56
  }
57
57
  }
@@ -3,11 +3,9 @@ var <storage, read> posVec: array<f32>;
3
3
 
4
4
  @group(0) @binding(1)
5
5
 
6
- var <storage, read> vecs : array<f32>;
6
+ var <storage, read_write> vecs : array<f32>;
7
7
 
8
- @group(0) @binding(2)
9
8
 
10
- var <storage, read_write> output: array<f32>;
11
9
 
12
10
 
13
11
  @compute @workgroup_size(64)
@@ -17,5 +15,5 @@ fn main(@builtin(global_invocation_id) id : vec3<u32>){
17
15
  if(x >= arrayLength(&vecs)){
18
16
  return;
19
17
  }
20
- output[x] = vecs[x] + posVec[x];
18
+ vecs[x] = vecs[x] + posVec[x];
21
19
  }
@@ -32,6 +32,6 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
32
32
  output[index] = grad;
33
33
  }
34
34
  else {
35
- output[index] = 0;
35
+ output[index] = grad * 0.02;
36
36
  }
37
37
  }
@@ -28,6 +28,6 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
28
28
  output[index] = x;
29
29
  }
30
30
  else {
31
- output[index] = 0;
31
+ output[index] = x * 0.02;
32
32
  }
33
33
  }
@@ -5,11 +5,8 @@ struct Params {
5
5
 
6
6
  @group(0) @binding(0)
7
7
 
8
- var<storage, read> probs: array<f32>;
8
+ var<storage, read_write> probs: array<f32>;
9
9
 
10
- @group(0) @binding(1)
11
-
12
- var<storage, read_write> output: array<f32>;
13
10
 
14
11
  @group(0) @binding(2)
15
12
 
@@ -32,8 +29,8 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
32
29
  return;
33
30
  }
34
31
  var targetIndex = targetToken[token];
35
- output[index] = probs[index];
32
+ probs[index] = probs[index];
36
33
  if(vocabIndex == u32(targetIndex)){
37
- output[index] -= 1;
34
+ probs[index] -= 1;
38
35
  }
39
36
  }
@@ -1,15 +0,0 @@
1
- export class Model {
2
- async forward(input: Number[], buffer: boolean): Promise<Float32Array | GPUBuffer>;
3
- async backward(output: GPUBuffer, target: number[], lr: number): Promise<{ acc: number, loss: number }>
4
- TrainTokenizer(dataset: string): void;
5
- constructor(device :GPUAdapter, embeddingSize: number, configs: {
6
- tokenizerName: string
7
- blockSize: number,
8
- dirname: string,
9
- contextSize: number,
10
- gpuName: string
11
-
12
- })
13
- async Save() : Promise<void>
14
- async CreateContext()
15
- }
@@ -1,95 +0,0 @@
1
- import { Embedding, Linear, Softmax, TransformerBlock, Tokenizer, PositionEmbedding, RMSNorm } from '../../index.js'
2
- import { join } from 'path'
3
- import fs from 'fs'
4
- import { OperationManager } from '../OperationManager.js'
5
- export class Model {
6
- embedding;
7
- posEmbedding;
8
- linear;
9
- softmax;
10
- blocks = [];
11
- blockSize;
12
- dimSize;
13
- tokenizer;
14
- device;
15
- configs;
16
- tokenizerName;
17
- op;
18
- tokens;
19
- rmsnorm
20
- constructor(device, embeddingSize = 64, configs) {
21
- this.device = device;
22
- this.dimSize = embeddingSize;
23
- this.blockSize = configs.blockSize;
24
- this.configs = configs
25
- this.tokenizer = new Tokenizer(configs.tokenizerName)
26
- this.tokenizerName = configs.tokenizerName
27
- this.op = new OperationManager(device)
28
- }
29
- async CreateContext() {
30
- this.embedding = new Embedding(this.device, this.dimSize, this.tokenizer.vocabSize, {
31
- save: {
32
- filename: join(this.configs.dirname, "./vec.bin")
33
- }
34
- })
35
- this.linear = new Linear(this.device, this.dimSize, this.tokenizer.vocabSize, {
36
- save: {
37
- filename: [join(this.configs.dirname, "weights.bin"), join(this.configs.dirname, "bias.bin")]
38
- }
39
- })
40
- this.softmax = new Softmax(this.device, this.dimSize, this.tokenizer.vocabSize);
41
- for (let a = 0; a < this.blockSize; a++) {
42
- console.log(`Load the Transfomer Block ${a + 1}...`)
43
- if (!fs.existsSync(join(this.configs.dirname, `block-${a}`))) fs.mkdirSync(join(this.configs.dirname, `block-${a}`));
44
- this.blocks[a] = new TransformerBlock(this.device, this.dimSize, {
45
- dirname: join(this.configs.dirname, `block-${a}`)
46
- })
47
- }
48
- this.posEmbedding = new PositionEmbedding(this.device, this.dimSize, this.configs.contextSize, {
49
- save: {
50
- filename: join(this.configs.dirname, "posVec.bin")
51
- }
52
- })
53
- }
54
- TrainTokenizer(text = "", mergeSize = 5) {
55
- this.tokenizer.trainTokenizer(text, mergeSize, this.tokenizerName)
56
- }
57
- async ClearInputCache() {
58
- await this.linear.ClearInputCache()
59
- for (let a = 0; a < this.blockSize; a++) {
60
- await this.blocks[a].ClearInputCache()
61
- }
62
- }
63
- async forward(input, readBack) {
64
- if (this.configs.contextSize < input.length) throw new Error("The Input is larger then contextSize")
65
- this.tokens = input;
66
- await this.ClearInputCache()
67
- let vec = await this.embedding.forward(input)
68
- vec = await this.posEmbedding.forward(vec)
69
- for (let a = 0; a < this.blockSize; a++) {
70
- vec = await this.blocks[a].forward(vec)
71
- }
72
- let logits = await this.linear.forward(vec);
73
- let probs = await this.softmax.forward(logits, readBack)
74
- return probs
75
- }
76
- async backward(outputGradient, target, lr = 0.02) {
77
- const loss = await this.softmax.crossEntropy(outputGradient, target)
78
- const dLogits = await this.softmax.backward(outputGradient, target);
79
- let DInput = await this.linear.backward(dLogits, lr);
80
- for (let a = this.blockSize - 1; a >= 0; a--) {
81
- DInput = await this.blocks[a].backward(DInput, lr);
82
- }
83
- this.embedding.backward(this.tokens, DInput, lr);
84
- this.posEmbedding.backward(DInput, lr)
85
- return loss
86
- }
87
- async Save() {
88
- await this.embedding.Save()
89
- await this.linear.Save()
90
- for (let a = this.blockSize - 1; a >= 0; a--) {
91
- await this.blocks[a].Save();
92
- }
93
- await this.posEmbedding.Save()
94
- }
95
- }