remove mat panel, mat_task goes on span like
This commit is contained in:
@@ -48,13 +48,16 @@ namespace StgSharp.Mathematics.Numeric.Runtime
|
||||
internal unsafe struct MatrixParallelTask
|
||||
{
|
||||
|
||||
[FieldOffset(104)] private ulong reversed;
|
||||
|
||||
[FieldOffset(0)] public L4.Handle Buffer0;
|
||||
[FieldOffset(16)] public L4.Handle Buffer1;
|
||||
[FieldOffset(32)] public L4.Handle Buffer2;
|
||||
[FieldOffset(48)] public L4.Handle Buffer3;
|
||||
[FieldOffset(112)] public M128 ScalarPack;
|
||||
[FieldOffset(64)] public M512 Profile;
|
||||
[FieldOffset(120)] public MatrixElementType ElementType;
|
||||
[FieldOffset(124)] public MatrixIntrinsicHandle ComputeHandle;
|
||||
[FieldOffset(64)] public MatrixElementType ElementType;
|
||||
[FieldOffset(68)] public MatrixIntrinsicHandle ComputeHandle;
|
||||
|
||||
public MatrixParallelTask()
|
||||
{
|
||||
@@ -71,5 +74,17 @@ namespace StgSharp.Mathematics.Numeric.Runtime
|
||||
sizeof(MatrixParallelTask));
|
||||
}
|
||||
|
||||
#region offset and length settings
|
||||
|
||||
[FieldOffset(72)] public int Offset0;
|
||||
[FieldOffset(76)] public int Count0;
|
||||
[FieldOffset(80)] public int Offset1;
|
||||
[FieldOffset(84)] public int Count1;
|
||||
[FieldOffset(88)] public int Offset2;
|
||||
[FieldOffset(92)] public int Count2;
|
||||
[FieldOffset(96)] public int Offset3;
|
||||
[FieldOffset(100)] public int Count3;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,6 @@
|
||||
#define PRIVATE static
|
||||
#define INTERNAL extern
|
||||
|
||||
#define u64 uint64_t
|
||||
|
||||
#endif //
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
|
||||
#pragma region matix function
|
||||
|
||||
INTERNAL void f32_normalize(sn_vec_f32 * source, sn_vec_f32 * target);
|
||||
INTERNAL void f32_normalize(VEC_SEGMENT(float) * source, VEC_SEGMENT(float) * target);
|
||||
|
||||
SN_MK_PROC_DECL_STD(float, sse, , k_quality);
|
||||
|
||||
|
||||
@@ -65,11 +65,37 @@ typedef union uint64_u {
|
||||
|
||||
typedef struct mat_kernel mat_kernel;
|
||||
|
||||
typedef struct mat_panel mat_panel;
|
||||
typedef union M128{
|
||||
#if SN_IS_ARCH(x86_64)
|
||||
__m128 m128;
|
||||
#endif
|
||||
float f32[4];
|
||||
double f64[2];
|
||||
int32_t i32[4];
|
||||
int64_t i64[2];
|
||||
}M128;
|
||||
|
||||
typedef union scalar_pack {
|
||||
uint64_t data[8];
|
||||
} scalar_pack;
|
||||
typedef union M256{
|
||||
#if SN_IS_ARCH(x86_64)
|
||||
__m256 m256;
|
||||
#endif
|
||||
float f32[8];
|
||||
double f64[4];
|
||||
int32_t i32[8];
|
||||
int64_t i64[4];
|
||||
}M256;
|
||||
|
||||
typedef union M512{
|
||||
#if SN_IS_ARCH(x86_64)
|
||||
__m512 m512;
|
||||
#endif
|
||||
uint64_t u64[8];
|
||||
uint32_t u32[16];
|
||||
float f32[16];
|
||||
double f64[8];
|
||||
int32_t i32[16];
|
||||
int64_t i64[8];
|
||||
}M512;
|
||||
|
||||
typedef struct sn_L4_cache_head {
|
||||
uint64_t reverse_mask_0;
|
||||
@@ -81,42 +107,33 @@ typedef struct sn_L4_cache_head {
|
||||
|
||||
typedef struct sn_L4_handle {
|
||||
void *ptr;
|
||||
sn_L4_cache_head head;
|
||||
sn_L4_cache_head* head;
|
||||
} sn_L4_handle;
|
||||
|
||||
typedef struct matrix_task_pack {
|
||||
typedef struct matrix_task {
|
||||
sn_L4_handle buffer_0;
|
||||
sn_L4_handle buffer_1;
|
||||
sn_L4_handle buffer_2;
|
||||
sn_L4_handle buffer_3;
|
||||
uint64_t reverse_0;
|
||||
uint64_t reverse_1;
|
||||
uint64_t reverse_2;
|
||||
uint64_t reverse_3;
|
||||
uint64_t reverse_4;
|
||||
uint64_t reverse_5;
|
||||
uint64_t reverse_6;
|
||||
uint64_t reverse_7;
|
||||
union {
|
||||
struct {
|
||||
int offset_0;
|
||||
int count_0;
|
||||
int offset_1;
|
||||
int count_1;
|
||||
int offset_2;
|
||||
int count_2;
|
||||
int offset_3;
|
||||
int count_3;
|
||||
uint64_t reverse;
|
||||
M128 scalar_pack;
|
||||
};
|
||||
M512 profile;
|
||||
};
|
||||
|
||||
} matrix_task_pack;
|
||||
|
||||
typedef struct matrix_task {
|
||||
void *mat_0;
|
||||
void *mat_1;
|
||||
void *mat_2;
|
||||
void *scalar;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t z;
|
||||
int32_t common_x;
|
||||
int32_t common_y;
|
||||
int32_t common_z;
|
||||
uint32_t mask;
|
||||
uint32_t reverse;
|
||||
scalar_pack padding;
|
||||
} matrix_task;
|
||||
|
||||
#define MAT_TASK(T) matrix_task_pack
|
||||
#define MAT_TASK(T) matrix_task
|
||||
|
||||
#if defined(__cplusplus)
|
||||
static_assert(sizeof(matrix_task) == 128, "matrix_parallel_task_package size mismatch");
|
||||
@@ -128,7 +145,7 @@ typedef void(SN_DECL *UNI_MK_PROC)(matrix_task *task);
|
||||
typedef void(SN_DECL *UNI_SK_PROC)(mat_kernel const *left, mat_kernel const *right,
|
||||
mat_kernel *restrict ans, uint64_t scalar);
|
||||
|
||||
typedef void(SN_DECL *VECTORNORMALIZEPROC)(sn_vec_f32 *source, sn_vec_f32 *target);
|
||||
typedef void(SN_DECL *VECTORNORMALIZEPROC)(VEC_SEGMENT(float) *source, VEC_SEGMENT(float) *target);
|
||||
typedef void(SN_DECL *DOTPROC)(void *transpose, __m128 *vector, __m128 *ans);
|
||||
typedef uint64_t(SN_DECL *FACTORIALROC)(int n);
|
||||
|
||||
|
||||
@@ -12,13 +12,14 @@
|
||||
#define YMMCOUNT(T) (sizeof(T) / 2)
|
||||
#define ZMMCOUNT(T) (sizeof(T) / 4)
|
||||
|
||||
#define SN_MAT_KERNEL_MEMBER(T) {\
|
||||
#define SN_MAT_KERNEL_MEMBER(T) \
|
||||
{ \
|
||||
__m128 x[XMMCOUNT(T)]; \
|
||||
__m256 y[YMMCOUNT(T)]; \
|
||||
__m512 z[ZMMCOUNT(T)]; \
|
||||
T m[4][4]; \
|
||||
}
|
||||
|
||||
/*
|
||||
#define SN_DEFINE_MAT_KERNEL_TYPE(name, T) \
|
||||
typedef union name SN_MAT_KERNEL_MEMBER(T) name
|
||||
|
||||
@@ -26,120 +27,36 @@
|
||||
SN_DEFINE_MAT_KERNEL_TYPE(sn_mat_kernel_float, float);
|
||||
SN_DEFINE_MAT_KERNEL_TYPE(sn_mat_kernel_double, double);
|
||||
SN_DEFINE_MAT_KERNEL_TYPE(sn_mat_kernel_uint64_t, uint64_t);
|
||||
|
||||
#define MAT_KERNEL_DEFINE(T) \
|
||||
/* */
|
||||
#define SN_MAT_KERNEL_DEFINE(T) \
|
||||
typedef union SN_MAT_KERNEL_TYPE_##T SN_MAT_KERNEL_MEMBER(T) SN_MAT_KERNEL_TYPE_##T
|
||||
|
||||
#define SN_MAT_KERNEL_TYPE(T) SN_MAT_KERNEL_TYPE_##T
|
||||
MAT_KERNEL_DEFINE(float);
|
||||
MAT_KERNEL_DEFINE(double);
|
||||
MAT_KERNEL_DEFINE(uint64_t);
|
||||
|
||||
#define MAT_KERNEL(T) SN_MAT_KERNEL_TYPE(T)
|
||||
#define SN_MAT_KERNEL_TYPE(T) SN_MAT_KERNEL_TYPE_##T
|
||||
|
||||
#define VEC(T) \
|
||||
union { \
|
||||
SN_MAT_KERNEL_DEFINE(float);
|
||||
SN_MAT_KERNEL_DEFINE(double);
|
||||
SN_MAT_KERNEL_DEFINE(uint64_t);
|
||||
|
||||
|
||||
#define SN_VEC_SEGMENT_MEMBER(T) \
|
||||
{ \
|
||||
__m128 f32_x[XMMCOUNT(T) / 4]; \
|
||||
__m256 f32_y[YMMCOUNT(T) / 4]; \
|
||||
__m512 f32_z[ZMMCOUNT(T) / 4]; \
|
||||
\
|
||||
__m128d f64_x[XMMCOUNT(T) / 4]; \
|
||||
__m256d f64_y[YMMCOUNT(T) / 4]; \
|
||||
__m512d f64_z[ZMMCOUNT(T) / 4]; \
|
||||
T v[4]; \
|
||||
}
|
||||
|
||||
typedef VEC(float) sn_vec_f32;
|
||||
#define SN_VEC_SEGMENT_DEFINE(T) \
|
||||
typedef union SN_VEC_SEGMENT_TYPE_##T SN_VEC_SEGMENT_MEMBER(T) SN_VEC_SEGMENT_TYPE_##T
|
||||
|
||||
/* Provide a named alias for the zero kernel type to ensure consistent linkage in C++. */
|
||||
typedef sn_mat_kernel_uint64_t sn_zero_kernel_u64;
|
||||
#define VEC_SEGMENT(T) SN_VEC_SEGMENT_TYPE(T)
|
||||
#define SN_VEC_SEGMENT_TYPE(T) SN_VEC_SEGMENT_TYPE_##T
|
||||
|
||||
/* Helpers (all compile-time): */
|
||||
#define SN_LANES(T_VEC, T) (sizeof(T_VEC) / sizeof(T))
|
||||
#define SN_MAX(a, b) (((a)) > ((b)) ? (a) : (b))
|
||||
#define SN_CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
|
||||
#define SN_BITS(x) ((int)(sizeof(x) * 8))
|
||||
#define PANEL_MINQ(T_VEC, T) SN_MAX(4, SN_MAX(SN_BITS(T_VEC) / 64, SN_BITS(T_VEC) / SN_BITS(T)))
|
||||
|
||||
/* Panel geometry helpers (all compile-time): */
|
||||
#define PANEL_Q(T, T_VEC, MINQ) SN_MAX(SN_LANES(T_VEC, T), (MINQ))
|
||||
#define PANEL_CHUNKS(T, T_VEC, MINQ) SN_CEIL_DIV(PANEL_Q(T, T_VEC, MINQ), SN_LANES(T_VEC, T))
|
||||
|
||||
/*
|
||||
Column-major square panel with minimum side Q:
|
||||
- Let R = lanes per vector = sizeof(T_VEC)/sizeof(T).
|
||||
- Side length Q = max(R, MINQ) to enforce the requested minimum extent.
|
||||
- Each column is stored contiguously via CH = ceil(Q/R) vector chunks.
|
||||
- Memory layout:
|
||||
vec[col][chunk] is a T_VEC holding up to R scalars of column 'col'
|
||||
spanning rows chunk*R .. chunk*R + (R - 1).
|
||||
flat[] mirrors the same column-major order (column stride = Q).
|
||||
- SIMD view remains integer-typed; cast inside micro-kernels to the
|
||||
appropriate floating-point/integer vector type on demand.
|
||||
*/
|
||||
#define MAT_PANEL_SQ_MIN_NOALIGN(T, T_VEC, MINQ) \
|
||||
union { \
|
||||
T_VEC vec[PANEL_Q(T, T_VEC, MINQ)][PANEL_CHUNKS(T, T_VEC, MINQ)]; \
|
||||
T flat[PANEL_Q(T, T_VEC, MINQ) * PANEL_Q(T, T_VEC, MINQ)]; \
|
||||
}
|
||||
|
||||
/* ISA presets with minimum square side:
|
||||
- SSE : MINQ=4 (avoid 2x2 for double)
|
||||
- AVX2 : MINQ computed as max(4, vector_bits/64, vector_bits/element_bits)
|
||||
- AVX-512: same rule (float/i32 naturally expand to 16)
|
||||
*/
|
||||
|
||||
/* SSE panel layout: column-major buffer holding 4 logical columns with MINQ=4.
|
||||
Columns: each column packs up to four scalars so ALIGN equals sizeof(__m128).
|
||||
Alignment: every column boundary lands on a 16-byte multiple for XMM loads. */
|
||||
#define MAT_PANEL_sse(T) SN_ALIGNAS(16) MAT_PANEL_SQ_MIN_NOALIGN(T, __m128, PANEL_MINQ(__m128, T))
|
||||
/* AVX2 panel layout: column-major buffer holding 8 logical columns with MINQ per PANEL_MINQ.
|
||||
Columns: each column stores up to lanes elements via contiguous chunks.
|
||||
Alignment: column starts are 32-byte aligned so AVX2 loads/stores remain contiguous. */
|
||||
#define MAT_PANEL_avx(T) SN_ALIGNAS(32) MAT_PANEL_SQ_MIN_NOALIGN(T, __m256, PANEL_MINQ(__m256, T))
|
||||
/* AVX2/FMA panel layout shares the same geometry as AVX2. */
|
||||
#define MAT_PANEL_avx_fma(T) \
|
||||
SN_ALIGNAS(32) MAT_PANEL_SQ_MIN_NOALIGN(T, __m256, PANEL_MINQ(__m256, T))
|
||||
/* AVX-512 panel layout: column-major buffer holding 8 or more columns depending on T.
|
||||
Columns: each column expands to ceil(Q/lanes) ZMM chunks.
|
||||
Alignment: column starts sit on 64-byte boundaries to match AVX-512 streaming access. */
|
||||
#define MAT_PANEL_512(T) SN_ALIGNAS(64) MAT_PANEL_SQ_MIN_NOALIGN(T, __m512, PANEL_MINQ(__m512, T))
|
||||
SN_VEC_SEGMENT_DEFINE(float);
|
||||
SN_VEC_SEGMENT_DEFINE(double);
|
||||
|
||||
/* Global zero kernel declaration (defined in dllmain.c), aligned to 64 bytes */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern __declspec(align(64)) sn_zero_kernel_u64 SN_ZERO_KERNEL;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Access helpers (all compile-time friendly):
|
||||
Given Q = PANEL_Q(...), CH = PANEL_CHUNKS(...), R = lanes per vector:
|
||||
- Column c occupies vec[c][0..CH-1].
|
||||
- Row r inside column c is located at vec[c][r / R] with lane (r % R).
|
||||
*/
|
||||
#define PANEL_COL_VEC(panel_obj, c, chunk) ((panel_obj).vec[(int)(c)][(int)(chunk)])
|
||||
/* Scalar flat index helper for column-major addressing */
|
||||
#define PANEL_ELEM(panel_obj, T, T_VEC, MINQ, r, c) \
|
||||
((panel_obj).flat[(int)(c) * PANEL_Q(T, T_VEC, MINQ) + (int)(r)])
|
||||
|
||||
/* API macros */
|
||||
#define BUILD_PANEL(arch, element) build_panel_##arch##_##element
|
||||
#define STORE_PANEL(arch, element) store_panel_##arch##_##element
|
||||
|
||||
#define DECLARE_BUILD_PANEL(arch, element) \
|
||||
INTERNAL void SN_DECL BUILD_PANEL(arch, element)( \
|
||||
MAT_PANEL_##arch(element) *restrict panel, \
|
||||
MAT_KERNEL(element) const *const matrix, int col_length, int row_length, \
|
||||
int col_index, int row_index)
|
||||
#define DECLARE_STORE_PANEL(arch, element) \
|
||||
INTERNAL void SN_DECL STORE_PANEL(arch, element)(MAT_PANEL_##arch(element) \
|
||||
const *const panel, \
|
||||
MAT_KERNEL(element) *restrict matrix, \
|
||||
int col_length, int row_length, \
|
||||
int col_index, int row_index)
|
||||
|
||||
|
||||
extern __declspec(align(64)) MAT_KERNEL(u64) SN_ZERO_KERNEL;
|
||||
|
||||
#endif /* SN_MATKERNEL */
|
||||
|
||||
@@ -46,73 +46,54 @@
|
||||
#define _SN_MATPROC_RIGHT_ANS_SCALAR 1
|
||||
#define _SN_MATPROC_ANS_SCALAR 1
|
||||
|
||||
#define _SN_MK_EXPAND_BUFFER_SIZE(i)\
|
||||
int offset_##i = task->offset_##i;\
|
||||
int count_##i = task->count_##i;\
|
||||
|
||||
#define _SN_MK_EXPAND_RIGHT_ANS \
|
||||
SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->buffer_1.ptr; \
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->buffer_2.ptr;
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->buffer_2.ptr;\
|
||||
_SN_MK_EXPAND_BUFFER_SIZE(1); \
|
||||
_SN_MK_EXPAND_BUFFER_SIZE(2);
|
||||
|
||||
#define _SN_MK_EXPAND_LEFT_RIGHT_ANS \
|
||||
SN_MAT_KERNEL_LOCAL const *left = (SN_MAT_KERNEL_LOCAL const *)task->buffer_0.ptr; \
|
||||
SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->buffer_1.ptr; \
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->buffer_2.ptr;
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->buffer_2.ptr;\
|
||||
_SN_MK_EXPAND_BUFFER_SIZE(0); \
|
||||
_SN_MK_EXPAND_BUFFER_SIZE(1);\
|
||||
_SN_MK_EXPAND_BUFFER_SIZE(2);
|
||||
|
||||
#define _SN_MK_EXPAND_RIGHT_ANS_SCALAR \
|
||||
SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->buffer_1.ptr; \
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->buffer_2.ptr; \
|
||||
scalar_pack *restrict scalar = (scalar_pack *restrict)task->scalar;
|
||||
scalar_pack *restrict scalar = (scalar_pack *restrict)task->scalar;\
|
||||
_SN_MK_EXPAND_BUFFER_SIZE(1);\
|
||||
_SN_MK_EXPAND_BUFFER_SIZE(2);
|
||||
|
||||
#define _SN_MK_EXPAND_LEFT_RIGHT_ANS_SCALAR \
|
||||
SN_MAT_KERNEL_LOCAL const *left = (SN_MAT_KERNEL_LOCAL const *)task->buffer_0.ptr; \
|
||||
SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->buffer_1.ptr; \
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->buffer_2.ptr; \
|
||||
scalar_pack *restrict scalar = (scalar_pack *restrict)task->scalar;
|
||||
scalar_pack *restrict scalar = (scalar_pack *restrict)task->scalar;\
|
||||
_SN_MK_EXPAND_BUFFER_SIZE(0);\
|
||||
_SN_MK_EXPAND_BUFFER_SIZE(1);\
|
||||
_SN_MK_EXPAND_BUFFER_SIZE(2);
|
||||
|
||||
#define _SN_MK_EXPAND_ANS_SCALAR \
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->buffer_2.ptr; \
|
||||
scalar_pack *restrict scalar = (scalar_pack *restrict)&(task->padding);
|
||||
scalar_pack *restrict scalar = (scalar_pack *restrict)&(task->padding);\
|
||||
_SN_MK_EXPAND_BUFFER_SIZE(2);
|
||||
|
||||
#define _SN_PARAM_STYLE(T) _SN_MATPROC_##T
|
||||
#define _SN_MK_EXPAND_PARAM(style) _SN_MK_EXPAND_##style
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region mem layout
|
||||
|
||||
#define _SN_MATPROC_LAYOUT_BUFFER 1
|
||||
#define _SN_MATPROC_LAYOUT_TILE 1
|
||||
#define _SN_MATPROC_LAYOUT_KERNEL 1
|
||||
|
||||
#define _MK_MKPROC_EXPAND_INDEX_BUFFER \
|
||||
size_t offset = UNSAFE_AS(size_t, task->padding.data[0]); \
|
||||
size_t count = UNSAFE_AS(size_t, task->padding.data[1]);
|
||||
|
||||
#define _MK_MKPROC_EXPAND_INDEX_BUFFER \
|
||||
size_t offset = UNSAFE_AS(size_t, task->padding.data[0]); \
|
||||
size_t count = UNSAFE_AS(size_t, task->padding.data[1]);
|
||||
|
||||
#define _MK_MKPROC_EXPAND_INDEX_KERNEL \
|
||||
size_t x = UNSAFE_AS(size_t, task->x); \
|
||||
size_t y = UNSAFE_AS(size_t, task->y); \
|
||||
size_t common_x = UNSAFE_AS(size_t, task->common_x); \
|
||||
size_t common_y = UNSAFE_AS(size_t, task->common_y); \
|
||||
size_t common_z = UNSAFE_AS(size_t, task->common_z);
|
||||
|
||||
#define _MK_MKPROC_EXPAND_INDEX_TILE \
|
||||
size_t x = UNSAFE_AS(size_t, task->x); \
|
||||
size_t y = UNSAFE_AS(size_t, task->y); \
|
||||
size_t common_x = UNSAFE_AS(size_t, task->common_x); \
|
||||
size_t common_y = UNSAFE_AS(size_t, task->common_y); \
|
||||
size_t common_z = UNSAFE_AS(size_t, task->common_z);
|
||||
|
||||
#define _SN_MK_EXPAND_MEM(mem) _MK_MKPROC_EXPAND_INDEX_##mem
|
||||
#define _SN_MEM_LAYOUT(T) _SN_MATPROC_LAYOUT_##T
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#define __mk_param_std(mem, param, T) \
|
||||
#define __mk_param_std(param, T) \
|
||||
typedef MAT_KERNEL(T) SN_MAT_KERNEL_LOCAL; \
|
||||
matrix_task_pack const *_ = (_SN_PARAM_STYLE(param), (_SN_MEM_LAYOUT(mem)), task); \
|
||||
_SN_MK_EXPAND_PARAM(param); \
|
||||
_SN_MK_EXPAND_MEM(mem)
|
||||
matrix_task const *_ = (_SN_PARAM_STYLE(param), task); \
|
||||
_SN_MK_EXPAND_PARAM(param)
|
||||
|
||||
#define __sk_param_std(T) \
|
||||
typedef MAT_KERNEL(T) SN_MAT_KERNEL_LOCAL; \
|
||||
|
||||
@@ -17,28 +17,28 @@
|
||||
|
||||
SN_MK_PROC_DECL_STD(float, sse, , fma_pack)
|
||||
{
|
||||
__mk_param_std(TILE, RIGHT_ANS, float);
|
||||
__mk_param_std(RIGHT_ANS, float);
|
||||
|
||||
memcpy(ans, right, sizeof(MAT_KERNEL(float)) * common_y * common_z);
|
||||
}
|
||||
|
||||
SN_MK_PROC_DECL_STD(float, avx, , fma_pack)
|
||||
{
|
||||
__mk_param_std(TILE, RIGHT_ANS, float);
|
||||
__mk_param_std(RIGHT_ANS, float);
|
||||
|
||||
memcpy(ans, right, sizeof(MAT_KERNEL(float)) * common_y * common_z);
|
||||
}
|
||||
|
||||
SN_MK_PROC_DECL_STD(float, 512, , fma_pack)
|
||||
{
|
||||
__mk_param_std(TILE, RIGHT_ANS, float);
|
||||
__mk_param_std(RIGHT_ANS, float);
|
||||
|
||||
memcpy(ans, right, sizeof(MAT_KERNEL(float)) * common_y * common_z);
|
||||
}
|
||||
|
||||
SN_MK_PROC_DECL_STD(float, sse, , fma)
|
||||
{
|
||||
__mk_param_std(TILE, LEFT_RIGHT_ANS, float);
|
||||
__mk_param_std(LEFT_RIGHT_ANS, float);
|
||||
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans_cur =
|
||||
ans + GET_INDEX(common_y, x, y); // GetKernelAddressUnsafe
|
||||
@@ -95,7 +95,7 @@ SN_MK_PROC_DECL_STD(float, sse, , fma)
|
||||
|
||||
SN_MK_PROC_DECL_STD(float, avx, , fma)
|
||||
{
|
||||
__mk_param_std(TILE, LEFT_RIGHT_ANS, float);
|
||||
__mk_param_std(LEFT_RIGHT_ANS, float);
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans_cur = ans + GET_INDEX(common_y, x, y);
|
||||
register __m256 c0 = _mm256_load_ps((float *)&ans_cur->y[0]);
|
||||
register __m256 c1 = _mm256_load_ps((float *)&ans_cur->y[1]);
|
||||
@@ -130,7 +130,7 @@ SN_MK_PROC_DECL_STD(float, avx, , fma)
|
||||
|
||||
SN_MK_PROC_DECL_STD(float, avx, _fma, fma)
|
||||
{
|
||||
__mk_param_std(TILE, LEFT_RIGHT_ANS, float);
|
||||
__mk_param_std(LEFT_RIGHT_ANS, float);
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans_cur = ans + GET_INDEX(common_y, x, y);
|
||||
register __m256 c0 = _mm256_load_ps((float *)&ans_cur->y[0]);
|
||||
register __m256 c1 = _mm256_load_ps((float *)&ans_cur->y[1]);
|
||||
@@ -166,7 +166,7 @@ SN_MK_PROC_DECL_STD(float, avx, _fma, fma)
|
||||
|
||||
SN_MK_PROC_DECL_STD(float, 512, , fma)
|
||||
{
|
||||
__mk_param_std(TILE, LEFT_RIGHT_ANS, float);
|
||||
__mk_param_std(LEFT_RIGHT_ANS, float);
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans_cur = ans + GET_INDEX(common_y, x, y);
|
||||
register __m512 c0 = _mm512_load_ps((float *)&ans_cur->z[0]);
|
||||
register __m512 c1 = _mm512_load_ps((float *)&ans_cur->z[0]);
|
||||
@@ -202,7 +202,7 @@ SN_MK_PROC_DECL_STD(float, 512, , fma)
|
||||
|
||||
SN_MK_PROC_DECL_STD(double, sse, , fma)
|
||||
{
|
||||
__mk_param_std(TILE, LEFT_RIGHT_ANS, double);
|
||||
__mk_param_std(LEFT_RIGHT_ANS, double);
|
||||
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans_cur =
|
||||
ans + GET_INDEX(common_y, x, y); // GetKernelAddressUnsafe
|
||||
@@ -243,7 +243,7 @@ SN_MK_PROC_DECL_STD(double, sse, , fma)
|
||||
|
||||
SN_MK_PROC_DECL_STD(double, avx, , fma)
|
||||
{
|
||||
__mk_param_std(TILE, LEFT_RIGHT_ANS, double);
|
||||
__mk_param_std(LEFT_RIGHT_ANS, double);
|
||||
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans_cur = ans + GET_INDEX(common_y, x, y); // tKernelAddressUnsafe
|
||||
|
||||
@@ -315,7 +315,7 @@ SN_MK_PROC_DECL_STD(double, avx, , fma)
|
||||
|
||||
SN_MK_PROC_DECL_STD(double, avx, _fma, fma)
|
||||
{
|
||||
__mk_param_std(TILE, LEFT_RIGHT_ANS, double);
|
||||
__mk_param_std(LEFT_RIGHT_ANS, double);
|
||||
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans_cur = ans + GET_INDEX(common_y, x, y); // GetKernelAddressUnsafe
|
||||
|
||||
@@ -371,7 +371,7 @@ SN_MK_PROC_DECL_STD(double, avx, _fma, fma)
|
||||
|
||||
SN_MK_PROC_DECL_STD(double, 512, , fma)
|
||||
{
|
||||
__mk_param_std(TILE, LEFT_RIGHT_ANS, double);
|
||||
__mk_param_std(LEFT_RIGHT_ANS, double);
|
||||
SN_MAT_KERNEL_LOCAL *restrict ans_cur = ans + GET_INDEX(common_y, x, y);
|
||||
|
||||
register __m512d c0 = _mm512_load_pd((double *)&ans_cur->z[0]);
|
||||
|
||||
@@ -0,0 +1,578 @@
|
||||
# NGRA → HIR → SSA → LLVM 设计笔记
|
||||
|
||||
## 当前结论
|
||||
|
||||
NGRA 不应直接承担完整 SSA 构建与数据流分析职责。
|
||||
|
||||
NGRA 的职责是:
|
||||
|
||||
* Token 分析
|
||||
* 岛屿压缩(Island Compression)
|
||||
* 结构识别
|
||||
* 局部语义绑定
|
||||
* 元数据传播
|
||||
* AST 构建
|
||||
|
||||
SSA 的职责是:
|
||||
|
||||
* CFG 构建
|
||||
* Def-Use 分析
|
||||
* Phi 插入
|
||||
* Value Versioning
|
||||
* 全局优化
|
||||
|
||||
---
|
||||
|
||||
# 总体架构
|
||||
|
||||
推荐架构:
|
||||
|
||||
```text
|
||||
Source Code
|
||||
↓
|
||||
NGRA
|
||||
↓
|
||||
五角星AST
|
||||
↓
|
||||
HIR(寄存器式)
|
||||
↓
|
||||
CFG
|
||||
↓
|
||||
SSA
|
||||
↓
|
||||
LLVM IR
|
||||
↓
|
||||
LLVM Backend
|
||||
↓
|
||||
Native Code / SPIR-V / CUDA
|
||||
```
|
||||
|
||||
而不是:
|
||||
|
||||
```text
|
||||
AST
|
||||
↓
|
||||
直接LLVM IR
|
||||
```
|
||||
|
||||
原因:
|
||||
|
||||
LLVM IR 过于底层。
|
||||
|
||||
NGRA 与语言语义高度相关。
|
||||
|
||||
中间需要一个:
|
||||
|
||||
```text
|
||||
Language HIR
|
||||
```
|
||||
|
||||
作为桥梁。
|
||||
|
||||
---
|
||||
|
||||
# 五角星AST职责
|
||||
|
||||
五角星AST承担:
|
||||
|
||||
```text
|
||||
Syntax
|
||||
+
|
||||
Metadata
|
||||
+
|
||||
Partial Semantic
|
||||
```
|
||||
|
||||
信息。
|
||||
|
||||
节点包含:
|
||||
|
||||
```csharp
|
||||
Parent
|
||||
Prev
|
||||
Next
|
||||
Left
|
||||
Right
|
||||
```
|
||||
|
||||
同时可附带:
|
||||
|
||||
```csharp
|
||||
Type
|
||||
Symbol
|
||||
Attribute
|
||||
SourceSpan
|
||||
Flags
|
||||
```
|
||||
|
||||
因此无需再构造独立 Bound AST。
|
||||
|
||||
---
|
||||
|
||||
# SCG(Semi Context Grammar)
|
||||
|
||||
SCG 不等于 SSA。
|
||||
|
||||
SCG 只负责:
|
||||
|
||||
## 1. 声明语义
|
||||
|
||||
例如:
|
||||
|
||||
```csharp
|
||||
class Foo : Bar
|
||||
```
|
||||
|
||||
直接得到:
|
||||
|
||||
```text
|
||||
Foo
|
||||
Bar
|
||||
Inheritance
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Token级语义
|
||||
|
||||
例如:
|
||||
|
||||
```csharp
|
||||
123
|
||||
```
|
||||
|
||||
立即得到:
|
||||
|
||||
```text
|
||||
Int32
|
||||
```
|
||||
|
||||
例如:
|
||||
|
||||
```csharp
|
||||
int a = "abc";
|
||||
```
|
||||
|
||||
立即报错。
|
||||
|
||||
---
|
||||
|
||||
## 3. 局部表达式语义
|
||||
|
||||
例如:
|
||||
|
||||
```csharp
|
||||
int + float
|
||||
```
|
||||
|
||||
归约时:
|
||||
|
||||
```text
|
||||
Implicit Conversion
|
||||
Operator Resolution
|
||||
```
|
||||
|
||||
直接完成。
|
||||
|
||||
---
|
||||
|
||||
## 4. 上下文元数据
|
||||
|
||||
允许读取:
|
||||
|
||||
```text
|
||||
当前岛屿
|
||||
父岛屿
|
||||
全局声明表
|
||||
```
|
||||
|
||||
中的信息。
|
||||
|
||||
例如:
|
||||
|
||||
```csharp
|
||||
namespace A
|
||||
{
|
||||
class B
|
||||
}
|
||||
```
|
||||
|
||||
Class Island 自动继承:
|
||||
|
||||
```text
|
||||
CurrentNamespace=A
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# SCG边界
|
||||
|
||||
SCG允许:
|
||||
|
||||
```text
|
||||
当前节点
|
||||
当前归约栈
|
||||
当前岛屿元数据
|
||||
父岛屿元数据
|
||||
全局声明表
|
||||
```
|
||||
|
||||
SCG禁止:
|
||||
|
||||
```text
|
||||
CFG
|
||||
Phi
|
||||
Def-Use
|
||||
Alias Analysis
|
||||
Call Graph
|
||||
Loop Analysis
|
||||
```
|
||||
|
||||
这些属于 SSA 阶段。
|
||||
|
||||
---
|
||||
|
||||
# HIR设计
|
||||
|
||||
最终决定:
|
||||
|
||||
不采用栈机IR。
|
||||
|
||||
原因:
|
||||
|
||||
AST 已经表达了操作数关系。
|
||||
|
||||
如果先降成:
|
||||
|
||||
```text
|
||||
load
|
||||
load
|
||||
add
|
||||
store
|
||||
```
|
||||
|
||||
属于:
|
||||
|
||||
```text
|
||||
丢失结构
|
||||
再恢复结构
|
||||
```
|
||||
|
||||
没有意义。
|
||||
|
||||
---
|
||||
|
||||
# HIR采用寄存器式设计
|
||||
|
||||
推荐形式:
|
||||
|
||||
```text
|
||||
%0 = const 2
|
||||
%1 = mul c, %0
|
||||
%2 = add b, %1
|
||||
|
||||
a := %2
|
||||
```
|
||||
|
||||
而不是:
|
||||
|
||||
```text
|
||||
load b
|
||||
load c
|
||||
push 2
|
||||
mul
|
||||
add
|
||||
store a
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Value模型
|
||||
|
||||
HIR中的表达式全部返回 Value。
|
||||
|
||||
例如:
|
||||
|
||||
```csharp
|
||||
HirValue EmitExpr(AstNode node)
|
||||
```
|
||||
|
||||
返回:
|
||||
|
||||
```csharp
|
||||
ValueId
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Symbol与Value分离
|
||||
|
||||
保留:
|
||||
|
||||
```text
|
||||
SymbolId
|
||||
ValueId
|
||||
```
|
||||
|
||||
两套体系。
|
||||
|
||||
例如:
|
||||
|
||||
```text
|
||||
a
|
||||
b
|
||||
c
|
||||
```
|
||||
|
||||
属于:
|
||||
|
||||
```text
|
||||
SymbolId
|
||||
```
|
||||
|
||||
表达式结果:
|
||||
|
||||
```text
|
||||
%0
|
||||
%1
|
||||
%2
|
||||
```
|
||||
|
||||
属于:
|
||||
|
||||
```text
|
||||
ValueId
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Assignment处理
|
||||
|
||||
例如:
|
||||
|
||||
```csharp
|
||||
a = b + c;
|
||||
```
|
||||
|
||||
生成:
|
||||
|
||||
```text
|
||||
%0 = add b,c
|
||||
|
||||
a := %0
|
||||
```
|
||||
|
||||
此时:
|
||||
|
||||
```text
|
||||
a
|
||||
```
|
||||
|
||||
仍不是 SSA。
|
||||
|
||||
只是:
|
||||
|
||||
```text
|
||||
Symbol → Current Value
|
||||
```
|
||||
|
||||
映射。
|
||||
|
||||
---
|
||||
|
||||
# SSA阶段
|
||||
|
||||
SSA阶段负责:
|
||||
|
||||
```text
|
||||
a
|
||||
↓
|
||||
a_0
|
||||
a_1
|
||||
a_2
|
||||
...
|
||||
```
|
||||
|
||||
版本化。
|
||||
|
||||
例如:
|
||||
|
||||
```csharp
|
||||
a = 1;
|
||||
a = 2;
|
||||
```
|
||||
|
||||
变:
|
||||
|
||||
```text
|
||||
a_0 = 1
|
||||
a_1 = 2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# CFG构建
|
||||
|
||||
真正的分界线
|
||||
|
||||
不是:
|
||||
|
||||
```text
|
||||
AST
|
||||
↓
|
||||
HIR
|
||||
```
|
||||
|
||||
而是:
|
||||
|
||||
```text
|
||||
HIR
|
||||
↓
|
||||
CFG
|
||||
```
|
||||
|
||||
因为:
|
||||
|
||||
```text
|
||||
树
|
||||
↓
|
||||
图
|
||||
```
|
||||
|
||||
在这里发生。
|
||||
|
||||
例如:
|
||||
|
||||
```csharp
|
||||
if(cond)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
生成:
|
||||
|
||||
```text
|
||||
BB0
|
||||
br cond
|
||||
|
||||
BB1
|
||||
...
|
||||
|
||||
BB2
|
||||
...
|
||||
|
||||
BB3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# LLVM IR定位
|
||||
|
||||
LLVM IR不是语言IR。
|
||||
|
||||
LLVM IR是:
|
||||
|
||||
```text
|
||||
SSA Optimization IR
|
||||
```
|
||||
|
||||
职责:
|
||||
|
||||
```text
|
||||
跨平台
|
||||
优化
|
||||
后端接口
|
||||
```
|
||||
|
||||
不负责:
|
||||
|
||||
```text
|
||||
泛型
|
||||
属性
|
||||
高级语义
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 最终路线
|
||||
|
||||
```text
|
||||
NGRA
|
||||
↓
|
||||
SCG
|
||||
↓
|
||||
五角星AST
|
||||
↓
|
||||
寄存器式HIR
|
||||
↓
|
||||
CFG
|
||||
↓
|
||||
SSA
|
||||
↓
|
||||
LLVM IR
|
||||
↓
|
||||
x86/ARM
|
||||
|
||||
或
|
||||
|
||||
SPIR-V
|
||||
|
||||
或
|
||||
|
||||
CUDA/NVVM
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 对蓝图系统的启发
|
||||
|
||||
SSA最重要的启发:
|
||||
|
||||
程序可以拆成:
|
||||
|
||||
```text
|
||||
Control Flow Graph
|
||||
+
|
||||
Data Flow Graph
|
||||
```
|
||||
|
||||
两张图。
|
||||
|
||||
因此未来节点管线系统可考虑:
|
||||
|
||||
```text
|
||||
State Graph
|
||||
+
|
||||
Value Graph
|
||||
```
|
||||
|
||||
双图结构。
|
||||
|
||||
从:
|
||||
|
||||
```text
|
||||
DAG
|
||||
```
|
||||
|
||||
演化为:
|
||||
|
||||
```text
|
||||
Parallel State Machine
|
||||
+
|
||||
Data Dependency Graph
|
||||
```
|
||||
|
||||
这样能够自然支持:
|
||||
|
||||
```text
|
||||
Branch
|
||||
Loop
|
||||
Coroutine
|
||||
Async
|
||||
Event
|
||||
```
|
||||
|
||||
等复杂控制流。
|
||||
Reference in New Issue
Block a user