我发现fftw在许多(比如8个以上)不同的进程中同时运行时效率非常低,即使我的机器上有很多核心(20)。这是非常令人惊讶的,因为我能够以这种非常简单的方式并行化许多其他cpu密集型任务。但fftw挣扎。
这是我创建的C ++测试程序的输出:
magland@jm3:~/dev/fftw_load_test$ ./fftw_load_test.js --num_processes=1 --task=fftw
Calling: bin/fftw_load_test --task=fftw
Creating plan...
Running fftw load test for M,N=4,40000000
Elapsed time (sec) for M,N=4,40000000 (1.20901e+7 nums per sec): 13.234
对比当运行相同的程序时,只需在6个独立的进程中启动!
Running fftw load test for M,N=4,40000000
Running fftw load test for M,N=4,40000000
Running fftw load test for M,N=4,40000000
Running fftw load test for M,N=4,40000000
Running fftw load test for M,N=4,40000000
Running fftw load test for M,N=4,40000000
Elapsed time (sec) for M,N=4,40000000 (1.10079e+7 nums per sec): 14.535
Elapsed time (sec) for M,N=4,40000000 (1.02328e+7 nums per sec): 15.636
Elapsed time (sec) for M,N=4,40000000 (1.01183e+7 nums per sec): 15.813
Elapsed time (sec) for M,N=4,40000000 (6.55845e+6 nums per sec): 24.396
Elapsed time (sec) for M,N=4,40000000 (6.16642e+6 nums per sec): 25.947
Elapsed time (sec) for M,N=4,40000000 (6.11084e+6 nums per sec): 26.183
这是我一直在寻找的东西。我花了相当长的时间来隔离这么简单的例子,因为我没有怀疑FFTW会有这样的基本限制。
这就是我调用fftw的方式:
typedef long long bigint;
struct Fftw_runner {
Fftw_runner() {
}
~Fftw_runner() {
fftw_free(data_in);
fftw_free(data_out);
}
void init(bigint M_in,bigint N_in,QString task_in) {
M=M_in;
N=N_in;
MN=M*N;
task=task_in;
data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * MN);
data_out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * MN);
int rank = 1;
int n[] = { (int)N };
int howmany = M;
int* inembed = n;
int istride = M;
int idist = 1;
int* onembed = n;
int ostride = M;
int odist = 1;
unsigned flags = FFTW_ESTIMATE;
if (task=="fftw") {
qDebug() << "Creating plan...";
p_fft = fftw_plan_many_dft(rank,n,howmany,data_in,inembed,istride,idist,data_out,onembed,ostride,odist,FFTW_FORWARD,flags);
}
}
void apply() {
if (task=="fftw") {
for (bigint i=0; i<MN; i++) {
data_in[i][0]=0;
data_in[i][1]=0;
}
//set input data
//fft
fftw_execute(p_fft);
//multiply by kernel
}
else if (task=="flops") {
double sum=0;
for (bigint n=0; n<N; n++) {
for (bigint m=0; m<M; m++) {
sum+=m*n;
}
}
printf("Print the result to force computation: %g\n",sum);
}
}
bigint M;
bigint N,MN;
QString task;
fftw_complex* data_in=0;
fftw_complex* data_out=0;
fftw_plan p_fft;
};
正如您所看到的,上面的程序也可以测试简单的浮点运算,所以我也测试了它,并且没有进程之间的干扰。
如果这是真的,对我的应用程序来说,这是一个非常严重的性能限制,我需要运行几十个同步进程。考虑在N为2的幂的简单情况下写我自己的1D fft。不应该那么难,对吗?