【发布时间】:2015-05-19 10:09:43
【问题描述】:
我用以下代码编写了一个简单的函数,用于计算一维数组中的最小值:
uint32_t get_minimum(const uint32_t* matrix) {
int min = 0;
min = matrix[0];
for (ssize_t i = 0; i < g_elements; i++){
if (min > matrix[i]){
min = matrix[i];
}
}
return min;
}
但是,我想提高此功能的性能,并建议使用线程,因此我将其修改为以下内容:
struct minargument{
const uint32_t* matrix;
ssize_t tid;
long long results;
};
static void *minworker(void *arg){
struct minargument *argument = (struct minargument *)arg;
const ssize_t start = argument -> tid * CHUNK;
const ssize_t end = argument -> tid == THREADS - 1 ? g_elements : (argument -> tid + 1) * CHUNK;
long long result = argument -> matrix[0];
for(ssize_t i = start; i < end; i++){
for(ssize_t x = 0; x < g_elements; x++){
if(result > argument->matrix[i]){
result = argument->matrix[i];
}
}
}
argument -> results = result;
return NULL;
}
uint32_t get_minimum(const uint32_t* matrix) {
struct minargument *args = malloc(sizeof(struct minargument) * THREADS);
long long min = 0;
for(ssize_t i = 0; i < THREADS; i++){
args[i] = (struct minargument){
.matrix = matrix,
.tid = i,
.results = min,
};
}
pthread_t thread_ids[THREADS];
for(ssize_t i =0; i < THREADS; i++){
if(pthread_create(thread_ids + i, NULL, minworker, args + i) != 0){
perror("pthread_create failed");
return 1;
}
}
for (ssize_t i = 0; i < THREADS; i++){
if(pthread_join(thread_ids[i], NULL) != 0){
perror("pthread_join failed");
return 1;
}
}
for(ssize_t i =0; i < THREADS; i++){
min = args[i].results;
}
free(args);
return min;
}
但是这似乎比第一个函数慢。 我是否正确使用线程使第一个函数运行得更快?如果是这样,我该如何修改第二个函数,使其比第一个函数更快?
【问题讨论】:
-
这个问题几乎肯定是内存受限的。如果工作集不适合 cpu 的私有缓存,则添加更多线程只会提高性能,然后直到共享内存带宽耗尽。您的测试用例可能需要达到 MB 级别才能从多线程中受益。
-
matrix中有多少个元素?这取决于数据大小、THREADS的值、您拥有的内核数量等。请注意,您最后也没有正确计算min:for(ssize_t i =0; i < THREADS; i++){ min = args[i].results; } -
@EOF 我已经针对大量元素进行了测试,所以我认为它仍然会受益。对 BlueMoon:我正在测试 20~20,000。你们能解释一下最后一部分是怎么错的吗
-
我相信线程优先级因素在优化中也有一定的作用。
-
20,000
long long ints 在大多数平台上是~160 kB。典型的 x86 具有~256 kB的私有 L2 缓存。除非第二个线程被安排在同一物理内核上的另一个超线程上,否则您的测试用例至少要小一个数量级。
标签: c multithreading pthreads