Windows批处理文件与多个处理器

4

我有一个Windows批处理文件,它需要对多个文件执行相同的操作。有没有一种方法可以让计算机使用不同的处理器核心来加速处理过程?否则,由于相同的处理器一直在使用,处理时间会更长。


应该在SU上提问,但很可能会被关闭,因为它是类似于http://superuser.com/questions/427550/start-a-background-task-from-windows-7-cmd的重复问题。 - Alexei Levenkov
DOS不支持多处理器。如果你在谈论Windows命令行批处理文件,那么请使用“start /affinity”,有很多例子。无论如何,这不会加速任何东西,因为Windows自动使用额外的处理器。 - wOxxOm
1
你可以假装你的计算机正在运行一个适当的操作系统,并使用GNU Parallel... http://blogs.msdn.com/b/hpctrekker/archive/2013/03/30/preparing-and-uploading-datasets-for-hdinsight.aspx - Mark Setchell
在紧急情况下,一个超级hacky的方法是将文件分割并在它们上面运行多个批处理实例。我相信我会在下一条评论中听到这种方法有多糟糕。 - cliffclof
2个回答

3
在Windows批处理文件中,您可以使用管道或start /b来进行多线程处理。
类似以下的代码应该能够正常运行:
@echo off
setlocal EnableDelayedExpansion
set "file1=%~1"

:startExtraThread
if NOT "%~2"=="" (
  start "Thread for %~2" /b "cmd /c %~f0 %~2"
  shift
  goto :startExtraThread
)

do my job with file1

假设我有一个程序myboxer.exe和一个文件block_base.dat。同时,假设该程序将文件从一种格式转换为另一种格式。在这种情况下,代码会是什么样子? - posfan12

3
虽然批处理文件可以启动多个并行线程,但与它们的同步相关的问题很多。通常的同步方法使用文件存在作为信号量,但检查信号量文件的代码会浪费CPU时间。虽然可以在此代码中插入延迟,但结果通常很繁琐和棘手。
我开发了一种高效的批处理文件多线程方案,使用管道获取同步信号;这一点允许等待代码不浪费CPU时间,因此所有CPU核心都可以用于数据处理。下面的程序是一个示例,处理由通配符选择的多个文件,但该代码可以轻松适应处理任何其他数据集;此方法专门设计用于仅当一个线程在同一时间结束其处理时,并且如果两个或多个文件的处理在非常短的时间间隔内结束,则可能会失败。
@echo off
setlocal EnableDelayedExpansion

rem Multi-thread scheme in Batch files
rem Antonio Perez Ayala aka Aacini

set "myID=%~2"
if "%~1" neq "" goto %1

set "signal=X"
for /L %%i in (1,1,10) do set "signal=!signal!!signal!"

rem Create the list of start commands for the concurrent working threads
set "numThreads=%NUMBER_OF_PROCESSORS%"
set "threads="
del availableThread* 2> NUL
for /L %%i in (1,1,%numThreads%) do (
   set "threads=!threads! & start "" /B cmd /C "%~NX0" Thread %%i"
   > availableThread%%i echo %%i
)

echo Start of application
del requestForThread* 2> NUL
( %threads:~3% ) | "%~NX0" Main
echo End of application
goto :EOF


:Main

echo Main - started

rem Controlling code: process all files and assign each one to available threads
for /F "delims=" %%f in ('dir /A-D /B *.txt') do (

   rem Get the number of next available thread; waits for anyone, if necessary
   if not exist availableThread* (
      echo X > mainIsWaiting
      echo Main - waiting for an available thread
      set /P availableSignal=
      del mainIsWaiting
   )

   set "nextThread="
   for %%t in (availableThread*) do if not defined nextThread (
      set /P "nextThread=" < %%t
      del %%t
   )

   if not defined nextThread (
      echo SYNCHRO FAILED^^!
      goto waitThreadsEnds
   )

   rem Assign the next file to the available thread
   echo %%f> requestForThread!nextThread!
   echo Main - file "%%f" assigned to thread #!nextThread!

)

echo Main - all files sent to processing

rem Wait until all threads ends their tasks
:waitThreadsEnds
   set availableThreads=0
   for %%t in (availableThread*) do set /A availableThreads+=1
if %availableThreads% lss %numThreads% goto :waitThreadsEnds
del availableThread*

rem Send "exit" signals to all threads
for /L %%i in (1,1,%numThreads%) do echo exit> requestForThread%%i
echo Main - end
goto :EOF


:Thread

rem Wait until a request for this thread appear
if not exist requestForThread%myID% goto Thread
set "request="
set /P "request=" < requestForThread%myID%
if not defined request goto Thread
del requestForThread%myID%
if "%request%" equ "exit" goto :EOF

rem Process the file
echo %time% - Thread #%myID% start: "%request%" > CON
set /A seconds=6+%random:~-1%
ping localhost -n %seconds% > NUL
echo %time% - Thread #%myID% end:   "%request%" > CON

rem Inform that this thread is available for other task
> availableThread%myID% echo %myID%
if exist mainIsWaiting echo %signal:~0,1021%

goto Thread

当然,为了使此方法按预期工作,您的Windows计算机必须仅处理此批处理文件,没有其他并发进程。
有关此解决方案中使用的方法的进一步说明,请参见this post

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接