@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.
- package/index.js +20 -0
- package/package.json +29 -6
- package/readme.md +959 -0
- package/src/Embedding/index.d.ts +21 -0
- package/src/Embedding/index.js +141 -0
- package/src/FFN/index.d.ts +23 -0
- package/src/FFN/index.js +45 -0
- package/src/Linear/index.d.ts +31 -0
- package/src/Linear/index.js +198 -0
- package/src/OperationManager.js +169 -0
- package/src/PositionEmbedding/index.d.ts +30 -0
- package/src/PositionEmbedding/index.js +65 -0
- package/src/RMSNorm/index.d.ts +30 -0
- package/src/RMSNorm/index.js +96 -0
- package/src/Relu/index.d.ts +25 -0
- package/src/Relu/index.js +110 -0
- package/src/SelfAttention/index.d.ts +28 -0
- package/src/SelfAttention/index.js +138 -0
- package/src/Softmax/index.d.ts +26 -0
- package/src/Softmax/index.js +225 -0
- package/src/Tokenizer/index.d.ts +12 -0
- package/src/Tokenizer/index.js +164 -0
- package/src/Tokenizer/vocabs.json +19618 -0
- package/src/TransformerBlock/index.d.ts +28 -0
- package/src/TransformerBlock/index.js +78 -0
- package/src/getVec.js +30 -0
- package/src/gpu.js +0 -0
- package/src/residualConnection/index.js +32 -0
- package/src/shaders/CalculateAcc.wgsl +50 -0
- package/src/shaders/CalculateLoss.wgsl +30 -0
- package/src/shaders/ComputeDInput.wgsl +32 -0
- package/src/shaders/EB.wgsl +33 -0
- package/src/shaders/EF.wgsl +25 -0
- package/src/shaders/LB.wgsl +75 -0
- package/src/shaders/LF.wgsl +60 -0
- package/src/shaders/Norm/rmsBackward.wgsl +65 -0
- package/src/shaders/Norm/rmsForward.wgsl +30 -0
- package/src/shaders/Norm/sumSquare.wgsl +38 -0
- package/src/shaders/Norm/updateGamma.wgsl +52 -0
- package/src/shaders/PB.wgsl +25 -0
- package/src/shaders/PF.wgsl +19 -0
- package/src/shaders/RB.wgsl +37 -0
- package/src/shaders/RF.wgsl +33 -0
- package/src/shaders/ReductionFunction.wgsl +28 -0
- package/src/shaders/SB.wgsl +36 -0
- package/src/shaders/SF.wgsl +75 -0
- package/src/shaders/SoftmaxBackward.wgsl +31 -0
- package/src/shaders/add.wgsl +30 -0
- package/src/shaders/attentionShader/CompueFinalForwardOutput.wgsl +29 -0
- package/src/shaders/attentionShader/ComputeDA.wgsl +30 -0
- package/src/shaders/attentionShader/ComputeDV.wgsl +37 -0
- package/src/shaders/attentionShader/ComputeK.wgsl +30 -0
- package/src/shaders/attentionShader/ComputedQ.wgsl +31 -0
- package/src/shaders/attentionShader/attentionSocres.wgsl +40 -0
- package/src/shaders/attentionShader/sumGradient.wgsl +24 -0
- package/src/shaders/calculateTotal.wgsl +26 -0
- package/README.md +0 -3
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { OperationManager } from "../OperationManager.js"
|
|
2
|
+
import { getVector, SaveVector } from "../getVec.js"
|
|
3
|
+
function GenerateVectors(embeddingSize, contextSize) {
|
|
4
|
+
const vec = new Float32Array(embeddingSize * contextSize).map(() => (Math.random() * 2 - 1) * 0.02)
|
|
5
|
+
return vec
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class PositionEmbedding {
|
|
9
|
+
vectors;
|
|
10
|
+
vecBuffer;
|
|
11
|
+
gpu;
|
|
12
|
+
embeddingSize;
|
|
13
|
+
contextSize;
|
|
14
|
+
params;
|
|
15
|
+
forwardShader;
|
|
16
|
+
backwardShader;
|
|
17
|
+
configs;
|
|
18
|
+
constructor(device, embeddingSize, contextSize, configs) {
|
|
19
|
+
this.embeddingSize = embeddingSize;
|
|
20
|
+
const total = embeddingSize * contextSize;
|
|
21
|
+
this.configs = configs;
|
|
22
|
+
this.contextSize = contextSize;
|
|
23
|
+
if (configs && configs.save) {
|
|
24
|
+
const vec = getVector(configs.save.filename, total);
|
|
25
|
+
if (vec) {
|
|
26
|
+
this.vectors = vec;
|
|
27
|
+
|
|
28
|
+
} else {
|
|
29
|
+
this.vectors = GenerateVectors(embeddingSize, contextSize)
|
|
30
|
+
SaveVector(this.configs.save.filename, this.vectors)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
} else {
|
|
34
|
+
this.vectors = GenerateVectors(embeddingSize, contextSize)
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
this.gpu = new OperationManager(device)
|
|
38
|
+
this.forwardShader = this.gpu.getShaderPipline("./src/shaders/PF.wgsl")
|
|
39
|
+
this.backwardShader = this.gpu.getShaderPipline("./src/shaders/PB.wgsl")
|
|
40
|
+
}
|
|
41
|
+
async forward(input, encoderMain) {
|
|
42
|
+
const encoder = encoderMain ? encoderMain : this.gpu.CreateEncoder()
|
|
43
|
+
if (!this.params) this.params = await this.gpu.createUniFormBuffer(4 * 4)
|
|
44
|
+
if (!this.vecBuffer) {
|
|
45
|
+
this.vecBuffer = await this.gpu.createBuffer(Float32Array.BYTES_PER_ELEMENT * this.contextSize * this.embeddingSize);
|
|
46
|
+
await this.gpu.WriteBuffer(this.vecBuffer, this.vectors)
|
|
47
|
+
}
|
|
48
|
+
const size = Math.ceil((input.size / 4) / 64);
|
|
49
|
+
const bindGroup = await this.gpu.createBindGroup(this.forwardShader, 0, [this.vecBuffer, input.mainBuffer])
|
|
50
|
+
await this.gpu.RunPipline(encoder, this.forwardShader, bindGroup, size);
|
|
51
|
+
if(!encoderMain) await this.gpu.submitQueue(encoder);
|
|
52
|
+
return input
|
|
53
|
+
}
|
|
54
|
+
async backward(outputGradient, lr, encoderMain){
|
|
55
|
+
const encoder = encoderMain ? encoderMain : await this.gpu.CreateEncoder()
|
|
56
|
+
await this.gpu.WriteBuffer(this.params, new Float32Array([lr,0]))
|
|
57
|
+
const bindGroup = await this.gpu.createBindGroup(this.backwardShader, 0, [this.vecBuffer, outputGradient.mainBuffer, this.params])
|
|
58
|
+
await this.gpu.RunPipline(encoder, this.backwardShader, bindGroup, Math.ceil((outputGradient.size / 4) / 64))
|
|
59
|
+
if(!encoderMain) await this.gpu.submitQueue(encoder);
|
|
60
|
+
}
|
|
61
|
+
async Save() {
|
|
62
|
+
const vec = await this.gpu.readBuffer(Float32Array.BYTES_PER_ELEMENT * this.contextSize * this.embeddingSize, this.vecBuffer)
|
|
63
|
+
SaveVector(this.configs.save.filename, vec)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class RMSNorm {
|
|
2
|
+
constructor(device: GPUAdapter, embeddingSize: number, {
|
|
3
|
+
save: {
|
|
4
|
+
filename: string
|
|
5
|
+
}
|
|
6
|
+
});
|
|
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>
|
|
30
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { OperationManager } from '../OperationManager.js'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import { SaveVector, getVector } from '../getVec.js'
|
|
4
|
+
|
|
5
|
+
export class RMSNorm {
|
|
6
|
+
embeddingSize;
|
|
7
|
+
reductionShader;
|
|
8
|
+
forwardShader;
|
|
9
|
+
backwardShader;
|
|
10
|
+
op;
|
|
11
|
+
gamma;
|
|
12
|
+
gammabuffer;
|
|
13
|
+
configs;
|
|
14
|
+
constructor(device, embeddingSize, configs) {
|
|
15
|
+
this.configs = configs
|
|
16
|
+
this.op = new OperationManager(device);
|
|
17
|
+
this.embeddingSize = embeddingSize;
|
|
18
|
+
this.reductionShader = this.op.getShaderPipline("./src/shaders/Norm/sumSquare.wgsl", {
|
|
19
|
+
embeddingSize: embeddingSize,
|
|
20
|
+
})
|
|
21
|
+
this.forwardShader = this.op.getShaderPipline("./src/shaders/Norm/rmsForward.wgsl", {
|
|
22
|
+
embeddingSize: embeddingSize
|
|
23
|
+
})
|
|
24
|
+
this.backwardShader = this.op.getShaderPipline("./src/shaders/Norm/rmsBackward.wgsl", {
|
|
25
|
+
embeddingSize: embeddingSize
|
|
26
|
+
})
|
|
27
|
+
this.updateGamma = this.op.getShaderPipline("./src/shaders/Norm/updateGamma.wgsl", {
|
|
28
|
+
embeddingSize: embeddingSize
|
|
29
|
+
})
|
|
30
|
+
if (configs) {
|
|
31
|
+
const ga = getVector(configs.save.filename, embeddingSize);
|
|
32
|
+
if (!ga) {
|
|
33
|
+
this.gamma = new Float32Array(embeddingSize).fill(1);
|
|
34
|
+
SaveVector(configs.save.filename, this.gamma)
|
|
35
|
+
} else {
|
|
36
|
+
this.gamma = ga
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
this.gamma = new Float32Array(embeddingSize).fill(1)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async forward(input) {
|
|
43
|
+
this.input = input;
|
|
44
|
+
if (!this.gammabuffer) {
|
|
45
|
+
this.gammabuffer = await this.op.createBuffer(4 * this.embeddingSize);
|
|
46
|
+
await this.op.WriteBuffer(this.gammabuffer, this.gamma);
|
|
47
|
+
}
|
|
48
|
+
let context = input.size / (this.embeddingSize * 4)
|
|
49
|
+
if (!this.rms) this.rms = await this.op.createBuffer(4 * context);
|
|
50
|
+
if (this.rms.size !== 4 * context) {
|
|
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 * this.embeddingSize * context || this.output.isDestroyed() || this.output.size == 0) {
|
|
56
|
+
this.output.destroy()
|
|
57
|
+
this.output = await this.op.ManageBuffer(input.size)
|
|
58
|
+
}
|
|
59
|
+
await this.output.count()
|
|
60
|
+
const bindGroup = await this.op.createBindGroup(this.reductionShader, 0, [input.mainBuffer, this.rms])
|
|
61
|
+
const encoder = await this.op.CreateEncoder()
|
|
62
|
+
await this.op.RunPipline(encoder, this.reductionShader, bindGroup, context)
|
|
63
|
+
const bindGroup1 = await this.op.createBindGroup(this.forwardShader, 0, [this.rms, input.mainBuffer, this.output.mainBuffer, this.gammabuffer])
|
|
64
|
+
await this.op.RunPipline(encoder, this.forwardShader, bindGroup1, Math.ceil((input.size / 4) / 64));
|
|
65
|
+
await this.op.submitQueue(encoder);
|
|
66
|
+
return this.output
|
|
67
|
+
}
|
|
68
|
+
async backward(outputGradient, lr) {
|
|
69
|
+
if (!this.input || !this.input.mainBuffer || this.input.isDestroyed?.()) {
|
|
70
|
+
throw new Error("RMSNorm.backward: input buffer is gone");
|
|
71
|
+
}
|
|
72
|
+
if (!this.rms || this.rms.isDestroyed?.()) {
|
|
73
|
+
throw new Error("RMSNorm.backward: rms buffer is gone");
|
|
74
|
+
}
|
|
75
|
+
if (!this.gradOut) this.gradOut = await this.op.ManageBuffer(outputGradient.size);
|
|
76
|
+
if (this.gradOut.size !== outputGradient.size || this.gradOut.isDestroyed() || this.gradOut.size == 0) {
|
|
77
|
+
this.gradOut.destroy()
|
|
78
|
+
this.gradOut = await this.op.ManageBuffer(outputGradient.size)
|
|
79
|
+
}
|
|
80
|
+
await this.gradOut.count()
|
|
81
|
+
if (!this.params) this.params = await this.op.createBuffer(4 * 2)
|
|
82
|
+
await this.op.WriteBuffer(this.params, new Float32Array([lr, 0]))
|
|
83
|
+
const bindGroup = await this.op.createBindGroup(this.backwardShader, 0, [this.input.mainBuffer, outputGradient.mainBuffer, this.rms, this.gammabuffer, this.gradOut.mainBuffer]);
|
|
84
|
+
const bindGroup2 = await this.op.createBindGroup(this.updateGamma, 0, [this.input.mainBuffer, outputGradient.mainBuffer, this.rms, this.gammabuffer, this.params]);
|
|
85
|
+
const encoder = await this.op.CreateEncoder()
|
|
86
|
+
await this.op.RunPipline(encoder, this.backwardShader, bindGroup, Math.ceil((this.input.size) / (this.embeddingSize * 4)))
|
|
87
|
+
await this.op.RunPipline(encoder, this.updateGamma, bindGroup2, Math.ceil(this.embeddingSize / 64))
|
|
88
|
+
await this.op.submitQueue(encoder)
|
|
89
|
+
return this.gradOut
|
|
90
|
+
}
|
|
91
|
+
async Save() {
|
|
92
|
+
const read = await this.op.readBuffer(4 * this.embeddingSize, this.gammabuffer);
|
|
93
|
+
SaveVector(this.configs.save.filename, read)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
}>
|
|
25
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { OperationManager } from "../OperationManager.js";
|
|
2
|
+
|
|
3
|
+
export class Relu {
|
|
4
|
+
embeddingSize;
|
|
5
|
+
paramBuffer;
|
|
6
|
+
oldParam;
|
|
7
|
+
forwardPipline;
|
|
8
|
+
gpu;
|
|
9
|
+
backwardPipline;
|
|
10
|
+
input;
|
|
11
|
+
constructor(device, embeddingSize) {
|
|
12
|
+
this.embeddingSize = embeddingSize
|
|
13
|
+
this.gpu = new OperationManager(device);
|
|
14
|
+
this.device = device;
|
|
15
|
+
this.forwardPipline = this.gpu.getShaderPipline("./src/shaders/RF.wgsl")
|
|
16
|
+
this.backwardPipline = this.gpu.getShaderPipline("./src/shaders/RB.wgsl")
|
|
17
|
+
}
|
|
18
|
+
async forward(input, encoderMain) {
|
|
19
|
+
const encoder = encoderMain ? encoderMain : this.device.createCommandEncoder()
|
|
20
|
+
const tokenCount = input.mainBuffer.size / (this.embeddingSize * 4)
|
|
21
|
+
if (!this.oldParam) {
|
|
22
|
+
this.oldParam = new Uint32Array([0, 0, 0]);
|
|
23
|
+
this.paramBuffer = await this.gpu.createUniFormBuffer(4 * 3);
|
|
24
|
+
}
|
|
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() || this.output.size == 0) {
|
|
27
|
+
this.output.destroy()
|
|
28
|
+
this.output = await this.gpu.ManageBuffer(input.mainBuffer.size);
|
|
29
|
+
}
|
|
30
|
+
await this.output.count()
|
|
31
|
+
if (this.oldParam[1] !== tokenCount) {
|
|
32
|
+
this.oldParam = new Uint32Array([this.embeddingSize, tokenCount, 0])
|
|
33
|
+
await this.gpu.WriteBuffer(this.paramBuffer, this.oldParam)
|
|
34
|
+
}
|
|
35
|
+
const bind = await this.device.createBindGroup({
|
|
36
|
+
layout: await this.forwardPipline.getBindGroupLayout(0),
|
|
37
|
+
entries: [
|
|
38
|
+
{
|
|
39
|
+
binding: 0,
|
|
40
|
+
resource: {
|
|
41
|
+
buffer: input.mainBuffer
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
binding: 1,
|
|
46
|
+
resource: {
|
|
47
|
+
buffer: this.paramBuffer
|
|
48
|
+
}
|
|
49
|
+
}, {
|
|
50
|
+
binding: 2,
|
|
51
|
+
resource: {
|
|
52
|
+
buffer: this.output.mainBuffer
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
})
|
|
57
|
+
await this.gpu.RunPipline(encoder, this.forwardPipline, bind, Math.ceil((tokenCount * this.embeddingSize) / 256))
|
|
58
|
+
if(!encoderMain) this.device.queue.submit([encoder.finish()])
|
|
59
|
+
this.input = input
|
|
60
|
+
return this.output
|
|
61
|
+
}
|
|
62
|
+
async backward(inputGradient, encoderMain) {
|
|
63
|
+
const encoder = encoderMain ? encoderMain : this.device.createCommandEncoder()
|
|
64
|
+
const tokenCount = inputGradient.size / (this.embeddingSize * 4)
|
|
65
|
+
if (!this.oldParam) {
|
|
66
|
+
this.oldParam = new Uint32Array([0, 0, 0]);
|
|
67
|
+
this.paramBuffer = await this.gpu.createUniFormBuffer(4 * 3);
|
|
68
|
+
}
|
|
69
|
+
if(!this.gradOut) this.gradOut = await this.gpu.ManageBuffer(inputGradient.size);
|
|
70
|
+
if(this.gradOut.size !== inputGradient.size || this.gradOut.isDestroyed() || this.gradOut.size == 0){
|
|
71
|
+
this.gradOut.destroy();
|
|
72
|
+
this.gradOut = await this.gpu.ManageBuffer(inputGradient.size)
|
|
73
|
+
}
|
|
74
|
+
await this.gradOut.count()
|
|
75
|
+
if (this.oldParam[1] !== tokenCount) {
|
|
76
|
+
this.oldParam = new Uint32Array([this.embeddingSize, tokenCount, 0])
|
|
77
|
+
await this.gpu.WriteBuffer(this.paramBuffer, this.oldParam)
|
|
78
|
+
}
|
|
79
|
+
const bind = await this.device.createBindGroup({
|
|
80
|
+
layout: await this.backwardPipline.getBindGroupLayout(0),
|
|
81
|
+
entries: [
|
|
82
|
+
{
|
|
83
|
+
binding: 0,
|
|
84
|
+
resource: {
|
|
85
|
+
buffer: this.input.mainBuffer
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
binding: 1,
|
|
90
|
+
resource: {
|
|
91
|
+
buffer: this.paramBuffer
|
|
92
|
+
}
|
|
93
|
+
}, {
|
|
94
|
+
binding: 2,
|
|
95
|
+
resource: {
|
|
96
|
+
buffer: this.gradOut.mainBuffer
|
|
97
|
+
}
|
|
98
|
+
}, {
|
|
99
|
+
binding: 3,
|
|
100
|
+
resource: {
|
|
101
|
+
buffer: inputGradient.mainBuffer
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
})
|
|
106
|
+
await this.gpu.RunPipline(encoder, this.backwardPipline, bind, Math.ceil((tokenCount * this.embeddingSize) / 256))
|
|
107
|
+
if(!encoderMain) await this.device.queue.submit([encoder.finish()])
|
|
108
|
+
return this.gradOut
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export class SelfAttention {
|
|
2
|
+
constructor(device: GPUAdapter, embeddingSize: number, configs: {
|
|
3
|
+
dirname: string
|
|
4
|
+
})
|
|
5
|
+
async forward(vec: {
|
|
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(dO: {
|
|
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,138 @@
|
|
|
1
|
+
import { Linear } from "../../index.js";
|
|
2
|
+
import { join } from 'path'
|
|
3
|
+
import { OperationManager } from "../OperationManager.js";
|
|
4
|
+
|
|
5
|
+
export class SelfAttention {
|
|
6
|
+
query;
|
|
7
|
+
value;
|
|
8
|
+
key;
|
|
9
|
+
q;
|
|
10
|
+
k;
|
|
11
|
+
v;
|
|
12
|
+
embeddingSize;
|
|
13
|
+
params;
|
|
14
|
+
attentionscoresShader;
|
|
15
|
+
softmaxForward;
|
|
16
|
+
gpu;
|
|
17
|
+
input;
|
|
18
|
+
constructor(device, embeddingSize, configs) {
|
|
19
|
+
this.embeddingSize = embeddingSize;
|
|
20
|
+
const dd = [1, 2, 3].map((e) => {
|
|
21
|
+
return {
|
|
22
|
+
save: {
|
|
23
|
+
filename: [join(configs.dirname, `SELF-W-${e}.bin`), join(configs.dirname, `SELF-B-${e}.bin`)]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
this.q = new Linear(device, embeddingSize, embeddingSize, dd[0])
|
|
28
|
+
this.k = new Linear(device, embeddingSize, embeddingSize, dd[1])
|
|
29
|
+
this.v = new Linear(device, embeddingSize, embeddingSize, dd[2])
|
|
30
|
+
this.gpu = new OperationManager(device)
|
|
31
|
+
this.attentionscoresShader = this.gpu.getShaderPipline("./src/shaders/attentionShader/attentionSocres.wgsl")
|
|
32
|
+
this.softmaxForward = this.gpu.getShaderPipline("./src/shaders/SF.wgsl")
|
|
33
|
+
this.softmaxBackward = this.gpu.getShaderPipline("./src/shaders/SoftmaxBackward.wgsl")
|
|
34
|
+
this.outputForward = this.gpu.getShaderPipline("./src/shaders/attentionShader/CompueFinalForwardOutput.wgsl")
|
|
35
|
+
this.dVShader = this.gpu.getShaderPipline("./src/shaders/attentionShader/ComputeDV.wgsl")
|
|
36
|
+
this.dAshader = this.gpu.getShaderPipline("./src/shaders/attentionShader/ComputeDA.wgsl")
|
|
37
|
+
this.dQshader = this.gpu.getShaderPipline("./src/shaders/attentionShader/ComputedQ.wgsl")
|
|
38
|
+
this.dKShader = this.gpu.getShaderPipline("./src/shaders/attentionShader/ComputeK.wgsl")
|
|
39
|
+
this.sumShader = this.gpu.getShaderPipline("./src/shaders/attentionShader/sumGradient.wgsl")
|
|
40
|
+
}
|
|
41
|
+
async forward(vec, encoderMain) {
|
|
42
|
+
this.input = vec.mainBuffer;
|
|
43
|
+
const tokenCount = vec.mainBuffer.size / (this.embeddingSize * 4)
|
|
44
|
+
if (!this.asParams) this.asParams = await this.gpu.createUniFormBuffer(4 * 3);
|
|
45
|
+
if (!this.softmaxParams) this.softmaxParams = await this.gpu.createUniFormBuffer(4 * 3);
|
|
46
|
+
const encoder = encoderMain ? encoderMain : await this.gpu.CreateEncoder()
|
|
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
|
+
}
|
|
54
|
+
await this.gpu.WriteBuffer(this.asParams, new Uint32Array([tokenCount, this.embeddingSize, 0]))
|
|
55
|
+
await this.gpu.WriteBuffer(this.softmaxParams, new Uint32Array([tokenCount, tokenCount, 0]))
|
|
56
|
+
this.query = await this.q.forward(vec, encoderMain)
|
|
57
|
+
this.key = await this.k.forward(vec, encoderMain)
|
|
58
|
+
this.value = await this.v.forward(vec, encoderMain)
|
|
59
|
+
const bindAttention = await this.gpu.createBindGroup(this.attentionscoresShader, 0, [this.query.mainBuffer, this.key.mainBuffer, this.scroes, this.asParams])
|
|
60
|
+
await this.gpu.RunPipline(encoder, this.attentionscoresShader, bindAttention, Math.ceil(tokenCount / 16), Math.ceil(tokenCount / 16))
|
|
61
|
+
if (this.weights) this.weights.destroy()
|
|
62
|
+
this.weights = await this.gpu.createBuffer(tokenCount * tokenCount * 4)
|
|
63
|
+
const bindSF = await this.gpu.createBindGroup(this.softmaxForward, 0, [this.scroes, this.weights, this.softmaxParams]);
|
|
64
|
+
await this.gpu.RunPipline(encoder, this.softmaxForward, bindSF, tokenCount)
|
|
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.size == 0 || this.finalOutput.isDestroyed()) {
|
|
69
|
+
this.finalOutput = await this.gpu.ManageBuffer(tokenCount * this.embeddingSize * 4)
|
|
70
|
+
}
|
|
71
|
+
await this.finalOutput.count()
|
|
72
|
+
const outputBind = await this.gpu.createBindGroup(this.outputForward, 0, [this.weights, this.value.mainBuffer, this.finalOutput.mainBuffer, this.asParams]);
|
|
73
|
+
await this.gpu.RunPipline(encoder, this.outputForward, outputBind, Math.ceil((tokenCount * this.embeddingSize) / 256))
|
|
74
|
+
if(!encoderMain) await this.gpu.submitQueue(encoder)
|
|
75
|
+
return this.finalOutput
|
|
76
|
+
}
|
|
77
|
+
async backward(dO, lr, encoderMain) {
|
|
78
|
+
const tokenCount = dO.size / (this.embeddingSize * 4);
|
|
79
|
+
const encoder = encoderMain ? encoderMain : await this.gpu.CreateEncoder();
|
|
80
|
+
if (!this.dV) this.dV = await this.gpu.createBuffer(dO.size);
|
|
81
|
+
if (!this.dA) this.dA = await this.gpu.createBuffer(tokenCount * tokenCount * 4);
|
|
82
|
+
if (!this.dS) this.dS = await this.gpu.createBuffer(tokenCount * tokenCount * 4);
|
|
83
|
+
if (!this.dQ) this.dQ = await this.gpu.createBuffer(tokenCount * this.embeddingSize * 4);
|
|
84
|
+
if (!this.dK) this.dK = await this.gpu.createBuffer(this.embeddingSize * tokenCount * 4)
|
|
85
|
+
if (this.dV.size !== dO.size || this.dV.size == 0) {
|
|
86
|
+
this.dV.destroy()
|
|
87
|
+
this.dV = await this.gpu.createBuffer(dO.size);
|
|
88
|
+
}
|
|
89
|
+
if (this.dA.size !== tokenCount * tokenCount * 4 || this.dA.size == 0) {
|
|
90
|
+
this.dA.destroy()
|
|
91
|
+
this.dA = await this.gpu.createBuffer(tokenCount * tokenCount * 4);
|
|
92
|
+
}
|
|
93
|
+
if (this.dS.size !== tokenCount * tokenCount * 4 || this.dS.size == 0) {
|
|
94
|
+
this.dS.destroy()
|
|
95
|
+
this.dS = await this.gpu.createBuffer(tokenCount * tokenCount * 4);
|
|
96
|
+
}
|
|
97
|
+
if (this.dQ.size !== tokenCount * this.embeddingSize * 4 || this.dQ.size == 0) {
|
|
98
|
+
this.dQ.destroy()
|
|
99
|
+
this.dQ = await this.gpu.createBuffer(tokenCount * this.embeddingSize * 4);
|
|
100
|
+
}
|
|
101
|
+
if (this.dK.size !== tokenCount * this.embeddingSize * 4 || this.dK.size == 0) {
|
|
102
|
+
this.dK.destroy()
|
|
103
|
+
this.dK = await this.gpu.createBuffer(tokenCount * this.embeddingSize * 4);
|
|
104
|
+
}
|
|
105
|
+
const DvBind = await this.gpu.createBindGroup(this.dVShader, 0, [this.weights, dO.mainBuffer, this.dV, this.asParams]);
|
|
106
|
+
await this.gpu.RunPipline(encoder, this.dVShader, DvBind, Math.ceil(tokenCount / 16), Math.ceil(this.embeddingSize / 16));
|
|
107
|
+
const DaBind = await this.gpu.createBindGroup(this.dAshader, 0, [dO.mainBuffer, this.value.mainBuffer, this.dA, this.asParams]);
|
|
108
|
+
await this.gpu.RunPipline(encoder, this.dAshader, DaBind, Math.ceil(tokenCount / 16), Math.ceil(tokenCount / 16))
|
|
109
|
+
const dSBind = await this.gpu.createBindGroup(this.softmaxBackward, 0, [this.weights, this.dA, this.dS, this.asParams])
|
|
110
|
+
await this.gpu.RunPipline(encoder, this.softmaxBackward, dSBind, Math.ceil((tokenCount * tokenCount) / 256))
|
|
111
|
+
const dQbind = await this.gpu.createBindGroup(this.dQshader, 0, [this.dS, this.key.mainBuffer, this.dQ, this.asParams]);
|
|
112
|
+
await this.gpu.RunPipline(encoder, this.dQshader, dQbind, Math.ceil(tokenCount / 16), Math.ceil(this.embeddingSize / 16))
|
|
113
|
+
const dKbind = await this.gpu.createBindGroup(this.dKShader, 0, [this.dS, this.query.mainBuffer, this.dK, this.asParams]);
|
|
114
|
+
await this.gpu.RunPipline(encoder, this.dKShader, dKbind, Math.ceil(tokenCount / 16), Math.ceil(this.embeddingSize / 16))
|
|
115
|
+
const dq = await this.q.backward({ mainBuffer: this.dQ, size: this.dQ.size}, lr, encoderMain)
|
|
116
|
+
const dk = await this.k.backward({ mainBuffer: this.dK, size: this.dK.size}, lr, encoderMain)
|
|
117
|
+
const dv = await this.v.backward({ mainBuffer: this.dV, size: this.dV.size}, lr, encoderMain)
|
|
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() || this.gradOut.size == 0){
|
|
120
|
+
this.gradOut.destroy()
|
|
121
|
+
this.gradOut = await this.gpu.ManageBuffer(tokenCount * 4 * this.embeddingSize)
|
|
122
|
+
}
|
|
123
|
+
await this.gradOut.count()
|
|
124
|
+
if(!dq || !dk || !dq || !this.gradOut){
|
|
125
|
+
throw new Error("Something is wrong!")
|
|
126
|
+
}
|
|
127
|
+
const outputBind = await this.gpu.createBindGroup(this.sumShader, 0, [dq.mainBuffer, dk.mainBuffer, dv.mainBuffer, this.gradOut.mainBuffer, this.asParams]);
|
|
128
|
+
await this.gpu.RunPipline(encoder, this.sumShader, outputBind, Math.ceil((tokenCount * this.embeddingSize / 256)));
|
|
129
|
+
if(!encoderMain) await this.gpu.submitQueue(encoder)
|
|
130
|
+
return this.gradOut
|
|
131
|
+
|
|
132
|
+
}
|
|
133
|
+
async Save() {
|
|
134
|
+
await this.q.Save()
|
|
135
|
+
await this.k.Save()
|
|
136
|
+
await this.v.Save()
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export class Softmax {
|
|
2
|
+
constructor(device: GPUAdapter, embeddingSize: number, vocabSize: number);
|
|
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: Function, acc: Function, clear : Function }>
|
|
26
|
+
}
|