在 Fortran 中优化数组乘法
Optimizing array multiplication in fortran
我正在尝试在 fortran 中优化以下类型的数组乘法:
do i = 1, n
do j = 1, n
do k = 1, n
do i1 = 1, n
do j1 = 1, n
do k1 = 1, n
B(k1,j1,i1) = B(k1,j1,i1) + &
A(k,j,i)*v1(k,k1)*v2(j,j1)*v3(i,i1)
enddo
enddo
enddo
enddo
enddo
enddo
这里 A 和 B 的大小为 (n,n,n),而 v1、v2 和 v3 的大小为 (n,n)。似乎应该有某种矢量化可以让我加快这个评估。我尝试了不同的指数排序。有没有更快的计算 B 的方法?
编辑:
好的,可以使用 matmul 获得大约 10 倍的加速:
do i = 1, n
do i1 = 1, n
do j = 1, n
do j1 = 1, n
B(:,j1,i1) = B(:,j1,i1) + &
matmul(A(:,j,i),v1)*v2(j,j1)*v3(i,i1)
enddo
enddo
enddo
enddo
我们可以做得更好吗?
您至少可以使用 matmul
或 BLAS/LAPACK 将两个循环对减少为矩阵乘法,例如
do i1=1,n
do i=1,n
B(:,:,i1) = B(:,:,i1) &
& + matmul(matmul(transpose(v1), A(:,:,i)), v2) * v3(i,i1)
enddo
enddo
您几乎肯定可以通过缓存双 matmul
的结果来进一步加快速度,例如
real :: intermediate(n,n,n)
do i=1,n
intermediate(:,:,i) = matmul(matmul(transpose(v1), A(:,:,i)), v2)
enddo
do i1=1,n
do i=1,n
B(:,:,i1) = B(:,:,i1) + intermediate(:,:,i) * v3(i,i1)
enddo
enddo
这可能反过来会被更多 matmul
加速,例如
real :: intermediate(n,n,n)
do i=1,n
intermediate(:,:,i) = matmul(matmul(transpose(v1), A(:,:,i)), v2)
enddo
do j1=1,n
B(:,j1,:) = matmul(intermediate(:,j1,:), v3))
enddo
我正在尝试在 fortran 中优化以下类型的数组乘法:
do i = 1, n
do j = 1, n
do k = 1, n
do i1 = 1, n
do j1 = 1, n
do k1 = 1, n
B(k1,j1,i1) = B(k1,j1,i1) + &
A(k,j,i)*v1(k,k1)*v2(j,j1)*v3(i,i1)
enddo
enddo
enddo
enddo
enddo
enddo
这里 A 和 B 的大小为 (n,n,n),而 v1、v2 和 v3 的大小为 (n,n)。似乎应该有某种矢量化可以让我加快这个评估。我尝试了不同的指数排序。有没有更快的计算 B 的方法?
编辑:
好的,可以使用 matmul 获得大约 10 倍的加速:
do i = 1, n
do i1 = 1, n
do j = 1, n
do j1 = 1, n
B(:,j1,i1) = B(:,j1,i1) + &
matmul(A(:,j,i),v1)*v2(j,j1)*v3(i,i1)
enddo
enddo
enddo
enddo
我们可以做得更好吗?
您至少可以使用 matmul
或 BLAS/LAPACK 将两个循环对减少为矩阵乘法,例如
do i1=1,n
do i=1,n
B(:,:,i1) = B(:,:,i1) &
& + matmul(matmul(transpose(v1), A(:,:,i)), v2) * v3(i,i1)
enddo
enddo
您几乎肯定可以通过缓存双 matmul
的结果来进一步加快速度,例如
real :: intermediate(n,n,n)
do i=1,n
intermediate(:,:,i) = matmul(matmul(transpose(v1), A(:,:,i)), v2)
enddo
do i1=1,n
do i=1,n
B(:,:,i1) = B(:,:,i1) + intermediate(:,:,i) * v3(i,i1)
enddo
enddo
这可能反过来会被更多 matmul
加速,例如
real :: intermediate(n,n,n)
do i=1,n
intermediate(:,:,i) = matmul(matmul(transpose(v1), A(:,:,i)), v2)
enddo
do j1=1,n
B(:,j1,:) = matmul(intermediate(:,j1,:), v3))
enddo