F#中多核并行机制中缓存局部性的最佳实践
我正在研究F#中的多核并行机制。 我不得不承认,不变性确实有助于编写正确的并行实现。 但是,当内核数量增长时,很难实现良好的加速和良好的可扩展性。 例如,我使用快速排序算法的经验是,许多尝试以纯功能方式实现并行快速排序并使用List
或Array
作为表示失败。 对那些实现进行分析表明,与顺序版本相比,高速缓存未命中的数量显着增加。 但是,如果使用阵列内部的突变实现并行快速排序,则可以获得较好的加速比。 因此,我认为突变可能是优化多核平行度的一种好方法。
我认为缓存局部性是功能语言中多核并行的一大障碍。 函数式编程涉及创建许多短暂的对象; 销毁这些对象可能会破坏CPU高速缓存的一致性。 例如,在这里和这里,我看到了很多关于如何改进命令式语言中的缓存局部性的建议。 但是我不清楚他们在函数式编程中是如何完成的,尤其是对于经常出现的树等递归数据结构。
是否有任何技术来改善不纯功能语言(特别是F#)中的缓存局部性? 任何建议或代码示例都是值得欢迎的。
据我所知,缓存局部性(多线程或其他)的关键是
为此 ;
实际上,这意味着你最终可能会使用不是理论上完美的计算机科学范例的数据结构 - 但没关系,计算机在理论上也不是理想的计算机科学范例。
关于此主题的一篇很好的学术论文是使用复制的缓存高效字符串排序
在F#中的函数中允许可变性是一种幸福,但它应该只在优化代码时使用。 纯功能的风格通常会产生更直观的实现,因此是首选。
以下是快速搜索的结果:Haskell中的并行Quicksort。 让我们继续关注性能的讨论。 选择一个处理器,然后用特定的算法进行处理。
为了回答你的问题而没有具体的问题,我会说Clojure的实现STM的方法可能是一般情况下的一个教训,关于如何分离多核处理器上的执行路径并改善缓存局部性。 但只有当读取次数超过写入次数时才有效。
我不是平行主义专家,但无论如何,这是我的建议。
上一篇: Best Practices for cache locality in Multicore Parallelism in F#
下一篇: The state of programming and compiling for multicore systems