如何使用fork和waitpid将C程序remover_ruido处理拆分为16个进程
多进程拆分去噪任务实现方案
原有实现问题
你当前的代码没有做任务拆分,16个子进程都会全量执行整个数组的去噪逻辑,同一份计算重复执行16次,完全达不到并行提速的效果。
多进程场景和你之前做多线程拆分的思路完全一致:都是把总任务拆成多份,每个执行单元只处理自己负责的部分。你这里已经用malloc_pshared分配了跨进程共享的内存,子进程对数组的修改父进程可以直接感知,不需要额外做进程间通信传结果,适配成本很低。
核心修改逻辑
- 把总样本数
n_amost平均拆成16份,总长度不能被16整除时,最后一个进程负责处理剩余的样本 - 每个子进程仅调用
remover_ruido处理自己所属区间的样本,不需要处理全量数据 - 所有子进程执行结束后父进程再继续后续逻辑
完整修改后代码
#include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <sys/mman.h> #include <string.h> #include <math.h> #include <sys/wait.h> #include <unistd.h> #define NMIN 4000 const int NPROCESSES = 16; double mytime(); void *malloc_pshared(size_t size); // 分配进程间共享内存 void remover_ruido(short *dados_out, short *dados_in, int nelem); int main(int argc, char *argv[]) { int n_amost; if (argc != 2 || (n_amost = atoi(argv[1])) < NMIN) { printf("语法: \"%s N\", N 不能小于 %d\n", argv[0], NMIN); exit(1); } short *amostras_in = (short *) malloc_pshared(sizeof(short) * n_amost); if (amostras_in == NULL) { exit(1); } else { for (int i = 0; i < n_amost; ++i) amostras_in[i] = i * 1.0; } short *amostras_out = (short *) malloc_pshared(sizeof(short) * n_amost); if (amostras_out == NULL) exit(1); double t0 = mytime(); pid_t pids[16]; int chunk_size = n_amost / NPROCESSES; int remainder = n_amost % NPROCESSES; for (int i = 0; i < NPROCESSES; i++) { pids[i] = fork(); if (pids[i] == 0) { int start = i * chunk_size; int process_count = (i == NPROCESSES - 1) ? chunk_size + remainder : chunk_size; remover_ruido(amostras_out + start, amostras_in + start, process_count); exit(0); } } for (int i = 0; i < NPROCESSES; i++) { waitpid(pids[i], NULL, 0); } printf("执行时间: %f (s)\n", mytime() - t0); return 0; } double mytime() { struct timeval tp; struct timezone tzp; gettimeofday(&tp,&tzp); return ( (double) tp.tv_sec + (double) tp.tv_usec * 1.e-6 ); } void *malloc_pshared(size_t size){ return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED| MAP_ANONYMOUS, -1, 0); } void remover_ruido(short *dados_out, short *dados_in, int nelem) { for (int i = 0; i != nelem; ++i) dados_out[i] = sqrt(dados_in[i] * dados_in[i]); }
注意事项
因为每个子进程处理的数组区间完全独立,不会出现多个进程写入同一个内存地址的情况,不需要额外加锁保证并发安全。
内容的提问来源于stack exchange,提问作者António Bezerra
相关产品推荐
相关产品推荐

