1
- import { SparseMatrix } from '../src/index.js ' ;
1
+ import Benchmark from 'benchmark ' ;
2
2
import { Matrix } from 'ml-matrix' ;
3
3
import { SparseMatrix as SparseMatrixOld } from './class/SparseMatrixOld.js' ;
4
- // import { SparseMatrix as SparseMatrixOld } from '../src/Elements.js';
5
- import fs from 'fs' ;
6
-
7
- function randomSparseMatrix ( rows , cols , density = 0.01 ) {
8
- const total = rows * cols ;
9
- const cardinality = Math . round ( total * density ) ;
10
- const positions = new Set ( ) ;
11
-
12
- // Generate unique random positions
13
- while ( positions . size < cardinality ) {
14
- positions . add ( Math . floor ( Math . random ( ) * total ) ) ;
15
- }
16
-
17
- // Build the matrix with zeros
18
- const matrix = Array . from ( { length : rows } , ( ) => new Float64Array ( cols ) ) ;
19
-
20
- // Assign random values to the selected positions
21
- for ( const pos of positions ) {
22
- const i = Math . floor ( pos / cols ) ;
23
- const j = pos % cols ;
24
- matrix [ i ] [ j ] = Math . random ( ) * 10 ;
25
- }
26
-
27
- return new SparseMatrix ( matrix ) ;
28
- }
29
-
30
- function benchmark ( fn , label , iterations = 5 , logIt = false ) {
31
- const times = [ ] ;
32
- for ( let i = 0 ; i < iterations ; i ++ ) {
33
- const t0 = performance . now ( ) ;
34
- fn ( ) ;
35
- const t1 = performance . now ( ) ;
36
- times . push ( t1 - t0 ) ;
37
- }
38
- const avg = times . reduce ( ( a , b ) => a + b , 0 ) / times . length ;
39
- if ( logIt ) {
40
- console . log ( `${ label } : avg ${ avg . toFixed ( 2 ) } ms over ${ iterations } runs` ) ;
41
- }
42
- return avg ;
43
- }
44
-
45
- function printWinner ( label1 , avg1 , label2 , avg2 ) {
46
- let winner , loser , win , lose ;
47
- if ( avg1 < avg2 ) {
48
- winner = label1 ;
49
- win = avg1 ;
50
- loser = label2 ;
51
- lose = avg2 ;
52
- } else {
53
- winner = label2 ;
54
- win = avg2 ;
55
- loser = label1 ;
56
- lose = avg1 ;
57
- }
58
-
59
- const percent = ( ( lose - win ) / lose ) * 100 ;
60
- console . log (
61
- ` -> ${ winner } was ${ ( lose / win ) . toFixed ( 2 ) } x faster (${ percent . toFixed (
62
- 1 ,
63
- ) } % faster) than ${ loser } \n`,
64
- ) ;
65
- }
4
+ import { randomSparseMatrix } from './utils/randomSparseMatrix.js' ;
5
+ import { printWinner } from './utils/printWinner.js' ;
66
6
67
7
function runBenchmarks ( ) {
68
8
const m = 256 ;
@@ -71,7 +11,6 @@ function runBenchmarks() {
71
11
const densityA = 0.01 ;
72
12
const densityB = 0.01 ;
73
13
74
- const nbIterations = 3 ;
75
14
const A = randomSparseMatrix ( m , n , densityA ) ;
76
15
const B = randomSparseMatrix ( n , p , densityB ) ;
77
16
@@ -84,141 +23,103 @@ function runBenchmarks() {
84
23
denseA = new Matrix ( denseA ) ;
85
24
denseB = new Matrix ( denseB ) ;
86
25
87
- denseA . mmul ( denseB ) ;
88
- // 1. add vs addNew
89
- // const addAvg = benchmark(() => {
90
- // const a = AOld.clone();
91
- // a.add(BOld);
92
- // }, 'add');
93
-
94
- // const addNewAvg = benchmark(() => {
95
- // const a = A.clone();
96
- // a.add(B);
97
- // }, 'addNew');
26
+ const results = [ ] ;
98
27
99
- // printWinner('add', addAvg, 'addNew', addNewAvg);
28
+ // 1. add vs addNew
29
+ const addSuite = new Benchmark . Suite ( 'add' ) ;
30
+ addSuite
31
+ . add ( 'add' , function ( ) {
32
+ const a = AOld . clone ( ) ;
33
+ a . add ( BOld ) ;
34
+ } )
35
+ . add ( 'addNew' , function ( ) {
36
+ const a = A . clone ( ) ;
37
+ a . add ( B ) ;
38
+ } )
39
+ . add ( 'addDense' , function ( ) {
40
+ const a = denseA . clone ( ) ;
41
+ a . add ( denseB ) ;
42
+ } )
43
+ . on ( 'cycle' , function ( event ) {
44
+ console . log ( String ( event . target ) ) ;
45
+ } )
46
+ . on ( 'complete' , function ( ) {
47
+ const fastest = this . filter ( 'fastest' ) . map ( 'name' ) ;
48
+ this . forEach ( ( bench ) => {
49
+ results . push ( { label : bench . name , avg : 1000 / bench . hz } ) ;
50
+ } ) ;
51
+ printWinner ( results ) ;
52
+ } )
53
+ . run ( { async : false } ) ;
100
54
101
55
// 2. mmul vs mmulNew
102
-
103
- const mmulNewAvg = benchmark (
104
- ( ) => {
56
+ const mmulSuite = new Benchmark . Suite ( 'mmul' ) ;
57
+ mmulSuite
58
+ . add ( 'mmulNew' , function ( ) {
105
59
A . mmul ( B ) ;
106
- } ,
107
- 'mmulNew' ,
108
- nbIterations ,
109
- ) ;
110
-
111
- const mmulAvg = benchmark (
112
- ( ) => {
60
+ } )
61
+ . add ( 'mmul' , function ( ) {
113
62
AOld . mmul ( BOld ) ;
114
- } ,
115
- 'mmul' ,
116
- nbIterations ,
117
- ) ;
118
-
119
- const denseAvg = benchmark (
120
- ( ) => {
63
+ } )
64
+ . add ( 'denseMatrix' , function ( ) {
121
65
denseA . mmul ( denseB ) ;
122
- } ,
123
- 'denseMatrix' ,
124
- nbIterations ,
125
- ) ;
126
-
127
- printWinner ( 'mmul' , mmulAvg , 'mmulNew' , mmulNewAvg ) ;
66
+ } )
67
+ . on ( 'cycle' , function ( event ) {
68
+ console . log ( String ( event . target ) ) ;
69
+ } )
70
+ . on ( 'complete' , function ( ) {
71
+ const mmulResults = [ ] ;
72
+ this . forEach ( ( bench ) => {
73
+ mmulResults . push ( { label : bench . name , avg : 1000 / bench . hz } ) ;
74
+ } ) ;
75
+ printWinner ( mmulResults ) ;
76
+ } )
77
+ . run ( { async : false } ) ;
128
78
129
79
// 3. kroneckerProduct vs kroneckerProductNew
130
- // const kronNewAvg = benchmark(() => {
131
- // A.kroneckerProduct(B);
132
- // }, 'kroneckerProductNew');
133
- // const kronAvg = benchmark(() => {
134
- // AOld.kroneckerProduct(BOld);
135
- // }, 'kroneckerProduct');
136
-
137
- // printWinner('kroneckerProduct', kronAvg, 'kroneckerProductNew', kronNewAvg);
80
+ const kronSuite = new Benchmark . Suite ( 'kroneckerProduct' ) ;
81
+ kronSuite
82
+ . add ( 'kroneckerProductNew' , function ( ) {
83
+ A . kroneckerProduct ( B ) ;
84
+ } )
85
+ . add ( 'kroneckerProduct' , function ( ) {
86
+ AOld . kroneckerProduct ( BOld ) ;
87
+ } )
88
+ . add ( 'kroneckerProductDense' , function ( ) {
89
+ denseA . kroneckerProduct ( denseB ) ;
90
+ } )
91
+ . on ( 'cycle' , function ( event ) {
92
+ console . log ( String ( event . target ) ) ;
93
+ } )
94
+ . on ( 'complete' , function ( ) {
95
+ const kronResults = [ ] ;
96
+ this . forEach ( ( bench ) => {
97
+ kronResults . push ( { label : bench . name , avg : 1000 / bench . hz } ) ;
98
+ } ) ;
99
+ printWinner ( kronResults ) ;
100
+ } )
101
+ . run ( { async : false } ) ;
138
102
139
103
// 4. matrix multiplication
140
- // const mulAvg = benchmark(() => {
141
- // A.mul(5);
142
- // }, 'mul');
143
-
144
- // const mulNewAvg = benchmark(() => {
145
- // AOld.mul(5);
146
- // }, 'mulNew');
147
-
148
- // printWinner('mul', mulAvg, 'mulNew', mulNewAvg);
149
- }
150
-
151
- function runSizeSweepBenchmark ( ) {
152
- const nbIterations = 3 ;
153
- const sizes = [ 32 , 64 , 128 , 256 ] ;
154
- const densities = [ 0.01 , 0.015 , 0.02 , 0.025 , 0.03 ] ;
155
- const results = [ ] ;
156
-
157
- for ( const densityA of densities ) {
158
- for ( const densityB of densities ) {
159
- for ( const m of sizes ) {
160
- for ( const n of sizes ) {
161
- for ( const p of sizes ) {
162
- // A: m x n, B: n x p
163
-
164
- const A = randomSparseMatrix ( m , n , densityA ) ;
165
- const B = randomSparseMatrix ( n , p , densityB ) ;
166
-
167
- let denseA = A . to2DArray ( ) ;
168
- let denseB = B . to2DArray ( ) ;
169
-
170
- const AOld = new SparseMatrixOld ( denseA ) ;
171
- const BOld = new SparseMatrixOld ( denseB ) ;
172
-
173
- denseA = new Matrix ( denseA ) ;
174
- denseB = new Matrix ( denseB ) ;
175
-
176
- const mmulNewAvg = benchmark (
177
- ( ) => {
178
- A . mmul ( B ) ;
179
- } ,
180
- 'mmulNew' ,
181
- nbIterations ,
182
- ) ;
183
-
184
- const mmulAvg = benchmark (
185
- ( ) => {
186
- AOld . mmul ( BOld ) ;
187
- } ,
188
- 'mmul' ,
189
- nbIterations ,
190
- ) ;
191
-
192
- const denseAvg = benchmark (
193
- ( ) => {
194
- denseA . mmul ( denseB ) ;
195
- } ,
196
- 'denseMatrix' ,
197
- nbIterations ,
198
- ) ;
199
-
200
- results . push ( {
201
- densityA,
202
- densityB,
203
- A_shape : [ m , n ] ,
204
- B_shape : [ n , p ] ,
205
- dense : denseAvg ,
206
- new : mmulNewAvg ,
207
- old : mmulAvg ,
208
- } ) ;
209
- }
210
- }
211
- }
212
- }
213
- }
214
-
215
- fs . writeFileSync (
216
- './benchmark/size_sweep_results-dense.json' ,
217
- JSON . stringify ( results , null , 2 ) ,
218
- ) ;
219
- console . log ( 'Size sweep benchmark results saved to size_sweep_results.json' ) ;
104
+ const mulSuite = new Benchmark . Suite ( 'mul' ) ;
105
+ mulSuite
106
+ . add ( 'mul' , function ( ) {
107
+ A . mul ( 5 ) ;
108
+ } )
109
+ . add ( 'mulNew' , function ( ) {
110
+ AOld . mul ( 5 ) ;
111
+ } )
112
+ . on ( 'cycle' , function ( event ) {
113
+ console . log ( String ( event . target ) ) ;
114
+ } )
115
+ . on ( 'complete' , function ( ) {
116
+ const mulResults = [ ] ;
117
+ this . forEach ( ( bench ) => {
118
+ mulResults . push ( { label : bench . name , avg : 1000 / bench . hz } ) ;
119
+ } ) ;
120
+ printWinner ( mulResults ) ;
121
+ } )
122
+ . run ( { async : false } ) ;
220
123
}
221
124
222
- // runBenchmarks();
223
- // Uncomment to run the size sweep benchmark
224
- runSizeSweepBenchmark ( ) ;
125
+ runBenchmarks ( ) ;
0 commit comments