因此,本质上,这是一个有关如何更有效地使用多核处理器的问题。
我有一个优化脚本(用matlab编写),可以调用20个matlab实例来评估函数。结果将另存为.mat文件,然后优化脚本将获取这些结果并执行其他一些工作。我调用20个matlab实例的方式是,首先使用matlab内置函数“ system”来调用批处理文件,然后再打开20个matlab实例来评估函数。
我在批处理文件中使用的代码是:
( start matlab -nosplash -nodesktop -minimize -r "Worker01;exit"
ping -n 5 127.0.0.1 >nul
start matlab -nosplash -nodesktop -minimize -r "Worker02;exit"
ping -n 5 127.0.0.1 >nul
...... % repeat the pattern
start matlab -nosplash -nodesktop -minimize -r "Worker19;exit"
ping -n 5 127.0.0.1 >nul
start matlab -nosplash -nodesktop -minimize -r "Worker20;exit"
ping -n 5 127.0.0.1 >nul ) | set /P "="
所有“开始”命令都包含在括号中,并在命令后面
"| set/P"=""
因为我希望我的优化脚本在完成所有20次评估后继续运行。我从另一个问题中学到了这项技术,但我并不真正了解它的真正作用。如果您还可以解释这一点,我将不胜感激。
无论如何,这是在不具有原始并行计算功能的matlab 2007下实现并行计算的一种方法。但是,我发现这不是同时运行20个实例的有效方法,因为打开12个实例后,我的cpu(至强服务器cpu,有14个内核)的使用率达到了100%。我的理论是,打开比cpu可以处理的实例更多的实例会使处理器效率降低。所以我认为最好的策略是这样的:
这将确保始终始终充分利用计算能力(cpu使用率始终为100%),而不会给cpu带来过多压力。
如何在批处理文件中实现此策略?如果批处理文件很难做到这一点,PowerShell可以做到吗?
请显示实际代码并说明。我不是程序员,所以我不太了解编码。
谢谢。
答案 0 :(得分:0)
我正在Powershell中考虑这一点...
<#
keep a queue of all jobs to be executed
keep a list of running jobs
number of running jobs cannot exceed the throttle value
#>
$throttle = 12
$queue = New-Object System.Collections.Queue
$running = New-Object System.Collections.Generic.List[System.Diagnostics.Process]
# generate x number of queue commands
# runs from 1 to x
1..20 | ForEach-Object {
# the variable $_ contains the current number
$program = "matlab"
$args = "-nosplash -nodesktop -minimize -r `"Worker$_;exit`""
# args will be
# -nosplash -nodesktop -minimize -r "Worker1;exit"
# -nosplash -nodesktop -minimize -r "Worker2;exit"
# etc
# save it
$queue.Enqueue(@($program, $args))
}
# begin executing jobs
while($queue.Count) {
# remove jobs that are done
$running.Where({ $_.HasExited }) |
ForEach-Object { [void]$running.Remove($_) }
if($running.Count -ge $throttle) {
# busy, so wait
Start-Sleep -Milliseconds 50
}
else {
# ready for new job
$cmd = $queue.Dequeue()
[void]$running.Add([System.Diagnostics.Process]::Start($cmd[0], $cmd[1]))
}
}
# wait for rest to be done
while($running.Where({ !$_.HasExited }).Count) {
Start-Sleep -Milliseconds 50
}