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