-1

我编写了一个程序来执行一些计算,然后合并结果。

我使用多线程并行计算。

在合并结果阶段,每个线程都会锁定全局数组,然后将单独的部分附加到它上面,并且会做一些额外的工作来消除重复。

我测试了一下,合并的开销随着线程数的增加而增加,而且速度出乎意料:

2线程:40,116,084(us)
6线程:511,791,532(us)

为什么:线程数增加时会发生什么?我该如何改变?

--------------------------斜线 ---------- -------------------------------------------

其实代码很简单,有伪代码:

typedef my_object{
长不;
整数计数;
双倍价值;
//其他的东西
} my_object_t;

静态 my_object_t** global_result_array; //大约十千个

静态 pthread_mutex_t global_lock;

void* thread_function(void* arg){
my_object_t** local_result;
int local_result_number;
诠释我;
my_object_t* ptr;
for(;;){
if( exit_condition ){ return NULL;}
if(merge_condition){
//开始记录时间点
pthread_mutex_lock( &global_lock);
for( i = local_result_number-1; i>=0 ;i++){
ptr = local_result[ i] ;
if( NULL == global_result_array[ ptr->no] ){
global_result_array[ ptr->no] = ptr; //第4步
}else{
global_result_array[ ptr->no] -> count += ptr->count; // 第 5 步
global_result_array[ ptr->no] -> value += ptr->value; // 第 6 步
}
}
pthread_mutex_unlock( &global_lock); // 记录的结束时间点
}else{
//做一些计算并产生部分和线程本地的结果,即local_result和local_result_number
}
}
}


如上,两个线程和六个线程的区别是第5步和第6步,我统计了第5步和第6步的执行顺序大约有几亿次。其他的都是一样的。
因此,在我看来,合并操作非常轻,尽管使用 2 线程或 6 线程,但它们都需要锁定和独占合并。
另一个令人吃惊的事情是:使用六线程时,第 4 步的成本飙升!这就是总成本暴涨的启动原因!

顺便说一句:测试服务器有两个 cpu,每个 cpu 有四个核心。

4

3 回答 3

1

显示的行为有多种原因:

  1. 更多的线程意味着更多的锁和更多的线程间阻塞时间。从您的描述中可以明显看出,您的实现使用互斥锁或类似的东西。如果数据集在很大程度上是独占的,那么线程的加速效果会更好。

  2. 除非您的系统具有与线程数一样多的处理器/内核,否则它们都不能同时运行。您可以使用 设置最大并发pthread_setconcurrency

于 2012-10-02T01:22:01.367 回答
0

这是 2/6 线程之间的巨大性能差异。很抱歉,您确实必须非常努力才能做出如此巨大的差异。你似乎成功了:((

正如其他人指出的那样,只有在线程间通信(锁等)上花费的时间少于并发操作所获得的时间时,才值得在一个数据集上使用多个线程。

例如,如果您发现您正在合并连续较小的数据部分(例如,使用合并排序),那么您正在有效地优化浪费在线程间通信和缓存抖动上的时间。这就是为什么一旦数据被划分为小于 L1 缓存大小的块时,多线程合并排序经常以就地排序开始。

'每个线程都会锁定全局数组' - 尽量不要这样做。长时间锁定大型数据结构,或在连续的短期内连续锁定它们,是一个非常糟糕的计划。锁定全局一次会使线程序列化并生成一个线程间通信过多的线程。持续锁定/释放会生成一个线程,线程间通信过多。

一旦操作变得如此短以至于回报减少到无用的地步,您最好将这些操作排队到一个线程来自行完成工作。

锁定经常被严重过度使用和/或误用。如果我发现自己锁定任何东西的时间超过了将指针推入/弹出队列或类似的时间,我开始感到紧张。

没有查看/分析代码,更重要的是,没有数据,(我想两者都很复杂),很难给出任何直接的建议:(

于 2012-10-02T11:03:20.107 回答
0

上下文切换是一种开销。因此差异。如果您的计算机有 6 个内核,它会更快。过度地,您需要为线程提供更多的上下文切换。

于 2012-10-02T01:07:55.417 回答