关于启动大型多线程编程项目的建议

Sis*_*utl 11 architecture simulation parallel-processing multithreading

我公司目前运行第三方仿真程序(自然灾难风险建模),从磁盘上吸取数GB的数据,然后压缩几天以产生结果.我很快就会被要求将其重写为一个多线程应用程序,以便它可以在几小时而不是几天内运行.我希望有大约6个月的时间来完成转换,并将独自工作.

我们有一个24-proc框来运行它.我可以访问原始程序的源代码(我认为用C++编写),但是在这一点上我对它的设计知之甚少.

我需要有关如何解决这个问题的建议.我是一名经验丰富的程序员(约30年,目前在C#3.5工作),但没有多处理器/多线程经验.如果合适的话,我愿意并渴望学习一门新语言.我正在寻找有关语言,学习资源,书籍,建筑指南的建议.等等

要求:Windows操作系统.商业级编译器,提供大量支持和良好的学习资源.不需要花哨的GUI - 它可能从配置文件运行并将结果放入SQL Server数据库.

编辑:当前的应用程序是C++但我几乎肯定不会使用该语言进行重写.我删除了某人添加的C++标记.

ire*_*ses 17

数值过程模拟通常在单个离散问题网格上运行(例如,地球表面气体和尘埃云),这通常排除了简单的任务耕作或并发方法.这是因为在表示物理空间区域的一组处理器上划分的网格不是一组独立任务.需要基于存储在逻辑空间中相邻的其他处理器上的网格单元的值来更新每个子网格边缘处的网格单元.

高性能计算中,通常使用MPIOpenMP 并行化模拟.MPI是一个消息传递库,包含许多语言的绑定,包括C,C++,Fortran,PythonC#.OpenMP是用于共享内存多处理的API.通常,MPI比OpenMP更难编码,并且更具侵入性,但也更灵活.OpenMP需要处理器之间共享的内存区域,因此不适合许多体系结构.混合方案也是可能的.

这种类型的编程有其特殊的挑战.除了竞争条件,死锁,活锁以及并发编程的所有其他乐趣之外,还需要考虑处理器网格的拓扑结构 - 如何选择在物理处理器之间拆分逻辑网格.这很重要,因为并行加速是处理器之间通信量的函数,处理器本身是分解网格总边长的函数.随着您添加更多处理器,此表面积会增加,从而增加通信开销.增加粒度最终会变得令人望而却步.

另一个重要的考虑因素是可以并行化的代码比例.然后,阿姆达尔定律规定了理论上可达到的最大加速比.在开始编写任何代码之前,您应该能够估计这一点.

这两个事实都将合谋限制您可以运行的最大处理器数量.甜蜜点可能比你想象的要低得多.

如果您能掌握它,我推荐高性能计算书.特别是,关于性能基准和调优的章节是无价的.

Lawerence Livermore国家实验室的介绍是关于并行计算的优秀在线概述,涵盖了主要问题.


moo*_*dow 12

多线程项目中最大的问题是跨线程可以看到太多的状态 - 编写以不安全的方式读取/改变数据的代码太容易了,特别是在多处理器环境中,如缓存一致性,内存弱一致等问题可能会发挥作用.

调试竞争条件显然是令人不快的.

如果你正在考虑在网络上的多台机器上分配你的工作,那就是你的设计:即确定哪些任务可以并行发生,每项任务的输入是什么,每项任务的输出是什么,在给定任务开始之前必须完成哪些任务.练习的目的是确保每个地方的数据对另一个线程可见,并且每个产生新线程的地方都要仔细考虑.

一旦这样的初始设计完成,将对数据的所有权进行明确划分,并明确获得/转让所有权的点数; 因此,您将处于非常有利的位置,可以利用多线程为您提供的各种可能性 - 廉价的共享数据,廉价的同步,无锁的共享数据结构 - 安全.


Jee*_*Bee 7

如果您可以将工作负载分成非依赖的工作块(即,数据集可以按位处理,没有很多数据依赖性),那么我将使用线程池/任务机制.据推测,无论C#与Java的java.util.concurrent相当.我将从数据创建工作单元,并将它们包装在一个任务中,然后将任务抛出到线程池中.

当然,性能可能是必要的.如果您可以按原样保留原始处理代码内核,则可以在C#应用程序中调用它.

如果代码具有大量数据依赖性,那么分解为线程化任务可能要困难得多,但您可能会将其分解为一系列操作.这意味着线程1将数据传递给线程2,线程2将数据传递给线程3到8,线程3到8将数据传递到线程9等.

如果代码有很多浮点数学,那么在OpenCL或CUDA中重写并在GPU而不是CPU上运行它可能是值得的.