主対角線上にゼロがあるnxn下三角行列Aの圧縮スパース列(csc)表現があり、bを
(A + I)' * x = b
これは私がこれを計算するために持っているルーチンです:
void backsolve(const int*__restrict__ Lp,
const int*__restrict__ Li,
const double*__restrict__ Lx,
const int n,
double*__restrict__ x) {
for (int i=n-1; i>=0; --i) {
for (int j=Lp[i]; j<Lp[i+1]; ++j) {
x[i] -= Lx[j] * x[Li[j]];
}
}
}
したがって、b
は引数を介して渡さx
れ、ソリューションによって上書きされます。Lp
、Li
、Lx
それぞれスパース行列の標準CSC表現の行、インデックス、及びデータポインタです。この関数はプログラムの一番上のホットスポットで、次の行があります。
x[i] -= Lx[j] * x[Li[j]];
費やされた時間の大部分である。でコンパイルgcc-8.3 -O3 -mfma -mavx -mavx512f
できます
backsolve(int const*, int const*, double const*, int, double*):
lea eax, [rcx-1]
movsx r11, eax
lea r9, [r8+r11*8]
test eax, eax
js .L9
.L5:
movsx rax, DWORD PTR [rdi+r11*4]
mov r10d, DWORD PTR [rdi+4+r11*4]
cmp eax, r10d
jge .L6
vmovsd xmm0, QWORD PTR [r9]
.L7:
movsx rcx, DWORD PTR [rsi+rax*4]
vmovsd xmm1, QWORD PTR [rdx+rax*8]
add rax, 1
vfnmadd231sd xmm0, xmm1, QWORD PTR [r8+rcx*8]
vmovsd QWORD PTR [r9], xmm0
cmp r10d, eax
jg .L7
.L6:
sub r11, 1
sub r9, 8
test r11d, r11d
jns .L5
ret
.L9:
ret
vtuneによると、
vmovsd QWORD PTR [r9], xmm0
最も遅い部分です。私は組み立ての経験がほとんどなく、この操作をさらに診断または最適化する方法について途方に暮れています。SSE、FMAなどを有効/無効にするために、さまざまなフラグを使用してコンパイルしようとしましたが、何も機能しませんでした。
プロセッサー:Xeon Skylake
質問この機能を最適化するにはどうすればよいですか?
Li[j]
がから切り離されていると仮定して、負荷を収集、ベクトル化し、i
競合検出命令で仮定を確認し、すべてのが切り離されていることを確認しi
、結果を計算、分散保存します。競合が検出された場合は、スカラー実装にフォールバックします。
i < Li[j] < n
ます。A.の下三角自然言及する質問を更新しました
i >= Li[j]
、すべてのためのj
内部ループでは?