для и запуска команд в пакете для параллельной и последовательной работы

У меня 8-ядерный процессор с 8 ГБ оперативной памяти, и яm создание пакетного файла для автоматизации 7-zip CLI при исчерпании большинства параметров и переменных для сжатия одного и того же набора файлов с конечной целью найти наиболее сильную комбинацию параметров и переменных, которая приведет к наименьшему возможному размеру архива.

Это очень трудоемкий характер, особенно когда набор файлов для обработки находится в гигабайтах. Мне нужен способ не только автоматизировать, но и ускорить весь этот процесс.

7-zip работает с различными алгоритмами сжатия, некоторые являются однопоточными, а некоторые многопоточными, некоторые не требуют большого объема памяти, а некоторые требуют огромных объемов и даже могут преодолеть барьер 8 ГБ. Я'Мы уже успешно создали автоматизированный пакет, работающий в последовательности, исключающей комбинации, требующие более 8 ГБ памяти.

разделить различные алгоритмы сжатия на несколько пакетов, чтобы упростить весь процесс. Например, сжатие в PPMd в виде архива 7z использует 1 поток и до 1024 МБ. Это моя текущая партия:

@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

xso а такжеmem параметры и чтоПосле каждой из них указываются переменные, с которыми будет работать 7z.exe.x а такжеs в этом случае это не имеет значения, они означают прочность на сжатие и размер блока для архива.

Эта партия будет работать нормально, но ограничена запуском только одного экземпляра 7z.exe за раз, и теперь яЯ ищу способ заставить его запускать больше экземпляров 7z.exe параллельно, но не превышая 8 ГБ ОЗУ или 8 потоков одновременно, в зависимости от того, что наступит раньше, прежде чем приступить к выполнению следующих в последовательности.

Как я могу улучшить это? У меня есть некоторые идеи, но я нене знаю, как заставить их работать в партии. Я думал о 2 других переменных, которые выигралиt взаимодействует с процессами 7z, но контролирует, когда будет запущен следующий экземпляр 7z. Одна переменная будет отслеживать, сколько потоков используется в данный момент, а другая будет отслеживать, сколько памяти используется. Может ли это работать?

Изменить: Извините, мне нужно добавить детали, яЯ новичок в этом стиле публикации. После этого ответа -https://stackoverflow.com/a/19481253/2896127 - Я упоминал, что было создано 8 партий, и одна из них была 7z.PPMd. Возможно, перечисление всех партий и то, как 7z работает с параметрами, поможет лучше понять весь вопрос. Я'начну с простых:

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, алгоритм может произвольно использовать переменное использование ЦП, вне моего контроля, непредсказуемо, но ограничение там установлено. - не более 8 тем. В случае 8 полностью используемых потоков это означает, что на моем 8-ядерном ЦП каждый экземпляр использует 100% ЦП.

Самые сложные из них - 7z.LZMA, 7z.LZMA2, zip.LZMA - требуют подробного объяснения, но сейчас у меня мало времени. Я'Я вернусь, чтобы редактировать партию LZMA, когда у меня будет больше свободного времени.

Еще раз спасибо.

РЕДАКТИРОВАТЬ: Добавление в LZMA часть.

7z.LZMA - каждый экземпляр n-поточный, в диапазоне от 1 до 2:

1 полностью используемая нить, зависит от словаря, от 64k до 512m:Словарь 64к использует 32м памяти...Словарь 512 м использует память 5407 мисключенный диапазон: от 768 до 1024 м (сверх предела 8192 м доступной памяти)2 частично используемых потока, зависящих от словаря, от 64k до 512m:Словарь 64к использует 38м памяти...Словарь 512 м использует память 5413 мисключенный диапазон: от 768 до 1024 м (сверх предела 8192 м доступной памяти)

7z.LZMA2 - каждый экземпляр n-поточный, в диапазоне от 1 до 8:

1 полностью используемая нить, зависит от словаря, от 64k до 512m:Словарь 64к использует 32м памяти...Словарь 512 м использует память 5407 мисключенный диапазон: от 768 до 1024 м (сверх предела 8192 м доступной памяти)2 или 3 частично используемых потока, зависящих от словаря, от 64k до 512m:Словарь 64к использует 38м памяти...Словарь 512 м использует память 5413 мисключенный диапазон: от 768 до 1024 м (сверх предела 8192 м доступной памяти)4 или 5 частично используемых потоков, зависящих от словаря, от 64k до 256m:Словарь 64k использует память 51m...256м словарь использует 5677м памятиисключенный диапазон: от 384 до 1024 м (сверх предела 8192 м доступной памяти)6 или 7 частично используемых потоков, зависящих от словаря, от 64k до 192m:Словарь 64к использует память 62м...192м словарь использует 6965м памятиисключенный диапазон: от 256 м до 1024 м (сверх предела 8192 м доступной памяти)8 частично используемых потоков, зависящих от словаря, от 64k до 128m:Словарь 64k использует память 72m...128м словарь использует 6717м памятиисключенный диапазон: от 192 до 1024 м (сверх предела 8192 м доступной памяти)

zip.LZMA - каждый экземпляр n-поточный, в диапазоне от 1 до 8:

1 полностью используемая нить, зависит от словаря, от 64k до 512m:64к словарь использует 3м памяти...Словарь 512 м использует память 5378 мисключенный диапазон: от 768 до 1024 м (сверх предела 8192 м доступной памяти)2 или 3 частично используемых потока, зависящих от словаря, от 64k до 512m:64к словарь использует 9м памяти...Словарь 512 м использует память 5384 мисключенный диапазон: от 768 до 1024 м (сверх предела 8192 м доступной памяти)4 или 5 частично используемых потоков, зависящих от словаря, от 64k до 256m:Словарь 64к использует 82м памяти...256м словарь использует 5456м памятиисключенный диапазон: от 384 до 1024 м (сверх предела 8192 м доступной памяти)6 или 7 частично используемых потоков, зависящих от словаря, от 64k до 256m:Словарь 64k использует память 123m...256-метровый словарь использует 8184 млн. (Очень близко к пределу, хотя, я могу рассмотреть его исключение)исключенный диапазон: от 384 до 1024 м (сверх предела 8192 м доступной памяти)8 частично используемых потоков, зависящих от словаря, от 64k до 128m:Словарь 64k использует память 164m...128м словарь использует 5536м памятиисключенный диапазон: от 192 до 1024 м (выше предела 8192 м доступной памяти) I '

Я пытаюсь понять поведение команд с nul в них. Я нене совсем понимаю, чточто происходит во время этой части, что эти символы ^> ^ & 1 "" предназначены, чтобы сказать.

    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="

Затем, позже: код ожидания:

    ) 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): Добавление текущей точки ситуации.

После исследования проб и ошибок, дополненного пошаговыми примечаниями о том, чтоПроисходило, я смог понять поведение выше. Я упростил строку с командой запуска до этого:

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

Хотя это работает, я все еще нене понимаю смысла1^>"filename" 2^>^&1 'command', Я знаю, что это связано с написанием текста в имени файла, что в противном случае будет отображаться для меня. В этом случае будет показан весь текст 7z.exe, но записанный в файле. Пока экземпляр 7z.exe не завершит свою работу, в файл ничего не записывается, но файл уже существует, но в то же времяне существует. Когда 7z.exe фактически завершается, файл завершается, и на этот раз он существует для следующей части скрипта.

Теперь я могу понять поведение обработки предложенного сценария ия дополняю его чем-то своим - я пытаюсь реализовать все партии водна партия делает все это скрипт. В упрощенном варианте это так:

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

Короче говоря, я хочу обработать все это максимально эффективным способом. Делать это, решая, сколько процессов может быть запущено одновременно, было бы неплохо, но тогдаs также память, необходимая для каждого процесса, так что сумма всей необходимой памяти для этих процессов выиграетт превышает 8192 МБ. Я получил эту часть работы.

@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 часть - они должны заменитьfor линия и перваяcmd переменная внутри:executeCycle, чтобы заставить его работать, как я собираюсь. Как я могу это сделать?

Другой вопрос, который у меня есть, оtempMem3, Я зарегистрировал всю необходимую память, когда командаcycleCmd3 будет работать. Это зависит от словаря. tempMem3 и cycleCmd3 связаны следующим образом:

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"

Таким образом, 1024m будет использовать 1055, 768m будет использовать 799, и так далее до 1 м, используя 32. Я нене знаю, как перевести это в сценарий.

Любая помощь приветствуется.

Ответы на вопрос(2)

Ваш ответ на вопрос