线程化方法学的四个步骤。
1, 分析(Analysis)
a) 必须对程序结构十分熟悉,算法精通。
b) 判断算法是否可以修改为并行算法。
c) 通过调试工具,获取程序最耗时的地方。
d) 修改占用时间最多的算法,获得最大收益。
2, 设计与实现(Design and implementation)
a)
3, 测试正确性(Test for Correctness)
a) 知道所有线程化得错误,产生的原因和产生的现象。
b) 学会使用线程调试工具和Debug调试工具。
4, 性能调优(Tune for Performance)
a) 线程化代码调优常用方法。
b) 学会使用线程调优软件。
开发方法:从串行到并行。先串行保证算法的正确,然后修改并行,跳过程序的性能。
理论模型:
并行随机访问机(Parallel Random Access Machine, PRAM)
问题核心:共享内存。共享内存导致两种类型的读操作限制和写操作限制:并发或者独占(Exclusive)。
内存访问模式 |
描述 |
并发读,并发写 (Concurrent Read, Concurrent Write,CRCW) |
多线程同时写一个内存位置,并且多个线程同时写入一个内存位置 |
并发读,独占写 (Exclusive Write,Concurrent Read, CREW) |
|
独占读,并发写 (Concurrent Write,Excusive Read, ERCW) |
|
独占读,独占写 (Concurrent Write,Excusive Read, EREW) |
分布式内存模型(Distributed-Memory)
常用可移植库:
l PVM(Parallel Virutual Machine,并行虚拟机)
l MPI(Message Passing Interface, 消息传递接口)。更多信息可以从Beowulf项目获得。
共享内存编程与分布式内存编程的比较
共有功能:
冗余工作:
1, 分布式肯定会因为发送数据和接受数据产生执行开销。
2, 多线程产生数据产生冗余开销。
分解工作:
1, 分配工作到不同的线程和进程中。
共享数据:
1, 部分数据根据程序需要被线程和进程共享。
工作的静态/动态分配:
1, 总执行时间大致等于每一部分工作的执行时间之和,应用于静态分配。
2, 当工作的数量远多于线程的数量,并且时间不能计算,应用于动态分配。
共享内存独有功能:
局部变量和线程局部存储。Windows和POSIX线程都定义了线程局部存储(Thread-Local Storage, TLS) API。TLS的值在不同函数之间保持不变,类似于静态变量。
内存效应:
多核之间共享缓存,要处理缓存置换问题。
多核之间独有缓存,效率比较低。
伪共享。线程的不同变量被包含在同一条缓存线(Cache Line)中。根据缓存一致性原则,当某个线程更新缓存中的一个变量,如果另一个线程希望访问缓存线其他内容是,需要先将改缓存线写回到内存中。
内存中的通信:
对同一个内存区域,进行读写。
互斥:
每次只允许一个线程访问相同的共享变量。
生产者和消费者:
读/写锁
缓存一致性协议参考文档: