我正在尝试将Intel内部函数转换为嵌入式程序集。
代码将要计算一个4x4矩阵。 A
和B
的大小分别为4 x kc
和kc x 4
。
这是完整的功能:
#define MR 4
#define NR 4
// compute C := beta * C + alpha * AB
static void dgemm_micro_kernel(int kc,
double alpha, const double *A, const double *B,
double beta,
double *C, int incRowC, int incColC)
{
double AB[MR*NR] __attribute__ ((aligned (32)));
int i, j, p;
register __m256d ab_00_10_20_30, ab_01_11_21_31, ab_02_12_22_32, ab_03_13_23_33;
register __m256d a_0123, b_0000, b_1111, b_2222, b_3333;
ab_00_10_20_30 = _mm256_setzero_pd();
ab_01_11_21_31 = _mm256_setzero_pd();
ab_02_12_22_32 = _mm256_setzero_pd();
ab_03_13_23_33 = _mm256_setzero_pd();
for (p = 0; p < kc; p++)
{
a_0123 = _mm256_load_pd(A);
b_0000 = _mm256_broadcast_sd(B);
b_1111 = _mm256_broadcast_sd(B + 1);
b_2222 = _mm256_broadcast_sd(B + 2);
b_3333 = _mm256_broadcast_sd(B + 3);
// Col 1
ab_00_10_20_30 = _mm256_fmadd_pd(a_0123, b_0000, ab_00_10_20_30);
// Col 2
ab_01_11_21_31 = _mm256_fmadd_pd(a_0123, b_1111, ab_01_11_21_31);
// Col 3
ab_02_12_22_32 = _mm256_fmadd_pd(a_0123, b_2222, ab_02_12_22_32);
// Col 4
ab_03_13_23_33 = _mm256_fmadd_pd(a_0123, b_3333, ab_03_13_23_33);
A += MR;
B += NR;
}
_mm256_store_pd(AB + 0, ab_00_10_20_30);
_mm256_store_pd(AB + 4, ab_01_11_21_31);
_mm256_store_pd(AB + 8, ab_02_12_22_32);
_mm256_store_pd(AB + 12, ab_03_13_23_33);
// Updata C := beta * C
if (beta == 0.0)
{
// C == 0
for (j = 0; j < NR; j++)
{
for (i = 0; i < MR; i++)
{
C[i * incRowC + j * incColC] = 0.0;
}
}
}
else if (beta != 1.0)
{
// C := beta * C
for (j = 0; j < NR; j++)
{
for (i = 0; i < MR; i++)
{
C[i * incRowC + j * incColC] *= beta;
}
}
}
// Updata C := C + alpha * AB
if (alpha == 1.0)
{
for (j = 0; j < NR; j++)
{
for (i = 0; i < MR; i++)
{
C[i * incRowC + j * incColC] += AB[j * MR + i];
}
}
}
else
{
for (j = 0; j < NR; j++)
{
for (i = 0; i < MR; i++)
{
C[i * incRowC + j * incColC] += alpha * AB[j * MR + i];
}
}
}
}
这是我的嵌入式程序集(只需发布相关零件):
double AB[16] __attribute__ ((aligned(32)));
__asm__ volatile
(
"movl %0, %%esi \n\t" // kc
"movq %1, %%rax \n\t" // A
"movq %2, %%rbx \n\t" // B
"movq %3, %%rcx \n\t" // AB
" \n\t"
"vxorpd %%ymm0, %%ymm0, %%ymm0 \n\t" // SET ZERO
"vxorpd %%ymm1, %%ymm1, %%ymm1 \n\t"
"vxorpd %%ymm2, %%ymm2, %%ymm2 \n\t"
"vxorpd %%ymm3, %%ymm3, %%ymm3 \n\t"
" \n\t"
"testl %%esi, %%esi \n\t" // CHECK
"je .DWRITEAB \n\t"
" \n\t"
".DLOOP: \n\t" // LOOP
"vmovapd (%%rax), %%ymm4 \n\t" // load a_0123
"vbroadcastsd (%%rbx), %%ymm5 \n\t" // load b_0000
"vbroadcastsd 8(%%rbx), %%ymm6 \n\t" // load b_1111
"vbroadcastsd 16(%%rbx), %%ymm7 \n\t" // load b_2222
"vbroadcastsd 24(%%rbx), %%ymm8 \n\t" // load b_3333
" \n\t"
"vfmadd132pd %%ymm4, %%ymm5, %%ymm0 \n\t" // Col 1
"vfmadd132pd %%ymm4, %%ymm6, %%ymm1 \n\t" // Col 2
"vfmadd132pd %%ymm4, %%ymm7, %%ymm2 \n\t" // Col 3
"vfmadd132pd %%ymm4, %%ymm8, %%ymm3 \n\t" // Col 4
" \n\t"
"addq $32, %%rax \n\t"
"addq $32, %%rbx \n\t"
" \n\t"
"decl %%esi \n\t"
"jne .DLOOP \n\t"
" \n\t"
".DWRITEAB: \n\t"
"vmovapd %%ymm0, (%%rcx) \n\t"
"vmovapd %%ymm1, 32(%%rcx) \n\t"
"vmovapd %%ymm2, 64(%%rcx) \n\t"
"vmovapd %%ymm3, 96(%%rcx) \n\t"
" \n\t"
: // output
: // input
"m" (kc), // 0
"m" (A), // 1
"m" (B), // 2
"m" (AB) // 3
: // clober list
"rax", "rbx", "rcx", "esi",
"xmm0", "xmm1", "xmm2", "xmm3", "xmm4",
"xmm5", "xmm6", "xmm7", "xmm8", "memory"
);
然后我编译并运行它,输出显示Segmentation fault (core dumped)
。但是,内在版本运行良好。我的内联汇编代码有什么问题?
答案 0 :(得分:2)
if( $(':focus').is('[formaction]') ) {
console.log($(':focus').attr('formaction'));
}
是一个数组,但是您将其用作指针。
另外,它是输出,但被列为输入。
最简单的解决方法是使用AB
而不是lea
将mov
的地址加载到AB
中。还要将rcx
作为输出。
更好的解决方案是让编译器进行寄存器分配,并删除eax,ebx,ecx和esi的掩盖内容。通过使用"=m"(AB)
约束,编译器将数组转换为指向其第一个元素的指针,并将该指针放入寄存器中。您可以通过列出两次数组操作数来避免内存破坏。
警告,这不太正确,因为它不能正确指示汇编代码更改了其输入寄存器。由于您尚未显示全部功能,因此无法确定是否会导致问题(但这绝对是错误的)。
"r"
这需要在汇编代码中更改对参数的所有引用,以使用asm ("..."
: // output
"=m"(AB)
: // input
"r"(kc), "r"(A), "r"(B), "r"(AB),
"m"(*(double (*)[4*kc])A), "m"(*(double (*)[4*kc])B)
: // clobber list
"xmm0", "xmm1", "xmm2", "xmm3", "xmm4",
"xmm5", "xmm6", "xmm7", "xmm8"
);
,%1
,%2
和%3
。