单线程与双线程






2.90/5 (39投票s)
2004年10月9日
2分钟阅读

105522

357
对英特尔双至强 HT 技术的一种优化方法的介绍。
目录
目标
我发布这篇文章的目的是分享一些简单的优化方法。就这样!
介绍
本文演示了双线程如何比单线程表现更好,尤其是在具有 HT 技术的英特尔双至强处理器中。我在这里发布的演示是一个简单的 PI 计算,作为计算密集型函数的示例。两个 PI 函数都将以 100% 的 CPU 利用率运行。
要求
很简单。为了看到显著的改进,您需要在双 CPU 机器上进行练习。
代码
演示代码非常简单。这是一个示例的开始..
SingleThreadPI
和 DualThreadPI
将做完全相同的事情,相同的结果,但不同的时间。主要区别在于 DualThreadPI
函数是使用数据并行化方法编写的。
#include "stdafx.h" #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <string.h> #include <time.h> #define NUM_THREADS 2 HANDLE thread_handles[NUM_THREADS]; CRITICAL_SECTION hUpdateMutex; static long num_steps = 100000 * 1000; double step; double global_sum = 0.0; int SingleThreadPI(); int DualThreadPI(); void ThreadPI(void *arg); int main(int argc, char* argv[]) { // Single Thread SingleThreadPI(); // Dual Thread DualThreadPI(); getchar(); return 0; } int SingleThreadPI() { int start, end, total; start = clock(); int i; double x, pi, sum = 0.0; step = 1.0/(double) num_steps; for (i=1;i<= num_steps; i++) { x = (i-0.5)*step; sum = sum + 4.0/(1.0+x*x); } pi = step * sum; printf("\nSingleThreadPI\n"); printf(" pi is %f \n",pi); end = clock(); total = end - start; printf("%d\n", total); return 0; } int DualThreadPI() { int start, end, total; start = clock(); double pi; int i; unsigned long threadID; int threadArg[NUM_THREADS]; for(i=0; i<NUM_THREADS; i++) threadArg[i] = i+1; InitializeCriticalSection(&hUpdateMutex); for (i=0; i<NUM_THREADS; i++) { thread_handles[i] = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) ThreadPI, &threadArg[i], 0, &threadID); } // wait until both threads end its processing WaitForMultipleObjects(NUM_THREADS, thread_handles, TRUE,INFINITE); pi = global_sum * step; printf("\nDualThreadPI\n"); printf(" pi is %f \n",pi); end = clock(); total = end - start; printf("%d\n", total); return 0; } void ThreadPI(void *arg) { int i, start; double x, sum = 0.0; start = *(int *) arg; // arg is actually the thread ID, i in the loop. step = 1.0/(double) num_steps; // NUM_THREADS in this case is 2 // so that thread ID=1, ThreadPI will compute odd number in the loop // thread ID=2, ThreadPI will compute even number in the loop for (i=start;i<= num_steps; i=i+NUM_THREADS) { x = (i-0.5)*step; sum = sum + 4.0/(1.0+x*x); } // try to make atomic statement, otherwise... EnterCriticalSection(&hUpdateMutex); global_sum += sum; LeaveCriticalSection(&hUpdateMutex); }
测试性能
根据性能分析,正如预期的那样,这种类型的优化在单处理器机器上运行不会有显著的改进。除非在双处理器机器上运行,否则您肯定会看到单线程和双线程之间的巨大差异。 这是一个实时示例...
Machine -> Pentium 4 (2.4GHz, 1GB Memory)
Profile: Function timing, sorted by time
Date: Sun Oct 10 02:23:09 2004
Program Statistics
------------------
Command line at 2004 Oct 10 02:23: "G:\j2\net\code project\article -
Optimise For Intel HT Technology\InLocal\PI\Release\PI"
Total time: 5342.205 millisecond
Time outside of functions: 38.445 millisecond
Call depth: 2
Total functions: 8
Total hits: 3
Function coverage: 37.5%
Overhead Calculated 4
Overhead Average 4
Module Statistics for pi.exe
----------------------------
Time in module: 5303.760 millisecond
Percent of time in module: 100.0%
Functions in module: 8
Hits in module: 3
Module function coverage: 37.5%
Func Func+Child Hit
Time % Time % Count Function
---------------------------------------------------------
2246.857 42.4 5303.760 100.0 1 _main (pi.obj)
1620.240 30.5 1620.240 30.5 1 SingleThreadPI(void) (pi.obj)
1436.662 27.1 1436.662 27.1 1 DualThreadPI(void) (pi.obj)
Contributed by Nigel
Machine -> Dell Precision 530, Pentium Xeon (2 x 2.0GHz, 512MB Memory)
Profile: Function timing, sorted by time
Date: Sat Oct 09 16:58:43 2004
Program Statistics
------------------
Command line at 2004 Oct 09 16:58: "D:\somewhere\PI_demo\PI\Debug\PI"
Total time: 10076.987 millisecond
Time outside of functions: 11.837 millisecond
Call depth: 2
Total functions: 7
Total hits: 3
Function coverage: 42.9%
Overhead Calculated 976
Overhead Average 976
Module Statistics for pi.exe
----------------------------
Time in module: 10065.150 millisecond
Percent of time in module: 100.0%
Functions in module: 7
Hits in module: 3
Module function coverage: 42.9%
Func Func+Child Hit
Time % Time % Count Function
---------------------------------------------------------
7175.142 71.3 10065.150 100.0 1 _main (pi.obj)
1931.827 19.2 1931.827 19.2 1 SingleThreadPI(void) (pi.obj)
958.182 9.5 958.182 9.5 1 DualThreadPI(void) (pi.obj)
Machine -> Pentium Xeon (2 x 2.8GHz, 512MB Memory)
(Pending...ToBeContinued...)
This one will have significant improvement. Anyone could volunteer?
最后
实际上我已经在我办公室看到了它的性能(双至强 2.8GHz,性能翻倍),只是现在我在家,我只能提供我电脑的性能(有一点改进),剩下的就让你们自己去证明了... *wink*
学习是乐趣 =)
建议/提示
阅读完本文后,您可能想在您的应用程序中尝试一下。假设您投入了大量的努力,在实施后,结果您没有得到您期望的结果。请不要冲我来。您可能在应用程序中找错了目标。 此外,也许,您已经在单 CPU 机器上测试了您的应用程序,您不会得到太大的改进。见“要求”。本文只会为您展示隧道中的一些光明,它不会让您走得很远。这里有一些提示给您。 为了利用这种类型的优化,我的做法是对我的应用程序进行性能分析,然后针对常用函数,尤其是计算密集型函数,如压缩、图像过滤过程和其他形态学过程等。
在大型服务器应用程序中,其硬件可能每台机器至少有 2-4 个 CPU,但我以前从未尝试过。 很可能我短期内也不会尝试,因为我不从事那个领域。 但您可能想尝试一下! 如果结果不错,请不要介意在这里分享经验.. 祝你好运!