@@ -359,29 +359,36 @@ TARGET_ARM_BF16_ATTRIBUTE static void dot4_with_fp32_arith_bfdot(
359359 int64_t len,
360360 float * out) {
361361 constexpr int64_t kElementsPerIteration = 8 ;
362- float32x4_t acc[4 ] = {
363- vdupq_n_f32 (0 .0f ),
364- vdupq_n_f32 (0 .0f ),
365- vdupq_n_f32 (0 .0f ),
366- vdupq_n_f32 (0 .0f )};
362+ float32x4_t acc0 = vdupq_n_f32 (0 .0f );
363+ float32x4_t acc1 = vdupq_n_f32 (0 .0f );
364+ float32x4_t acc2 = vdupq_n_f32 (0 .0f );
365+ float32x4_t acc3 = vdupq_n_f32 (0 .0f );
367366 int64_t idx = 0 ;
368367 for (; idx + kElementsPerIteration <= len; idx += kElementsPerIteration ) {
369368 // See NOTE[Intrinsics in bfdot variant] above.
370369 const auto v1 = vld1q_bf16 (reinterpret_cast <const bfloat16_t *>(&vec1[idx]));
371- for (int64_t j = 0 ; j < 4 ; ++j) {
372- const auto v2 = vld1q_bf16 (
373- reinterpret_cast <const bfloat16_t *>(&vec2[j * stride2 + idx]));
374- acc[j] = vbfdotq_f32 (acc[j], v1, v2);
375- }
370+ const auto v20 =
371+ vld1q_bf16 (reinterpret_cast <const bfloat16_t *>(&vec2[idx]));
372+ const auto v21 =
373+ vld1q_bf16 (reinterpret_cast <const bfloat16_t *>(&vec2[stride2 + idx]));
374+ const auto v22 = vld1q_bf16 (
375+ reinterpret_cast <const bfloat16_t *>(&vec2[2 * stride2 + idx]));
376+ const auto v23 = vld1q_bf16 (
377+ reinterpret_cast <const bfloat16_t *>(&vec2[3 * stride2 + idx]));
378+ acc0 = vbfdotq_f32 (acc0, v1, v20);
379+ acc1 = vbfdotq_f32 (acc1, v1, v21);
380+ acc2 = vbfdotq_f32 (acc2, v1, v22);
381+ acc3 = vbfdotq_f32 (acc3, v1, v23);
376382 }
377383 const float32x4_t sums =
378- vpaddq_f32 (vpaddq_f32 (acc[ 0 ], acc[ 1 ] ), vpaddq_f32 (acc[ 2 ], acc[ 3 ] ));
384+ vpaddq_f32 (vpaddq_f32 (acc0, acc1 ), vpaddq_f32 (acc2, acc3 ));
379385 vst1q_f32 (out, sums);
380386 for (; idx < len; ++idx) {
381- for (int64_t j = 0 ; j < 4 ; ++j) {
382- out[j] += static_cast <float >(vec1[idx]) *
383- static_cast <float >(vec2[j * stride2 + idx]);
384- }
387+ const float v1 = static_cast <float >(vec1[idx]);
388+ out[0 ] += v1 * static_cast <float >(vec2[idx]);
389+ out[1 ] += v1 * static_cast <float >(vec2[stride2 + idx]);
390+ out[2 ] += v1 * static_cast <float >(vec2[2 * stride2 + idx]);
391+ out[3 ] += v1 * static_cast <float >(vec2[3 * stride2 + idx]);
385392 }
386393}
387394
@@ -411,6 +418,123 @@ TARGET_ARM_BF16_ATTRIBUTE static void gemv_transa_with_fp32_arith_bfdot(
411418#endif // COMPILER_SUPPORTS_ARM_BF16_TARGET
412419
413420#if defined(__aarch64__)
421+ C10_ALWAYS_INLINE float32x4_t
422+ initialize_gemv_acc_neon (float beta, const float * c) {
423+ if (beta == 0 .0f ) {
424+ return vdupq_n_f32 (0 .0f );
425+ }
426+ const float32x4_t value = vld1q_f32 (c);
427+ return beta == 1 .0f ? value : vmulq_n_f32 (value, beta);
428+ }
429+
430+ template <typename b_t >
431+ C10_ALWAYS_INLINE void gemv_notrans_block64_neon (
432+ int64_t output_offset,
433+ int64_t k,
434+ float alpha,
435+ const BFloat16* a,
436+ int64_t lda,
437+ const b_t * b,
438+ float beta,
439+ float * c) {
440+ float32x4_t acc0 = initialize_gemv_acc_neon (beta, c + output_offset);
441+ float32x4_t acc1 = initialize_gemv_acc_neon (beta, c + output_offset + 4 );
442+ float32x4_t acc2 = initialize_gemv_acc_neon (beta, c + output_offset + 8 );
443+ float32x4_t acc3 = initialize_gemv_acc_neon (beta, c + output_offset + 12 );
444+ float32x4_t acc4 = initialize_gemv_acc_neon (beta, c + output_offset + 16 );
445+ float32x4_t acc5 = initialize_gemv_acc_neon (beta, c + output_offset + 20 );
446+ float32x4_t acc6 = initialize_gemv_acc_neon (beta, c + output_offset + 24 );
447+ float32x4_t acc7 = initialize_gemv_acc_neon (beta, c + output_offset + 28 );
448+ float32x4_t acc8 = initialize_gemv_acc_neon (beta, c + output_offset + 32 );
449+ float32x4_t acc9 = initialize_gemv_acc_neon (beta, c + output_offset + 36 );
450+ float32x4_t acc10 = initialize_gemv_acc_neon (beta, c + output_offset + 40 );
451+ float32x4_t acc11 = initialize_gemv_acc_neon (beta, c + output_offset + 44 );
452+ float32x4_t acc12 = initialize_gemv_acc_neon (beta, c + output_offset + 48 );
453+ float32x4_t acc13 = initialize_gemv_acc_neon (beta, c + output_offset + 52 );
454+ float32x4_t acc14 = initialize_gemv_acc_neon (beta, c + output_offset + 56 );
455+ float32x4_t acc15 = initialize_gemv_acc_neon (beta, c + output_offset + 60 );
456+
457+ for (int64_t l = 0 ; l < k; ++l) {
458+ const float b_val = static_cast <float >(b[l]) * alpha;
459+ const auto * a_col =
460+ reinterpret_cast <const uint16_t *>(a + l * lda + output_offset);
461+
462+ uint16x8_t a_bf16 = vld1q_u16 (a_col);
463+ acc0 = vfmaq_n_f32 (
464+ acc0,
465+ vreinterpretq_f32_u32 (vshll_n_u16 (vget_low_u16 (a_bf16), 16 )),
466+ b_val);
467+ acc1 = vfmaq_n_f32 (
468+ acc1, vreinterpretq_f32_u32 (vshll_high_n_u16 (a_bf16, 16 )), b_val);
469+ a_bf16 = vld1q_u16 (a_col + 8 );
470+ acc2 = vfmaq_n_f32 (
471+ acc2,
472+ vreinterpretq_f32_u32 (vshll_n_u16 (vget_low_u16 (a_bf16), 16 )),
473+ b_val);
474+ acc3 = vfmaq_n_f32 (
475+ acc3, vreinterpretq_f32_u32 (vshll_high_n_u16 (a_bf16, 16 )), b_val);
476+ a_bf16 = vld1q_u16 (a_col + 16 );
477+ acc4 = vfmaq_n_f32 (
478+ acc4,
479+ vreinterpretq_f32_u32 (vshll_n_u16 (vget_low_u16 (a_bf16), 16 )),
480+ b_val);
481+ acc5 = vfmaq_n_f32 (
482+ acc5, vreinterpretq_f32_u32 (vshll_high_n_u16 (a_bf16, 16 )), b_val);
483+ a_bf16 = vld1q_u16 (a_col + 24 );
484+ acc6 = vfmaq_n_f32 (
485+ acc6,
486+ vreinterpretq_f32_u32 (vshll_n_u16 (vget_low_u16 (a_bf16), 16 )),
487+ b_val);
488+ acc7 = vfmaq_n_f32 (
489+ acc7, vreinterpretq_f32_u32 (vshll_high_n_u16 (a_bf16, 16 )), b_val);
490+ a_bf16 = vld1q_u16 (a_col + 32 );
491+ acc8 = vfmaq_n_f32 (
492+ acc8,
493+ vreinterpretq_f32_u32 (vshll_n_u16 (vget_low_u16 (a_bf16), 16 )),
494+ b_val);
495+ acc9 = vfmaq_n_f32 (
496+ acc9, vreinterpretq_f32_u32 (vshll_high_n_u16 (a_bf16, 16 )), b_val);
497+ a_bf16 = vld1q_u16 (a_col + 40 );
498+ acc10 = vfmaq_n_f32 (
499+ acc10,
500+ vreinterpretq_f32_u32 (vshll_n_u16 (vget_low_u16 (a_bf16), 16 )),
501+ b_val);
502+ acc11 = vfmaq_n_f32 (
503+ acc11, vreinterpretq_f32_u32 (vshll_high_n_u16 (a_bf16, 16 )), b_val);
504+ a_bf16 = vld1q_u16 (a_col + 48 );
505+ acc12 = vfmaq_n_f32 (
506+ acc12,
507+ vreinterpretq_f32_u32 (vshll_n_u16 (vget_low_u16 (a_bf16), 16 )),
508+ b_val);
509+ acc13 = vfmaq_n_f32 (
510+ acc13, vreinterpretq_f32_u32 (vshll_high_n_u16 (a_bf16, 16 )), b_val);
511+ a_bf16 = vld1q_u16 (a_col + 56 );
512+ acc14 = vfmaq_n_f32 (
513+ acc14,
514+ vreinterpretq_f32_u32 (vshll_n_u16 (vget_low_u16 (a_bf16), 16 )),
515+ b_val);
516+ acc15 = vfmaq_n_f32 (
517+ acc15, vreinterpretq_f32_u32 (vshll_high_n_u16 (a_bf16, 16 )), b_val);
518+ }
519+
520+ vst1q_f32 (c + output_offset, acc0);
521+ vst1q_f32 (c + output_offset + 4 , acc1);
522+ vst1q_f32 (c + output_offset + 8 , acc2);
523+ vst1q_f32 (c + output_offset + 12 , acc3);
524+ vst1q_f32 (c + output_offset + 16 , acc4);
525+ vst1q_f32 (c + output_offset + 20 , acc5);
526+ vst1q_f32 (c + output_offset + 24 , acc6);
527+ vst1q_f32 (c + output_offset + 28 , acc7);
528+ vst1q_f32 (c + output_offset + 32 , acc8);
529+ vst1q_f32 (c + output_offset + 36 , acc9);
530+ vst1q_f32 (c + output_offset + 40 , acc10);
531+ vst1q_f32 (c + output_offset + 44 , acc11);
532+ vst1q_f32 (c + output_offset + 48 , acc12);
533+ vst1q_f32 (c + output_offset + 52 , acc13);
534+ vst1q_f32 (c + output_offset + 56 , acc14);
535+ vst1q_f32 (c + output_offset + 60 , acc15);
536+ }
537+
414538template <int64_t kRegisterPairs , typename b_t >
415539C10_ALWAYS_INLINE void gemv_notrans_block_neon (
416540 int64_t output_offset,
@@ -444,7 +568,7 @@ C10_ALWAYS_INLINE void gemv_notrans_block_neon(
444568 const float32x4_t a_low =
445569 vreinterpretq_f32_u32 (vshll_n_u16 (vget_low_u16 (a_bf16), 16 ));
446570 const float32x4_t a_high =
447- vreinterpretq_f32_u32 (vshll_n_u16 ( vget_high_u16 ( a_bf16) , 16 ));
571+ vreinterpretq_f32_u32 (vshll_high_n_u16 ( a_bf16, 16 ));
448572 acc[r * 2 ] = vfmaq_n_f32 (acc[r * 2 ], a_low, b_val);
449573 acc[r * 2 + 1 ] = vfmaq_n_f32 (acc[r * 2 + 1 ], a_high, b_val);
450574 }
@@ -468,7 +592,7 @@ void gemv_notrans_neon(
468592 float * c) {
469593 int64_t i = 0 ;
470594 for (; i + 64 <= m; i += 64 ) {
471- gemv_notrans_block_neon< 8 > (i, k, alpha, a, lda, b, beta, c);
595+ gemv_notrans_block64_neon (i, k, alpha, a, lda, b, beta, c);
472596 }
473597 for (; i + 32 <= m; i += 32 ) {
474598 gemv_notrans_block_neon<4 >(i, k, alpha, a, lda, b, beta, c);
0 commit comments