multithreading - 我怎样才能避免这个循环中的 "i"依赖?语言

我在我的代码中使用 OpenMP,但为了做到这一点,我必须解决这个依赖关系:

do q=1,pppp
    i=0
    
    DO j=1, pppp
        do c1=1,3
            vect(c1)=xx(q,c1)-xx(j,c1)
        end do
        dist=sqrt(vect(1)**2+vect(2)**2+vect(3)**2)
        if(dist<0.0001)then
            i=i+1
            if(i>10)i=10
            caravec(q,i)=j
        endif
    ENDDO
ENDDO  

我试图避免 ordered 子句,因为它很昂贵,但我不知道如何删除依赖项。我该怎么做?
感谢大家的帮助

最佳答案

在 @dreamcrash 上,您可以做一些 Fortran 语言的改进。 ' 出色的回答:

  • Fortran 是 column-major ,所以你想迭代内部循环中最左边的索引,而不是最右边的索引。所以你应该转置 xx , 所以它是 3*pppp索引为 xx(c1,q) 的数组而不是 pppp*3索引为 xx(q,c1) 的数组.

  • 您可能希望使用整个数组操作而不是单个元素操作,因为它们更有可能被向量化。

  • 您可以存储 dist<0.0001 的结果而不是 dist .

  • 您可以替换 if (i>10)...min语句,它将是无分支的,因此可能运行得更快。

所以代码看起来像这样:

do q=1,pppp        
  do j=1,pppp
    vect = xx(:,q)-xx(:,j)
    within_tolerance(j, q) = dot_product(vect, vect) < 1.0e-8
  enddo
enddo

do q=1,pppp
  i=0    
  do j=1,pppp
    if (within_tolerance(j, q)) then
      i = min(i+1, 10)
      caravec(q,i)=j
    endif
  enddo
enddo

您可能还想转置 caravec , 但这将取决于它在其他地方的使用方式。

一个XY problem解决方案

如果这是您的代码的瓶颈,您可能需要研究基于体素的方法来查找向量集中的最近邻居。快速谷歌带来例如this .

体素方法消除了对 q 的双重循环的需要和 j ,这可能会让您更快地进行此类比较。

另一方面,体素方法非常复杂,我认为它们并不适合所有情况(例如,如果点的区域非常密集,而点的区域非常稀疏,那么我认为体素方法会斗争)。

关于multithreading - 我怎样才能避免这个循环中的 "i"依赖?语言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72836033/

相关文章:

string - 如何将字符串中的 "Umlaute"(ü)转为 "ue"?

c# - 返回匿名类型的 IEnumerable

java - 使用流 groupingBy 时将字符串分组为多个组

java - BitSet 的 set 方法如何处理向左移动的位?

sql - SQL Server 中 OVER 和 PARTITION BY 生成的值的状态

bash - awk 或条件

r - 为什么带有 %in% 的条件会忽略缺失值?

python - FastAPI 多个路由绑定(bind)到同一个函数。如何知道请求了哪一个

excel - 按分隔符幂查询的 X 实例拆分行

sql - 如何在 Snowflake 的枢轴中使用 LISTAGG?