【问题标题】:Vectorization of Linked-list in FortranFortran中链表的向量化
【发布时间】:2019-05-18 02:33:41
【问题描述】:

我有数百万个数据点,每个数据点都经过相同的数学运算,并且它们不相互依赖。因此,这个问题理论上应该是可向量化的。

现在这些数据点将最方便地存储为 Fortran 中的链表,因此删除/添加非常简单。然后主循环将类似于

do while(associated(data_points)) 

     data_points => data_points% next
       ......
enddo 

这如何与矢量化一起工作?

另一种选择是将所有变量存储在一个有组织的声明类型中,并分配一个该类型的数组,该数组等于数据点的数量,例如:

type(type_data_points) :: data_points(1:no_data_types)

然后做循环就是

do i = 1, no_data_types 
    data_points(i)% x = (...) 
    data_points(i)% y = (...) 
     ....
enddo

甚至后者是否会被矢量化 - 除了将每个变量 (x,y, ...) 定义为 no_data_points 的数组并执行计算之外,我还有哪些选项。

【问题讨论】:

  • 这个问题很宽泛,但一般内存布局越简单,定义越明确,就越容易。为什么不是二维数组?那将是我的首选解决方案。最终,如果你真的在乎,你必须实现几个方法并进行测试。
  • 感谢您的评论。我只是在尝试使用这种链表代码样式探索任何选项,同时保持向量化。数组的问题在于我的模拟是动态的,因此,根据具体情况,我可能不得不重新分配并再次分配以扩大数组 - 所以认为建议的方式可能更优雅,并且在分配时会避免所有复制并解除分配。
  • 分配/解除分配的频率如何?您可能需要进行一些测试。有很多文献可用于这类实现问题 - 例如,我熟悉 CFD 中的自适应网格细化这个问题。我知道的一篇论文是arc.aiaa.org/doi/abs/10.2514/6.2014-3080
  • 感谢您的论文!这取决于具体情况——我确实有一个初始的大分配来尝试为此合并。但即便如此,内存需求也可能相当广泛,因为许多数据点最终会消失并知道会被引入。使用数组方法,仅添加/删除它们并不简单。
  • 测试它可能很简单,因为只需在矢量化报告中查看它是否矢量化。 (假设 -vec-report3 和 ifort)。还有诸如 UNION /MAP 之类的技巧,或其他一些连续处理数据的方法……但链表有点暗示像 Qbert 一样跳跃。

标签: linked-list fortran vectorization fortran90 intel-fortran


【解决方案1】:

除了您在问题中已经提到的之外,可以考虑以下选项:

  1. deallocateallocate 每次添加或删除数据点时都会生成一个数组。

  2. 声明一个比预期数据大得多的数组并跟踪添加了多少数据点。然后您可以对切片数组本身执行数学运算。预计这将提供非常好的性能。如果您遇到需要更大数组的点,您可能必须再次使用deallocateallocate 数组。这需要比以前更少的分配,因此是一个更简洁的选择。

  3. 建议的非标准语言扩展 here

您的链表数据结构也可以,但在与MPI 并行时要适当考虑。与数组的通信要高效得多,也方便得多。由于数据是独立的,并且您打算独立执行操作,我认为您还需要再次收集所有数据。在链表的情况下,您可能必须首先收集所有数据以在缓冲区中进行通信,然后发送/接收/全部收集。但是,如果它已经在数组中结构化,则要容易得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多