我正在嘗試撰寫一個函式,該函式將使用 ymm 暫存器用零填充我的浮點矩陣。
不久后我寫了這個函式:
void fillMatrixByZeros(float matrix[N][N]){
for (int k = 0; k < N; k = 8){
for (int i = 0; i < N; i){
asm volatile (
"vxorps %%ymm0, %%ymm0, %%ymm0;"
"vmovups %%ymm0, (%0)"
: "=m"(matrix[i] k)
:
: "%ymm0", "memory"
);
}
}
}
我試圖編譯我的整個代碼,但出現此錯誤:
prog.cpp: In function ‘void fillMatrixByZeros(float (*)[16])’:
prog.cpp:35:8: error: lvalue required in asm statement
35 | );
| ^
prog.cpp:35:8: error: invalid lvalue in asm output 0
我得出的結論matrix[i] k是右值或類似的東西,所以不能在那里使用。
谷歌搜索后,我想出了兩個解決方案:
第一:
void fillMatrixByZeros(float matrix[N][N]){
for (int k = 0; k < N; k = 8){
for (int i = 0; i < N; i){
asm volatile (
"vxorps %%ymm0, %%ymm0, %%ymm0;"
"vmovups %%ymm0, (%0)"
:
: "r"(matrix[i] k)
: "%ymm0", "memory"
);
}
}
}
第二:
void fillMatrixByZeros(float matrix[N][N]){
long long int matrixPointer;
for (int k = 0; k < N; k = 8){
for (int i = 0; i < N; i){
asm volatile (
"vxorps %%ymm0, %%ymm0, %%ymm0;"
"vmovups %%ymm0, (%0)"
: "=r"(matrixPointer)
: "0"(matrix[i] k)
: "%ymm0", "memory"
);
}
}
}
這些功能正常作業。我想知道為什么。
為什么第一個函式中沒有任何左值問題?第二個函式中發生了什么?
uj5u.com熱心網友回復:
您不能分配給matrix[i] k,因此它不是左值。該m約束預計在記憶體中的物件,而不是它的地址。因此,要解決此問題,請提供要分配給的物件而不是其地址:
void fillMatrixByZeros(float matrix[N][N]){
for (int k = 0; k < N; k = 8){
for (int i = 0; i < N; i){
asm volatile (
"vxorps %%ymm0, %%ymm0, %%ymm0;"
"vmovups %%ymm0, %0"
: "=m"(matrix[i][k])
:
: "%ymm0", "memory"
);
}
}
}
這是在行內匯編陳述句中訪問記憶體中物件的正確方法。
解決方案使用r帶有運算元地址的約束,然后執行顯式取消參考作業。但它們的效率可能較低,因為它們會阻止編譯器使用某些其他尋址模式,例如 SIB 尋址模式。相反,它必須首先在暫存器中實作地址。
你的最后一個例子有點傻。它使用耦合的 asm 運算元matrixPointer = matrix[i] k在將其傳遞給行內匯編陳述句之前執行。這是一種非常迂回的方法,根本不需要。
也就是說,為了進一步提高效率,您應該提升ymm0回圈外的清除。也許是這樣的?
#include <immintrin.h>
#define N 1000
void fillMatrixByZeros(float matrix[N][N]){
for (int k = 0; k < N; k = 8){
for (int i = 0; i < N; i){
asm volatile (
"vmovups %1, %0"
: "=m"(matrix[i][k])
: "x"(_mm256_setzero_ps())
: "memory"
);
}
}
}
請注意,僅呼叫memset可能比手動行內匯編執行得更好。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/365370.html
