| 630 | } |
| 631 | |
| 632 | void quantize_row_q8_0(const float * restrict x, void * restrict vy, int k) { |
| 633 | assert(QK8_0 == 32); |
| 634 | assert(k % QK8_0 == 0); |
| 635 | const int nb = k / QK8_0; |
| 636 | |
| 637 | block_q8_0 * restrict y = vy; |
| 638 | |
| 639 | #if defined(__ARM_NEON) |
| 640 | for (int i = 0; i < nb; i++) { |
| 641 | float32x4_t srcv [8]; |
| 642 | float32x4_t asrcv[8]; |
| 643 | float32x4_t amaxv[8]; |
| 644 | |
| 645 | for (int j = 0; j < 8; j++) srcv[j] = vld1q_f32(x + i*32 + 4*j); |
| 646 | for (int j = 0; j < 8; j++) asrcv[j] = vabsq_f32(srcv[j]); |
| 647 | |
| 648 | for (int j = 0; j < 4; j++) amaxv[2*j] = vmaxq_f32(asrcv[2*j], asrcv[2*j+1]); |
| 649 | for (int j = 0; j < 2; j++) amaxv[4*j] = vmaxq_f32(amaxv[4*j], amaxv[4*j+2]); |
| 650 | for (int j = 0; j < 1; j++) amaxv[8*j] = vmaxq_f32(amaxv[8*j], amaxv[8*j+4]); |
| 651 | |
| 652 | const float amax = vmaxvq_f32(amaxv[0]); |
| 653 | |
| 654 | const float d = amax / ((1 << 7) - 1); |
| 655 | const float id = d ? 1.0f/d : 0.0f; |
| 656 | |
| 657 | y[i].d = GGML_FP32_TO_FP16(d); |
| 658 | |
| 659 | for (int j = 0; j < 8; j++) { |
| 660 | const float32x4_t v = vmulq_n_f32(srcv[j], id); |
| 661 | const int32x4_t vi = vcvtnq_s32_f32(v); |
| 662 | |
| 663 | y[i].qs[4*j + 0] = vgetq_lane_s32(vi, 0); |
| 664 | y[i].qs[4*j + 1] = vgetq_lane_s32(vi, 1); |
| 665 | y[i].qs[4*j + 2] = vgetq_lane_s32(vi, 2); |
| 666 | y[i].qs[4*j + 3] = vgetq_lane_s32(vi, 3); |
| 667 | } |
| 668 | } |
| 669 | #elif defined(__wasm_simd128__) |
| 670 | for (int i = 0; i < nb; i++) { |
| 671 | v128_t srcv [8]; |
| 672 | v128_t asrcv[8]; |
| 673 | v128_t amaxv[8]; |
| 674 | |
| 675 | for (int j = 0; j < 8; j++) srcv[j] = wasm_v128_load(x + i*32 + 4*j); |
| 676 | for (int j = 0; j < 8; j++) asrcv[j] = wasm_f32x4_abs(srcv[j]); |
| 677 | |
| 678 | for (int j = 0; j < 4; j++) amaxv[2*j] = wasm_f32x4_max(asrcv[2*j], asrcv[2*j+1]); |
| 679 | for (int j = 0; j < 2; j++) amaxv[4*j] = wasm_f32x4_max(amaxv[4*j], amaxv[4*j+2]); |
| 680 | for (int j = 0; j < 1; j++) amaxv[8*j] = wasm_f32x4_max(amaxv[8*j], amaxv[8*j+4]); |
| 681 | |
| 682 | const float amax = MAX(MAX(wasm_f32x4_extract_lane(amaxv[0], 0), |
| 683 | wasm_f32x4_extract_lane(amaxv[0], 1)), |
| 684 | MAX(wasm_f32x4_extract_lane(amaxv[0], 2), |
| 685 | wasm_f32x4_extract_lane(amaxv[0], 3))); |
| 686 | |
| 687 | const float d = amax / ((1 << 7) - 1); |
| 688 | const float id = d ? 1.0f/d : 0.0f; |
| 689 |
nothing calls this directly
no test coverage detected