我的f90程序中有一部分占用了大量的计算时间。我基本上是在遍历三个矩阵(尺寸相同,尺寸高达250×250),并试图确保值保持在区间- 1.0,1.0的范围内。我知道最好的做法是避免循环中的条件,但我很难找到如何重写这段代码以获得最佳性能。有没有办法“解开”循环,或者使用某种内置函数来“向量化”条件语句?
do ind2 = 1, size(u_mat,2)
do ind1 = 1,size(u_mat,1)
! Dot product 1 must be bounded between [-1,1]
if (b1_dotProd(ind1,ind2) .GT. 1.0_dp) then
b1_dotProd(ind1,ind2) = 1.0_dp
else if (b1_dotProd(ind1,ind2) .LT. -1.0_dp) then
b1_dotProd(ind1,ind2) = -1.0_dp
end if
! Dot product 2 must be bounded between [-1,1]
if (b2_dotProd(ind1,ind2) .GT. 1.0_dp) then
b2_dotProd(ind1,ind2) = 1.0_dp
else if (b2_dotProd(ind1,ind2) .LT. -1.0_dp) then
b2_dotProd(ind1,ind2) = -1.0_dp
end if
! Dot product 3 must be bounded between [-1,1]
if (b3_dotProd(ind1,ind2) .GT. 1.0_dp) then
b3_dotProd(ind1,ind2) = 1.0_dp
else if (b3_dotProd(ind1,ind2) .LT. -1.0_dp) then
b3_dotProd(ind1,ind2) = -1.0_dp
end if
end do
end do值得的是,我正在使用ifort进行编译。
发布于 2021-11-13 14:49:25
发布于 2021-11-16 10:33:10
@veryreverie的答案肯定是正确的,但是有两件事需要考虑。
where语句是另一个明智的选择。因为它仍然是有条件的选择--同样的警告这是否真的避免了分支,如果它实际上更快,但它至少要简洁得多
仍然适用。
一个例子是:
pure function clamp(X) result(res)
real, intent(in) :: X(:)
real :: res(size(X))
where (X < -1.0)
res = -1.0
else where (X > 1.0)
res = 1.0
else
res = X
end where
end functiona == 1等,而无需考虑浮点相等问题。根据您的代码,我还会考虑点积接近于零的情况。当然,这一点只适用于,如果你只感兴趣的标志。 pure function get_sign(X) result(res)
real, intent(in) :: X(:)
integer :: res(size(X))
! Or use another appropiate choice to test for near_zero
where (abs(X) < epsilon(X) * 10.)
res = 0
else where (X < 0.0)
res = -1
else where (X > 0.0)
res = +1
end where
end functionhttps://stackoverflow.com/questions/69955176
复制相似问题