这就是我要做的。 假设我有一个名为myprogram.exe
的程序,我必须执行 1000 次。
在Windows下,我通常可以做一些简单的事情,比如:
for /L %n in (1,1,1000) do start /myfolder/myprogram.exe
但是,假设我只有 5 个 CPU 线程可以用于运行 1000 个myprogram.exe
实例,这样我只启动 5 个,然后当其中一个完成时启动另一个,依此类推,直到整个 1000 个结束。
在Linux下并使用GNU Parallel,我可以简单地做:
seq 1000 | parallel -N0 -j5 "nohup myprogram.exe"
我怎样才能在 Windows 命令行中实现类似的东西?请注意,在我的情况下,使用Cygwin不是一个选项,因此在Windows下诉诸xargs和GNU Parallel也不是选项。
这是一种方法,通过使用powershell进行进程计数。 并使用简单的set /a
作为计数器。
@echo off
setlocal enabledelayedexpansion
set /a cnt=0
:counter
if !cnt! lss 1000 (
for /F "tokens=*" %%i in ('powershell ^(Get-Process -Name 'myprogram'^).count') do set proc=%%i
if !proc! lss 5 (
start "C:myfoldermyprogram.exe"
set /a cnt+=1
)
goto :counter
)
如果您想查看计数,可以在goto :counter
之前在行中添加echo !cnt!
。
它可以在不使用delayedexpansion
的情况下完成,但我更喜欢在这里使用它。
这将并行运行五个进程。每次其中一个完成时,下一个进程就会开始(所以总是有 5 个,直到它们全部完成(
@ECHO off
setlocal enabledelayedexpansion
set bunch=5
for /l %%a in (1,1,1000) do (
call :loop
echo processing: %%a
start "MyCommand" cmd /c timeout !random:~-1!
)
call :loop
goto :eof
:loop REM waits for available slot
for /f %%x in ('tasklist /fi "windowtitle eq MyCommand" ^| find /c "cmd.exe"') do set x=%%x
if %x% geq %bunch% goto :loop
goto :eof
将/min
开关添加到start
以最大程度地减少启动的进程。
给他们一个独特的窗口标题(MyCommand
这里(以便能够计算它们。
将cmd /c timeout !random:~-1!
替换为实际命令。
编辑一个稍微修改过的脚本,如果myprogram
是一个 GUI,它可能工作得更好(上面的脚本在 CLI 应用程序中会更好地工作(:
@ECHO off
setlocal enabledelayedexpansion
set bunch=5
for /l %%a in (1,1,100) do (
call :loop
echo processing: %%a
start notepad.exe
)
call :loop
goto :eof
:loop REM waits for available slot
for /f %%x in ('tasklist /fi "imagename eq Notepad.exe"^|find /c "."') do set x=%%x
if %x% geq %bunch% goto :loop
goto :eof