- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想使用大量不同的参数组合来整合一个微分方程组,并存储属于一组特定参数的变量的最终值。因此,我实现了一个简单的 for 循环,其中创建了随机初始条件和参数组合,集成了系统并将感兴趣的值存储在各自的数组中。由于我打算为一个相当复杂的系统(这里我只使用一个玩具系统进行说明)的许多参数组合执行此操作,它也可能变得僵硬,我想并行化模拟以使用 Python 的“多处理”来加速该过程模块。
但是,当我运行模拟时,for 循环总是比它的并行版本更快。到目前为止,比我发现的 for 循环更快的唯一方法是使用“apply_async”而不是“apply”。对于 10 种不同的参数组合,我得到例如以下输出(使用下面的代码):
The for loop took 0.11986207962 seconds!
[ 41.75971761 48.06034375 38.74134139 25.6022232 46.48436046
46.34952734 50.9073202 48.26035086 50.05026187 41.79483135]
Using apply took 0.180637836456 seconds!
41.7597176061
48.0603437545
38.7413413879
25.6022231983
46.4843604574
46.3495273394
50.9073202011
48.2603508573
50.0502618731
41.7948313502
Using apply_async took 0.000414133071899 seconds!
41.7597176061
48.0603437545
38.7413413879
25.6022231983
46.4843604574
46.3495273394
50.9073202011
48.2603508573
50.0502618731
41.7948313502
尽管在此示例中,“apply”和“apply_async”的结果顺序相同,但一般情况下似乎并非如此。因此,我想使用“apply_async”,因为它要快得多,但在这种情况下,我不知道如何将模拟结果与我用于相应模拟的参数/初始条件相匹配。
因此我的问题是:
1) 为什么在这种情况下“应用”比简单的 for 循环慢得多?
2) 当我使用“apply_async”而不是“apply”时,并行化版本变得比 for-loop 快得多,但是我如何才能将模拟结果与我在相应模拟中使用的参数相匹配?
3) 在这种情况下,“apply”和“apply_async”的结果具有相同的顺序。这是为什么?巧合?
我的代码可以在下面找到:
from pylab import *
import multiprocessing as mp
from scipy.integrate import odeint
import time
#my system of differential equations
def myODE (yn,tvec,allpara):
(x, y, z) = yn
a, b = allpara['para']
dx = -x + a*y + x*x*y
dy = b - a*y - x*x*y
dz = x*y
return (dx, dy, dz)
#for reproducibility
seed(0)
#time settings for integration
dt = 0.01
tmax = 50
tval = arange(0,tmax,dt)
numVar = 3 #number of variables (x, y, z)
numPar = 2 #number of parameters (a, b)
numComb = 10 #number of parameter combinations
INIT = zeros((numComb,numVar)) #initial conditions will be stored here
PARA = zeros((numComb,numPar)) #parameter combinations for a and b will be stored here
RES = zeros(numComb) #z(tmax) will be stored here
tic = time.time()
for combi in range(numComb):
INIT[combi,:] = append(10*rand(2),0) #initial conditions for x and y are randomly chosen, z is 0
PARA[combi,:] = 10*rand(2) #parameter a and b are chosen randomly
allpara = {'para': PARA[combi,:]}
results = transpose(odeint(myODE, INIT[combi,:], tval, args=(allpara,))) #integrate system
RES[combi] = results[numVar - 1][-1] #store z
#INIT[combi,:] = results[:,-1] #update initial conditions
#INIT[combi,-1] = 0 #set z to 0
toc = time.time()
print 'The for loop took ', toc-tic, 'seconds!'
print RES
#function for the multi-processing part
def runMyODE(yn,tvec,allpara):
return transpose(odeint(myODE, yn, tvec, args=(allpara,)))
tic = time.time()
pool = mp.Pool(processes=4)
results = [pool.apply(runMyODE, args=(INIT[combi,:],tval,{'para': PARA[combi,:]})) for combi in range(numComb)]
toc = time.time()
print 'Using apply took ', toc-tic, 'seconds!'
for sol in range(numComb):
print results[sol][2,-1] #print final value of z
tic = time.time()
resultsAsync = [pool.apply_async(runMyODE, args=(INIT[combi,:],tval,{'para': PARA[combi,:]})) for combi in range(numComb)]
toc = time.time()
print 'Using apply_async took ', toc-tic, 'seconds!'
for sol in range(numComb):
print resultsAsync[sol].get()[2,-1] #print final value of z
最佳答案
请注意,您的 apply_async 比 for 循环快 289 倍这一事实有点可疑!现在,您可以保证按照提交的顺序获得结果,即使这不是您想要的最大并行性。
apply_async 启动一个任务,它不会等到它完成; .get() 就是这样做的。所以这个:
tic = time.time()
resultsAsync = [pool.apply_async(runMyODE, args=(INIT[combi,:],tval,{'para': PARA[combi,:]})) for combi in range(numComb)]
toc = time.time()
这不是一个非常公平的衡量标准;你已经开始了所有的任务,但它们不一定已经完成。
另一方面,一旦你 .get() 结果,你就知道任务已经完成并且你有了答案;所以这样做
for sol in range(numComb):
print resultsAsync[sol].get()[2,-1] #print final value of z
意味着您肯定会按顺序获得结果(因为您正在按顺序遍历 ApplyResult 对象并 .get()ing 它们);但是您可能希望在结果准备就绪后立即获得结果,而不是一次一个地阻塞等待步骤。但这意味着您需要以一种或另一种方式用结果的参数标记结果。
您可以在任务完成后使用回调来保存结果,并将参数与结果一起返回,以允许完全异步返回:
def runMyODE(yn,tvec,allpara):
return allpara['para'],transpose(odeint(myODE, yn, tvec, args=(allpara,)))
asyncResults = []
def saveResult(result):
asyncResults.append((result[0], result[1][2,-1]))
tic = time.time()
for combi in range(numComb):
pool.apply_async(runMyODE, args=(INIT[combi,:],tval,{'para': PARA[combi,:]}), callback=saveResult)
pool.close()
pool.join()
toc = time.time()
print 'Using apply_async took ', toc-tic, 'seconds!'
for res in asyncResults:
print res[0], res[1]
给你更合理的时间;结果几乎总是有序的,因为任务花费的时间非常相似:
Using apply took 0.0847041606903 seconds!
[ 6.02763376 5.44883183] 41.7597176061
[ 4.37587211 8.91773001] 48.0603437545
[ 7.91725038 5.2889492 ] 38.7413413879
[ 0.71036058 0.871293 ] 25.6022231983
[ 7.78156751 8.70012148] 46.4843604574
[ 4.61479362 7.80529176] 46.3495273394
[ 1.43353287 9.44668917] 50.9073202011
[ 2.64555612 7.74233689] 48.2603508573
[ 0.187898 6.17635497] 50.0502618731
[ 9.43748079 6.81820299] 41.7948313502
Using apply_async took 0.0259671211243 seconds!
[ 4.37587211 8.91773001] 48.0603437545
[ 0.71036058 0.871293 ] 25.6022231983
[ 6.02763376 5.44883183] 41.7597176061
[ 7.91725038 5.2889492 ] 38.7413413879
[ 7.78156751 8.70012148] 46.4843604574
[ 4.61479362 7.80529176] 46.3495273394
[ 1.43353287 9.44668917] 50.9073202011
[ 2.64555612 7.74233689] 48.2603508573
[ 0.187898 6.17635497] 50.0502618731
[ 9.43748079 6.81820299] 41.7948313502
请注意,除了循环应用之外,您还可以使用 map:
pool.map_async(lambda combi: runMyODE(INIT[combi,:], tval, para=PARA[combi,:]), range(numComb), callback=saveResult)
关于Python 的多处理 : speed up a for-loop for several sets of parameters, "apply"与 "apply_async",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30282688/
目前我正在尝试创建一个 Web 部署包。所以我在我的项目的根目录中添加了一个 parameters.xml 并指定了一些自定义参数。 我发现我的很多参数都部分相同。所以我想做某种参数引用。寻找这个,我
如何设置我的 Symfony 2 项目以使用 parameters.yml 而不是 parameters.ini? 在 Controller 中,我可以像这样从 parameters.ini 中获取变
有什么建议说明为什么此 AWS CloudFormation 不断回滚吗? { "Description" : "Single Instance", "Resources" : {
PARAMETERS: p_1 TYPE i, p_2 TYPE i. 因此在初始屏幕中,我看到了 2 个文本框,每个参数一个。 如果我填写其中一个,但不按回车键,然后我在第二个上调用 F4 帮助,我
我需要存储 Parameter由 Build() 返回作为 Parameter (因为我将参数存储在一个数组中,另一种方法就是为每个参数数量复制粘贴相同的类太多,因为 c# 没有可变参数泛型)。 问题
我正在为我的 CS 类(class)做作业,它使用了 const,我对何时使用它们感到有点困惑。 这3个函数有什么区别? int const function(parameters) int fu
在 xgboost 的文档中,我读到: base_score [default=0.5] : the initial prediction score of all instances, global
我正在创建一个新的 REST 服务。 向 REST 服务传递参数的标准是什么。在 Java 的不同 REST 实现中,您可以将参数配置为路径的一部分或请求参数。例如, 路径参数 http://www.
在我的程序中,我需要验证传递给程序的参数是一个整数,所以我创建了这个小函数来处理用户键入“1st”而不是“1”的情况。 问题是它根本不起作用。我尝试调试,我只能告诉你参数是 12,long 是 2。(
谁能告诉我如何使用存储在 &rest 指定值中的参数。 我已经阅读了很多,似乎作者只知道如何列出所有参数。 (defun test (a &rest b) b) 这很高兴看到,但并不是很有用。 到目前
我使用 git 有一段时间了,但大多数时候我更喜欢与 Intelij IDEA 的集成。现在,为了扩展我对系统的知识和理解,我决定更多地使用命令行。我观察到的是有两种类型的参数: --paramete
我正在用 RAML 编写一些 REST 文档,但我被卡住了。 我的问题: - 我有一个用于搜索的 GET 请求,它可以采用参数“id”或( 独占或 )“引用”。拥有 只有其中之一 是必须的。 我知道怎
我定义了一个这样的 Action : /secure/listaAnnunci.action /login.jsp 我可以从 Action 内部访问参数吗?谢谢 最佳答案 您需要实现 S
我有一个 TeamCity 8.0.3 项目,其中包含多个配置,其中有一个通用参数(定义为项目参数):targetServerIP .这些配置之一是“一键部署”,它通过使用快照依赖项启动其他配置。我已
try{ Class.forName("com.mysql.jdbc.Driver"); mycon = DriverManager.getConnec
我在实际的 javascript 项目中遇到了一个非常奇怪的情况。我创建了一个自定义事件并将数组放入该事件 $.publish("merilon/TablesLoaded", getTables())
在使用参数数组进行插入/更新期间,可以忽略一个/一些特定行的一个/一些参数。 我提供了一个简单的例子。想象一下,我们有一个包含 3 列的表:X、Y 和 Z。我们想在 block 中执行更新(如果缺少某
如何编写接受未定义参数的函数?我想它可以像那样工作: void foo(void undefined_param) { if(typeof(undefined_param) == int) {
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界. 这篇CFSDN的博客文章PDO版本问题 Invalid parameter number: no
Jenkins 管道作业如下所示: 部分 Jenkinsfile(我们使用脚本化管道)是: properties([parameters([string(defaultValue: "", descr
我是一名优秀的程序员,十分优秀!