编辑3:

最终(我认为)版本,更清晰,更快速地融入max9111’s answer的创意.

import numpy as np

from numba import as nb

@nb.njit()

def func1_jit(a, b, c, d):

# Precompute

exp_min = 5 - (a + b + c + d)

exp_max = b

exp = 2. ** np.arange(exp_min, exp_max + 1)

fact_e = np.empty((a + b - 2))

fact_e[0] = 1

for ei in range(1, len(fact_e)):

fact_e[ei] = ei * fact_e[ei - 1]

# Loops

B = 0

for ai in range(0, a):

for bi in range(0, b):

for ci in range(0, c):

for di in range(0, d):

for ei in range(0, ai + bi):

for fi in range(0, ci + di):

B += exp[ei - fi - ai - ci - di + 1 - exp_min] * (ei * ei - 2 * (ei * fi) - 7 * di) * fact_e[ei]

return B

这已经比以前的任何选项都快得多,但我们仍然没有利用多个CPU.一种方法是在函数本身内,例如并行化外循环.这会在每次调用时增加一些开销来创建线程,因此对于小输入实际上有点慢,但对于更大的值应该明显更快:

import numpy as np

from numba import as nb

@nb.njit(parallel=True)

def func1_par(a, b, c, d):

# Precompute

exp_min = 5 - (a + b + c + d)

exp_max = b

exp = 2. ** np.arange(exp_min, exp_max + 1)

fact_e = np.empty((a + b - 2))

fact_e[0] = 1

for ei in range(1, len(fact_e)):

fact_e[ei] = ei * fact_e[ei - 1]

# Loops

B = np.empty((a,))

for ai in nb.prange(0, a):

Bi = 0

for bi in range(0, b):

for ci in range(0, c):

for di in range(0, d):

for ei in range(0, ai + bi):

for fi in range(0, ci + di):

Bi += exp[ei - fi - ai - ci - di + 1 - exp_min] * (ei * ei - 2 * (ei * fi) - 7 * di) * fact_e[ei]

B[ai] = Bi

return np.sum(B)

或者,如果您有许多要评估函数的点,也可以在该级别进行并行化.这里a_arr,b_arr,c_arr和d_arr是要评估函数的值的向量:

from numba import as nb

@nb.njit(parallel=True)

def func1_arr(a_arr, b_arr, c_arr, d_arr):

B_arr = np.empty((len(a_arr),))

for i in nb.prange(len(B_arr)):

B_arr[i] = func1_jit(a_arr[i], b_arr[i], c_arr[i], d_arr[i])

return B_arr

最佳配置取决于您的输入,使用模式,硬件等,因此您可以根据您的情况组合不同的想法.

编辑2:

实际上,忘记我之前说过的话.最好的是JIT编译算法,但是以更有效的方式.首先计算昂贵的部分(我采用指数和阶乘),然后将其传递给编译的循环函数:

import numpy as np

from numba import njit

def func1(a, b, c, d):

exp_min = 5 - (a + b + c + d)

exp_max = b

exp = 2. ** np.arange(exp_min, exp_max + 1)

ee = np.arange(a + b - 2)

fact_e = scipy.special.factorial(ee)

return func1_inner(a, b, c, d, exp_min, exp, fact_e)

@njit()

def func1_inner(a, b, c, d, exp_min, exp, fact_e):

B = 0

for ai in range(0, a):

for bi in range(0, b):

for ci in range(0, c):

for di in range(0, d):

for ei in range(0, ai + bi):

for fi in range(0, ci + di):

B += exp[ei - fi - ai - ci - di + 1 - exp_min] * (ei * ei - 2 * (ei * fi) - 7 * di) * fact_e[ei]

return B

在我的实验中,这是迄今为止最快的选项,并且只占用很少的额外内存(只有预先计算的值,输入上的大小为线性).

a, b, c, d = 4, 6, 3, 4

# The original function

%timeit func1_orig(a, b, c, d)

# 2.07 ms ± 33.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

# The grid-evaluated function

%timeit func1_grid(a, b, c, d)

# 256 µs ± 25 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

# The precompuation + JIT-compiled function

%timeit func1_jit(a, b, c, d)

# 19.6 µs ± 3.25 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)

那么总是可以选择网格评估整个事情:

import numpy as np

import scipy.special

def func1(a, b, c, d):

ai, bi, ci, di, ei, fi = np.ogrid[:a, :b, :c, :d, :a + b - 2, :c + d - 2]

# Compute

B = (2.) ** (ei - fi - ai - ci - di + 1) * (ei ** 2 - 2 * (ei * fi) - 7 * di) * scipy.special.factorial(ei)

# Mask out of range elements for last two inner loops

m = (ei < ai + bi) & (fi < ci + di)

return np.sum(B * m)

print(func1(4, 6, 3, 4))

# 21769947.844726562

显而易见,随着参数的增加,其内存成本将快速增长.代码实际上执行的计算比必要的多,因为两个内部循环具有不同的迭代次数,因此(在此方法中)您必须使用最大的,然后删除您不需要的.希望是矢量化将弥补这一点.一个小的IPython基准:

a, b, c, d = 4, 6, 3, 4

# func1_orig is the original loop-based version

%timeit func1_orig(a, b, c, d)

# 2.9 ms ± 110 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

# func1 here is the vectorized version

%timeit func1(a, b, c, d)

# 210 µs ± 6.34 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

编辑:

请注意,以前的方法也不是一个全有或全无的事情.您可以选择仅对某些循环进行网格评估.例如,两个最里面的循环可以像这样矢量化:

def func1(a, b, c, d):

B = 0

e = np.arange(a + b - 2).reshape((-1, 1))

f = np.arange(c + d - 2)

for ai in range(0, a):

for bi in range(0, b):

ei = e[:ai + bi]

for ci in range(0, c):

for di in range(0, d):

fi = f[:ci + di]

B += np.sum((2.) ** (ei - fi - ai - ci - di + 1) * (ei ** 2 - 2 * (ei * fi) - 7 * di) * scipy.special.factorial(ei))

return B

这仍然有循环,但它确实避免了额外的计算,并且内存要求低得多.哪一个最好取决于我猜的输入大小.在我的测试中,使用原始值(4,6,3,4),这甚至比原始函数慢;此外,对于这种情况,似乎在每个循环上为ei和fi创建新数组比在预先创建的循环上操作更快.但是,如果将输入乘以4(14,24,12,16),那么这比原始(约x5)快得多,尽管仍然比完全矢量化的(约x3)慢.另一方面,我可以计算输入的值,用十(40,60,30,40)来缩放这个(在~5分钟内)而不是前一个因为内存(我没有测试如何)它需要与原始功能一起使用).使用@ numba.jit有点帮助,虽然不是很大(由于阶乘函数不能使用nopython).您可以尝试使用或多或少的循环向量化,具体取决于输入的大小.

python向量化和c哪个快_在python中向量化6 for循环累积和相关推荐

  1. python 字典查询比列表快_为什么python字典要比列表快以及哈希查找解释。

    为什么字典会查询速度会快呢?因为他是hash类型的,那什么是hash呢? 哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值. 哈希值是一段数据唯一且极其紧凑的数值 ...

  2. python程序写完后点哪个运行快_让 Python 代码运行更快的最佳方式!

    PyPy与CPython PyPy是Python解释器CPython的直接替代品.CPython将Python编译为中间字节码然后由虚拟机解释,而PyPy使用实时(JIT)编译将Python代码转换为 ...

  3. 学python后还要学什么语言_除了 Python,为什么机器学习还需要一种新的编程语言?...

    原标题:除了 Python,为什么机器学习还需要一种新的编程语言? 编者按:任何足够复杂的机器学习系统都需要一个特定的.非强制要求.优弊共存的编程语言.如今 Python 虽然在人工智能领域应用广泛, ...

  4. python支持的编程范式有_【Python学习手册】chapter1 前面

    读书笔记! Python命名:以英国喜剧组'Monty Python'命名--BBC20世纪70年代的<Monty Python's and the Holy Grai>的制片方,和我们认 ...

  5. python一般学多久可以考试_为何Python适合初学者 一般Python要学习多久

    为何Python适合初学者?一般Python要学习多久?很多人都觉得,Python是一门很好学的语言,非常适合入门.但更多人都是不清楚具体原因的.那么,我们不如一起来看看Python为何更适合初学者, ...

  6. python每秒20个请求_使用Python每秒百万个请求

    python每秒20个请求 by Paweł Piotr Przeradowski 通过PawełPiotr Przeradowski 使用Python每秒百万个请求 (A million reque ...

  7. python核心编程第三版_《Python核心编程(第3版)》

    <Python核心编程(第3版)>是经典畅销图书<Python核心编程(第二版)>的全新升级版本,本书适合具有一定经验的Python开发人员阅读,总共分为3部分.第1部分为讲解 ...

  8. python修改散点图中点的颜色_更改散点图中不同虚拟值的点的颜色 - python

    在我的数据集中,我有一个Price列用于房价,还有5个虚拟列用于城市中的不同位置.我要做的是用不同的颜色在散点图上显示数据点. 例如,在一个包含所有房屋价格的散点图上,我想要: 当dummy1表示房屋 ...

  9. python硬件编程_Python学习日记_《Python硬件编程实战》笔记_Mr_Ouyang

    书名: Python硬件编程实战 作者: 李茂 出版社: 机械工业出版社 [此处需要插入图片 Python封面] 笔者简评:不太适宜购买,全书大篇幅在用图片来解释极简单的细节,对于那些需要作者去深挖. ...

最新文章

  1. php display_errors
  2. mysql深入浅出_《深入浅出mysql》学习笔记
  3. python脚本批量生成数据
  4. django-oscar页面出现Error 10002 - Security header is not valid
  5. 人物肖像速写_深度视频肖像
  6. 【Python CheckiO 题解】House Password
  7. 小毛驴走呀走的openeim001
  8. 002Linux应用领域
  9. qt 程序异常结束_【心电国际指南2009专家解读】浦介麟 冉玉琴老师:QT 间期的规范化测量及其意义...
  10. Extjs6(六)——增删查改之查询
  11. flask-mail异步发送邮件_Spring Boot邮件发送功能的实现与原理介绍
  12. php mysql join查询结果_PHP mySQL表JOIN查询 - 最有效的方法?
  13. Deep learning-based CSI Feedback for Beamforming 2
  14. vim 模式下的几个快捷用法
  15. 足球大数据分析大小球胜平负的技巧与经验实例附分析软件
  16. Android+8.0+微信表情,微信8.0版本重大更新!emoji表情包动态化,安卓版也可以下载了...
  17. TrinityCore3.3.5环境搭建
  18. (最详细)Cloudera Manager安装部署
  19. 电车难题和他的n个**变种分享
  20. 关于TCP/IOCP构架中出现的假死连接解决方案

热门文章

  1. java前言_Java Web前言
  2. 【vue开发】 父组件传值给子组件时 ,watch props 监听不到解决方案
  3. JDBC_设计架构_驱动类加载_建立Connection_效率测试
  4. kafka operation
  5. Java开启/关闭tomcat服务器
  6. 语言统计学中的几个定律,可作为设计检索的参考
  7. transformer bert GPT(未完)
  8. [区块链与密码学][王小云院士][部分PPT][20200507]
  9. python 在gui中显示logging_如何在GUI中显示print()的输出python
  10. wampserver php乱码,WampServer搭建php环境可能遇到的问题