Phase C & D: unit-stride-innermost traversal and offset/length SIMD kernels for Double#115
Conversation
Co-authored-by: Quafadas <24899792+Quafadas@users.noreply.github.com>
Co-authored-by: Quafadas <24899792+Quafadas@users.noreply.github.com>
Bytecode audit (Tier 1) —
|
| threshold | value | provenance |
|---|---|---|
MaxTrivialSize |
6 | discovered |
MaxInlineSize |
35 | discovered |
FreqInlineSize |
325 | discovered |
MaxInlineLevel |
15 | discovered |
InlineSmallCode |
2500 | discovered |
NodeCountInliningCutoff |
18000 | assumed |
HugeMethodLimit |
8000 | assumed |
-XX:HugeMethodLimit= was rejected on the command line: a develop flag compiled out of this product build, so 8000 is taken from the HotSpot source and cannot be confirmed against the running JVM.
| metric | now | baseline | delta |
|---|---|---|---|
| cheatsheet methods | 97 | — | — |
| total bytes | 42067 | 51103 | -17.7% |
| distinct library ops | 198 | 178 | +11.2% |
| bytes per op | 212.5 | 287.1 | -26.0% |
| severity | check | at | method | detail |
|---|---|---|---|---|
| WARN | C1 | cheatsheet.scala:118 |
CheatsheetTest$.matrixRangeSlicing |
5643 bytes, past 68% of HugeMethodLimit=8000 (assumed) |
Annotated methods (168)
| method | annotations | bytes | budget used | loop | at |
|---|---|---|---|---|---|
vecxt.intarrays$.$plus |
@Thin |
24 | 69% of 35 | no | intarrays.scala:546 |
vecxt.intarrays$.$minus |
@Thin |
24 | 69% of 35 | no | intarrays.scala:399 |
vecxt.NDArrayFloatOps$.compareGeneral |
@HotPath |
195 | 60% of 325 | yes | ndarrayFloatOps.scala:67 |
vecxt.NDArrayFloatOps$.binaryOpGeneral |
@HotPath |
195 | 60% of 325 | yes | ndarrayFloatOps.scala:20 |
vecxt.NDArrayIntOps$.compareGeneral |
@HotPath |
186 | 57% of 325 | yes | ndarrayIntOps.scala:67 |
vecxt.NDArrayIntOps$.binaryOpGeneral |
@HotPath |
186 | 57% of 325 | yes | ndarrayIntOps.scala:19 |
vecxt.NDArrayDoubleOps$.compareGeneral |
@HotPath |
186 | 57% of 325 | yes | ndarrayDoubleOps.scala:74 |
vecxt.NDArrayDoubleOps$.binaryOpGeneral |
@HotPath |
186 | 57% of 325 | yes | ndarrayDoubleOps.scala:24 |
vecxt.doublearrays$.clamp$bang |
@AllocFree @HotPath |
180 | 55% of 325 | yes | doublearrays.scala:898 |
vecxt.matrix$Layout.linearIndex |
@Thin |
19 | 54% of 35 | no | matrix.scala:48 |
vecxt.floatarrays$.clamp$bang |
@AllocFree @HotPath |
172 | 53% of 325 | yes | floatarrays.scala:417 |
vecxt.NDArrayFloatOps$.compareScalarGeneral |
@HotPath |
165 | 51% of 325 | yes | ndarrayFloatOps.scala:94 |
vecxt.NDArrayFloatOps$.binaryOpInPlaceGeneral |
@HotPath |
162 | 50% of 325 | yes | ndarrayFloatOps.scala:119 |
vecxt.NDArrayDoubleOps$.compareScalarGeneral |
@HotPath |
157 | 48% of 325 | yes | ndarrayDoubleOps.scala:102 |
vecxt.NDArrayIntOps$.compareScalarGeneral |
@HotPath |
156 | 48% of 325 | yes | ndarrayIntOps.scala:94 |
vecxt.NDArrayIntOps$.binaryOpInPlaceGeneral |
@HotPath |
153 | 47% of 325 | yes | ndarrayIntOps.scala:119 |
vecxt.NDArrayDoubleOps$.binaryOpInPlaceGeneral |
@HotPath |
153 | 47% of 325 | yes | ndarrayDoubleOps.scala:131 |
vecxt.NDArrayIntOps$.unaryOpGeneral |
@HotPath |
152 | 47% of 325 | yes | ndarrayIntOps.scala:42 |
vecxt.NDArrayDoubleOps$.unaryOpGeneral |
@HotPath |
152 | 47% of 325 | yes | ndarrayDoubleOps.scala:48 |
vecxt.intarrays$.$minus |
@Thin |
16 | 46% of 35 | no | intarrays.scala:519 |
vecxt.doublearrays$.fillLinspace |
@AllocFree @HotPath |
133 | 41% of 325 | yes | doublearrays.scala:34 |
vecxt.intarrays$.increments |
@HotPath |
121 | 37% of 325 | yes | intarrays.scala:219 |
vecxt.ndarray$.mkNDArray |
@Thin |
13 | 37% of 35 | no | ndarray.scala:188 |
vecxt.doublearrays$.$div |
@AllocFree @HotPath |
118 | 36% of 325 | yes | doublearrays.scala:1281 |
vecxt.doublearrays$.$plus |
@AllocFree @HotPath |
116 | 36% of 325 | yes | doublearrays.scala:1035 |
vecxt.doublearrays$.$minus |
@AllocFree @HotPath |
116 | 36% of 325 | yes | doublearrays.scala:1098 |
vecxt.doublearrays$.increments |
@HotPath |
110 | 34% of 325 | yes | doublearrays.scala:397 |
vecxt.intarrays$.dot |
@AllocFree @HotPath |
108 | 33% of 325 | yes | intarrays.scala:372 |
vecxt.doublearrays$.unary_$minus |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:172 |
vecxt.doublearrays$.tanh |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:365 |
vecxt.doublearrays$.tan |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:354 |
vecxt.doublearrays$.sqrt |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:317 |
vecxt.doublearrays$.sinh |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:339 |
vecxt.doublearrays$.sin |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:328 |
vecxt.doublearrays$.log1p |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:306 |
vecxt.doublearrays$.log10 |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:295 |
vecxt.doublearrays$.log |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:284 |
vecxt.doublearrays$.expm1 |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:273 |
vecxt.doublearrays$.exp |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:262 |
vecxt.doublearrays$.cosh |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:251 |
vecxt.doublearrays$.cos |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:240 |
vecxt.doublearrays$.cbrt |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:229 |
vecxt.doublearrays$.atan |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:218 |
vecxt.doublearrays$.asin |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:207 |
vecxt.doublearrays$.acos |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:196 |
vecxt.doublearrays$.abs |
@HotPath |
108 | 33% of 325 | yes | doublearrays.scala:184 |
vecxt.intarrays$.$less |
@HotPath |
106 | 33% of 325 | yes | intarrays.scala:48 |
vecxt.intarrays$.$less$eq |
@HotPath |
106 | 33% of 325 | yes | intarrays.scala:52 |
vecxt.intarrays$.$greater |
@HotPath |
106 | 33% of 325 | yes | intarrays.scala:56 |
vecxt.intarrays$.$greater$eq |
@HotPath |
106 | 33% of 325 | yes | intarrays.scala:60 |
vecxt.intarrays$.$eq$colon$eq |
@HotPath |
106 | 33% of 325 | yes | intarrays.scala:40 |
vecxt.intarrays$.$bang$colon$eq |
@HotPath |
106 | 33% of 325 | yes | intarrays.scala:44 |
vecxt.floatarrays$.unary_$minus |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:114 |
vecxt.floatarrays$.tanh |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:303 |
vecxt.floatarrays$.tan |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:292 |
vecxt.floatarrays$.sqrt |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:259 |
vecxt.floatarrays$.sinh |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:281 |
vecxt.floatarrays$.sin |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:270 |
vecxt.floatarrays$.log1p |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:248 |
vecxt.floatarrays$.log10 |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:237 |
vecxt.floatarrays$.log |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:226 |
vecxt.floatarrays$.expm1 |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:215 |
vecxt.floatarrays$.exp |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:204 |
vecxt.floatarrays$.cosh |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:193 |
vecxt.floatarrays$.cos |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:182 |
vecxt.floatarrays$.cbrt |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:171 |
vecxt.floatarrays$.atan |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:160 |
vecxt.floatarrays$.asin |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:149 |
vecxt.floatarrays$.acos |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:138 |
vecxt.floatarrays$.abs |
@HotPath |
104 | 32% of 325 | yes | floatarrays.scala:126 |
vecxt.intarrays$.mean |
@Thin |
11 | 31% of 35 | no | intarrays.scala:287 |
vecxt.doublearrays$.sumSIMD |
@AllocFree @HotPath |
102 | 31% of 325 | yes | doublearrays.scala:703 |
vecxt.doublearrays$.tanh$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.tan$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.sqrt$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.sinh$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.sin$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.log1p$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.log10$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.log$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.expm1$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.exp$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.cosh$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.cos$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.cbrt$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.atan$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.asin$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.acos$bang |
@HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.abs$bang |
@AllocFree @HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.doublearrays$.$minus$bang |
@AllocFree @HotPath |
98 | 30% of 325 | yes | doublearrays.scala:151 |
vecxt.floatarrays$.increments |
@HotPath |
97 | 30% of 325 | yes | floatarrays.scala:652 |
vecxt.doublearrays$.$times$times$bang |
@HotPath |
95 | 29% of 325 | yes | doublearrays.scala:372 |
vecxt.intarrays$.$less |
@HotPath |
94 | 29% of 325 | yes | intarrays.scala:139 |
vecxt.intarrays$.$less$eq |
@HotPath |
94 | 29% of 325 | yes | intarrays.scala:143 |
vecxt.intarrays$.$greater |
@HotPath |
94 | 29% of 325 | yes | intarrays.scala:147 |
vecxt.intarrays$.$greater$eq |
@HotPath |
94 | 29% of 325 | yes | intarrays.scala:151 |
vecxt.intarrays$.$eq$colon$eq |
@HotPath |
94 | 29% of 325 | yes | intarrays.scala:131 |
vecxt.intarrays$.$bang$colon$eq |
@HotPath |
94 | 29% of 325 | yes | intarrays.scala:135 |
vecxt.floatarrays$.tanh$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.tan$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.sqrt$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.sinh$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.sin$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.log1p$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.log10$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.log$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.expm1$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.exp$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.cosh$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.cos$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.cbrt$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.atan$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.asin$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.acos$bang |
@HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.abs$bang |
@AllocFree @HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.floatarrays$.$minus$bang |
@AllocFree @HotPath |
93 | 29% of 325 | yes | floatarrays.scala:94 |
vecxt.intarrays$.variance |
@Thin |
10 | 29% of 35 | no | intarrays.scala:304 |
vecxt.intarrays$.std |
@Thin |
10 | 29% of 35 | no | intarrays.scala:361 |
vecxt.doublearrays$.variance |
@AllocFree @Thin |
10 | 29% of 35 | no | doublearrays.scala:541 |
vecxt.doublearrays$.$minus$eq |
@AllocFree @HotPath |
92 | 28% of 325 | yes | doublearrays.scala:1145 |
vecxt.doublearrays$.$plus$eq |
@AllocFree @HotPath |
90 | 28% of 325 | yes | doublearrays.scala:1057 |
vecxt.doublearrays$.$times$eq |
@AllocFree @HotPath |
88 | 27% of 325 | yes | doublearrays.scala:1220 |
vecxt.doublearrays$.productSIMD |
@AllocFree @HotPath |
86 | 26% of 325 | yes | doublearrays.scala:726 |
vecxt.floatarrays$.$times$times$bang |
@HotPath |
85 | 26% of 325 | yes | floatarrays.scala:314 |
vecxt.doublearrays$.sumSIMD |
@AllocFree @HotPath |
85 | 26% of 325 | yes | doublearrays.scala:677 |
vecxt.doublearrays$.fma$bang |
@AllocFree @HotPath |
85 | 26% of 325 | yes | doublearrays.scala:1120 |
vecxt.intarrays$.$plus$eq |
@AllocFree @HotPath |
84 | 26% of 325 | yes | intarrays.scala:555 |
vecxt.intarrays$.$minus$eq |
@AllocFree @HotPath |
84 | 26% of 325 | yes | intarrays.scala:527 |
vecxt.floatarrays$.$times$eq |
@AllocFree @HotPath |
84 | 26% of 325 | yes | floatarrays.scala:874 |
vecxt.floatarrays$.$plus$eq |
@AllocFree @HotPath |
84 | 26% of 325 | yes | floatarrays.scala:772 |
vecxt.floatarrays$.$minus$eq |
@AllocFree @HotPath |
84 | 26% of 325 | yes | floatarrays.scala:812 |
vecxt.ndarrayOps.expandDims |
@Thin |
9 | 26% of 35 | no | ndarrayOps.scala |
vecxt.intarrays.stdDev |
@Thin |
9 | 26% of 35 | no | intarrays.scala |
vecxt.intarrays.meanAndVariance |
@Thin |
9 | 26% of 35 | no | intarrays.scala |
vecxt.intarrays.lte |
@Thin |
9 | 26% of 35 | no | intarrays.scala |
vecxt.intarrays.lte |
@Thin |
9 | 26% of 35 | no | intarrays.scala |
vecxt.intarrays.lt |
@Thin |
9 | 26% of 35 | no | intarrays.scala |
vecxt.intarrays.lt |
@Thin |
9 | 26% of 35 | no | intarrays.scala |
vecxt.intarrays.gte |
@Thin |
9 | 26% of 35 | no | intarrays.scala |
vecxt.intarrays.gte |
@Thin |
9 | 26% of 35 | no | intarrays.scala |
vecxt.intarrays.gt |
@Thin |
9 | 26% of 35 | no | intarrays.scala |
vecxt.intarrays.gt |
@Thin |
9 | 26% of 35 | no | intarrays.scala |
vecxt.intarrays$.variance |
@Thin |
9 | 26% of 35 | no | intarrays.scala:291 |
vecxt.intarrays$.stdDev |
@Thin |
9 | 26% of 35 | no | intarrays.scala:364 |
vecxt.intarrays$.std |
@Thin |
9 | 26% of 35 | no | intarrays.scala:357 |
vecxt.intarrays$.meanAndVariance |
@Thin |
9 | 26% of 35 | no | intarrays.scala:308 |
vecxt.doublearrays.meanAndVariance |
@Thin |
9 | 26% of 35 | no | doublearrays.scala |
vecxt.doublearrays$.meanAndVariance |
@Thin |
9 | 26% of 35 | no | doublearrays.scala:555 |
vecxt.intarrays$.minSIMD |
@AllocFree @HotPath |
82 | 25% of 325 | yes | intarrays.scala:575 |
vecxt.intarrays$.maxSIMD |
@AllocFree @HotPath |
82 | 25% of 325 | yes | intarrays.scala:595 |
vecxt.floatarrays$.productSIMD |
@AllocFree @HotPath |
82 | 25% of 325 | yes | floatarrays.scala:537 |
vecxt.intarrays$.sumSIMD |
@AllocFree @HotPath |
81 | 25% of 325 | yes | intarrays.scala:265 |
vecxt.floatarrays$.sumSIMD |
@AllocFree @HotPath |
81 | 25% of 325 | yes | floatarrays.scala:516 |
vecxt.floatarrays$.fma$bang |
@AllocFree @HotPath |
80 | 25% of 325 | yes | floatarrays.scala:340 |
vecxt.floatarrays$.$times$eq |
@AllocFree @HotPath |
78 | 24% of 325 | yes | floatarrays.scala:926 |
vecxt.ndarray.shapeArray |
@Thin |
8 | 23% of 35 | no | ndarray.scala |
vecxt.matrix$Matrix.rows |
@Thin |
8 | 23% of 35 | no | matrix.scala:192 |
vecxt.matrix$Matrix.rowStride |
@Thin |
8 | 23% of 35 | no | matrix.scala:198 |
vecxt.matrix$Matrix.offset |
@Thin |
8 | 23% of 35 | no | matrix.scala:204 |
vecxt.matrix$Matrix.numel |
@Thin |
8 | 23% of 35 | no | matrix.scala:207 |
vecxt.matrix$Matrix.isDenseRowMajor |
@Thin |
8 | 23% of 35 | no | matrix.scala:213 |
vecxt.matrix$Matrix.isDenseColMajor |
@Thin |
8 | 23% of 35 | no | matrix.scala:210 |
vecxt.matrix$Matrix.hasSimpleContiguousMemoryLayout |
@Thin |
8 | 23% of 35 | no | matrix.scala:225 |
vecxt.matrix$Matrix.cols |
@Thin |
8 | 23% of 35 | no | matrix.scala:195 |
vecxt.matrix$Matrix.colStride |
@Thin |
8 | 23% of 35 | no | matrix.scala:201 |
vecxt.intarrays$.countsToIdx |
@HotPath |
70 | 22% of 325 | yes | intarrays.scala:244 |
vecxt.intarrays$.$minus$eq |
@AllocFree @HotPath |
67 | 21% of 325 | yes | intarrays.scala:408 |
vecxt.floatarrays$.$plus$eq |
@AllocFree @HotPath |
24 | 7% of 325 | no | floatarrays.scala:731 |
Method sizes
| band | methods |
|---|---|
| <= 6 (trivial, always inlined) | 1411 |
| 7-35 (inlinable cold) | 3589 |
| 36-325 (inlinable when hot) | 691 |
| 326-8000 (not inlined) | 105 |
| > 8000 (NEVER JIT COMPILED) | 0 |
| bytes | method | module | at |
|---|---|---|---|
| 5643 | CheatsheetTest$.matrixRangeSlicing |
experiments | cheatsheet.scala:118 |
| 3815 | CheatsheetTest$.matrixReverseSlicing |
experiments | cheatsheet.scala:125 |
| 3801 | CheatsheetTest$.ndArrayInt |
experiments | cheatsheet.scala:416 |
| 3779 | CheatsheetTest$.ndArrayBoolean |
experiments | cheatsheet.scala:430 |
| 3061 | CheatsheetTest$.ndArrayFloat |
experiments | cheatsheet.scala:395 |
| 3015 | CheatsheetTest$.ndArrayFloatReductions |
experiments | cheatsheet.scala:405 |
| 2811 | CheatsheetTest$.matrixCreation |
experiments | cheatsheet.scala:72 |
| 2597 | CheatsheetTest$.matrixOps |
experiments | cheatsheet.scala:167 |
| 2500 | vecxt_re.Tower.show |
vecxt_re | Tower.scala:63 |
| 1896 | vecxt.JvmFloatMatrix$.floatmatrixSubVector |
vecxt | floatmatrix.scala:300 |
| 1594 | vecxt.ndarrayOps$.apply |
vecxt | ndarrayOps.scala:452 |
| 1581 | vecxt.JvmDoubleMatrix$.$plus$eq |
vecxt | doublematrix.scala:197 |
| 1557 | vecxt.JvmFloatMatrix$.floatmatrixAddVectorInPlace |
vecxt | floatmatrix.scala:218 |
| 1557 | vecxt.JvmFloatMatrix$.floatmatrixSubVectorInPlace |
vecxt | floatmatrix.scala:318 |
| 1460 | CheatsheetTest$.indexingAndSlicing |
experiments | cheatsheet.scala:98 |
| 1435 | vecxt.JvmDoubleMatrix$.$plus$eq |
vecxt | doublematrix.scala:279 |
| 1420 | vecxt.JvmFloatMatrix$.floatmatrixAddScalarInPlace |
vecxt | floatmatrix.scala:394 |
| 1420 | vecxt.JvmFloatMatrix$.floatmatrixSubScalarInPlace |
vecxt | floatmatrix.scala:466 |
| 1308 | CheatsheetTest$.arrayManipulation |
experiments | cheatsheet.scala:305 |
| 1122 | vecxt.Svd$.pinv |
vecxt | svd.scala:42 |
| 1028 | CheatsheetTest$.matrixFloat |
experiments | cheatsheet.scala:445 |
| 969 | vecxt_re.Scenarr$.combine |
vecxt_re | scenarr.scala:160 |
| 923 | CheatsheetTest$.matrixInt |
experiments | cheatsheet.scala:461 |
| 908 | vecxt.Svd$.svd |
vecxt | svd.scala:135 |
| 896 | vecxt_re.NegativeBinomial$.volweightedMle |
vecxt_re | NegativeBinomial.scala:281 |
Proposed baseline
{
"jdkMajor": 25,
"c9": { "totalBytes": 42067, "distinctOps": 198 },
"annotated": {
"vecxt.NDArrayDoubleOps$.binaryOpGeneral(Lvecxt/ndarray$NDArray;Lvecxt/ndarray$NDArray;Lscala/Function2;)Lvecxt/ndarray$NDArray;": 186,
"vecxt.NDArrayDoubleOps$.binaryOpInPlaceGeneral(Lvecxt/ndarray$NDArray;Lvecxt/ndarray$NDArray;Lscala/Function2;)V": 153,
"vecxt.NDArrayDoubleOps$.compareGeneral(Lvecxt/ndarray$NDArray;Lvecxt/ndarray$NDArray;Lscala/Function2;)Lvecxt/ndarray$NDArray;": 186,
"vecxt.NDArrayDoubleOps$.compareScalarGeneral(Lvecxt/ndarray$NDArray;DLscala/Function2;)Lvecxt/ndarray$NDArray;": 157,
"vecxt.NDArrayDoubleOps$.unaryOpGeneral(Lvecxt/ndarray$NDArray;Lscala/Function1;)Lvecxt/ndarray$NDArray;": 152,
"vecxt.NDArrayFloatOps$.binaryOpGeneral(Lvecxt/ndarray$NDArray;Lvecxt/ndarray$NDArray;Lscala/Function2;)Lvecxt/ndarray$NDArray;": 195,
"vecxt.NDArrayFloatOps$.binaryOpInPlaceGeneral(Lvecxt/ndarray$NDArray;Lvecxt/ndarray$NDArray;Lscala/Function2;)V": 162,
"vecxt.NDArrayFloatOps$.compareGeneral(Lvecxt/ndarray$NDArray;Lvecxt/ndarray$NDArray;Lscala/Function2;)Lvecxt/ndarray$NDArray;": 195,
"vecxt.NDArrayFloatOps$.compareScalarGeneral(Lvecxt/ndarray$NDArray;FLscala/Function2;)Lvecxt/ndarray$NDArray;": 165,
"vecxt.NDArrayIntOps$.binaryOpGeneral(Lvecxt/ndarray$NDArray;Lvecxt/ndarray$NDArray;Lscala/Function2;)Lvecxt/ndarray$NDArray;": 186,
"vecxt.NDArrayIntOps$.binaryOpInPlaceGeneral(Lvecxt/ndarray$NDArray;Lvecxt/ndarray$NDArray;Lscala/Function2;)V": 153,
"vecxt.NDArrayIntOps$.compareGeneral(Lvecxt/ndarray$NDArray;Lvecxt/ndarray$NDArray;Lscala/Function2;)Lvecxt/ndarray$NDArray;": 186,
"vecxt.NDArrayIntOps$.compareScalarGeneral(Lvecxt/ndarray$NDArray;ILscala/Function2;)Lvecxt/ndarray$NDArray;": 156,
"vecxt.NDArrayIntOps$.unaryOpGeneral(Lvecxt/ndarray$NDArray;Lscala/Function1;)Lvecxt/ndarray$NDArray;": 152,
"vecxt.doublearrays$.$div([DDII[DI)V": 118,
"vecxt.doublearrays$.$minus$bang([D)V": 98,
"vecxt.doublearrays$.$minus$eq([DD)V": 92,
"vecxt.doublearrays$.$minus([DDII[DI)V": 116,
"vecxt.doublearrays$.$plus$eq([DD)V": 90,
"vecxt.doublearrays$.$plus([DDII[DI)V": 116,
"vecxt.doublearrays$.$times$eq([D[D)V": 88,
"vecxt.doublearrays$.$times$times$bang([DD)V": 95,
"vecxt.doublearrays$.abs$bang([D)V": 98,
"vecxt.doublearrays$.abs([D)[D": 108,
"vecxt.doublearrays$.acos$bang([D)V": 98,
"vecxt.doublearrays$.acos([D)[D": 108,
"vecxt.doublearrays$.asin$bang([D)V": 98,
"vecxt.doublearrays$.asin([D)[D": 108,
"vecxt.doublearrays$.atan$bang([D)V": 98,
"vecxt.doublearrays$.atan([D)[D": 108,
"vecxt.doublearrays$.cbrt$bang([D)V": 98,
"vecxt.doublearrays$.cbrt([D)[D": 108,
"vecxt.doublearrays$.clamp$bang([DDD)V": 180,
"vecxt.doublearrays$.cos$bang([D)V": 98,
"vecxt.doublearrays$.cos([D)[D": 108,
"vecxt.doublearrays$.cosh$bang([D)V": 98,
"vecxt.doublearrays$.cosh([D)[D": 108,
"vecxt.doublearrays$.exp$bang([D)V": 98,
"vecxt.doublearrays$.exp([D)[D": 108,
"vecxt.doublearrays$.expm1$bang([D)V": 98,
"vecxt.doublearrays$.expm1([D)[D": 108,
"vecxt.doublearrays$.fillLinspace([DDD)V": 133,
"vecxt.doublearrays$.fma$bang([DDD)V": 85,
"vecxt.doublearrays$.increments([D)[D": 110,
"vecxt.doublearrays$.log$bang([D)V": 98,
"vecxt.doublearrays$.log([D)[D": 108,
"vecxt.doublearrays$.log10$bang([D)V": 98,
"vecxt.doublearrays$.log10([D)[D": 108,
"vecxt.doublearrays$.log1p$bang([D)V": 98,
"vecxt.doublearrays$.log1p([D)[D": 108,
"vecxt.doublearrays$.meanAndVariance([D)Lvecxt/MeanAndVariance;": 9,
"vecxt.doublearrays$.productSIMD([D)D": 86,
"vecxt.doublearrays$.sin$bang([D)V": 98,
"vecxt.doublearrays$.sin([D)[D": 108,
"vecxt.doublearrays$.sinh$bang([D)V": 98,
"vecxt.doublearrays$.sinh([D)[D": 108,
"vecxt.doublearrays$.sqrt$bang([D)V": 98,
"vecxt.doublearrays$.sqrt([D)[D": 108,
"vecxt.doublearrays$.sumSIMD([D)D": 85,
"vecxt.doublearrays$.sumSIMD([DII)D": 102,
"vecxt.doublearrays$.tan$bang([D)V": 98,
"vecxt.doublearrays$.tan([D)[D": 108,
"vecxt.doublearrays$.tanh$bang([D)V": 98,
"vecxt.doublearrays$.tanh([D)[D": 108,
"vecxt.doublearrays$.unary_$minus([D)[D": 108,
"vecxt.doublearrays$.variance([DLvecxt/VarianceMode;)D": 10,
"vecxt.doublearrays.meanAndVariance([DLvecxt/VarianceMode;)Lvecxt/MeanAndVariance;": 9,
"vecxt.floatarrays$.$minus$bang([F)V": 93,
"vecxt.floatarrays$.$minus$eq([FF)V": 84,
"vecxt.floatarrays$.$plus$eq([FF)V": 84,
"vecxt.floatarrays$.$plus$eq([F[F)V": 24,
"vecxt.floatarrays$.$times$eq([FF)V": 78,
"vecxt.floatarrays$.$times$eq([F[F)V": 84,
"vecxt.floatarrays$.$times$times$bang([FF)V": 85,
"vecxt.floatarrays$.abs$bang([F)V": 93,
"vecxt.floatarrays$.abs([F)[F": 104,
"vecxt.floatarrays$.acos$bang([F)V": 93,
"vecxt.floatarrays$.acos([F)[F": 104,
"vecxt.floatarrays$.asin$bang([F)V": 93,
"vecxt.floatarrays$.asin([F)[F": 104,
"vecxt.floatarrays$.atan$bang([F)V": 93,
"vecxt.floatarrays$.atan([F)[F": 104,
"vecxt.floatarrays$.cbrt$bang([F)V": 93,
"vecxt.floatarrays$.cbrt([F)[F": 104,
"vecxt.floatarrays$.clamp$bang([FFF)V": 172,
"vecxt.floatarrays$.cos$bang([F)V": 93,
"vecxt.floatarrays$.cos([F)[F": 104,
"vecxt.floatarrays$.cosh$bang([F)V": 93,
"vecxt.floatarrays$.cosh([F)[F": 104,
"vecxt.floatarrays$.exp$bang([F)V": 93,
"vecxt.floatarrays$.exp([F)[F": 104,
"vecxt.floatarrays$.expm1$bang([F)V": 93,
"vecxt.floatarrays$.expm1([F)[F": 104,
"vecxt.floatarrays$.fma$bang([FFF)V": 80,
"vecxt.floatarrays$.increments([F)[F": 97,
"vecxt.floatarrays$.log$bang([F)V": 93,
"vecxt.floatarrays$.log([F)[F": 104,
"vecxt.floatarrays$.log10$bang([F)V": 93,
"vecxt.floatarrays$.log10([F)[F": 104,
"vecxt.floatarrays$.log1p$bang([F)V": 93,
"vecxt.floatarrays$.log1p([F)[F": 104,
"vecxt.floatarrays$.productSIMD([F)F": 82,
"vecxt.floatarrays$.sin$bang([F)V": 93,
"vecxt.floatarrays$.sin([F)[F": 104,
"vecxt.floatarrays$.sinh$bang([F)V": 93,
"vecxt.floatarrays$.sinh([F)[F": 104,
"vecxt.floatarrays$.sqrt$bang([F)V": 93,
"vecxt.floatarrays$.sqrt([F)[F": 104,
"vecxt.floatarrays$.sumSIMD([F)F": 81,
"vecxt.floatarrays$.tan$bang([F)V": 93,
"vecxt.floatarrays$.tan([F)[F": 104,
"vecxt.floatarrays$.tanh$bang([F)V": 93,
"vecxt.floatarrays$.tanh([F)[F": 104,
"vecxt.floatarrays$.unary_$minus([F)[F": 104,
"vecxt.intarrays$.$bang$colon$eq([II)[Z": 94,
"vecxt.intarrays$.$bang$colon$eq([I[I)[Z": 106,
"vecxt.intarrays$.$eq$colon$eq([II)[Z": 94,
"vecxt.intarrays$.$eq$colon$eq([I[I)[Z": 106,
"vecxt.intarrays$.$greater$eq([II)[Z": 94,
"vecxt.intarrays$.$greater$eq([I[I)[Z": 106,
"vecxt.intarrays$.$greater([II)[Z": 94,
"vecxt.intarrays$.$greater([I[I)[Z": 106,
"vecxt.intarrays$.$less$eq([II)[Z": 94,
"vecxt.intarrays$.$less$eq([I[I)[Z": 106,
"vecxt.intarrays$.$less([II)[Z": 94,
"vecxt.intarrays$.$less([I[I)[Z": 106,
"vecxt.intarrays$.$minus$eq([II)V": 67,
"vecxt.intarrays$.$minus$eq([I[I)V": 84,
"vecxt.intarrays$.$minus([II)[I": 16,
"vecxt.intarrays$.$minus([I[I)[I": 24,
"vecxt.intarrays$.$plus$eq([I[I)V": 84,
"vecxt.intarrays$.$plus([I[I)[I": 24,
"vecxt.intarrays$.countsToIdx([I)[I": 70,
"vecxt.intarrays$.dot([I[I)I": 108,
"vecxt.intarrays$.increments([I)[I": 121,
"vecxt.intarrays$.maxSIMD([I)I": 82,
"vecxt.intarrays$.mean([I)D": 11,
"vecxt.intarrays$.meanAndVariance([I)Lvecxt/MeanAndVariance;": 9,
"vecxt.intarrays$.minSIMD([I)I": 82,
"vecxt.intarrays$.std([I)D": 9,
"vecxt.intarrays$.std([ILvecxt/VarianceMode;)D": 10,
"vecxt.intarrays$.stdDev([I)D": 9,
"vecxt.intarrays$.sumSIMD([I)I": 81,
"vecxt.intarrays$.variance([I)D": 9,
"vecxt.intarrays$.variance([ILvecxt/VarianceMode;)D": 10,
"vecxt.intarrays.gt([II)[Z": 9,
"vecxt.intarrays.gt([I[I)[Z": 9,
"vecxt.intarrays.gte([II)[Z": 9,
"vecxt.intarrays.gte([I[I)[Z": 9,
"vecxt.intarrays.lt([II)[Z": 9,
"vecxt.intarrays.lt([I[I)[Z": 9,
"vecxt.intarrays.lte([II)[Z": 9,
"vecxt.intarrays.lte([I[I)[Z": 9,
"vecxt.intarrays.meanAndVariance([ILvecxt/VarianceMode;)Lvecxt/MeanAndVariance;": 9,
"vecxt.intarrays.stdDev([ILvecxt/VarianceMode;)D": 9,
"vecxt.matrix$Layout.linearIndex(II)I": 19,
"vecxt.matrix$Matrix.colStride()I": 8,
"vecxt.matrix$Matrix.cols()I": 8,
"vecxt.matrix$Matrix.hasSimpleContiguousMemoryLayout()Z": 8,
"vecxt.matrix$Matrix.isDenseColMajor()Z": 8,
"vecxt.matrix$Matrix.isDenseRowMajor()Z": 8,
"vecxt.matrix$Matrix.numel()I": 8,
"vecxt.matrix$Matrix.offset()I": 8,
"vecxt.matrix$Matrix.rowStride()I": 8,
"vecxt.matrix$Matrix.rows()I": 8,
"vecxt.ndarray$.mkNDArray(Ljava/lang/Object;[I[II)Lvecxt/ndarray$NDArray;": 13,
"vecxt.ndarray.shapeArray(Lvecxt/ndarray$NDArray;)[I": 8,
"vecxt.ndarrayOps.expandDims(Lvecxt/ndarray$NDArray;I)Lvecxt/ndarray$NDArray;": 9
}
}
|
@copilot The extra kernels you've added should also be annotated @hotpath or @AllocFree ? Please annotate as appropriate |
…it tests Co-authored-by: Quafadas <24899792+Quafadas@users.noreply.github.com>
Added |
Blocker 1 — the segment / kernel isn't self-consistentval recip = DoubleVector.broadcast(spd, 1.0 / d)
while i < bound do ... .mul(recip) ... // reciprocal multiply
while i < end do dest(i + shift) = vec(i) / d // true divisionVector body multiplies by 1/d, scalar tail divides. So within one call, whether an element gets x * (1/d) or x / d depends on its index modulo the lane count. For d = 3.0 and the test's own backing values, indices whose value is 5, 7, 10, 14, 17, 20, 23, 25, 28… differ by 1 ulp between the two forms. I checked this rather than asserting it: mismatch values for d=3: [5, 7, 10, 14, 17, 20, 23, 25, 28, 31, ...] The new test doesn't catch it because it picks d = 2.0, where the reciprocal is exact. Change the divisor to 3.0, assert exact equality, and it fails — the tail values in that test are 26, 27, 28, and 28 is in the mismatch set. Fix is one line (tail multiplies by the same scalar reciprocal), and it aligns with whole-array /=, which is already dscal(1.0/d) throughout. Worth noting the pre-existing consequence too: JVM /= is reciprocal-based while JS/Native do true division, so goal #3 is already slightly violated there. That's a separate issue, but this PR shouldn't add an intra-array version of the same problem. Blocker 2 — publishing JVM-only public API with no callersThe PR explicitly defers wiring the segment kernels ("needs a JVM-specific dispatch seam that doesn't yet exist"). So we'd be adding ~8 public extension overloads to doublearrays that: exist on JVM only, so any user who writes against them breaks their cross-platform build, Add a scala.compiletime.error in their cross platform equivalents. Blocker 3Layout property test (op(view) == op(copy)), which will go red on maximum — fix that too. The layout space is small and structured, so enumerate it The interesting dimension is layout kind, not layout values, and the kinds are countable: // (rows, cols, rowStride, colStride, offset, padding)
val corpus = for
(r, c) <- List((1,1), (1,4), (4,1), (2,3), (3,2), (3,3))
kind <- List(RowMajor, ColMajor, RowMajorPadded, ColMajorPadded, DoublyStrided)
offset <- List(0, 1, 7)
yield mkLayout(r, c, kind, offset)That's ~90 cases, runs in milliseconds on all three platforms, and — the bit that matters for goal #3 — JVM, JS and Native all run the identical corpus. A random generator gives each platform a different sample unless you pin the seed, which quietly weakens "the same tests pass everywhere" into "some tests passed everywhere." For a cross-platform consistency gate that's the wrong trade. Deterministic also means a failure is a failure, not a Tuesday. An intermittent red on main from an unlucky seed is corrosive in a way that's hard to walk back. The oracle matters far more than the randomness This is the part I'd focus your energy on. The property is only worth anything if the reference side is written independently of the code under test. If materialise routes through foreach2D or the same linearIndex loops, you're comparing the implementation against itself and the test is vacuous — it would have passed happily on main with sqrt! applying twice. So the oracle should be a deliberately stupid model, in the test source, that shares nothing with vecxt: // model: logical (i,j) -> value, nothing but arithmetic
def model[A](m: Matrix[A]): (Int, Int) => A =
(i, j) => m.raw(m.layout.offset + i * m.layout.rowStride + j * m.layout.colStride)
// property: for every op, every layout
forEachLayout { lay =>
val view = Matrix(backing, lay)
val got = op(view)
val want = /* op applied elementwise via model, into a fresh dense matrix */
assertLogicallyEqual(got, want) // compares (i,j) -> value, NOT raw arrays
}```
Two details that do the real work:
Compare logically, not rawly. assertLogicallyEqual walks (i, j) through each side's own layout. Compare raw arrays and you'll false-positive on the maximum row/col-major bug in the wrong direction — or miss it.
Non-square, distinct values. Use Array.tabulate(i => (i + 1).toDouble). Distinctness is what makes a transposition visible; random doubles are also distinct but the failure message is unreadable, and Array.fill(1.0) would hide maximum entirely. Non-square is what makes a transposed shape an error rather than a silent value swap. |
…-ups-again # Conflicts: # vecxt/src-jvm/doublearrays.scala # vecxt/src/doublematrix.scala Co-authored-by: Quafadas <24899792+Quafadas@users.noreply.github.com>
…pus test Co-authored-by: Quafadas <24899792+Quafadas@users.noreply.github.com>
... All three addressed:
Also rebased onto |
Follow-up to the
Layoutextraction (#108/#109): 58 elementwise/strided loops across the matrix implementation walkedrowsouter /colsinner regardless of which axis was actually contiguous in memory, making every submatrix view cache-hostile and unvectorisable. Separately, all SIMD kernels indoublearrays.scalawere whole-array only, so strided views could never reach them at all.Unit-stride-innermost traversal (Phase C)
Layout.unitStrideAxis(0 = rows, 1 = cols, -1 = neither) and a sharedinlineLayout.foreach2D(inline body: (Int, Int) => Unit)helper that nests the loop so the contiguous axis is always innermost, for both source reads and column-major destination writes.foreach2D, across:vecxt/src/doublematrix.scala,vecxt/src/MatrixInstance.scala(shared)vecxt/src-jvm/floatmatrix.scala,vecxt/src-jvm/doublematrix.scala,vecxt/src-jvm/intmatrix.scalavecxt/src-js/doublematrix.scalavecxt/src-native/doublematrix_native.scalaprintMat) and already-fast-pathed/???branches were left untouched.Offset/length SIMD kernels (Phase D, Double/JVM only)
Layout.segmentCount/segmentLength/segmentStart— decomposes a layout with a unit-stride axis into its contiguous runs.(from, len)and(d, from, len, dest, destFrom)overloads tovecxt/src-jvm/doublearrays.scalaforsumSIMD,norm,multInPlace/*=,/=,+,-,/, so a single contiguous column/row segment of a view can go through BLAS/Vector-API kernels without first materialising the whole array. Whole-array methods are unchanged.vecxt/test/src-jvm/doublearraysSegment.test.scala, validating each new overload against the equivalent whole-array kernel run on a sliced copy.Deferred, not in scope for this PR: wiring
DoubleMatrix's strided scalar-op branches (*=,*,/,+,-) to dispatch through these segment kernels, and the JMH crossover-size benchmarking called for in the issue. The call sites live in cross-platform shared code while the new kernels are intentionally JVM-only, so this needs a JVM-specific dispatch seam that doesn't yet exist — left as a follow-up rather than bolted on here.