gpt4 book ai didi

python - Cython 程序比普通 Python 慢(10M 选项 3.5s vs 3.25s Black Scholes)——我错过了什么?

转载 作者:行者123 更新时间:2023-11-28 16:25:29 25 4
gpt4 key购买 nike

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

另存为 CyBlack.pyx 文件进行编译(注意所有输入都是 float64 除了 Black_callputint64 , 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 built with VS2015 for Python 3.5 64bit 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)

好的,这是我非常快速的 numpy 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))

最佳答案

我在你的 cython 代码中的函数之前添加了以下几行,我从 Cython 得到的结果比 Python 2.7 更快

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)

我的 1000 万积分结果

%timeit PyBlack(BlackPnL, Black_S, Black_Texpiry, Black_strike, Black_volatility, Black_IR, Black_callput)
1 loops, best of 3: 3.49 s per loop

%timeit CyBlack(BlackPnL, Black_S, Black_Texpiry, Black_strike, Black_volatility, Black_IR, Black_callput)
1 loops, best of 3: 2.12 s per loop

编辑

CyBlack.pyx

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 fabs(double)

cdef double a1 = 0.254829592
cdef double a2 = -0.284496736
cdef double a3 = 1.421413741
cdef double a4 = -1.453152027
cdef double a5 = 1.061405429
cdef double p = 0.3275911

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
cdef inline double erf(double x):
cdef int sign = 1
if (x < 0):
sign = -1
x = fabs(x)

cdef double t = 1.0/(1.0 + p*x)
cdef double y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x)

return sign*y

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
cdef double std_norm_cdf(double x):
return 0.5*(1+erf(x/sqrt(2.0)))

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
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

try:
from setuptools import setup
from setuptools import Extension
except ImportError:
from distutils.core import setup
from distutils.extension import Extension

from Cython.Distutils import build_ext
import numpy as np

ext_modules = [Extension("CyBlack",["CyBlack.pyx"])]

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

关于python - Cython 程序比普通 Python 慢(10M 选项 3.5s vs 3.25s Black Scholes)——我错过了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37170077/

25 4 0
文章推荐: javascript - 使用 jQuery 事件显示和隐藏
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com