问题描述
我尝试了一些方法,但无法奏效,接下来是规范,谢谢
使用 fork 和 waitpid 函数,实现该程序的新版本,其中 remover_ruido 执行的处理分为 16 个进程。
我的第一种方法是使用这个:
const int NPROCESSES = 16;
pid_t pids[128];
for (int i = 0; i < NPROCESSES;i ++) {
pids[i] = fork();
if (!pids[i]) {
remover_ruido(amostras_out,amostras_in,n_amost);
exit(0);
}
}
for (int i = 0; i < NPROCESSES; i++)
waitpid(pids[i],0);
我做了一个类似的项目,但使用线程,要求将进程划分为 50 个线程。不知道能不能用同样的方法。
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <string.h>
#include <math.h>
#define NMIN 4000
double mytime();
void *malloc_pshared(size_t size); // aloca memória partilhada entre processos
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("Sintaxe: \"%s N\",com N não inferior a %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();
remover_ruido(amostras_out,n_amost);
printf("Tempo de execução: %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,int nelem)
{
// não implementada
for (int i = 0; i != nelem; ++i)
dados_out[i] = sqrt(dados_in[i] * dados_in[i]);
}
解决方法
这里有一个轻微的重构,用于在每个进程的基础上拆分数据。我编码了它,但没有编译或测试它:
const int NPROCESSES = 16;
pid_t pids[128];
int chunksize = n_amost / NPROCESSES; // number of elements per process
int remain = n_amost; // number of elements remaining
int curoff; // current offset into arrays
int cursize; // current length for process
for (int i = 0; i < NPROCESSES; i++,remain -= cursize) {
pids[i] = fork();
if (! pids[i]) {
// get index into arrays for this process
curoff = i * chunksize;
// assume we're a middle process -- use the calculated length
cursize = chunksize;
// last process must get the remainder of the array
if (i >= (NPROCESSES - 1))
cursize = remain;
remover_ruido(&amostras_out[curoff],&amostras_in[curoff],cursize);
exit(0);
}
}
for (int i = 0; i < NPROCESSES; i++)
waitpid(pids[i],0);
请注意,还有其他方法可以拆分偏移量/长度,但这应该会让您开始
请注意,您应该仔细检查您的 mmap
调用以确保它符合您的要求。
此变体与 Craig Estey 的变体非常相似,不同之处在于它实际上有效,因为它不会修改子代中的变量,前提是它会在父代中被修改。 ;-)
只有您第一个方法的路线
remover_ruido(amostras_out,amostras_in,n_amost);
需要改成
int from = n_amost*i/NPROCESSES,to = n_amost*(i+1)/NPROCESSES;
remover_ruido(amostras_out+from,amostras_in+from,to-from);