【问题标题】:Windows batch files and multiple processorsWindows 批处理文件和多处理器
【发布时间】:2015-09-05 05:57:44
【问题描述】:

我有一个 Windows 批处理文件,它多次执行相同的操作,但在多个文件上除外。有没有办法告诉计算机使用不同的处理器内核来加快处理速度?否则,由于一直在使用同一个处理器,因此需要更长的时间。

【问题讨论】:

  • 应该在 SU 上询问,但可能会因为类似superuser.com/questions/427550/… 之类的东西而被关闭。
  • DOS 不支持多处理器。如果您谈论的是 Windows 命令行批处理文件,请使用 start /affinity,这里有很多示例。无论如何,它不会加速任何事情,因为 Windows 会自动使用额外的处理器。
  • 您可以假装您的计算机正在运行正确的操作系统并使用 GNU Parallel...blogs.msdn.com/b/hpctrekker/archive/2013/03/30/…
  • 超级 hacky 方法可以在紧要关头完成它,拆分文件并在它们上运行 bat 的多个实例。我相信我会在下一条评论中听到这有多糟糕。

标签: windows multithreading batch-file multiprocessing


【解决方案1】:

虽然一个 Batch 文件可以启动多个并行线程,但它们的同步存在多个问题。通常的同步方法使用信号量之类的文件的存在,但是检查信号量文件的代码会浪费 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

【讨论】:

    【解决方案2】:

    在 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。假设程序将文件从一种格式转换为另一种格式。在这种情况下,代码会是什么样子?
    猜你喜欢
    • 2014-11-15
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    • 2018-06-29
    相关资源
    最近更新 更多