C 使用线程改进简单函数
我用以下代码编写了一个简单函数,用于计算一维数组中的最小数:C 使用线程改进简单函数,c,multithreading,pthreads,C,Multithreading,Pthreads,我用以下代码编写了一个简单函数,用于计算一维数组中的最小数: 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 m
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;
}
但是,这似乎比第一个函数慢。
我使用线程使第一个函数运行得更快,对吗?如果是这样,我如何修改第二个函数以使其比第一个函数快?由于创建线程、调度线程和等待它们全部完成的开销,可用于运行它们的线程数多于可用于运行它们的内核数的线程总是比单个线程慢 您提供的示例不太可能从编译器将为您提供的优化之外的任何优化中获益,因为它是一个简短的操作。如果您在多核系统上执行更复杂的操作,例如将两个巨大的矩阵相乘,或者在高速实时数据上运行相关算法,那么多线程可能是解决方案 对于你的问题,一个更抽象的答案是另一个问题:你真的需要优化它吗?除非您知道存在性能问题,否则您最好将时间花在为程序添加更多功能上,而不是修复实际上不存在的问题上 编辑-比较 我刚刚在一个运行40 MHz指令时钟的16位ARM微控制器上运行了OP代码的代表性版本。使用GCC编译的代码没有优化 找到20000个32位整数的最小值需要25毫秒多一点 在时钟频率为2.67 GHz的双Intel 5150处理器的不同内核上运行线程时,40 KB的页面大小可以容纳20000个4字节值数组的一半,仅执行上下文切换和分页操作就需要近50毫秒
一个简单的单线程微控制器实现的实时时间是多线程桌面实现的一半。这个问题几乎肯定是内存受限的。如果工作集不适合cpu的专用缓存,那么添加更多线程只能提高性能,直到共享内存带宽耗尽。您的测试用例可能需要达到兆字节的数量级才能从多线程中获益?它取决于数据大小、线程值、拥有的内核数等。请注意,最后的最小值计算也不正确:ForSize\u t i=0;i<线程;i++{min=args[i].results;}@EOF我已经针对大量元素进行了测试,所以我认为它仍然会受益。对蓝月亮:我在20~20000之间测试。你们能解释一下最后一部分是怎么错的吗?我相信线程优先级因素在优化中也有作用。在大多数平台上,20000个长整数约为160 kB。典型的x86具有约256KB的专用二级缓存。除非第二个线程被安排在同一物理内核上的另一个超线程上,否则您的测试用例至少太小了一个数量级。如果工作集足够大,则完全可以通过多线程来提高线性搜索的性能。@EOF Yes,前提是您有多个内核来运行线程。否则,线程只在将某些进程安排为后台任务时有用,而其他时间更为关键的线程则会运行,直到结果可用且需要为止。如果样本集足够大,并且您有可用的处理资源,那么它可以提高性能。否则,正如OP观察到的那样,它将产生相反的效果。您可能需要重新考虑优化,尤其是如果这是您工作的一部分。这段代码会在数亿个元素的数组上运行吗?它会在一次执行中在更小的阵列上运行数千次吗?这是一个实时应用程序,如果你不修复它,用户会盯着屏幕看20分钟吗?它会成批运行吗?它是某个更大的应用程序的一部分吗?首先考虑优化其他东西,比如I/O剃须刀10毫秒的运行时间是有趣的,并不总是需要的。我在嵌入式软件领域工作,从ISR中删除一两条指令可以区分好产品和无用产品。对于复杂的信号处理,将算法委托给DSP协处理器是必不可少的。在OP的情况下,我倾向于在填充数组时跟踪最小值。你的最后一句话是对钱的猛击!