我正在嘗試使用 AVX 實作以下操作:
for (i=0; i<N; i ) {
for(j=0; j<N; j ) {
for (k=0; k<K; k ) {
d[i][j] = 2 * a[i][k] * ( b[k][j]- c[k]);
}
}
}
for (int i=0; i<N; i ){
f = d[ind[i]][ind[i]]/2;
}
其中 d 是 NxN 矩陣,a 是 NxK,ba KxN 和 ca 長度為 K 的向量。它們都是雙精度數。當然,所有的資料都是對齊的,我是#pragma vector aligned用來幫助編譯器(gcc)的。
我知道如何將 AVX 擴展與一維陣列一起使用,但對我來說用矩陣來做這件事有點棘手。目前,我有以下內容,但我沒有得到正確的結果:
for (int i=0; i< floor (N/4); i ){
for (int j=0; j< floor (N/4); j ){
__m256d D, A, B, C;
D = _mm256_setzero_pd();
#pragma vector aligned
for (int k=0; k<K_MAX; k ){
A = _mm256_load_pd(a[i] k*4);
B = _mm256_load_pd(b[k] j*4);
C = _mm256_load_pd(c 4*k);
B = _mm256_sub_pd(B, C);
A = _mm256_mul_pd(A, B);
D = _mm256_add_pd(_mm256_set1_pd(2.0), A);
_mm256_store_pd(d[i] j*4, D);
}
}
}
for (int i=0; i<N; i ){
f = d[ind[i]][ind[i]]/2;
}
我希望有人能告訴我錯誤在哪里。
提前致謝。
注意:我不愿意介紹 OpenMP,只使用 SIMD 英特爾指令
uj5u.com熱心網友回復:
假設 N 和 K 數字都相對較大(遠大于硬體矢量大小的 4),這是矢量化主回圈的一種方法。未經測驗。
主要思想是矢量化中間回圈而不是內部回圈。這樣做有兩個原因。
這避免了水平操作。當僅對內部回圈進行向量化時,我們必須計算向量的水平和。
該
b[k][j]加載在加載 4 個連續k值時具有不幸的 RAM 訪問模式,需要 4 個單獨的加載指令或收集加載,這兩種方法都相對較慢。為 4 個連續j值加載元素是一個全向量加載指令,非常有效,尤其是在您對齊輸入時。
const int N_aligned = ( N / 4 ) * 4;
for( int i = 0; i < N; i )
{
int j = 0;
for( ; j < N_aligned; j = 4 )
{
// Load 4 scalars from d
__m256d dv = _mm256_loadu_pd( &d[ i ][ j ] );
// Run the inner loop which only loads from RAM but never stores any data
for( int k = 0; k < K; k )
{
__m256d av = _mm256_broadcast_sd( &a[ i ][ k ] );
__m256d bv = _mm256_loadu_pd( &b[ k ][ j ] );
__m256d cv = _mm256_broadcast_sd( &c[ k ] );
// dv = 2*av*( bv - cv )
__m256d t1 = _mm256_add_pd( av, av ); // 2*av
__m256d t2 = _mm256_sub_pd( bv, cv ); // bv - cv
dv = _mm256_fmadd_pd( t1, t2, dv );
}
// Store the updated 4 values
_mm256_storeu_pd( &d[ i ][ j ], dv );
}
// Handle remainder with scalar code
for( ; j < N; j )
{
double ds = d[ i ][ j ];
for( int k = 0; k < K; k )
ds = 2 * a[ i ][ k ] * ( b[ k ][ j ] - c[ k ] );
d[ i ][ j ] = ds;
}
}
如果您想進一步優化,請嘗試將內部回圈展開像 2 這樣的小因子,使用 2 個獨立的累加器,用 初始化_mm256_setzero_pd(),在回圈之后添加它們。可能是在某些處理器上,此版本在 FMA 指令的延遲上停止,而不是使加載埠或 ALU 飽和。多個獨立的累加器有時會有所幫助。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/468814.html
上一篇:簡單快速排序程式中的分段錯誤
