-1

我有一个项目,我在这里总结了一些伪代码来说明问题。我没有编译器问题,无论是使用 boost 还是 pthreads,我的代码都能很好地编译。请记住,这是旨在说明问题的伪代码,不能直接编译。

我遇到的问题是,对于多线程函数,内存使用和处理时间总是比使用串行编程(例如 for/while 循环)实现相同的函数要长。

这是我面临的问题的简化版本:

class aproject(){

public:

typedef struct
{
char** somedata;
double output,fitness;
}entity;

entity **entity_array;

int whichthread,numthreads;
pthread_mutex_t mutexdata;



aproject(){
numthreads = 100;
*entity_array=new entity[numthreads];
for(int i;i<numthreads;i++){
entity_array[i]->somedata[i] = new char[100];
}

/*.....more memory allocations for entity_array.......*/
this->initdata();
this->eval_thread();

}
void initdata(){
/**put zeros and ones in entity_array**/

}
float somefunc(char *somedata){

float output=countzero();       //someother function not listed

return output;
}

void* thread_function()
{
    pthread_mutex_lock (&mutexdata);

    int currentthread = this->whichthread;
    this->whichthread+=1;

        pthread_mutex_unlock (&mutexdata);

    entity *ent = this->entity_array[currentthread];


    double A=0,B=0,C=0,D=0,E=0,F=0;
    int i,j,k,l;



         A = somefunc(ent->somedata[0]);
         B = somefunc(ent->somedata[1]);

        t4 = anotherfunc(A,B);



        ent->output   = t4;
        ent->fitness  = sqrt(pow(t4,2)); 





                    }



static void* staticthreadproc(void* p){


return reinterpret_cast<ga*>(p)->thread_function();

}


void eval_thread(){

//use multithreading to evaluate individuals in parallel 

int i,j,k;
nthreads = this->numthreads;
pthread_t threads[nthreads];

//create threads
pthread_mutex_init(&this->mutexdata,NULL);
this->whichthread=0;

for(i=0;i<nthreads;i++){

pthread_create(&threads[i],NULL,&ga::staticthreadproc,this);

//printf("creating thread, %d\n",i);
}


//join threads
for(i=0;i<nthreads;i++){

pthread_join(threads[i],NULL);

}

}

};

我在这里使用 pthreads 是因为它在内存较少的机器上比 boost 效果更好。每个线程都在 eval_thread 中启动并在那里终止。我正在使用互斥锁来确保每个线程都以 entity_array 的正确索引开始,因为每个线程仅将其工作应用于由变量 this->whichthread 索引的相应 entity_array。这个变量是唯一需要被互斥锁锁定的东西,因为它是为每个线程更新的,并且不能被其他线程更改。您可以愉快地忽略除了 thread_function、eval_threads 和 staticthreadproc 之外的所有其他函数,因为它们是唯一相关的函数,假设除了 init 之外的所有其他函数都是处理器和内存密集型的。

所以我的问题是为什么以这种方式使用多线程比完全不使用线程的传统方法在内存和速度方面的成本更高?

我必须重申代码是伪代码,问题不在于它是否会编译

谢谢,如果您对 pthreads 和/或 boost 解决方案有任何建议,我将不胜感激。

4

2 回答 2

2

每个线程都需要它自己的调用堆栈,这会消耗内存。函数的每个局部变量(以及调用堆栈上的所有其他函数)都计入该内存。

创建新线程时,为其调用堆栈保留空间。我不知道 pthreads 的默认值是什么,但您可能想研究一下。如果您知道所需的堆栈空间比默认保留的要少,则可以通过在生成线程时显式指定所需的堆栈大小来显着减少内存消耗。

至于性能部分 - 它可能取决于几个问题。通常,您不应期望将数字运算操作并行化到比您拥有的内核更多的线程上来提高性能(不知道这里是否是这种情况)。由于上下文切换的额外开销、缓存未命中数量的增加等原因,这最终可能会变慢。有一些方法可以对此进行分析,具体取决于您的平台(例如,Visual Studio 分析器可以计算缓存未命中,并且还有适用于 Linux 的工具)。

于 2012-11-28T15:46:42.050 回答
0

创建线程是一项相当昂贵的操作。如果每个线程只做非常少量的工作,那么你的程序可能会被创建它们所花费的时间所支配。此外,大量活动线程会增加调度它们所需的工作,从而降低系统性能。而且,正如另一个答案所提到的,每个线程都需要自己的堆栈内存,因此内存使用量将随着线程数的增加而增长。

另一个问题可能是缓存失效;当一个线程将其结果写入其entity结构时,它可能会使附近的缓存内存无效并强制其他线程从更高级别的缓存或主内存中获取数据。

如果您使用较少数量的线程,每个线程处理较大的数据子集,您可能会获得更好的结果。对于这样的 CPU 密集型任务,每个 CPU 一个线程可能是最好的——这意味着您可以让所有 CPU 保持忙碌,并且无需浪费时间在每个 CPU 上调度多个线程。确保每个线程处理的实体都位于数组中,因此不会使其他线程缓存的实体无效。

于 2012-11-28T16:02:27.207 回答