Pthreads 在具有4个双核Cpu的服务器上使用1-8个线程的程序出现计时问题';s
我在我大学的服务器上运行一个程序,该服务器有4个双核AMD Opteron(tm)处理器2210,操作系统是Linux版本2.6.27.25-78.2.56.fc9.x86_64。我的程序实现了康威生活游戏,它使用pthreads和openmp运行。我使用GetTimeOfDay()函数使用1-8个线程对程序的并行部分计时。但时机似乎不太合适。我使用1个线程获得了最大的时间(正如预期的那样),然后时间变小了。但我得到的最短时间是当我使用4个线程时 下面是一个使用阵列1000x1000的示例 使用1个线程9,62秒,使用2个线程4,73秒,使用3~3.64秒,使用4~2.99秒,使用5~4,19秒,使用6~3.84秒,使用7~3.34秒,使用8~3.12秒 上面的计时是在我使用pthreads时进行的。当我使用openmp时,计时更小,但遵循相同的模式 我预计时间会从1-8减少,因为有4个双核CPU?我认为因为有4个CPU,每个CPU有2个内核,所以可以同时运行8个线程。它是否与服务器运行的操作系统有关 我还在另一台服务器上测试了相同的程序,该服务器有7个双核AMD Opteron(tm)处理器8214,运行Linux版本2.6.18-194.3.1.el5。我得到的时间正是我所期望的。从1(最大)到8(最小执行时间),计时变得更小 该程序使用pthreads和openmp实现了正确的生活游戏,我只是不明白为什么计时与我发布的示例类似。总之,我的问题是: 1) 系统上可以同时运行的线程数取决于CPU的内核?虽然每个cpu都有多个内核,但它只取决于cpu?这取决于所有以前的版本和操作系统 2) 这与我将1000x1000数组除以线程数的方式有关吗?但是如果我这样做了,那么openmp代码就不会给出相同的计时模式了 3) 为什么我会有这样的时间安排 这是我在openmp中使用的代码:Pthreads 在具有4个双核Cpu的服务器上使用1-8个线程的程序出现计时问题';s,pthreads,openmp,benchmarking,Pthreads,Openmp,Benchmarking,我在我大学的服务器上运行一个程序,该服务器有4个双核AMD Opteron(tm)处理器2210,操作系统是Linux版本2.6.27.25-78.2.56.fc9.x86_64。我的程序实现了康威生活游戏,它使用pthreads和openmp运行。我使用GetTimeOfDay()函数使用1-8个线程对程序的并行部分计时。但时机似乎不太合适。我使用1个线程获得了最大的时间(正如预期的那样),然后时间变小了。但我得到的最短时间是当我使用4个线程时 下面是一个使用阵列1000x1000的示例 使用
#define Row 1000+2
#define Col 1000+2 int num; int (*temp)[Col]; int (*a1)[Col]; int (*a2)[Col];
int main() {
int i,j,l,sum;
int array1[Row][Col],array2[Row][Col];
struct timeval tim;
struct tm *tm;
double start,end;
int st,en;
for (i=0; i<Row; i++)
for (j=0; j<Col; j++)
{
array1[i][j]=0;
array2[i][j]=0;
}
array1[3][16]=1;
array1[4][16]=1;
array1[5][15]=1;
array1[6][15]=1;
array1[6][16]=1;
array1[7][16]=1;
array1[5][14]=1;
array1[4][15]=1;
a1=array1;
a2=array2;
printf ("\nGive number of threads:");
scanf("%d",&num);
gettimeofday(&tim,NULL);
start=tim.tv_sec+(tim.tv_usec/1000000.0); omp_set_num_threads(num);
#pragma omp parallel private(l,i,j,sum)
{
printf("Number of Threads:%d\n",omp_get_num_threads());
for (l=0; l<100; l++)
{
#pragma omp for
for (i=1; i<(Row-1); i++)
{
for (j=1; j<(Col-1); j++)
{
sum=a1[i-1][j-1]+a1[i-1][j]+a1[i-1][j+1]+a1[i][j-1]+a1[i][j+1]+a1[i+1][j-1]+a1[i+1][j]+a1[i+1][j+1];
if ((a1[i][j]==1) && (sum==2||sum==3))
a2[i][j]=1;
else if ((a1[i][j]==1) && (sum<2))
a2[i][j]=0;
else if ((a1[i][j]==1) && (sum>3))
a2[i][j]=0;
else if ((a1[i][j]==0 )&& (sum==3))
a2[i][j]=1;
else if (a1[i][j]==0)
a2[i][j]=0;
}//end of iteration J
}//end of iteration I
#pragma omp barrier
#pragma omp single
{
temp=a1;
a1=a2;
a2=temp;
}
#pragma omp barrier
}//end of iteration L
}//end of paraller region
gettimeofday(&tim,NULL);
end=tim.tv_sec+(tim.tv_usec/1000000.0);
printf("\nTime Elapsed:%.6lf\n",end-start);
printf("all ok\n");
return 0; }
#定义第1000+2行
#定义列1000+2整数;内部(*温度)[Col];int(*a1)[Col];int(*a2)[Col];
int main(){
int i,j,l,和;
int array1[行][Col],array2[行][Col];
结构时间间隔;
struct tm*tm;
双起点,双终点;
int-st,en;
对于(i=0;i您必须记住的一点是,您是在共享内存体系结构上执行此操作的。您尝试并行执行的加载/存储越多,您就越有可能遇到内存访问方面的争用,这是一个相对缓慢的操作。因此,在我的经验中,在典型应用程序中,不要从更多的操作中获益不超过6个核。(这是一个轶事,我可以深入了解很多细节,但我不想打字。我只想说,对这些数字有点保留)
如果可能,尽量减少对共享资源的访问,看看这对您的性能有什么影响。否则,请针对您得到的资源进行优化,并记住以下几点:
向一个问题扔更多的内核并不意味着它会更快。就像税收一样,当内核的数量开始影响程序的最大性能时,会有一个曲线。找到“最佳点”,并使用它。你写的
以上时间是我使用
pthreads。当我使用openmp时
它们较小,但遵循相同的规则
模式
恭喜你,你已经发现了所有并行程序都遵循的模式!如果你将执行时间与处理器数量进行对比,曲线最终会变平并开始上升;你达到了一个点,即添加更多处理器会减慢速度
有趣的问题是,您可以使用多少处理器,这取决于许多因素。@jer指出了影响共享内存计算机上程序可伸缩性的一些因素。其他因素,主要是通信与计算的比率,确保性能的形状在分布式内存计算机上,曲线也将是相同的
在测量程序的并行可伸缩性时,另一个很重要的因素是您使用的问题大小。当您尝试使用1414 x 1414单元格的网格时,性能曲线会如何变化?我预计曲线将低于1000 x 1000单元格的问题曲线,稍后会变平
进一步阅读谷歌的阿姆达尔定律和古斯塔夫森定律。可能是因为你的系统管理员控制着你可以同时执行多少个线程,或者你可以运行多少个内核。我不知道在系统管理员级别上是否可行,但可以肯定地告诉一个进程
或者,您的算法可能使用二级缓存的效果很差。当一个线程正在执行耗时较长的操作,而另一个线程没有执行时,超线程或任何他们称之为超线程的方法现在效果最好。访问不在二级缓存中的内存很慢,线程在等待时会暂停。这只是ti在单核上运行多个线程的方法来自。四核内存总线可能允许每个核同时访问一些ram,但不允许每个核中的每个线程。如果两个线程都使用ram,那么它们基本上是按顺序运行的。因此,这可能就是4的来源
您可以查看是否可以更改循环,使其在连续RAM上运行。如果您将问题分解为适合二级缓存的小块数据,并对这些块进行迭代,则可能会得到8x。如果您搜索“英特尔机器语言程序员指南”以了解其最新处理器,他们会讨论这些问题。是的,我知道存在数据依赖关系,但是(解决它们超出了g