您好,
我创建了一个多线程应用程序,用于使用pthreads将两个矩阵相乘,但令我惊讶的是,多线程程序花费的时间超出了我的预期。
我知道我的代码中的问题在哪里,代码片段在下面给出了::
#include "pthreads.h"
#include "cv.h"
#include "cxcore.h"
CvMat * matA; /* first matrix */
CvMat * matB; /* second matrix */
CvMat * matRes; /* result matrix */
int size_x_a; /* this variable will be used for the first dimension */
int size_y_a; /* this variable will be used for the second dimension */
int size_x_b,size_y_b;
int size_x_res;
int size_y_res;
struct v {
int i; /* row */
int j; /* column */
};
void *printThreadID(void *threadid)
{
/*long id = (long) threadid;
//printf("Thread ID: %ld\n", id);
arrZ[id] = arrX[id] + arrY[id];
pthread_exit(NULL);*/
return 0;
}
int main()
{
/* assigining the values of sizes */
size_x_a = 200;
size_y_a = 200;
size_x_b = 200;
size_y_b = 200;
/* resultant matrix dimensions */
size_x_res = size_x_a;
size_y_res = size_y_b;
matA = cvCreateMat(size_x_a,size_y_a,CV_64FC1);
matB = cvCreateMat(size_x_b,size_y_b,CV_64FC1);
matRes = cvCreateMat(size_x_res,size_y_res,CV_64FC1);
pthread_t thread1;
pthread_t thread2;
pthread_t multThread[200][200];
int res1;
int res2;
int mulRes;
/*******************************************************************************/
/*Creating a thread*/
res1 = pthread_create(&thread1,NULL,initializeA,(void*)matA);
if(res1!=0)
{
perror("thread creation of thread1 failed");
exit(EXIT_FAILURE);
}
/*Creating a thread*/
res2 = pthread_create(&thread2,NULL,initializeB,(void*)matB);
if(res2!=0)
{
perror("thread creation of thread2 failed");
exit(EXIT_FAILURE);
}
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
/*Multiplication of matrices*/
for(int i=0;i<size_x_a;i++)
{
for(int j=0;j<size_y_b;j++)
{
struct v * data = (struct v*)malloc(sizeof(struct v));
data->i = i;
data->j = j;
mulRes = pthread_create(&multThread[i][j],NULL,multiplication, (void*)data);
}
}
for(int i=0;i<size_x_a;i++)
{
for(int j=0;j<size_y_b;j++)
{
pthread_join(multThread[i][j],NULL);
}
}
for(int i =0;i<size_x_a;i++)
{
for(int j = 0;j<size_y_a;j++)
{
printf("%f ",cvmGet(matA,i,j));
}
}
return 0;
}
void * multiplication(void * param)
{
struct v * data = (struct v *)param;
double sum =0;
for(int k=0;k<size_x_a;k++)
sum += cvmGet(matA,data->i,k) * cvmGet(matB,k,data->j);
cvmSet(matRes,data->i,data->j,sum);
pthread_exit(0);
return 0;
}
void * initializeA(void * arg)
{
CvMat * matA = (CvMat*)arg;
//matA = (CvMat*)malloc(size_x_a * sizeof(CvMat *));
/*initialiazing random values*/
for (int i = 0; i < size_x_a; i++)
{
for (int j = 0; j < size_y_a; j++)
{
cvmSet(matA,i,j,size_y_a + j); /* just some unique number for each element */
}
}
return 0;
}
void * initializeB(void * arg)
{
CvMat* matB = (CvMat*)arg;
//matB = (CvMat*)malloc(size_x_b * sizeof(CvMat *));
/*initialiazing random values*/
for (int i = 0; i < size_x_b; i++)
{
for (int j = 0; j < size_y_b; j++)
{
cvmSet(matB,i,j,size_y_b + j); /* just some unique number for each element */
}
}
return 0;
}
void * initializeRes(void * arg)
{
CvMat * res = (CvMat*)arg;
//res = (CvMat*)malloc(size_x_res * sizeof(CvMat *));
/* for matrix matRes, allocate storage for an array of ints */
for (int i = 0; i < size_x_res; i++)
{
for (int j = 0; j < size_y_res; j++)
{
cvmSet(matRes,i,j,0);
}
}
return 0;
}
我是第一次进行多线程处理。 请帮助我,任何建议或更正都会非常有帮助。
提前致谢。
答案 0 :(得分:3)
您正在创建大量线程,这将涉及大量上下文切换。如果每个线程都在进行纯计算,并且不会涉及任何类型的等待(如网络,套接字等),那么线程没有理由比没有线程更快。除非您使用多CPU /核心机器,否则您应该为每个核心创建一个线程。通过这种处理,比核心更多的线程只会降低它的速度。
您可以做的是将工作集划分为可以入队的任务,并使用工作线程(一个/ CPU核心)将任务从公共工作队列中拉出。这是标准的生产者/消费者问题。
Here是关于生产者/消费者问题的一般信息。
自从我完成矩阵乘法以来已经很久了,所以请耐心等待:)看来你可以将以下内容分成不同的任务:
/*Multiplication of matrices*/
for(int i=0;i<size_x_a;i++)
{
for(int j=0;j<size_y_b;j++)
{
struct v * data = (struct v*)malloc(sizeof(struct v));
data->i = i;
data->j = j;
/* Instead of creating a thread, create a task and put it on the queue
* mulRes = pthread_create(&multThread[i][j],NULL,multiplication, (void*)data);
*/
/* Im not going to implement the queue here, since there are several available
* But remember that the queue access MUST be mutex protected. */
enqueue_task(data);
}
}
以前,您必须创建所谓的线程池(工作线程,每个CPU核心一个),其工作者功能将尝试拉出队列并执行工作。有一些方法可以使用pthread条件变量来执行此操作,如果队列为空,则线程在cond var上被阻塞/等待,并且一旦填充了队列,就会发出cond var信号,从而释放线程以便它们可以启动工作
如果这不是一个逻辑分工,而你找不到,那么这个问题可能不适合多线程。