基础要素
任务/数据划分
多个控制流并行,划分带来的负载均衡和通信开销也对程序的性能有决定性的作用
并发访问控制
多个控制流需要访问不同或者相同的资源,如何协调这些资源变得非常重要
并行化和面向对象
并行需要去除数据和控制的依赖关系,而面向对象把大问题解决成小问题,然后通过对象之间的通信来解决小问题,进而解决大问题。
面向对象鼓励隐藏对象拥有的数据,而并行化需要分析作用在数据上的操作的依赖关系。
对并行设计来说,合适的方法是:过程化的设计方法加上以数据为中心。并行化的本质是以数据为中心的,显式的传递数据对于并行更为合适。通过过程化的设计方法设计程序流程,以数据为中心进行并行化已经是流行的设计方式。
实践中,需要寻找数据热点并优化数据热点。
计算规模一定时,如果程序中存在不能并行的部分,那程序是很难实现完全线性加速的。
并发访问控制
并行程序需要协调对某个控制资源的访问。
基于消息传递并发访问控制,数据的交流通过传递消息进行,各个控制流拥有自己的存储器内容。
基于共享存储的并发访问控制,各个控制流访问共享的数据,访问之间有可能冲突,比如读后写、写后写、写后读,通常是采用互斥的方式来保证。
常见的并发访问控制流是文件
通常有两种做法:
只有一个文件,一个控制流读取文件并分发消息给其他控制流。
把一个文件分割成多个子文件,每个控制流读取一个子文件。
前一种做法比较简单,但数据分发是串行的,容易因为通信开销而成为瓶颈。
并发访问控制的其他常见做法是分为写和读,不同的控制流可以读同一个数据,此时无需访问控制,而多个数据流写的就必须特殊控制,对于一个数据流,有些控制流读,有些控制流写时必须特殊处理。
并行的实现
进程级并行、线程级并行,由于进程的资源是独立的,而线程的资源是共享的,进程间的并行更加容易,但基于多核的处理器上线程间的并行通常更高效。因此多核处理器选择线程级并行,而多机系统选择进程级并行。也可以混用这两种方式:节点间采用进程间并行,而节点内的多核上选择线程间并行。也称为超级并行。
同步和异步、阻塞和非阻塞
阻塞和非阻塞是对进程或线程本身而言的,如果一个操作不阻塞进程或线程,接着执行代码,称之为非阻塞,反之称之为阻塞。相对于非阻塞,阻塞更为常见,非阻塞要求开发人员手动保证操作的完成。
同步和异步值通信的多个进程和线程,如果一个进程或线程与其他进程或线程通信时不需要等待其他进程和线程准备完成,那就是异步,反之为同步。