【问题标题】:Pthread program taking longer time than expectedPthread 程序花费的时间比预期的要长
【发布时间】:2012-07-10 09:35:19
【问题描述】:

你好,

我创建了一个多线程应用程序,用于使用 pthreads 将两个矩阵相乘,但令我惊讶的是,多线程程序花费的时间比我预期的要多。

我不知道我的代码哪里出了问题,下面给出了代码sn-p::

#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;
}

我是第一次做这种多线程。 请帮助我,任何建议或更正都会非常有帮助。

提前致谢。

【问题讨论】:

    标签: c multithreading opencv pthreads matrix-multiplication


    【解决方案1】:

    您正在创建大量线程,这将涉及大量上下文切换。如果每个线程都在进行纯计算,并且不涉及任何类型的等待(如网络、套接字等),那么线程没有理由比不线程更快。当然,除非您使用的是多 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 信号,从而释放线程以便它们可以启动工作。

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

    【讨论】:

    • 感谢您的回复,这就是我没有得到的,如何使用更少的线程进行计算。我有一个 4 核的 cpu 意味着我可以创建 4 个线程,假设我创建了 4 个线程而不是我应该如何为每个线程分配工作?
    • 你能告诉我任何阅读材料,我可以从中阅读并更好地理解。??
    • 基本上,您需要能够将任务分解为可以放入队列的子任务。然后每个线程将其任务从队列中拉出,当一个线程完成时,获取下一个任务。我会添加更多细节。
    • 我正在做矩阵的乘法,那么我怎样才能把它分成不同的任务呢??
    • @user1140170,我在答案中添加了更多信息。您应该调查几个领域:线程池、生产者/消费者队列、pthread 条件变量,这些超出了这个问题的范围,但通过一些简单的搜索,您应该会找到您需要的内容:)
    猜你喜欢
    • 2016-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 2020-04-01
    相关资源
    最近更新 更多