| 2 | #include "quant.h" |
| 3 | |
| 4 | torch::Tensor quantize_q2_k(torch::Tensor& input) { |
| 5 | // Row-major quantization (equivalent to block size [1, 256]) |
| 6 | // of input tensor using Q2_K scheme. |
| 7 | TORCH_CHECK(input.ndimension() == 2, "input must be 2D"); |
| 8 | TORCH_CHECK(input.size(1) % QK_K == 0, "ncols must be divisible by QK_K"); |
| 9 | TORCH_CHECK(input.dtype() == torch::kFloat32, "input must be float32"); |
| 10 | if (!input.is_contiguous()) { |
| 11 | input = input.contiguous(); |
| 12 | } |
| 13 | const int64_t nrows = input.size(0); |
| 14 | const int64_t ncols = input.size(1); |
| 15 | const int64_t blocks_per_row = ncols / QK_K; |
| 16 | const int64_t block_size = sizeof(block_q2_K); |
| 17 | |
| 18 | auto options = torch::TensorOptions().dtype(torch::kUInt8).device(torch::kCPU); |
| 19 | auto output = torch::empty({nrows, blocks_per_row * block_size}, options); |
| 20 | |
| 21 | const float* input_ptr = input.data_ptr<float>(); |
| 22 | uint8_t* output_ptr = output.data_ptr<uint8_t>(); |
| 23 | |
| 24 | // Parallelize over rows |
| 25 | #pragma omp parallel for |
| 26 | for (int64_t row = 0; row < nrows; row++) { |
| 27 | const float* row_input = input_ptr + row * ncols; |
| 28 | block_q2_K* row_output = reinterpret_cast<block_q2_K*>(output_ptr + row * blocks_per_row * block_size); |
| 29 | |
| 30 | quantize_row_q2_K_ref(row_input, row_output, ncols); |
| 31 | } |
| 32 | |
| 33 | return output; |
| 34 | } |
| 35 | |
| 36 | torch::Tensor quantize_q3_k(torch::Tensor& input) { |
| 37 | // Row-major quantization (equivalent to block size [1, 256]) |
nothing calls this directly
no test coverage detected