use individual panel define as compute unit, kernel is now storage and loading unit

This commit is contained in:
Youmu Liu
2025-11-12 21:13:00 +08:00
parent bbe69f0384
commit 2dfb4ae86a
33 changed files with 522 additions and 58 deletions
+1
View File
@@ -39,6 +39,7 @@ typedef union scalar_pack {
typedef void(SN_DECL *VECTORNORMALIZEPROC)(__m128 *source, __m128 *target);
typedef void(SN_DECL *DOTPROC)(void *transpose, __m128 *vector, __m128 *ans);
typedef void(SN_DECL *PANEL_PROC_AS)(MAT_PANEL_SSE(int));
typedef void(SN_DECL *MAT_PROC_AS)(mat_kernel *ans, scalar_pack *scalar);
typedef void(SN_DECL *MAT_PROC_LA)(mat_kernel *left, mat_kernel *ans);
typedef void(SN_DECL *MAT_PROC_LRA)(mat_kernel *left, mat_kernel *right, mat_kernel *ans);
+102 -6
View File
@@ -8,12 +8,12 @@
#include <immintrin.h>
#define MAT_KERNEL(T) \
union { \
__m128 xmm[XMMCOUNT(T)]; \
__m256 ymm[YMMCOUNT(T)]; \
__m512 zmm[ZMMCOUNT(T)]; \
T m[4][4]; \
#define MAT_KERNEL(T) \
union { \
__m128 xmm[XMMCOUNT(T) / 4]; \
__m256 ymm[YMMCOUNT(T) / 4]; \
__m512 zmm[ZMMCOUNT(T) / 4]; \
T m[4][4]; \
}
#define VEC(T) \
@@ -25,3 +25,99 @@
}
#endif
#include <stddef.h>
#include <stdint.h>
/* align decoration */
#if __cplusplus && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
#define ML_ALIGNAS(n) _Alignas(n)
#elif defined(_MSC_VER)
#define ML_ALIGNAS(n) __declspec(align(n))
#else
#define ML_ALIGNAS(n) __attribute__((aligned(n)))
#endif
/* Round up to the alignment boundary in bytes */
#ifndef ML_ALIGN_UP
#define ML_ALIGN_UP(x, a) (((size_t)(x) + ((size_t)(a) - 1)) & ~((size_t)(a) - 1))
#endif
/* Vector register width in bytes */
#define ML_BYTES_XMM 16u
#define ML_BYTES_YMM 32u
#define ML_BYTES_ZMM 64u
/* Compute the aligned leading-direction element stride (LEp) */
#define ML_PANEL_STRIDE_ELEMS(T, LE, ALIGN) \
(ML_ALIGN_UP((size_t)(LE) * sizeof(T), (size_t)(ALIGN)) / sizeof(T))
/* Total element count and total byte count */
#define ML_PANEL_TOT_ELEMS(T, LE, MINOR, ALIGN) \
((size_t)ML_PANEL_STRIDE_ELEMS(T, (LE), (ALIGN)) * (size_t)(MINOR))
#define ML_TOT_BYTES(T, ELEMS) ((size_t)(ELEMS) * sizeof(T))
/* Number of SIMD view slots (ceil by total bytes) */
#define ML_XMM_COUNT(TOT_BYTES) (((size_t)(TOT_BYTES) + ML_BYTES_XMM - 1) / ML_BYTES_XMM)
#define ML_YMM_COUNT(TOT_BYTES) (((size_t)(TOT_BYTES) + ML_BYTES_YMM - 1) / ML_BYTES_YMM)
#define ML_ZMM_COUNT(TOT_BYTES) (((size_t)(TOT_BYTES) + ML_BYTES_ZMM - 1) / ML_BYTES_ZMM)
/* ========== Unified "panel" union (no enum/descriptor fields) ==========
Usage:
MAT_PANEL(float, 8, 32, 32) P; // LE=8, MINOR=32, aligned to 32 bytes
Views:
P.xmm[] / P.ymm[] / P.zmm[] // raw SIMD blocks
P.blk[MINOR][LEp] // 2D scalar view (includes padding for alignment)
P.flat[MINOR*LEp] // flat array
Notes:
- LE/MINOR/ALIGN must be compile-time constants
- LEp = ML_PANEL_STRIDE_ELEMS(T, LE, ALIGN)
- Layout/semantics defined by the calling convention (e.g. blk[k][r] is element r of block k)
*/
#define MAT_PANEL(T, LE, MINOR, ALIGN) \
ML_ALIGNAS(ALIGN) union { \
/* Raw SIMD view: cast to __m256/__m512d inside the micro-kernel on demand */ \
__m128i xmm[ML_XMM_COUNT( \
ML_TOT_BYTES(T, ML_PANEL_TOT_ELEMS(T, (LE), (MINOR), (ALIGN))))]; \
__m256i ymm[ML_YMM_COUNT( \
ML_TOT_BYTES(T, ML_PANEL_TOT_ELEMS(T, (LE), (MINOR), (ALIGN))))]; \
__m512i zmm[ML_ZMM_COUNT( \
ML_TOT_BYTES(T, ML_PANEL_TOT_ELEMS(T, (LE), (MINOR), (ALIGN))))]; \
/* Scalar 2D view: minor �� LEp (LE dimension contains alignment padding) */ \
T blk[(MINOR)][ML_PANEL_STRIDE_ELEMS(T, (LE), (ALIGN))]; \
/* Flat view */ \
T flat[ML_PANEL_TOT_ELEMS(T, (LE), (MINOR), (ALIGN))]; \
}
/* ---------- SSE preset ---------- */
#undef PANEL_LE
#undef PANEL_MINOR
#undef PANEL_ALIGN
#define PANEL_LE 4
#define PANEL_MINOR 32
#define PANEL_ALIGN 16
/* ======== SSE preset ========
4 x 32, 16B aligned
*/
#define MAT_PANEL_SSE(T) MAT_PANEL(T, PANEL_LE, PANEL_MINOR, PANEL_ALIGN)
/* ---------- AVX2 preset ---------- */
#undef PANEL_LE
#undef PANEL_MINOR
#undef PANEL_ALIGN
#define PANEL_LE 8
#define PANEL_MINOR 64
#define PANEL_ALIGN 32
#define MAT_PANEL_AVX(T) MAT_PANEL(T, PANEL_LE, PANEL_MINOR, PANEL_ALIGN) /* 8 x 64, 32B aligned */
/* ---------- AVX-512 preset ---------- */
#undef PANEL_LE
#undef PANEL_MINOR
#undef PANEL_ALIGN
#define PANEL_LE 16
#define PANEL_MINOR 64
#define PANEL_ALIGN 64
#define MAT_PANEL_512(T) \
MAT_PANEL(T, PANEL_LE, PANEL_MINOR, PANEL_ALIGN); /* 16 x 64, 64B aligned */
+30 -3
View File
@@ -1,5 +1,9 @@
#include "sn_intrinsic.h"
INTERNAL void SN_DECL f32_fma_sse(MAT_PANEL_SSE(int) * left)
{
}
// ans = left * right + ans
// right is not transposed
INTERNAL void SN_DECL f32_fma_sse(MAT_KERNEL(float) const *restrict left,
@@ -41,9 +45,32 @@ INTERNAL void SN_DECL f32_fma_avx(MAT_KERNEL(float) const *restrict left,
MAT_KERNEL(float) const *restrict right,
MAT_KERNEL(float) *restrict ans)
{
/*
* to be implemented
*/
register __m256 source0 = _mm256_load_ps(&left->ymm[0]);
register __m256 source1 = _mm256_load_ps(&left->ymm[1]);
register __m256 ans0 = _mm256_load_ps(&ans->ymm[0]);
register __m256 ans1 = _mm256_load_ps(&ans->ymm[1]);
register __m128 bs0, bs1;
register __m256 broadcast;
for (size_t i = 0; i < 4; i++) {
bs0 = _mm_load_ps(&right->xmm[i]);
__m128 lo = _mm_shuffle_ps(bs0, bs0, 0x00);
__m128 hi = _mm_shuffle_ps(bs0, bs0, 0x55);
broadcast = _mm256_castps128_ps256(lo);
broadcast = _mm256_insertf128_ps(broadcast, bs0, 1);
ans0 = _mm256_add_ps(ans0, _mm256_mul_ps(source0, broadcast));
lo = _mm_shuffle_ps(bs0, bs0, 0xAA);
hi = _mm_shuffle_ps(bs0, bs0, 0xFF);
broadcast = _mm256_castps128_ps256(lo);
broadcast = _mm256_insertf128_ps(broadcast, bs0, 1);
ans1 = _mm256_add_ps(ans1, _mm256_mul_ps(source1, broadcast));
}
_mm256_store_ps(&ans->ymm[0], ans0);
_mm256_store_ps(&ans->ymm[1], ans1);
}
// ans = left * right + ans