我正在使用MingW64来为Python 3.7编译Cython。该任务完全是一项练习,我在其中为点网格计算Julia集。我将跟着《高性能Python》这本书,该书将介绍如何使用Cython。我以前曾使用-O标志来设置DSP硬件的优化,并通过将其设置为更高的值(即-O3)获得了重大改进。但是,Cython代码不是这种情况。
当使用Cython代码执行相同的操作时,随着优化的增加,它会稳定地产生较慢的结果,这似乎没有意义。我得到的时序为:
-O1 = 0.41s
-02 = 0.46s
-O3 = 0.47s
-Ofast = 0.48s
-Os = 0.419s
有谁知道为什么这似乎在相反的优化中起作用?
cython代码位于文件cythonfn.pyx中
def calculate_z(maxiter, zs, cs):
# add type primitives to improve execution time
cdef unsigned int i, n
cdef double complex z, c
output = [0] * len(zs)
for i in range(len(zs)):
n = 0
z = zs[i]
c = cs
# while n < maxiter and abs(z) < 2:
while n < maxiter and (z.real * z.real + z.imag * z.imag) < 4: # increases performance
z = z * z + c
n += 1
output[i] = n
return output
设置在这里为setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass={'build_ext': build_ext},
ext_modules=[Extension("calculate", ["cythonfn.pyx"])]
)
主要代码是
import calculate
import time
c_real,c_imag = -0.62772, -0.42193 # point for investigation
x1, x2, y1, y2 = -1.8, 1.8, -1.8, 1.8
def calc_julia(desired_width, max_iter):
x_step = (float(x2 - x1) / float(desired_width))
y_step = (float(y1 - y2) / float(desired_width))
x = []
y = []
ycoord = y2
while ycoord > y1:
y.append(ycoord)
ycoord += y_step
xcoord = x1
while xcoord < x2:
x.append(xcoord)
xcoord += x_step
zs = []
cs = complex(c_real, c_imag)
for ycoord in y:
for xcoord in x:
zs.append(complex(xcoord, ycoord))
st = time.time()
output = calculate.calculate_z(max_iter, zs, cs)
et = time.time()
print(f"Took {et-st} seconds")
if __name__ == '__main__':
calc_julia(desired_width=1000, max_iter=300)
是的,我知道这里有很多可以改进的地方,例如cs可以只是一个标量,因为它们都是一样的。这更多的是练习,但是它为优化带来了令人惊讶的结果。
看来,这里至少已部分解释了对此的答案,gcc优化标志-O3使代码比-O2慢。
为了总结结果,使用-O3实际上使用了与-O2不同的比较/分支技术,因此,在此任务中进行多次比较的任务中,选择如何完成很重要。由于循环的可预测性,因此使用此优化可以增加执行时间。
这仍然不能解决从-O1到-O2的原因,但是该来源足以描述一种情况。也许另一个人知道答案?
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句