我编写了一个简单的函数,其中包含以下代码,用于计算一维数组中的最小数字:
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;
}
然而,这似乎比第一个功能慢。 我是否正确使用线程使第一个函数运行得更快?如果是这样,我如何修改第二个函数,使其比第一个函数更快?
答案 0 :(得分:0)
由于创建它们的开销,调度它们并等待它们全部完成,所以拥有比运行它们的可用内核更多的线程总是比单个线程慢。
您提供的示例不太可能受益于编译器将为您执行的任何优化,因为它是一个简短的操作。如果你在多核系统上做一些更复杂的事情,例如乘以两个巨大的矩阵,在高速实时数据上运行相关算法,那么多线程可能就是解决方案。
对你的问题更抽象的答案是另一个问题:你真的需要优化它吗?除非您知道 性能问题,否则您的时间会更好地为您的程序添加更多功能,而不是解决实际上不存在的问题。
修改 - 比较
我刚刚在运行40 MHz指令时钟的16位ARM微控制器上运行(代表性版本)OP代码。使用GCC编译的代码没有优化。
找到最少20,000个32位整数需要25多个毫秒。
对于40k字节的页面大小(占用20,000字节的4字节值的一半),线程运行在时钟频率为2.67 GHz的双Intel 5150处理器的不同内核上,上下文切换只需要近50 ms和分页操作!
简单的单线程微控制器实现所需的实时时间是多线程桌面实现的一半。