使用批处理文件打开多个MATLAB文件实例,这些实例只会使CPU承受100%的压力

时间:2018-12-09 00:51:05

标签: matlab powershell batch-file cmd

因此,本质上,这是一个有关如何更有效地使用多核处理器的问题。

我有一个优化脚本(用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可以处理的实例更多的实例会使处理器效率降低。所以我认为最好的策略是这样的:

  1. 启动前12个实例;
  2. 当前任何正在运行的实例完成后,
  3. 从列表中开始下一个。 (即使工人大约在同一时间被打开并从事相同的工作,他们仍然倾向于在不同的时间完成工作。)

这将确保始终始终充分利用计算能力(cpu使用率始终为100%),而不会给cpu带来过多压力。

如何在批处理文件中实现此策略?如果批处理文件很难做到这一点,PowerShell可以做到吗?

请显示实际代码并说明。我不是程序员,所以我不太了解编码。

谢谢。

1 个答案:

答案 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
}