[当我为蒙特卡洛方法实现解决方案以计算pi数时,其中以中心为圆的圆具有坐标(0,0),半径为1并刻在正方形中,给定的公式如下:pi = 4 *(圈中的点数)/(总点数)。我使用2个程序serial.c(单进程)和multithread.c(多线程进程)来实现该解决方案,以比较这两个解决方案的执行速度。
程序serial.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
void circle_point();
static long int total_point;
static long int count_circle=0;
clock_t start_time, end_time;
int main(int argc, char *argv[]){
if(argc==1){
printf("Enter number point\n");
return -1;
}
if(argc!=2){
printf("Argument is wrong\n");
return -1;
}
total_point=atoll(argv[1]);
start_time=clock();
circle_point();
double pi=4.0*(double)count_circle/(double)total_point;
end_time=clock();
printf("PI = %17.15f\n",pi);
printf("Time to compute= %g second\n",(double)(end_time-start_time)/CLOCKS_PER_SEC);
return 0;
}
void circle_point(){
srand(time(NULL));
int i;
for(i=0;i<total_point;i++){
double x= (double)rand()/(double)RAND_MAX;
double y=(double)rand()/(double)RAND_MAX;
double r= sqrt(x*x+y*y);
if(r<=1) count_circle+=1;
}
}
程序multithread.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <pthread.h>
#define NUM_THREAD 4
void* circle_point(void *param);
pthread_t tid[NUM_THREAD]={0};
int count[NUM_THREAD]={0};
clock_t start_time, end_time;
static long int total_point;
static long int count_circle=0;
int main(int argc, char const *argv[]){
if(argc==1){
printf("Enter number point\n");
return -1;
}
if(argc!=2){
printf("Argument is wrong\n");
return -1;
}
total_point=atoll(argv[1])/NUM_THREAD;
start_time= clock();
srand(time(NULL));
static int i;
for(i=0; i<NUM_THREAD;i++)
pthread_create(&tid[i],NULL,circle_point,&count[i]);
for(i=0;i<NUM_THREAD;i++){
pthread_join(tid[i],NULL);
count_circle+=count[i];
}
double pi=4.0*(double)count_circle/(double)total_point/(double)NUM_THREAD;
end_time=clock();
printf("PI = %17.15f\n",pi);
printf("Time to compute= %g second\n",(double)(end_time-start_time)/CLOCKS_PER_SEC);
return 0;
}
void* circle_point(void *param){
int *pcount= (int*)param;
int i;
for(i=0; i<total_point;i++){
double x= (double)rand()/(double)RAND_MAX;
double y=(double)rand()/(double)RAND_MAX;
double r= sqrt(x*x+y*y);
if(r<=1) *pcount=*pcount+1;
}
pthread_exit(0);
}
我遇到的问题是,在输入总点数相同的情况下,例如10 ^ 7,串行的执行速度为0.45秒,而多线程的执行速度为6.06秒,类似于其他输入,执行时间串行数总是大于多线程。我不明白我遇到了什么问题?因为从理论上讲,多线程将比串行执行更快,所以实际上在任何情况下串行都比多线程执行得更快。
单线程:
void circle_point(){
srand(time(NULL));
int i;
for(i=0;i<total_point;i++){
double x= (double)rand()/(double)RAND_MAX;
double y=(double)rand()/(double)RAND_MAX;
double r= sqrt(x*x+y*y);
if(r<=1) count_circle+=1;
}
}
多线程:
void* circle_point(void *param){
int *pcount= (int*)param;
int i;
for(i=0; i<total_point;i++){
double x= (double)rand()/(double)RAND_MAX;
double y=(double)rand()/(double)RAND_MAX;
double r= sqrt(x*x+y*y);
if(r<=1) *pcount=*pcount+1;
}
pthread_exit(0);
我猜您对多线程程序的每个线程都使用与单线程相同的total_point
(这意味着在两种情况下,第二个程序中的每个线程都使用total_point = 10^7
)。因此,在多线程程序中,您需要计算NUM_THREAD * total_point
点。您可以尝试使用NUM_THREAD = 1
,两种情况下的执行时间都相似。或者,您可以测量每个线程的执行时间以进行验证。
如果要比较两个程序的速度,则必须使多线程程序计算出的总点数与单线程相同。例如,第一个线程计算10^7/4
点,然后第二个线程计算10^7/4
点,依此类推。
理论上,多线程程序可以比顺序程序更快地完成,因为它所做的某些工作可以同时进行。在所有处理器上花费的时间总和将高于顺序版本(因为添加了协调的东西),但是从开始到结束所用的时间可能会更短。