F#作为HPC语言

时间:2010-11-04 12:56:18

标签: .net f# hpc

我使用F#开发了Lattice Boltzmann(流体动力学)代码。我现在正在24核128 GB内存服务器上测试代码。代码基本上由一个用于时间演化的主递归函数和一个用于三维空间迭代的System.Threading.Tasks.Parallel.For循环内部组成。 3D空间是500x500x500大,一个时间周期永远:)。

let rec timeIterate time =
  // Time consuming for loop
  System.Threading.Tasks.Parallel.For(...)

我希望服务器能够使用所有24个内核,即100%使用。我观察到的是1%-30%的使用率。

我的问题是:

  1. F#是否适合在此类服务器上进行HPC计算?
  2. 使用高达100%的CPU来解决现实问题是否现实?
  3. 我应该怎样做才能获得高速度?所有东西都在一个大的并行循环中,所以我希望它就是我应该做的......
  4. 如果F#不是一种合适的语言,那是什么语言?
  5. 感谢您提出任何建议。

    编辑:如果有兴趣的话,我愿意分享这些代码。

    EDIT2:以下是代码的剥离版本:http://dl.dropbox.com/u/4571/LBM.zip 它没有做任何合理的事情,我希望我没有通过剥离代码来引入任何错误:)

    启动文件是ShearFlow.fs,文件底部是

    let rec mainLoop (fA: FArrayO) (mR: MacroResult) time =
      let a = LBM.Lbm.lbm lt pA getViscosity force g (fA, mR)
    

7 个答案:

答案 0 :(得分:5)

  

1。 F#是否适合在此类服务器上进行HPC计算?

它(F#),作为一种语言,可以鼓励并行运行的代码 - 至少部分是减少状态可变性和高阶函数 - 这是一个可以而不是 。然而,对于HPC,存在许多专业编程语言/编译器和/或负载分配方式(例如,共享统一存储器或分布式微内核)。 F#仅仅是通用编程语言:它可以或可以不具有对各种技术的访问(例如,可能存在或可能不存在绑定)。 (这甚至适用于非分布式并行计算。)

  

2。对于现实世界的问题,使用高达100%的CPU是否现实?

这取决于限制因素是什么。与我的 5k + 100k +核心HPC研发的朋友交谈,交换数据和空闲时间通常是限制因素(当然,这是一个更高的n :-),因此即使IO减少(效率或不同算法)的微小改进也可以带来显着的收益。不要忘记在同一台机器上简单地在CPU /缓存之间移动数据的成本!当然,磁盘IO速度太慢......

  

3。我该怎么做才能获得高速度?所有东西都在一个大的并行循环中,所以我希望它就是我应该做的......

找出缓慢部分的位置并修复它们(它们):-)例如运行配置文件分析。请记住,它可能需要使用完全不同的算法或方法。

  

4。如果F#不是一种合适的语言,那么语言是什么?

虽然我不是在争论它,但我的博士朋友使用/工作Charm++:它是一种非常集中的语言,用于分布式并行计算(不是有问题的环境,但我试图说明一点:-) - F#试图成为一种不错的通用语言。

答案 1 :(得分:4)

F#应该和任何语言一样好。编写代码的方式多于决定性能的语言本身。

如果您的计算受CPU限制,您应该能够接近100%,至少在90%的高范围内。

可能有几个原因导致您无法获得100%的CPU。

  1. 您的计算可能受I / O限制(您是否在for循环中执行文件或网络操作?)
  2. 你有同步问题,比如多次锁定(你是否在线程之间有共享状态,包括你“提交”结果的地方?)

答案 2 :(得分:3)

  

F#是否适合在此类服务器上进行HPC计算?

我不太了解F#,但我宁愿怀疑它非常适合 。它拥有所有正确的工具,它是一种功能语言,可以高度并行执行。

  

对于现实世界的问题,使用高达100%的CPU是否现实?

是的,或者非常接近。但实际上,如果你有24个内核,你的应用程序应该使用2400%的CPU功率!至少,这是它通常显示的方式。如果您观察到30%的使用率,则可能是在单个核心上运行,甚至没有使用该核心。

  

我应该怎样做才能获得高速度?所有东西都在一个大的并行循环中,所以我希望它就是我应该做的......

好吧,你没有显示你的代码。我只能假设代码中的某些内容阻止它并行执行。

或者(CPU使用率为1%到30%)您的问题实际上并不是计算限制,并且计算总是等待其他资源(如辅助内存)。这不一定取决于问题 - 毕竟,流体动力学 是计算限制的问题! - 而是你的特定实施。到目前为止,很多指向资源争用。

答案 3 :(得分:2)

  1. 我不认为F#已经成为HPC的主流,Fortran,C和C ++占主导地位,但我没有看到任何特殊原因,你应该避免它。

  2. 不,不是,不是任何延长的时间段。迟早所有(可疑的断言)HPC代码变得内存带宽有限 - CPU可以比RAM加载和存储更快地处理数字。在长时间运行的计算中,您可以使用CPU可以执行的理论最大FLOP数的10%。

  3. 我真的不太了解F#,无法为您的配置提供具体建议(我是HPC Fortran程序员之一)。但总的来说,您需要确保良好的负载平衡(即所有核心执行相同的工作量),高效且有效地使用内存层次结构(随着语言变得“更高级别”而变得困难,因为它们往往会使其变得困难管理低级别的流程),您可以做的最好的事情是选择最佳算法。最好的并行算法不一定是并行的最佳串行算法,我怀疑算法的最佳功能(实现)可能不是最好的(命令式实现)算法。

  4. 的Fortran。

答案 4 :(得分:1)

线程池具有最大线程数,具体取决于各种情况。

来自MSDN

  

最大线程池线程数

     

可以排队到线程池的操作数量仅受可用>的限制。记忆;但是,线程池会限制同时在进程中处于活动状态的线程数。从.NET Framework版本4开始,进程的线程池的默认大小取决于几个因素,例如虚拟地址的大小>空间。进程可以调用GetMaxThreads方法来确定线程数。

     

您可以使用GetMaxThreads和SetMaxThreads方法控制最大线程数。

如有必要,还可以尝试增加MinThreads。系统上的内核数量可能会导致Threadpool优化算法失效?值得一试。

再次,来自MSDN

  

线程池按需提供新的工作线程或I / O完成线程,直到达到每个类别的指定最小值。您可以使用GetMinThreads方法获取这些最小值。

     

当达到最小值时,线程池可以创建其他线程或等到某些任务完成。从.NET Framework 4开始,线程池创建并销毁工作线程以优化吞吐量,吞吐量定义为每单位时间完成的任务数。线程太少可能无法充分利用可用资源,而太多线程可能会增加资源争用。

答案 5 :(得分:1)

功能编程侧重于高级抽象,即,您将常见的编程模式抽象出来并使它们通常可重用。高性能计算是关于让事情并行运行,考虑不同线程之间的位,考虑数据局部性以使缓存命中率高。这是两个不同的方向。

如今,人们倾向于认为FP是所有并行的银弹,包括高性能计算。没有。否则你会在高性能会议上看到很多FP论文。其实很少。

您现在使用的是Task Parallel库,它是C#/ F#/ VB的.Net库。不是F#特定的。我相信,这本身就是用C#编写的。

考虑到这一点,让我们回到你的问题。为什么不能使用100%CPU?这些技能可以帮助您找到与F#关系不大的瓶颈。对程序进行概要分析,看一些线程是否在等待其他人完成(你需要完成Paralle.For中的所有计算才能继续)。

答案 6 :(得分:0)

您是否尝试过使用Visual Studio中包含的线程分析工具:使用性能向导中的并发分析器选项?