| 119 | #endif |
| 120 | |
| 121 | static void _matmul( |
| 122 | float* xout, float* x, float* w, int n, int d, |
| 123 | const int* block_size, float* scale, |
| 124 | void* unused_aqb |
| 125 | ) { |
| 126 | // W (d,n) @ x (n,) -> xout (d,) |
| 127 | (void)unused_aqb; |
| 128 | static float one = 1.0f; |
| 129 | int dummy_block_size[2] = {d, n}; |
| 130 | if (scale == nullptr) { |
| 131 | scale = &one; |
| 132 | block_size = dummy_block_size; |
| 133 | } |
| 134 | int scale_num_cols = (n + block_size[1] - 1) / block_size[1]; |
| 135 | for (int scale_i = 0; scale_i < cdiv(d, block_size[0]); scale_i++) { |
| 136 | int ii; |
| 137 | #pragma omp parallel for private(ii) |
| 138 | for (ii = 0; ii < block_size[0]; ii++) { |
| 139 | int i = scale_i * block_size[0] + ii; |
| 140 | if (i >= d) { |
| 141 | continue; |
| 142 | } |
| 143 | float val = 0.0f; |
| 144 | for (int scale_j = 0; scale_j < cdiv(n, block_size[1]); scale_j++) { |
| 145 | float scale_val = scale[scale_i * scale_num_cols + scale_j]; |
| 146 | for (int jj = 0; jj < block_size[1]; jj++) { |
| 147 | int j = scale_j * block_size[1] + jj; |
| 148 | if (j >= n) { |
| 149 | break; |
| 150 | } |
| 151 | val += (w[i * n + j] * x[j]) * scale_val; |
| 152 | } |
| 153 | } |
| 154 | xout[i] = val; |
| 155 | } |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | // matmul supporting float16 weights via the F16C extension, which allows |
| 160 | // conversion into float32 values before calculations. |
no test coverage detected