@mineproness/tensorloop 2.1.0 → 2.1.2

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.0",
3
+ "version": "2.1.2",
4
4
  "description": "Raw-JAVASCRIPT Based Matirx and AI LLM Package called Tensorloop.",
5
5
  "keywords": [
6
6
  "ai",
@@ -1,4 +1,5 @@
1
1
  import { Softmax } from '../../index.js';
2
+ import { GPUAttention } from '../gpiInit.js';
2
3
  import { Linear } from '../Linear/index.js'
3
4
 
4
5
  export class SelfAttention {
@@ -13,6 +14,7 @@ export class SelfAttention {
13
14
  score;
14
15
  softmax;
15
16
  weights;
17
+ gpu;
16
18
  constructor(embeddingSize, configs) {
17
19
  this.configs = configs
18
20
  this.softmax = new Softmax()
@@ -22,96 +24,29 @@ export class SelfAttention {
22
24
  this.value = new Linear(embeddingSize, embeddingSize, { save: { filename: [`${configs.dirname}/value.bin`, `${configs.dirname}/valueBias.bin`] } })
23
25
  }
24
26
  forward(vectors) {
27
+ if(!this.gpu) this.gpu = new GPUAttention(vectors[0].length, vectors.length);
25
28
  this.q = this.query.forward(vectors)
26
29
  this.v = this.value.forward(vectors)
27
30
  this.k = this.key.forward(vectors)
28
- const attentionSocres = []
29
- for (let i = 0; i < this.q.length; i++) {
30
- attentionSocres[i] = new Float32Array(this.k.length);
31
-
32
- for (let j = 0; j < this.k.length; j++) {
33
- if (j > i) {
34
- attentionSocres[i][j] = -1e9; // mask future
35
- continue;
36
- }
37
-
38
- let dot = 0;
39
-
40
- for (let d = 0; d < this.q[i].length; d++) {
41
- dot += this.q[i][d] * this.k[j][d];
42
- }
43
-
44
- attentionSocres[i][j] = dot / this.score;
45
- }
46
- }
47
-
31
+ const attentionSocres = this.gpu.attentionScores(this.q, this.k, this.score);
48
32
  const weights = this.softmax.forward(attentionSocres)
49
33
  this.weights = weights
50
- const output = [];
51
-
52
- for (let i = 0; i < weights.length; i++) {
53
- output[i] = new Float32Array(this.v[0].length);
54
-
55
- for (let j = 0; j < this.v.length; j++) {
56
- for (let d = 0; d < this.v[j].length; d++) {
57
- output[i][d] += weights[i][j] * this.v[j][d];
58
- }
59
- }
60
- }
61
-
34
+ const output = this.gpu.attentionOutput(weights, this.v)
62
35
  return output;
63
36
  }
64
- softmaxBack(probs, dOut) {
65
- const dIn = new Float32Array(probs.length);
66
37
 
67
- for (let i = 0; i < probs.length; i++) {
68
- let sum = 0;
69
- for (let j = 0; j < probs.length; j++) {
70
- const jacobian =
71
- i === j
72
- ? probs[i] * (1 - probs[i])
73
- : -probs[i] * probs[j];
74
-
75
- sum += jacobian * dOut[j];
76
- }
77
- dIn[i] = sum;
78
- }
79
-
80
- return dIn;
81
- }
82
38
  backward(dOutput, learningRate) {
83
- const dV = this.v.map((e) => new Float32Array(e.length));
84
- const dWeights = []
85
- for (let a = 0; a < this.weights.length; a++) {
86
- dWeights[a] = new Float32Array(this.weights[a].length)
87
- for (let j = 0; j < this.v.length; j++) {
88
- for (let r = 0; r < this.v[j].length; r++) {
89
- dWeights[a][j] += dOutput[a][r] * this.v[j][r]
90
- dV[j][r] += dOutput[a][r] * this.weights[a][j]
91
- }
92
- }
93
- }
94
- const dScores = []
95
- for (let t = 0; t < dWeights.length; t++) {
96
- dScores[t] = this.softmaxBack(this.weights[t], dWeights[t])
97
- }
98
- const dQ = this.q.map(q => new Float32Array(q.length));
99
- const dK = this.k.map(k => new Float32Array(k.length));
100
- for (let a = 0; a < this.q.length; a++) {
101
- for (let j = 0; j < this.k.length; j++) {
102
- if (j > a) continue;
103
- for (let r = 0; r < this.q[a].length; r++) {
104
- dQ[a][r] += dScores[a][j] * this.k[j][r] / this.score;
105
- dK[j][r] += dScores[a][j] * this.q[a][r] / this.score;
106
- }
107
- }
108
- }
39
+ const dWeights = this.gpu.dWeightsKernel(dOutput, this.v)
40
+ const dV = this.gpu.dVKernel(dOutput, this.weights);
41
+ const dScores = this.gpu.softmaxBackKernel(this.weights, dWeights)
42
+ const dQ = this.gpu.dQKernel(dScores, this.k, this.score)
43
+ const dK = this.gpu.dKKernel(dScores, this.q, this.score)
109
44
  const dInput = this.q.map(() => new Float32Array(this.q[0].length))
110
45
  const dq = this.query.backward(dQ, learningRate)
111
46
  const dk = this.key.backward(dK, learningRate)
112
47
  const dv = this.value.backward(dV, learningRate)
113
48
  for (let a = 0; a < this.q.length; a++) {
114
- for (let b = 0; b < dq.length; b++) {
49
+ for (let b = 0; b < dq[a].length; b++) {
115
50
  dInput[a][b] = dq[a][b] + dk[a][b] + dv[a][b]
116
51
  }
117
52
  }
package/src/gpiInit.js CHANGED
@@ -261,12 +261,14 @@ export class GPUSoftmax {
261
261
  const maxLogits = this.cacheMaxCache(logits)
262
262
  const sumes = this.cacheSumCalculate(maxLogits, logits)
263
263
  const splitedLogits = split2DByColumns(logits)
264
- const result = Array.from({ length: this.contextSize }, () => [])
264
+ const result = Array.from({ length: this.contextSize }, () => new Float32Array(logits[0].length))
265
+ let offset = 0
265
266
  for (let i = 0; i < splitedLogits.length; i++) {
266
267
  const out = this.cacheSF[i](splitedLogits[i], sumes, maxLogits)
267
268
  for (let a = 0; a < this.contextSize; a++) {
268
- result[a].push(...out[a])
269
+ result[a].set(out[a] , offset)
269
270
  }
271
+ offset += out[0].length
270
272
  }
271
273
  maxLogits.delete()
272
274
  sumes.delete()
@@ -274,12 +276,14 @@ export class GPUSoftmax {
274
276
  }
275
277
  backward(probs, target) {
276
278
  const splitedProbs = split2DByColumns(probs)
277
- const result = Array.from({ length: this.contextSize }, () => [])
279
+ const result = Array.from({ length: this.contextSize }, () => new Float32Array(probs[0].length))
280
+ let offset = 0;
278
281
  for (let i = 0; i < this.cacheSB.length; i++) {
279
282
  const out = this.cacheSB[i](splitedProbs[i], target)
280
283
  for (let a = 0; a < this.contextSize; a++) {
281
- result[a].push(...out[a])
284
+ result[a].set(out[a], offset)
282
285
  }
286
+ offset += out[0].length
283
287
  }
284
288
  return result
285
289
  }
@@ -601,4 +605,121 @@ export class GELUGPU {
601
605
  backward(dOutput, input) {
602
606
  return this.cacheGB(input, dOutput)
603
607
  }
608
+ }
609
+
610
+ export class GPUAttention {
611
+ attentionScores;
612
+ attentionOutput;
613
+ dWeightsKernel;
614
+ dVKernel;
615
+ softmaxBackKernel;
616
+ dQKernel;
617
+ dKKernel;
618
+ constructor(embeddingSize, contextSize) {
619
+ this.attentionScores = gpu.createKernel(function (q, k, scale) {
620
+ const i = this.thread.y;
621
+ const j = this.thread.x;
622
+ if (j > i) {
623
+ return -1e9;
624
+ }
625
+ let sum = 0;
626
+ for (let d = 0; d < this.constants.D; d++) {
627
+ sum += q[i][d] * k[j][d];
628
+ }
629
+ return sum / scale;
630
+ }, {
631
+ output: [contextSize, contextSize],
632
+ constants: {
633
+ D: embeddingSize
634
+ }
635
+ });
636
+ this.attentionOutput = gpu.createKernel(function (weights, v) {
637
+ const i = this.thread.y;
638
+ const d = this.thread.x;
639
+ let sum = 0;
640
+ for (let j = 0; j < this.constants.CONTEXT; j++) {
641
+ sum += weights[i][j] * v[j][d];
642
+ }
643
+ return sum;
644
+ }, {
645
+ output: [embeddingSize, contextSize],
646
+ constants: {
647
+ CONTEXT: contextSize
648
+ },
649
+ });
650
+ this.dWeightsKernel = gpu.createKernel(function (dOutput, v) {
651
+ const a = this.thread.y;
652
+ const j = this.thread.x;
653
+ let sum = 0;
654
+ for (let r = 0; r < this.constants.D; r++) {
655
+ sum += dOutput[a][r] * v[j][r];
656
+ }
657
+ return sum;
658
+ }, {
659
+ output: [contextSize, contextSize],
660
+ pipeline: true,
661
+ immutable: true,
662
+ constants: {
663
+ D: embeddingSize
664
+ }
665
+ });
666
+ this.dVKernel = gpu.createKernel(function (dOutput, weights) {
667
+ const j = this.thread.y;
668
+ const r = this.thread.x;
669
+ let sum = 0;
670
+ for (let a = 0; a < this.constants.C; a++) {
671
+ sum += weights[a][j] * dOutput[a][r];
672
+ }
673
+ return sum;
674
+ }, {
675
+ output: [embeddingSize, contextSize],
676
+
677
+ constants: {
678
+ C: contextSize
679
+ }
680
+ });
681
+ this.softmaxBackKernel = gpu.createKernel(function (probs, dOut) {
682
+ const a = this.thread.y;
683
+ const i = this.thread.x;
684
+ let dot = 0;
685
+ for (let j = 0; j < this.constants.C; j++) {
686
+ dot += probs[a][j] * dOut[a][j];
687
+ }
688
+ return probs[a][i] * (dOut[a][i] - dot);
689
+ }, {
690
+ output: [contextSize, contextSize],
691
+ pipeline: true,
692
+ immutable: true,
693
+ constants: {
694
+ C: contextSize
695
+ }
696
+ });
697
+ this.dQKernel = gpu.createKernel(function (dScores, k, scale) {
698
+ const a = this.thread.y;
699
+ const r = this.thread.x;
700
+ let sum = 0;
701
+ for (let j = 0; j <= a; j++) {
702
+ sum += dScores[a][j] * k[j][r];
703
+ }
704
+ return sum / scale;
705
+ }, {
706
+ output: [embeddingSize, contextSize],
707
+
708
+ });
709
+ this.dKKernel = gpu.createKernel(function (dScores, q, scale) {
710
+ const j = this.thread.y;
711
+ const r = this.thread.x;
712
+ let sum = 0;
713
+ for (let a = j; a < this.constants.C; a++) {
714
+ sum += dScores[a][j] * q[a][r];
715
+ }
716
+ return sum / scale;
717
+ }, {
718
+ output: [embeddingSize, contextSize],
719
+
720
+ constants: {
721
+ C: contextSize
722
+ }
723
+ });
724
+ }
604
725
  }