我有一個8核心CPU與8GB內存,我創建一個批處理文件來自動化7-zip CLI在耗盡大多數參數和變量來壓縮相同最終目標是找到最強大的參數和變量組合,從而實現最小的檔案大小。爲並行和順序工作批處理和啓動命令
這本質上是非常耗時的,特別是當要處理的文件集是千兆字節時。我需要一種不僅自動化而且加速整個過程的方法。
7-ZIP的作品有不同的壓縮算法,有些是單線程只,還有一些是多線程的,一些並不需要的內存量多,有的需要它的大量的,甚至可能超過8GB屏障。我已經成功地創建了一個自動化的批處理序列,它排除了需要超過8GB內存的組合。
我已經分幾批分解了不同的壓縮算法,以簡化整個過程。例如,在PPMd中作爲7z壓縮文件壓縮使用1線程和高達1024MB。這是我目前批:
@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
,s
,o
和mem
是參數,什麼是後他們每個人都是其中7z.exe將與變量。在這種情況下,x
和s
是無關緊要的,它們表示存檔的壓縮強度和固體塊大小。
該批處理可以正常工作,但一次只能運行7z.exe的一個實例,現在我正在尋找一種方法使它能夠並行運行更多的7z.exe實例,但不會超過8GB RAM或8個線程,以先到者爲準,然後繼續執行序列中的下一個。
我該如何改進?我有一些想法,但我不知道如何讓他們在一個批次中工作。我正在考慮另外兩個變量,它們不會與7z進程交互,但會控制下一個7z實例何時開始。一個變量會跟蹤當前有多少線程正在使用,另一個會跟蹤正在使用多少內存。這可以工作嗎?
編輯: 對不起,我需要補充資料,我是新來這篇文章風格。回答這個問題 - https://stackoverflow.com/a/19481253/2896127 - 我提到了8個批次都創建了,而7z.PPMd批次就是其中之一。也許列出所有的批次以及7z如何處理這些參數將會對整個問題提供更好的見解。我將從簡單的開始:
- 7z.PPMd - 1充分利用線程和字典依賴每個實例的32m-1055m內存使用量。
- 7z.BZip2 - 每個實例8個完全使用的線程和固定的109m內存使用量。
- zip.Bzip2 - 8個部分使用的線程和每個實例固定的336m內存使用量。
- zip.Deflate - 每個實例8個部分使用的線程和固定的260m內存使用量。
- zip.PPMd - 每個實例8個部分使用的線程和字典依賴的280m-2320m內存使用量。
我的意思是部分利用的線程是,雖然我分配了8個線程供每個7.exe實例使用,但算法可以隨機地執行可變CPU使用率,超出我的控制範圍,不可預知,但限制在那裏設置 - 不超過8個線程。在8個充分利用線程的情況下,這意味着我的8芯CPU上,每個實例是利用CPU的100%。
最複雜的 - 7z.LZMA,7z.LZMA2,zip.LZMA - 將需要詳細地解釋,但我在很短的時間,現在運行。我會回來的,每當我有更多的時間來編輯LZMA部分。
再次感謝。
編輯:添加在LZMA部分。
7z.LZMA - 每個實例是正螺紋,範圍從1到2:
- 1充分利用螺紋,字典依賴性,64K到512M:
- 64k的字典用途32M內存
- ...
- 512米字典使用5407米內存
- 不含uded範圍:768米到1024米(以上8192米存儲器的可用的極限)
- 2部分利用線程,字典依賴性,64K到512M:
- 64k的字典使用38米存儲器
- ...
- 512米字典使用5413米存儲器
- 排除範圍:768米到1024米(以上8192米存儲器的可用的極限)
- 1充分利用螺紋,字典依賴性,64K到512M:
7z.LZMA2 - 每個實例正螺紋,範圍從1至8:
- 1充分利用螺紋,字典依賴性,64K到512M:
- 64k的字典使用32M內存
- ...
- 512米字典使用5407米存儲器
- 排除範圍:768米到1024米(以上8192米存儲器的可用的極限)
- 2或3部分使用的線程,字典依賴性,64K到512M:
- 64k的字典使用38米存儲器
- ...
- 512米字典使用5413米存儲器
- 排除範圍:768米到1024米(以上8192米存儲器的可用的極限)
- 4或5部分使用的線程,字典依賴性,64K爲256M:
- 64K字典使用51米內存
- ...
- 256米字典使用5677米內存
- 排除[R安格:384米到1024米(以上8192米存儲器的可用的極限)
- 6或7部分使用的線程,字典依賴性,64K到192米:
- 64k的字典使用62米存儲器
- ...
- 192米字典使用6965米存儲器
- 排除範圍:256米到1024米(以上8192米存儲器的可用的極限)
- 8部分使用的線程,字典依賴性,64K至1.28:
- 64k的字典使用72米存儲器
- ...
- 128米字典使用6717米存儲器
- 排除範圍:192米到1024米(上述8192米存儲器的可用的極限)
- 1充分利用螺紋,字典依賴性,64K到512M:
zip.LZMA - 每個實例是正螺紋,範圍從1至8:
- 1充分利用螺紋,字典依賴性,64K到512M:
- 64k的字典使用3米存儲器
- ...
- 512米字典使用5378米存儲器
- 排除範圍:768米到1024m(超過8192m內存的限制)
- 2或3個部分使用的線程,字典相關,64k t o 512m:
- 64k字典使用9m內存
- ...
- 512米字典使用5384米存儲器
- 排除範圍:768米到1024米(以上8192米存儲器的可用的極限)
- 4或5部分使用的線程,字典依賴性,64K爲256M:
- 64K字典使用82米內存
- ...
- 256米字典使用5456米內存
- 排除[R安格:384米到1024米(以上8192米存儲器的可用的極限)
- 6或7部分使用的線程,字典依賴性,64K爲256M:
- 64k的字典使用123米存儲器
- ...
- 256米字典使用8184米(非常接近極限雖然,我可以考慮不包括它)
- 排除範圍:384米到1024米(以上8192米存儲器的可用的極限)
- 8個部分使用的線程,字典依賴性,64K至1.28:
- 64k的字典使用164米存儲器
- ...
- 128米字典使用5536米存儲器
- 排除範圍:192米到1024米(以上8192米存儲器的可用的極限)
- 1充分利用螺紋,字典依賴性,64K到512M:
我想了解這些命令的行爲與nul在他們的行爲。我不太明白那部分發生了什麼,這些符號意味着什麼。
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%*
EDIT 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
總之,我想以最有效的方式處理所有這些。通過確定多少進程可以同時運行在做這將是一個辦法,但再有就是還爲每個進程所需要的內存,使所有需要存儲的這些進程的總和不會超過8192 MB。我有這部分工作。
@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
線和:executeCycle
裏面的第一個cmd
變量,讓它工作,我打算。我怎麼做?
其他的問題,我有大約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"
所以1024米將使用1055,768米將使用32使用799,依此類推,直到1米我不知道該如何翻譯成劇本。
任何幫助表示讚賞。
爲什麼你這樣做?如果您想要更好/更高效和性能平衡的算法壓縮,爲什麼不使用7ZIP「MAX」標準配置文件,請自行設置字典大小和其他參數? – ElektroStudios
傳統觀點認爲,源文件的字節組成也會影響壓縮大小 - 因此,對於一組測試文件而言,可能最佳的設置對於另一組源文件可能不是最理想的。 – foxidrive