Fortran 循环未矢量化,因为它包含对非矢量内在函数的引用
我正在编写一个大型Fortran程序,其中性能至关重要。我使用模块来存储公共参数和变量。但问题是,如果模块变量用于某种数组操作,编译器就不会对其进行矢量化。以此为例,Fortran 循环未矢量化,因为它包含对非矢量内在函数的引用,fortran,vectorization,Fortran,Vectorization,我正在编写一个大型Fortran程序,其中性能至关重要。我使用模块来存储公共参数和变量。但问题是,如果模块变量用于某种数组操作,编译器就不会对其进行矢量化。以此为例, module name integer :: p end module name program name1 use name real(kind=8) :: x(10,10), y(10) integer :: i,j p=9 do i=1,10 do
module name
integer :: p
end module name
program name1
use name
real(kind=8) :: x(10,10), y(10)
integer :: i,j
p=9
do i=1,10
do j =1,10
x(i,j) = i+j
enddo
enddo
y = x(:,p)*x(:,p-1)
print *, y
end program name1
现在,当我使用ftn-eD file.f90
在Cray(XC50)
上编译它时,生成的.lst
文件显示
9. program name1
10. ! implicit none
11. use name
12. real(kind=8) :: x(10,10), y(10)
13. integer :: i,j
14. do i=1,10
15. do j =1,10
16. x(i,j) = i+j
17. enddo
18. enddo
19.
20. y = x(:,p)*x(:,p-1)
ftn-6263 ftn: VECTOR NAME1, File = test.f90, Line = 20
A loop starting at line 20 was not vectorized because it contains a reference to a non-vector intrinsic on line 20.
21. print *, y
22. end program name1
23.
24.
我一直认为使用
:
执行数组操作会更容易让编译器将其矢量化。但若使用模块变量不利于矢量化,那个么在性能至关重要时使用模块是否也不好呢?我是不是弄糊涂了?如何提高这些情况下的性能?您可以通过执行类似于y=dot_乘积(x(:,p-1),x(:,p))
的操作来强制编译器对您的操作进行向量化吗?好的,现在它显示从第20行开始的循环已部分向量化。
如果您的CPU具有4/8通道SIMD 64位浮点操作功能,大小为10的数组无法完全矢量化,因此编译器可能会将范围[1:4]和[5:8]作为SIMD运行,而元素9和10将是串行代码。另外:我注意到您没有计算点积,所以我以前的评论不是对您原始代码的有效替换。一种选择是尝试对所有(i=1:10)y(i)=x(i,p)*x(i,p-1)进行,或者类似地,对于do concurrent
,上面的例子非常简单。实际的操作可能更大更复杂,我有数千个这样的操作。那么,在这种情况下,你最后会建议遵循什么?(可能你可以在这里输入答案。)它可能已经决定不进行矢量化,因为矢量长度很短。如果你让它变长会发生什么?如果长度作为参数传递给子程序,会发生什么情况?