在现代计算中,多核处理器的普及使得并行计算成为了提升程序性能的重要手段。本文将探讨在多核处理器上应用线程的算法优化技术,并通过C#和C++实现的案例分析,展示如何通过减少锁操作、使用用户空间同步对象等方法来提高程序的执行效率。
选择的问题是:对于1到1000000之间的每一个数字n,应用以下函数,直到数字变为1,同时计数应用该函数的次数。这个算法将对1到1000000之间的所有数字执行,程序将打印结果和计算结果所需的执行时间(以毫秒为单位)。测试机器的配置为:AMD Athlon 2 P340 Dual Core 2.20 GHz,4 GB RAM,Windows 7 Ultimate x64。将使用C#和C++(Visual Studio 2010)来实现这个算法。
将使用一个队列来存储要处理的数字。对于每个可用的处理器核心,将创建一个工作线程。所有工作线程都操作(仅读取)这个共享队列。每个工作线程从队列中提取一个数字并计算所需的值。数字由主线程写入队列,主线程是唯一写入队列的线程。工作线程运行,直到所有数字都被处理完毕。
在C++中,将使用前一篇文章中介绍的算法。在C#中,将使用anlarke提出的算法:
for (int iCurrentCycleCount = 1; iNumberToTest != 1; ++iCurrentCycleCount)
{
if ((iNumberToTest & 0x1) == 0x01)
{
iNumberToTest += (iNumberToTest >> 1) + 1;
++iCurrentCycleCount;
}
else
iNumberToTest >>= 1;
}
在最初的实现中,C++的执行时间非常长,这主要是由于以下两个原因:
为了解决第一个问题,将使用一个队列为每个工作线程,并将并发问题限制在主线程和每个工作线程之间。为了最小化一个线程必须等待另一个线程释放其锁的时间,将队列分成NumCore个队列。
对于第二个问题,选择不是一次写入一个数字到队列中,而是一次写入250个数字(通过测试确定的数字)。
在优化后,C++和C#的执行时间都得到了显著的改善。C++的执行时间比C#慢,因为在C++中使用互斥锁(在内核空间实现),而在C#中使用lock关键字,它使用临界区(在用户空间实现)。