如何避免包含`a(i)= b(i,c(i))`的显式循环?

时间:2017-11-25 14:11:50

标签: fortran vectorization

您可以使用符号:索引或根本没有索引(在F95中)将您的普通矢量加法编码为do循环。我想这对编译器没有任何影响。不幸的是,我有一个嵌套语句,如:

CREATE INDEX index3_m ON movie_info_idx(movie_id, info_type_id, info(20));
CREATE INDEX index3_t ON title(kind_id, title(30));
CREATE INDEX index3_ci ON cast_info(movie_id, nr_order, role_id);

当然do i=1,n a(i)=b(i,c(i)) end do 是非法的。任何摆脱显式do循环的想法?

1 个答案:

答案 0 :(得分:0)

更新:经过一番思考之后,你实际上可以只使用一个隐含的数组构造函数(它不是显式的)。这只是

a = (/ (b(i,c(i)), i=1,SIZE(c)) /)

a = [ (b(i,c(i)), i=1,SIZE(c)) ]

请参阅标准的section 4.8

以下使用重塑和指针的原始答案。

它可以在没有循环的情况下完成,但如果这是一个好的做法,它是......非常值得怀疑。

首先,您需要知道数组存储在column-major order

这意味着在大小为(/ n,m /)的数组上,元素(i,j)位于内存位置i + n*(j-1)。因此,您需要做的就是重塑和提取,您可以通过以下方式执行:

  d = RESHAPE(b,(/ SIZE(b) /))                    ! reshape
  a = d((/ (i,i=1,SIZE(c)) /) + (c(:)-1)*SIZE(c)) ! extract

它不需要循环,但你必须分配更多的内存。除非你破解你的方式进入记忆。这可以通过指针

完成
  TYPEOFB, POINTER, DIMENSION(:) :: p
  p(1:SIZE(b)) => b(:,1)             ! just close your eyes
  a = p((/ (i,i=1,SIZE(c)) /) + (c(:)-1)*SIZE(c))

示例程序:

PROGRAM reshape
  IMPLICIT NONE
  !-- declaration of variables -----------------------------
  INTEGER, DIMENSION(4,3),TARGET :: b  !< target for pointer
  INTEGER, DIMENSION(4) :: c,a,a2
  INTEGER, DIMENSION(12) :: d
  INTEGER, DIMENSION(:), POINTER :: p  !< ugly pointer
  INTEGER :: i,j
  !-- setup of the test case ------------------------------
  c(1)=3; c(2)=2; c(3)=1; c(4)=2
  DO i=1,4
     DO j=1,3
        b(i,j) = i + 4*(j-1)
     END DO
  END DO
  !-- reshape and extract ---------------------------------
  d = RESHAPE(b,(/ SIZE(b) /))                    ! reshape
  a = d((/ (i,i=1,SIZE(c)) /) + (c(:)-1)*SIZE(c)) ! extract
  !-- ugly pointer hack -----------------------------------
  p(1:SIZE(b)) => b(:,1)             ! just close your eyes
  a2 = p((/ (i,i=1,SIZE(c)) /) + (c(:)-1)*SIZE(c))
  !-- print output ----------------------------------------
  DO i=1,4
     PRINT *, i, b(i,c(i)), a(i), a2(i)
  END DO
END PROGRAM reshape

输出

 % ./a.out 
 1 9 9 9
 2 6 6 6
 3 3 3 3
 4 8 8 8