【问题标题】:Fortran possible to dot divide 2d array by 1d arrayFortran 可以将 2d 数组除以 1d 数组
【发布时间】:2015-09-01 13:11:04
【问题描述】:

为了最大限度地提高速度,我正在尝试对以下内容进行矢量化(以使编译器能够按照它认为好的方式进行矢量化):

integer  :: i,j
real :: a(4),b(4,5),c(4,5)
!... setting values to a and b...

do i=1,5
  do j=1,4
    c(j,i)=b(j,i)/a(i)
  end do
end do

我已经尝试了以下

c=b/a

但这不起作用:

错误 #6366:数组表达式的形状不符合。

我的想法是,既然你可以做 a/i,(数组/标量),我希望可以做(2d 数组/数组)。首先 b 和 c 的维度是 (5,4),我认为这就是问题所在,它需要符合第一级排名较小的变量,但情况似乎并非如此。截至目前,我想知道这是否有可能???还是我必须坚持使用 do 循环? (当然我可以对内循环向量化感到满意)

对任何与此相关的 cmets 或想法都非常满意。 (我在 Windows 上使用 ifort 16)

【问题讨论】:

  • c(j,:)=b(j,:)/a ?编译器通常很乐意对循环进行矢量化,因此我不希望性能发生太大变化。
  • 是的..这就是我的选择......或者相反(因为列主要安排)......好的,谢谢弗拉基米尔F
  • 您可以声明a(4,5) 并适当地初始化它,这样c=b/a 就正确了。顺便说一句,当您声明 a(4) 并在 i,5 上循环 a(i) 时,您的初始代码不正确

标签: arrays fortran vectorization intel-fortran fortran95


【解决方案1】:

如果您还没有得到答案,看似的非矢量化代码如下所示:

!Non-vectorized
do i=1,5
  do j=1,4
    c(j,i) = b(j,i) / a(j)
  enddo
enddo

看似这样的矢量化版本:

!Vectorized
do i=1,5
  c(:,i) = b(:,i) / a(:)
enddo

但是intel 编译器将它们都向量化了。要确定某个循环是否已被矢量化,请使用标志-qopt-report-phase=vec。这会生成有关已编译程序的矢量化报告,并且是了解某个循环是否已被矢量化的一种简洁方法。

以上代码生成的向量化报告如图:

.... Beginning stuff...
LOOP BEGIN at vect_div.f90(11,5)
remark #15542: loop was not vectorized: inner loop was already vectorized

 LOOP BEGIN at vect_div.f90(12,5)
    remark #15300: LOOP WAS VECTORIZED
 LOOP END
LOOP END

LOOP BEGIN at vect_div.f90(18,5)
remark #15542: loop was not vectorized: inner loop was already vectorized

 LOOP BEGIN at vect_div.f90(19,7)
    remark #15300: LOOP WAS VECTORIZED
 LOOP END
LOOP END

这里,(11,5)、(12,5) 等是我的 .f90 文本文件中 do 关键字所在的行号和列号。您可能会注意到,外部循环没有矢量化,而内部循环是矢量化的。它们都是矢量化的,也没有任何明显的区别。

可以通过更改 ifort 标志 -qopt-report=[n] 中的“n”值来生成更详细的报告

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-28
    • 2014-10-23
    • 1970-01-01
    • 1970-01-01
    • 2013-01-08
    • 2017-07-29
    • 1970-01-01
    • 2019-04-07
    相关资源
    最近更新 更多