这两天在搞多线程并行, 有以下几点体会:
1 shared resource 是毒药, 尤其是在频繁需要加锁的时候。当计算的core增多时,其性能扩展不明显
2 要尽量用现成的并行framework. .NET的TPL, c++的opencl和amp。这些framework能够形成一个thread pool, 能够根据系统当前的状况自动来schedule最佳的线程数和调度策略,任务分配等。能够使cpu一直处于满负荷的状态工作
3 并行要用coarse-grained。fine-grained会使系统创建和调度线程的cost大于真正所执行的任务的时间。在recursive 的程序尤其要注意,比如quiksort, 如果划分不合理会使并行的时间大于顺序执行的时间。
4 I/O是最耗时的部分。在多线程下同时读写多个文件,性能不会明显提高,反而会有可能降低。这个我还得仔细研究下,没怎么弄清楚。
5 如何开发non-blocking 的程序需要再去研究
6 spinlock与lock mutex的区别: spinwait不会让thread从内核中跳出,而mutex等不到的时候会使thread调出。
7 find the bottleneck and tackle it.
8 Amdahl‘s law. The most efficient time in theory.:不可并行计算的存在是很重要的,因为它将限制并行化的潜在好处。阿姆达尔定律指明如果一个计算的1/S本质上是顺序的,那么最大的性能改进将受限于因数S。其论证如下,一个并行计算的执行时间TP将是顺序部分计算时间和可并行化部分计算时间两者的和。如果该计算顺序地执行需要花费的时间是TS,则当有P个处理器时,TP可表示为S=n/[1+(n-1)f]
Task[] tasks = new Task[subcount];
for i = 0; i < subcount; i++)
{
task[i] = Task.Factory.StartNew(convert(sub));
}
Task[] allTasks = tasks;
// Print completion notices one by one as tasks finish.
while (tasks.Length > 0)
{
taskIndex = Task.WaitAny(tasks);
//progress bar updated.
tasks = tasks.Where((t) => t != tasks[taskIndex]).ToArray();
}
// Observe any exceptions that might have occurred.
try
{
Task.WaitAll(allTasks);
}
catch (AggregateException ae)
{
...
}