Багаторядкова командна команда Windows FOR


11

чи знаєте ви, чи є простий спосіб запустити команду FOR у пакетному файлі на декількох потоках? Який сенс мати 4 ядра, якщо я не можу виконувати завдання в 4 паралельних потоках?

Наприклад, якщо я оптимізую PNG за допомогою PNGOUT, я використовую команду

for %i in (*.png) do pngout "%i"

Але це дуже паралельне завдання, в якому підзадачі взагалі не залежать один від одного.

Щоб виконати це в 4 'черги', я б написав щось подібне

for -thread 4 %i in (*.png) do pngout "%i"

Чи потрібно мені написати власний подібний додаток, який міг би це зробити чи є доступне безкоштовне рішення?


перевірити folowing відповідь на використання зовнішнього інструменту: [ stackoverflow.com/a/12041213/365229][1] [1]: stackoverflow.com/a/12041213/365229
Behrouz.M

Відповіді:


13

Я написав пакетний файл, який виконує лише максимальну кількість команд деякий час тому на Stack Overflow: Паралельне виконання оболонок :

@echo off
for /l %%i in (1,1,20) do call :loop %%i
goto :eof

:loop
call :checkinstances
if %INSTANCES% LSS 5 (
    rem just a dummy program that waits instead of doing useful stuff
    rem but suffices for now
    echo Starting processing instance for %1
    start /min wait.exe 5 sec
    goto :eof
)
rem wait a second, can be adjusted with -w (-n 2 because the first ping returns immediately;
rem otherwise just use an address that's unused and -n 1)
echo Waiting for instances to close ...
ping -n 2 ::1 >nul 2>&1
rem jump back to see whether we can spawn a new process now
goto loop
goto :eof

:checkinstances
rem this could probably be done better. But INSTANCES should contain the number of running instances afterwards.
for /f "usebackq" %%t in (`tasklist /fo csv /fi "imagename eq wait.exe"^|find /v /c ""`) do set INSTANCES=%%t
goto :eof

Він породжує максимум чотири нові процеси, які виконуються паралельно і мінімізуються. Час очікування потрібно скоригувати, ймовірно, залежно від того, скільки працює кожен процес і як довго він працює. Можливо, вам також потрібно буде скоригувати ім'я процесу, для якого шукається список завдань, якщо ви робите щось інше.

Однак немає можливості правильно підрахувати процеси, породжені цією партією. Одним із способів було б створити випадкове число на початку партії ( %RANDOM%) та створити помічну партію, яка виконує обробку (або породить програму обробки), але яка може встановити її заголовок вікна параметром:

@echo off
title %1
"%2" "%3"

Це був би простий пакет, який встановлює свій заголовок першому параметру, а потім запускає другий параметр з третім як аргумент. Потім можна фільтрувати у списку завдань, вибравши лише процеси з вказаним заголовком вікна ( tasklist /fi "windowtitle eq ..."). Це повинно працювати досить надійно і запобігати занадто багато хибних позитивних результатів. Пошук cmd.exeбуде поганою ідеєю, якщо у вас все ще запущені деякі екземпляри, оскільки це обмежує ваш набір робочих процесів.

Ви можете використовувати %NUMBER_OF_PROCESSORS%для створення розумного за замовчуванням кількість екземплярів, які потрібно нерестувати.

Ви також можете легко адаптувати це до використання psexecдля віддаленого нерестування процесів (але це не буде дуже життєздатним, оскільки вам доведеться мати права адміністратора на іншій машині, а також вводити пароль у пакеті). Тоді вам доведеться використовувати назви процесів для фільтрації.


це якась серйозна магія чорної партії! Я б хотів, щоб я міг заплатити більше разів!
Аксарідакс

Ні, це досить основні речі, як тільки ви отримаєте повісити його ;-)
Joey

Команда 'wc' недоступна в моєму командному рядку Win10. Що я можу використовувати ще?
PeterCo

1
@PeterCo: find /c /v "".
Джой

1

Пакетні файли призначені для надзвичайно базових сценаріїв і не підтримують будь-якого типу багатопотокової роботи. Вам потрібно буде написати власну утиліту, щоб робити те, що ви хочете досягти.

Крім того, Windows PowerShell може надати більше можливостей для наближення до своєї мети.

Якщо ви просто хочете виконати кілька операцій одночасно, ви можете скористатися командою start для запуску утиліти PNGOUT у новому вікні. Цикл FOR продовжить, не чекаючи, коли кожна операція завершиться.

Змінена лінія виглядатиме так:

for %i in (*.png) do start pngout "%i"

Однак зауважте, що це дозволить одночасно запустити PNGOUT для ВСІХ файлів у каталозі, що, швидше за все, не бажано.


Це наївний підхід, і, як ви згадуєте, це, мабуть, не бажано. Ви хочете запустити стільки процесів, скільки у вас є ядер. Якщо у вас є 4 ядра та 1000 файлів, ви дійсно хочете обробляти лише 4 одночасно, поки всі 1000 не будуть оброблені. Якщо ви спробуєте обробити всі 1000 одночасно на 4 ядрах, ваш комп'ютер сповільниться до марного сканування.
Адісак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.