【发布时间】:2014-03-29 10:37:30
【问题描述】:
为了求解 PDE(薛定谔方程),我需要计算三个维度的拉普拉斯算子。我目前的解决方案是这样的(到目前为止需要最多时间的部分代码):
for n in range(Ntstep): # loop
for i in range(self.Nixyz[0]): # internal levels of wavefunction
wf.psi[i,:,:,:]=self.expu * wf.psi[i,:,:,:] # potential
if n < Ntstep - 1: # compute laplacian in 3d
wf.psi[i,:,:,:]=\
sf.ifft(self.expkx*sf.fft(wf.psi[i,:,:,:],
axis=0,**fft_args),axis=0,**fft_args)
wf.psi[i,:,:,:]=\
sf.ifft(self.expky*sf.fft(wf.psi[i,:,:,:],
axis=1,**fft_args),axis=1,**fft_args)
wf.psi[i,:,:,:]=\
sf.ifft(self.expkz*sf.fft(wf.psi[i,:,:,:],
axis=2,**fft_args),axis=2,**fft_args)
为了获得更好的性能,我尝试/做了/考虑了以下几点:
不要直接执行 3D FFT。拉普拉斯算子是可分离的,因此可以分成三个 1D FFT,这应该会将复杂度从
n^3降低到3n。 (在上面的代码中完成。)我针对 MKL 编译了 numpy 和 scipy,希望获得一些性能,特别是希望能够启用多线程计算。对于某些操作,使用了多个线程(矩阵向量乘法),但 numpy.fft 和 scipy.fftpack 都没有使用多个内核。
我编译了 libfftw 和 pyfftw 并将其用作 np/sp 的替代品。我有一个 Intel Core i7-3770K,即四核八线程。当使用带有 fftw 的两个或四个线程时,与 np/sp 相比,我的性能大约是 np/sp 的两倍。出于某种原因,一个线程或四个以上的线程会更慢。
所以,我现在的主要问题基本上是:
FFT(W) 是否可并行化,性能是否随可用内核/线程的数量而扩展?如果是,我需要考虑什么?目前,两到四个线程似乎是我的最佳选择。更多(或更少)会更慢,尽管我的 CPU 上有 8 个线程可用。
-
我应该尝试并行化我的 Python 代码吗?例如。将三个一维 FFT 放在三个不同的内核上。当然我必须确保我不会同时在不同线程中读取和写入同一个变量,所以我需要在上面的代码中添加一些额外的“临时”变量,例如:
- 线程 1:TempA = FFT(psi..., axis=0)
- 线程 2:TempB = FFT(psi..., axis=1)
- 线程 3:TempC = FFT(psi..., axis=1)
- 最后一步:psi = TempA + TempB + TempC
axis=0的 FFT 所需的时间是其他轴的两倍(!)。是否有可能摆脱这种差异并使所有 FFT 都同样快?-
(新)究竟是 FFT 方法是最佳选择,还是用户 Rory 的有限差分方法总是更好,至少在性能方面?
我认为有效计算拉普拉斯算子是一个已被广泛研究的主题,因此即使是论文、书籍等的一些链接或提示也可能会有所帮助。
【问题讨论】: