我正在编写一个多线程程序来遍历n x n
矩阵,其中主对角线中的元素以并行方式处理,如下代码所示:
int main(int argc, char * argv[] )
{
/* VARIABLES INITIALIZATION HERE */
gettimeofday(&start_t, NULL); //start timing
for (int slice = 0; slice < 2 * n - 1; ++slice)
{
z = slice < n ? 0 : slice - n + 1;
int L = 0;
pthread_t threads[slice-z-z+1];
struct thread_data td[slice-z-z+1];
for (int j=z; j<=slice-z; ++j)
{
td[L].index= L;
printf("create:%dn", L );
pthread_create(&threads[L],NULL,mult_thread,(void *)&td[L]);
L++;
}
for (int j=0; j<L; j++)
{
pthread_join(threads[j],NULL);
}
}
gettimeofday(&end_t, NULL);
printf("Total time taken by CPU: %ld n", ( (end_t.tv_sec - start_t.tv_sec)*1000000 + end_t.tv_usec - start_t.tv_usec));
return (0);
}
void *mult_thread(void *t)
{
struct thread_data *my_data= (struct thread_data*) t;
/* SOME ADDITIONAL CODE LINES HERE */
printf("ThreadFunction:%dn", (*my_data).index );
return (NULL);
}
问题是,与串行(幼稚)实现相比,这个多线程实现给了我非常糟糕的性能。
是否可以进行一些调整来提高多线程版本的性能??
线程池可能会让它变得更好。
如下定义一个新的结构类型。
typedef struct {
struct thread_data * data;
int status; // 0: ready
// 1: adding data
// 2: data handling, 3: done
int next_free;
} thread_node;
init:
size_t thread_size = 8;
thread_node * nodes = (thread_node *)malloc(thread_size * sizeof(thread_node));
for(int i = 0 ; i < thread_size - 1 ; i++ ) {
nodes[i].next_free = i + 1;
nodes[i].status = 0 ;
}
nodes[thread_size - 1].next_free = -1;
int current_free_node = 0 ;
pthread_mutex_t mutex;
获取线程:
int alloc() {
pthread_mutex_lock(&mutex);
int rt = current_free_node;
if(current_free_node != -1) {
current_free_node = nodes[current_free_node].next_free;
nodes[rt].status = 1;
}
pthread_mutex_unlock(&mutex);
return rt;
}
返回线程:
void back(int idx) {
pthread_mutex_lock(&mutex);
nodes[idx].next_free = current_free_node;
current_free_node = idx;
nodes[idx].status = 0;
pthread_mutex_unlock(&mutex);
}
首先创建线程,然后使用alloc()尝试获取空闲线程,更新指针。
- 不要使用join来判断状态
- 将多线程修改为循环,在作业完成后,只需将状态更改为3
- 对于线程中的每个循环,您可能会给它更多的工作
我希望它能给你一些帮助。
------------更新日期:2015年4月23日------------------
这里有一个例子。
编译&使用命令运行$g++thread_pool.cc-o tp-phread--std=c++
yu:thread_pool yu$ g++ tp.cc -o tp -pthread --std=c++11 && ./tp
1227135.147 1227176.546 1227217.944 1227259.340...
time cost 1 : 1068.339091 ms
1227135.147 1227176.546 1227217.944 1227259.340...
time cost 2 : 548.221607 ms
您还可以删除定时器,它也可以编译为stdc99文件。
目前,线程大小已限制为2。您还可以调整参数thread_size,并重新编译&再次运行。更多的线程可能会给你带来更多的优势(在我的电脑中,如果我将线程大小更改为4,任务将在280ms内完成),而如果你没有足够的cpu线程,过多的线程数可能对你没有太大帮助。