并在一个批处理的并行和串行工作启动命令 [英] for and start commands in a batch for parallel and sequential work

查看:185
本文介绍了并在一个批处理的并行和串行工作启动命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有8GB内存的8核CPU,而我创建一个批处理文件自动排气中的大多数参数和变量COM preSS同一组文件与最终目标的7-Zip CLI调查结果导致在最小存档大小可能参数和变量最强的组合。

I have an 8 core CPU with 8GB of RAM, and I'm creating a batch file to automate 7-zip CLI in exhausting most parameters and variables to compress the same set of files with the ultimate goal of finding the strongest combination of parameters and variables that result in the smallest archive size possible.

这是很费时间的性质消耗特别是当要处理的文件集是在千兆字节。我需要一种方法不仅自动化而且加快了整个过程。

This is very time consuming by nature especially when the set of files to be processed is in gigabytes. I need a way not only to automate but to speed up this whole process.

7-ZIP适用于不同的COM pression算法,有些是单线程只,还有一些是多线程的,一些并不需要的内存量多,有的需要它的大量的,甚至可能超越8GB的障碍。我已经成功地创建一个自动批处理,在不计需要比8GB的内存更多的组合顺序的工作。

7-zip works with different compression algorithms, some are single-threaded only, and some are multi-threaded, some do not require much amount of memory, and some require huge amounts of it and could even surpass the 8GB barrier. I've already successfully created an automated batch that works in sequence which exclude combinations requiring more than 8GB of memory.

我在几个批次分割不同的COM pression算法来简化整个过程。例如,在PPMD玉米pression作为7Z归档使用1线程和高达1024MB。这是我目前的批处理:

I've split the different compression algorithms in several batches to simplify the whole process. For example, compression in PPMd as a 7z archive uses 1-thread and up to 1024MB. This is my current batch:

@echo off
echo mem=1m 2m 3m 4m 6m 8m 12m 16m 24m 32m 48m 64m 96m 128m 192m 256m 384m 512m 768m 1024m
echo o=2 3 4 5 6 7 8 10 12 14 16 20 24 28 32
echo s=off 1m 2m 4m 8m 16m 32m 64m 128m 256m 512m 1g 2g 4g 8g 16g 32g 64g on
echo x=1 3 5 7 9

for %%x IN (9) DO for %%d IN (1024m 768m 512m 384m 256m 192m 128m 96m 64m 48m 32m 24m 16m 12m 8m 6m 4m 3m 2m 1m) DO for %%w IN (32 28 24 20 16 14 12 10 8 7 6 5 4 3 2) DO for %%s IN (on) DO 7z.exe a teste.resultado\%%xx.ppmd.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -m0=PPMd:mem=%%d:o=%%w -ms=%%s
exit

X 取值 0 纪念品是参数,什么是后他们每个人都是其中7z.exe将与变量。 X 取值在这种情况下是不关心的,他们的意思是COM pression实力和坚实的块大小存档。

x, s, o and mem are parameters, and what's after each of them are the variables which 7z.exe will work with. x and s in this case are of no concern, they mean compression strength and solid block size for the archive.

这一批将正常工作,但仅限于在同一时间仅运行1 7z.exe实例,现在我正在寻找一种方式,使其在平行但不超过8GB的内存运行更7z.exe实例或8个线程一次,以先到者为准,继续做下那些序列中之前。

That batch will work fine, but is limited to running only 1 instance of 7z.exe at a time and now I'm looking for a way to make it run more 7z.exe instances in parallel but without exceeding 8GB of RAM or 8 threads at once, whichever comes first, before proceeding to do the next ones in the sequence.

我怎么能提高呢?我有一些想法,但我不知道如何让他们在一个批处理工作。我在想,不会与7Z流程交互,但会控制在下一7Z实例将启动2其他变量。一个变量会保留多少个线程使用目前的轨道,另外将跟踪多少内存都在使用。难道这项工作?

How can I improve this? I have some ideas but I don't know how to make them work in a batch. I was thinking of 2 other variables that won't interact with the 7z processes but would control when the next 7z instance would start. One variable would keep track of how many threads are currently in use and another would track how much memory are in use. Could that work?

编辑:
对不起,我需要补充的细节,我是新来这个回帖风格。在此之后的答案 - http://stackoverflow.com/a/19481253/2896127 - 我所说的8批次创建并7z.PPMd一批是其中之一。也许列出所有批次,如何7Z涉及的参数会给整个问题更好的洞察力。我会用简单的那些启动:

Sorry, I need to add details, I'm new to this posting style. Following this answer - http://stackoverflow.com/a/19481253/2896127 - I mentioned 8 batches were created and that 7z.PPMd batch was one of them. Maybe listing all the batches and how 7z deals with the parameters will give a better insight on the whole issue. I'll start with the simple ones:


  • 7z.PPMd - 1充分利用线程,每个实例字典依赖32米-1055米内存使用

  • 7z.BZip2 - 8充分利用线程,每个实例固定109米内存使​​用

  • zip.Bzip2 - 8部分使用线程,每个实例固定336米内存使用

  • zip.Deflate - 8部分使用线程,每个实例固定260米内存使用

  • zip.PPMd - 8部分使用线程,每个实例字典依赖280米-2320米内存使用

我的意思有部分使用线程的是,虽然我分配8线程每个7.exe实例使用,该算法可以在随机的方式进行变量的CPU使用率,在我的掌握中,未predictable ,但不限于设置有 - 不超过8个线程。在8充分利用线程的情况下,这意味着我的8芯CPU上,每个实例是利用100%的CPU。

What I mean with partially utilized threads is that, while I assign 8 threads to be used by each 7.exe instance, the algorithm can do variable CPU usage at a randomly fashion, out of my control, unpredictable, but the limitation is set there - no more than 8 threads. In the case of 8 fully utilized threads, it means that on my 8 core CPU, each instance is utilizing 100% of CPU.

最复杂的 - 7z.LZMA,7z.LZMA2,zip.LZMA - 将需要详细解释,但我的时间短,现在运行。我会回来的,每当我有更多的时间来编辑LZMA一部分。

The most complex ones - 7z.LZMA, 7z.LZMA2, zip.LZMA - will need to be explained in detail but I am running short on time now. I'll be back to edit the LZMA part whenever I have more free time.

再次感谢。

编辑:添加在LZMA部分

Adding in LZMA part.


  • 7z.LZMA - 每个实例正螺纹,范围从1到2:

  • 7z.LZMA - each instance is n-threaded, ranging from 1 to 2:


  • 1充分利用线程,字典依赖,64K 512M的:

    • 64K字典使用32M内存

    • ...

    • 512米字典使用5407米内存

    • 排除范围:768米到1024米(以上8192米内存的限制可用)


    • 64K字典使用38米内存

    • ...

    • 512米字典使用5413米内存

    • 排除范围:768米到1024米(以上8192米内存的限制可用)

    7z.LZMA2 - 每个实例正螺纹,范围从1至8:

    7z.LZMA2 - each instance is n-threaded, ranging from 1 to 8:


    • 1充分利用线程,字典依赖,64K 512M的:

      • 64K字典使用32M内存

      • ...

      • 512米字典使用5407米内存

      • 排除范围:768米到1024米(以上8192米内存的限制可用)


      • 64K字典使用38米内存

      • ...

      • 512米字典使用5413米内存

      • 排除范围:768米到1024米(以上8192米内存的限制可用)


      • 64K字典使用51米内存

      • ...

      • 256米字典使用5677米内存

      • 排除范围:384米到1024米(以上8192米内存的限制可用)


      • 64K字典使用62米内存

      • ...

      • 192米字典使用6965米内存

      • 排除范围:256米到1024米(以上8192米内存的限制可用)


      • 64K字典使用72米内存

      • ...

      • 128米字典使用6717米内存

      zip.LZMA - 每个实例正螺纹,范围从1至8:

      zip.LZMA - each instance is n-threaded, ranging from 1 to 8:


      • 1充分利用线程,字典依赖,64K 512M的:

        • 64K字典使用3米内存

        • ...

        • 512米字典使用5378米内存

        • 排除范围:768米到1024米(以上8192米内存的限制可用)


        • 64K字典使用9米内存

        • ...

        • 512米字典使用5384米内存

        • 排除范围:768米到1024米(以上8192米内存的限制可用)


        • 64K字典使用82米内存

        • ...

        • 256米字典使用5456米内存

        • 排除范围:384米到1024米(以上8192米内存的限制可用)


        • 64K字典使用123米内存

        • ...

        • 256米字典使用8184米(非常接近极限,虽然,我可能会考虑排除它)

        • 排除范围:384米到1024米(以上8192米内存的限制可用)


        • 64K字典使用164米内存

        • ...

        • 128米字典使用5536米内存

        • 排除范围:192米到1024米(以上8192米内存的限制可用)

        我想了解在他们NUL命令的行为。我不太明白,部分中发生了什么,有什么那些^> ^&放符号; 1。是的意思是说

        I'm trying to understand the behaviour of the commands with nul in them. I don't quite understand what's happening during that part, what those symbols ^ > ^&1 "" are meant to say.

            2>nul del %lock%!nextProc!
            %= Redirect the lock handle to the lock file. The CMD process will     =%
            %= maintain an exclusive lock on the lock file until the process ends. =%
            start /b "" cmd /c %lockHandle%^>"%lock%!nextProc!" 2^>^&1 !cpu%%N! !cmd!
          )
          set "launch="
        

        然后后来,在:等待code:

        Then later on, at the :wait code:

            ) 9>>"%lock%%%N"
          ) 2>nul
          if %endCount% lss %startCount% (
            1>nul 2>nul ping /n 2 ::1
            goto :wait
          )
        
        2>nul del %lock%*
        


        编辑2(29-10-2013):添加的情况在当前点


        EDIT 2 (29-10-2013): Adding the current point of the situation.

        反复试验研究,一步发生了什么步骤笔记补充后,我能够理解上述行为。我简化了启动命令行这样:

        After trial and error research, complemented with step by step notes of what's happening, I was able to understand the behaviour above. I simplified the line with start command to this:

        start /b /low cmd /c !cmd!>"%lock%!nextProc!"
        

        虽然它的作品,我还是不明白 1 ^&GT的意思;文件名2 ^> ^&放大器; 1'命令'。我知道这是关系到什么,否则将显示给我的文件名输入文字。在这种情况下,这将显示所有7z.exe文本而是写在文件中。直到7z.exe情况下完成自己的工作,没有什么是写入文件,但该文件已经存在,但同时不存在。当7z.exe实际上完成后,该文件定稿,这个时候它的存在为脚本的一个部分。

        Though it works, I still don't understand the meaning of 1^>"filename" 2^>^&1 'command'. I know it is related to writing text in the filename what would otherwise be displayed to me. In this case, it would show all of 7z.exe text but written in the file. Until 7z.exe instance finishes its job, nothing is written in the file, but the file already exists, yet at the same time doesn't exist. When 7z.exe actually finishes, the file is finalized and this time it exists for the next part of the script.

        现在我能理解建议的脚本的处理行为,我用我自己的东西补充它 - 我想实现所有批次为一批做到这一切的剧本。在简化版本,这是它:

        Now I can understand the processing behaviour of the suggested script and I'm complementing it with something of my own - I am trying to implement all batches into "one batch do it all" script. In the simplified version, this is it:

        echo 8 threads - maxproc=1
        for %%x IN (9) DO for %%t IN (8) DO for %%d IN (900k) DO for %%s IN (on) DO 7z.exe a teste.resultado\%%xx.bzip2.%%tt.%%dd.%%ss.7z .\teste.original\* -mx=%%x -ms=%%s -m0=BZip2:d=%%d:mt=%%t
        for %%x IN (9) DO for %%t IN (8) DO for %%d IN (900k) DO 7z.exe a teste.resultado\%%xx.bzip2.%%tt.%%dd.zip .\teste.original\* -mx=%%x -mm=BZip2:d=%%d -mmt=%%t
        for %%x IN (9) DO for %%t IN (8) DO for %%w IN (257 256 192 128 96 64 48 32 24 16 12 8) DO 7z.exe a teste.resultado\%%xx.deflate64.%%tt.%%ww.zip .\teste.original\* -mx=%%x -mm=deflate64:fb=%%w -mmt=%%t
        for %%x IN (9) DO for %%t IN (8) DO for %%w IN (258 256 192 128 96 64 48 32 24 16 12 8) DO 7z.exe a teste.resultado\%%xx.deflate.%%tt.%%ww.zip .\teste.original\* -mx=%%x -mm=deflate:fb=%%w -mmt=%%t
        for %%x IN (9) DO for %%t IN (8) DO for %%d IN (256m 128m 64m 32m 16m 8m 4m 2m 1m) DO for %%w IN (16 15 14 13 12 11 10 9 8 7 6 5 4 3 2) DO 7z.exe a teste.resultado\%%xx.ppmd.%%tt.%%dd.%%ww.zip .\teste.original\* -mx=%%x -mm=PPMd:mem=%%d:o=%%w -mmt=%%t
        
        echo 4 threads - maxproc=2
        for %%x IN (9) DO for %%t IN (4) DO for %%d IN (256m) DO for %%w IN (273 256 192 128 96 64 48 32 24 16 12 8) DO for %%s IN (on) DO 7z.exe a teste.resultado\%%xx.lzma2.%%tt.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -ms=%%s -m0=lzma2:d=%%d:fb=%%w -mmt=%%t
        
        echo 2 threads - maxproc=4
        for %%x IN (9) DO for %%t IN (2) DO for %%d IN (512m) DO for %%w IN (273 256 192 128 96 64 48 32 24 16 12 8) DO for %%s IN (on) DO 7z.exe a teste.resultado\%%xx.lzma.%%tt.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -ms=%%s -m0=LZMA:d=%%d:fb=%%w -mmt=%%t
        for %%x IN (9) DO for %%t IN (2) DO for %%d IN (512m) DO for %%w IN (273 256 192 128 96 64 48 32 24 16 12 8) DO for %%s IN (on) DO 7z.exe a teste.resultado\%%xx.lzma2.%%tt.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -ms=%%s -m0=lzma2:d=%%d:fb=%%w -mmt=%%t
        for %%x IN (9) DO for %%t IN (2) DO for %%d IN (512m) DO for %%w IN (273 256 192 128 96 64 48 32 24 16 12 8) DO 7z.exe a teste.resultado\%%xx.lzma.%%tt.%%dd.%%ww.zip .\teste.original\* -mx=%%x -mm=lzma:d=%%d:fb=%%w -mmt=%%t
        
        echo 1 threads - maxproc=8
        for %%x IN (9) DO for %%t IN (1) DO for %%d IN (512m) DO for %%w IN (273 256 192 128 96 64 48 32 24 16 12 8) DO for %%s IN (on) DO 7z.exe a teste.resultado\%%xx.lzma.%%tt.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -ms=%%s -m0=LZMA:d=%%d:fb=%%w -mmt=%%t
        for %%x IN (9) DO for %%t IN (1) DO for %%d IN (512m) DO for %%w IN (273 256 192 128 96 64 48 32 24 16 12 8) DO for %%s IN (on) DO 7z.exe a teste.resultado\%%xx.lzma2.%%tt.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -ms=%%s -m0=lzma2:d=%%d:fb=%%w -mmt=%%t
        for %%x IN (9) DO for %%d IN (1024m 768m 512m 384m 256m 192m 128m 96m 64m 48m 32m 24m 16m 12m 8m 6m 4m 3m 2m 1m) DO for %%w IN (32 28 24 20 16 14 12 10 8 7 6 5 4 3 2) DO for %%s IN (on) DO 7z.exe a teste.resultado\%%xx.ppmd.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -m0=PPMd:mem=%%d:o=%%w -ms=%%s
        for %%x IN (9) DO for %%t IN (1) DO for %%d IN (512m) DO for %%w IN (273 256 192 128 96 64 48 32 24 16 12 8) DO 7z.exe a teste.resultado\%%xx.lzma.%%tt.%%dd.%%ww.zip .\teste.original\* -mx=%%x -mm=lzma:d=%%d:fb=%%w -mmt=%%t
        

        总之,我要处理所有以最有效的方式。通过决定多少进程可以一次运行操作的这将是一种方法,但然后有也为每个过程所要求的存储器,让所有需要的存储器的由这些过程的总和不会超过8192 MB。我得到这个工作的一部分。

        In short, I want to process all that in the most efficient manner possible. Doing it by deciding how many processes can run at a time would be a way, but then there's also the memory required for each process, so that the sum of all required memory by those processes won't exceed 8192 MB. I got this part working.

        @echo off
        setlocal enableDelayedExpansion
        
        set "maxMem=8192"
        set "maxThreads=8"
        
        :cycle1
        set "cycleCount=4"
        set "cycleThreads=1"
        set "maxProc="
        set /a "maxProc=maxThreads/cycleThreads"
        set "cycleFor1=for %%x IN (9) DO for %%t IN (1) DO for %%d IN (512m) DO for %%w IN (273 256 192 128 96 64 48 32 24 16 12 8) DO for %%s IN (on) DO ("
        set "cycleFor2=for %%x IN (9) DO for %%t IN (1) DO for %%d IN (512m) DO for %%w IN (273 256 192 128 96 64 48 32 24 16 12 8) DO for %%s IN (on) DO ("
        set "cycleFor3=for %%x IN (9) DO for %%d IN (1024m 768m 512m 384m 256m 192m 128m 96m 64m 48m 32m 24m 16m 12m 8m 6m 4m 3m 2m 1m) DO for %%w IN (32 28 24 20 16 14 12 10 8 7 6 5 4 3 2) DO for %%s IN (on) DO ("
        set "cycleFor4=for %%x IN (9) DO for %%t IN (1) DO for %%d IN (512m) DO for %%w IN (273 256 192 128 96 64 48 32 24 16 12 8) DO ("
        set "cycleCmd1=7z.exe a teste.resultado\%%xx.lzma.%%tt.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -ms=%%s -m0=LZMA:d=%%d:fb=%%w -mmt=%%t"
        set "cycleCmd2=7z.exe a teste.resultado\%%xx.lzma2.%%tt.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -ms=%%s -m0=lzma2:d=%%d:fb=%%w -mmt=%%t"
        set "cycleCmd3=7z.exe a teste.resultado\%%xx.ppmd.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -m0=PPMd:mem=%%d:o=%%w -ms=%%s"
        set "cycleCmd4=7z.exe a teste.resultado\%%xx.lzma.%%tt.%%dd.%%ww.zip .\teste.original\* -mx=%%x -mm=lzma:d=%%d:fb=%%w -mmt=%%t"
        set "tempMem1=5407"
        set "tempMem2=5407"
        set "tempMem3=1055"
        set "tempMem4=5378"
        rem set "tempMem1=5407"
        rem set "tempMem2=5407"
        rem set "tempMem3=1055 799 543 415 287 223 159 127 95 79 63 55 47 43 39 37 35 34 33 32"
        rem set "tempMem4=5378"
        set "memSum=0"
        if not defined memRem set "memRem=!maxMem!"
        
        for /l %%N in (1 1 %cycleCount%) DO (set "tempProc%%N=")
        for /l %%N in (1 1 %cycleCount%) DO (
          set memRem
          set /a "tempProc%%N=%memRem%/tempMem%%N"
          set /a "memSum+=tempMem%%N"
          set /a "memRem-=tempMem%%N"
          set /a "maxProc=!tempProc%%N!"
          call :executeCycle
          set /a "memRem+=tempMem%%N"
          set /a "memSum-=tempMem%%N"
          set /a "maxProc-=!tempProc%%!
        )
        goto :fim
        
        :executeCycle
        set "lock=lock_%random%_"
        set /a "startCount=0, endCount=0"
        for /l %%N in (1 1 %maxProc%) DO set "endProc%%N="
        
            set launch=1
            for %%x IN (9) DO for %%t IN (1) DO for %%d IN (512m) DO for %%w IN (273 256 192 128 96 64 48 32 24 16 12 8) DO for %%s IN (on) DO (
              set "cmd=7z.exe a teste.resultado\%%xx.lzma.%%tt.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -ms=%%s -m0=LZMA:d=%%d:fb=%%w -mmt=%%t"
              if !startCount! lss %maxProc%  (
                set /a "startCount+=1, nextProc=startCount"
              ) else (
                call :wait
              )
              set cmd!nextProc!=!cmd!
              echo !time! - proc!nextProc!: starting !cmd!
              2>nul del %lock%!nextProc!
              start /b /low cmd /c !cmd!>"%lock%!nextProc!"
            )
            set "launch="
        :wait
                for /l %%N in (1 1 %startCount%) do (
                  if not defined endProc%%N if exist "%lock%%%N" (
                    echo !time! - proc%%N: finished !cmd%%N!
                    if defined launch (
                      set nextProc=%%N
                      exit /b
                    )
                    set /a "endCount+=1, endProc%%N=1"
                  ) 9>>"%lock%%%N"
                ) 2>nul
                if %endCount% lss %startCount% (
                1>nul 2>nul ping /n 2 ::1
                goto :wait
              )
        
        2>nul del %lock%*
        echo ===
        echo Thats all folks!
        exit /b
        :fim
        pause
        

        我有 cycleFor1 cycleCmd1 位于麻烦:CYCLE1 部分 - 它们应该被替换线和 CMD 变量>:executeCycle ,使其工作,我打算。我该怎么做呢?

        I have trouble with cycleFor1 and cycleCmd1 located in :cycle1 part - they should be replacing the for line and the first cmd variable inside the :executeCycle, to make it work as I intend to. How do I do that?

        另一个问题我已经是关于 tempMem3 。我已经登录时,该命令 cycleCmd3 将运行所需的所有内存。这是字典依赖。 tempMem3和cycleCmd3都与这样的:

        The other issue I have is about tempMem3. I have logged all memory required when the command cycleCmd3 would be running. It is dictionary dependant. tempMem3 and cycleCmd3 are related like this:

        for %%d IN (1024m 768m 512m 384m 256m 192m 128m 96m 64m 48m 32m 24m 16m 12m 8m 6m 4m 3m 2m 1m) DO
        set "tempMem3=1055 799 543 415 287 223 159 127 95 79 63 55 47 43 39 37 35 34 33 32"
        

        所以1024米将使用1055,768米使用32将使用799,依此类推,直到1米我不知道该怎么翻译成剧本。

        So 1024m would use 1055, 768m would use 799, and so on till 1m using 32. I don't know how to translate that into the script.

        任何帮助是AP preciated。

        Any help is appreciated.

        推荐答案

        我已经发布,在的壳流程并行执行的。该脚本使用嵌入脚本内的命令的列表。按照链接,看看它是如何工作的。

        I've already posted a robust batch solution that limits the number of parallel processes at Parallel execution of shell processes. That script uses a list of commands that is embedded within the script. Follow the link to see how it works.

        我修改了脚本生成使用FOR循环根据你的问题的命令。我也将限制设置为8个同步进程。

        I modified that script to generate the commands using FOR loops as per your question. I also set the limit to 8 simultaneous processes.

        您最大内存为1G,你永远不超过8个过程,所以我不看你怎能超过8克。如果增加每过程中的最大内存,那么你就不用担心内存总量。你将需要添加额外的逻辑来跟踪多少内存被使用,以及CPU的ID是可用的。需要注意的是批号限于〜2G,所以我建议在计算兆使用的内存。

        Your maximum memory is 1g, and you never have more than 8 processes, so I don't see how you could ever exceed 8g. If you increase the max memory per processes, then you do have to worry about total memory. you will have to add additional logic to keep track of how much memory is being used, and which cpu IDs are available. Note that batch numbers are limited to ~2g, so I recommend computing memory used in megabytes.

        默认情况下,脚本隐藏命令的输出。如果你想看到的输出,然后用运行/ O 选项。

        By default, the script hides the output of the commands. If you want to see the output, then run it with the /O option.

        @echo off
        setlocal enableDelayedExpansion
        
        :: Display the output of each process if the /O option is used
        :: else ignore the output of each process
        if /i "%~1" equ "/O" (
          set "lockHandle=1"
          set "showOutput=1"
        ) else (
          set "lockHandle=1^>nul 9"
          set "showOutput="
        )
        
        :: Define the maximum number of parallel processes to run.
        :: Each process number can optionally be assigned to a particular server
        :: and/or cpu via psexec specs (untested).
        set "maxProc=8"
        
        :: Optional - Define CPU targets in terms of PSEXEC specs
        ::           (everything but the command)
        ::
        :: If a cpu is not defined for a proc, then it will be run on the local machine.
        :: I haven't tested this feature, but it seems like it should work.
        ::
        :: set cpu1=psexec \\server1 ...
        :: set cpu2=psexec \\server1 ...
        :: set cpu3=psexec \\server2 ...
        :: etc.
        
        :: For this demo force all cpu specs to undefined (local machine)
        for /l %%N in (1 1 %maxProc%) do set "cpu%%N="
        
        :: Get a unique base lock name for this particular instantiation.
        :: Incorporate a timestamp from WMIC if possible, but don't fail if
        :: WMIC not available. Also incorporate a random number.
          set "lock="
          for /f "skip=1 delims=-+ " %%T in ('2^>nul wmic os get localdatetime') do (
            set "lock=%%T"
            goto :break
          )
          :break
          set "lock=%temp%\lock%lock%_%random%_"
        
        :: Initialize the counters
          set /a "startCount=0, endCount=0"
        
        :: Clear any existing end flags
          for /l %%N in (1 1 %maxProc%) do set "endProc%%N="
        
        :: Launch the commands in a loop
          set launch=1
          echo mem=1m 2m 3m 4m 6m 8m 12m 16m 24m 32m 48m 64m 96m 128m 192m 256m 384m 512m 768m 1024m
          echo o=2 3 4 5 6 7 8 10 12 14 16 20 24 28 32
          echo s=off 1m 2m 4m 8m 16m 32m 64m 128m 256m 512m 1g 2g 4g 8g 16g 32g 64g on
          echo x=1 3 5 7 9
          for %%x IN (9) DO for %%d IN (1024m 768m 512m 384m 256m 192m 128m 96m 64m 48m 32m 24m 16m 12m 8m 6m 4m 3m 2m 1m) DO (
            set "cmd=7z.exe a teste.resultado\%%xx.ppmd.%%dd.%%ww.%%ss.7z .\teste.original\* -mx=%%x -m0=PPMd:mem=%%d:o=%%w -ms=%%s"
            if !startCount! lss %maxProc% (
              set /a "startCount+=1, nextProc=startCount"
            ) else (
              call :wait
            )
            set cmd!nextProc!=!cmd!
            if defined showOutput echo -------------------------------------------------------------------------------
            echo !time! - proc!nextProc!: starting !cmd!
            2>nul del %lock%!nextProc!
            %= Redirect the lock handle to the lock file. The CMD process will     =%
            %= maintain an exclusive lock on the lock file until the process ends. =%
            start /b "" cmd /c %lockHandle%^>"%lock%!nextProc!" 2^>^&1 !cpu%%N! !cmd!
          )
          set "launch="
        
        :wait
        :: Wait for procs to finish in a loop
        :: If still launching then return as soon as a proc ends
        :: else wait for all procs to finish
          :: redirect stderr to null to suppress any error message if redirection
          :: within the loop fails.
          for /l %%N in (1 1 %startCount%) do (
            %= Redirect an unused file handle to the lock file. If the process is    =%
            %= still running then redirection will fail and the IF body will not run =%
            if not defined endProc%%N if exist "%lock%%%N" (
              %= Made it inside the IF body so the process must have finished =%
              if defined showOutput echo ===============================================================================
              echo !time! - proc%%N: finished !cmd%%N!
              if defined showOutput type "%lock%%%N"
              if defined launch (
                set nextProc=%%N
                exit /b
              )
              set /a "endCount+=1, endProc%%N=1"
            ) 9>>"%lock%%%N"
          ) 2>nul
          if %endCount% lss %startCount% (
            1>nul 2>nul ping /n 2 ::1
            goto :wait
          )
        
        2>nul del %lock%*
        if defined showOutput echo ===============================================================================
        echo Thats all folks!
        

        这篇关于并在一个批处理的并行和串行工作启动命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆