Pthread程序花费的时间比预期的要长

时间:2012-07-10 09:35:19

标签: c multithreading opencv pthreads matrix-multiplication

您好,

我创建了一个多线程应用程序,用于使用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;
}

我是第一次进行多线程处理。 请帮助我,任何建议或更正都会非常有帮助。

提前致谢。

1 个答案:

答案 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信号,从而释放线程以便它们可以启动工作

如果这不是一个逻辑分工,而你找不到,那么这个问题可能不适合多线程。