solve or inv starts

This commit is contained in:
Youmu Liu
2026-01-13 18:25:25 +08:00
parent ad3b2212fa
commit f133cc9147
11 changed files with 103 additions and 147 deletions
+1 -1
View File
@@ -159,7 +159,7 @@
<ClCompile Include="sn-src\m.basic.x86.c" />
<ClCompile Include="sn-src\dllmain.c" />
<ClCompile Include="sn-src\m.bufop.x86.c" />
<ClCompile Include="sn-src\m.pivot.x86.c" />
<ClCompile Include="sn-src\m.solve.x86.c" />
<ClCompile Include="sn-src\m.fma_tile.x86.c" />
<ClCompile Include="sn-src\s.factorial.x86.c" />
<ClCompile Include="sn-src\m.fma.x86.c" />
@@ -57,7 +57,7 @@
<ClCompile Include="sn-src\m.panel.x86.c">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="sn-src\m.pivot.x86.c">
<ClCompile Include="sn-src\m.solve.x86.c">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="sn-src\cpuid.x86.c">
@@ -149,6 +149,8 @@ DECLARE_PNL_PROC_ANS(double, sse, , clear);
DECLARE_PNL_PROC_ANS(double, avx, , clear);
DECLARE_PNL_PROC_ANS(double, 512, , clear);
DECLARE_KER_PROC_RIGHT_ANS(float, sse, , quality);
DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, , fma);
DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, , fma);
DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, _fma, fma);
-70
View File
@@ -1,70 +0,0 @@
#include "sn_target.h"
#if SN_IS_ARCH(SN_ARCH_X86_64)
#include "sn_intrinsic.h"
// Hybrid implementation: SIMD for Abs, Scalar for Max
// Assumes Column-Major layout for both MAT_KERNEL content and Kernel sequence
INTERNAL void SN_DECL pivot_float(MAT_KERNEL(float) const *source, size_t col_begin,
size_t col_length, size_t *restrict ans)
{
float max_v[4] = { -1.0f, -1.0f, -1.0f, -1.0f };
// Initialize ans with the first row index of the search range
size_t start_row = col_begin * 4;
ans[0] = start_row;
ans[1] = start_row;
ans[2] = start_row;
ans[3] = start_row;
const MAT_KERNEL(float) *k_ptr = source + col_begin;
// Mask for absolute value: 0x7FFFFFFF (clears the sign bit)
__m128i abs_mask = _mm_set1_epi32(0x7FFFFFFF);
for (size_t i = 0; i < col_length; ++i) {
const float *mat_ptr = (const float *)(k_ptr + i);
size_t base_row = (col_begin + i) * 4;
// Iterate over 4 columns of the kernel
for (int c = 0; c < 4; ++c) {
// Load column c: 4 floats (Column-Major: contiguous in memory)
__m128 col_vec = _mm_load_ps(mat_ptr + c * 4);
// Convert to integer vector, AND with mask, convert back
__m128i col_i = _mm_castps_si128(col_vec);
col_i = _mm_and_si128(col_i, abs_mask);
col_vec = _mm_castsi128_ps(col_i);
VEC(float) vals;
_mm_store_ps(vals.v, col_vec);
// Local reduction to find the max within this column chunk (4 elements)
// This breaks the dependency chain and reduces branches/cmovs on the global max_v
float v0 = vals.v[0];
float v1 = vals.v[1];
float v2 = vals.v[2];
float v3 = vals.v[3];
// Compare pairs (0 vs 1) and (2 vs 3) - these can execute in parallel
int i01 = (v1 > v0) ? 1 : 0;
float m01 = (v1 > v0) ? v1 : v0;
int i23 = (v3 > v2) ? 3 : 2;
float m23 = (v3 > v2) ? v3 : v2;
// Compare winners
int i_local = (m23 > m01) ? i23 : i01;
float m_local = (m23 > m01) ? m23 : m01;
// Single check against global maximum
if (m_local > max_v[c]) {
max_v[c] = m_local;
ans[c] = base_row + i_local;
}
}
}
}
#endif
+45
View File
@@ -0,0 +1,45 @@
#include "sn_target.h"
#if SN_IS_ARCH(SN_ARCH_X86_64)
#include "sn_intrinsic.h"
DECLARE_KER_PROC_RIGHT_ANS(float, sse, , quality)
{
static const __m128 abs_mask_source = { .m128_i32 = { 0x80000000, 0x80000000, 0x80000000,
0x80000000 } };
register __m128 abs_mask = _mm_load_ps(abs_mask_source.m128_i32);
register __m128 col0 = _mm_andnot_ps(abs_mask, _mm_load_ps((float *)&right->f32_x[0]));
register __m128 col1 = _mm_andnot_ps(abs_mask, _mm_load_ps((float *)&right->f32_x[1]));
register __m128 col2 = _mm_andnot_ps(abs_mask, _mm_load_ps((float *)&right->f32_x[2]));
register __m128 col3 = _mm_andnot_ps(abs_mask, _mm_load_ps((float *)&right->f32_x[3]));
// norm
register __m128 row_sum = _mm_add_ps(col0, col1);
row_sum = _mm_add_ps(row_sum, col2);
row_sum = _mm_add_ps(row_sum, col3);
// max(0,2) and max(1,3)
register __m128 max = _mm_max_ps(row_sum, _mm_movehl_ps(row_sum, row_sum));
max = _mm_max_ps(max, _mm_shuffle_ps(max, max, _MM_SHUFFLE(2, 3, 0, 1)));
float norm = _mm_cvtss_f32(max);
ans->f32_x[0].m128_f32[0] = norm;
// min on cross
col1 = _mm_shuffle_ps(col1, col1, _MM_SHUFFLE(0, 3, 2, 1));
col2 = _mm_shuffle_ps(col2, col2, _MM_SHUFFLE(1, 0, 3, 2));
col3 = _mm_shuffle_ps(col3, col3, _MM_SHUFFLE(2, 1, 0, 3));
max = _mm_min_ps(col0, col2);
register max0 = _mm_min_ps(max, col1);
max = _mm_min_ps(max0, max);
float min_val = _mm_cvtss_f32(max);
ans->f32_x[0].m128_f32[1] = min_val;
float quality = min_val / (norm + 1e-20f);
ans->f32_x[0].m128_f32[2] = quality;
}
#endif