Cython程序比普通Python慢​​(10M选项3.5s vs 3.25s Black Scholes) - 我缺少什么?

时间:2016-05-11 17:56:38

标签: python numpy cython

好的,这是我下面的第一个Cython项目,代价是欧洲期货期权(Black Scholes没有股息)。它在10M选项上以3.5s运行,而不是我在下面发布的直接numpy Python 3.25s的代码。任何人都可以指出为什么我的Cython代码更慢 - 就像因为我使用循环而不是向量化调用(不确定在C中如何做到这一点,生成的cython代码似乎可以向量化它)。即使变量是从numpy数组传入的,我可以在这个循环中使用nogilopenmp吗?在Cython的示例中发布的简单示例无法在循环http://docs.cython.org/src/userguide/parallelism.html#module-cython.parallel上使用cython.parallel prange正确编译。反馈非常感谢,为一个有些开放式的问题道歉 - 其他人可以在这里自由使用此代码作为起点,因为它已经比我在C和Python中看到的其他在线工作更快。这是:

另存为CyBlack.pyx文件进行编译(请注意所有输入均为float64Black_callput除外int64,1表示调用,-1表示放置)。编译后,from CyBlack.CyBlack import CyBlack

from numpy cimport ndarray
cimport numpy as np
cimport cython

cdef extern from "math.h":
    double exp(double)
    double sqrt(double)
    double log(double)
    double erf(double)

cdef double std_norm_cdf(double x):
    return 0.5*(1+erf(x/sqrt(2.0)))

@cython.boundscheck(False)
cpdef CyBlack(ndarray[np.float64_t, ndim=1] BlackPnL, ndarray[np.float64_t, ndim=1] Black_S, ndarray[np.float64_t, ndim=1] Black_Texpiry, ndarray[np.float64_t, ndim=1] Black_strike, ndarray [np.float64_t, ndim=1] Black_volatility, ndarray[np.float64_t, ndim=1] Black_IR, ndarray[np.int64_t, ndim=1] Black_callput):

    cdef Py_ssize_t i
    cdef Py_ssize_t N = BlackPnL.shape[0]
    cdef double d1, d2


    for i in range(N):
        d1 = ((log(Black_S[i] / Black_strike[i]) + Black_Texpiry[i] * Black_volatility[i] **2 / 2)) / (Black_volatility[i] * sqrt(Black_Texpiry[i]))
        d2 = d1 - Black_volatility[i] * sqrt(Black_Texpiry[i])
        BlackPnL[i] = exp(-Black_IR[i] * Black_Texpiry[i]) * (Black_callput[i] * Black_S[i] * std_norm_cdf(Black_callput[i] * d1) - Black_callput[i] * Black_strike[i] * std_norm_cdf(Black_callput[i] * d2)) 

    return BlackPnL

以下是setup.py,因此其他人可以构建此类型:python setup.py build_ext --inplace使用VS2015为Python 3.5 64位Windows构建。

from setuptools import setup
from setuptools import Extension
from Cython.Distutils import build_ext
import numpy as np

ext_modules = [Extension("CyBlack",sources=["CyBlack.pyx"],
          extra_compile_args=['/Ox', '/openmp', '/favor:INTEL64'],
          language='c++')]

setup(
    name= 'Generic model class',
    cmdclass = {'build_ext': build_ext},
    include_dirs = [np.get_include()],
    ext_modules = ext_modules)

好的,这是我非常快速的只有Python的代码:

import numpy as np
from scipy.stats import norm

d1=((np.log(Black_S / Black_strike) + Black_Texpiry * Black_volatility **2 / 2)) / (Black_volatility * np.sqrt(Black_Texpiry))
d2=d1 - Black_volatility * np.sqrt(Black_Texpiry)
BlackPnL = np.exp(-Black_IR * Black_Texpiry) * (Black_callput * Black_S * norm.cdf(Black_callput * d1) - Black_callput * Black_strike * norm.cdf(Black_callput * d2))

0 个答案:

没有答案