2008-10-29 5 views
4

У меня есть этот большой проект на C++, который мне нужно построить на платформе, которая не имеет параллельного make (например, make -j на Linux). Сервер имеет 6 процессоров, и я хочу сделать параллельную сборку вручную.Каков наилучший способ выполнения задач параллельно в Ksh и Perl?

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

сделать -f Makefile obj1.o

сделать -f Makefile obj2.o

сделать -f Makefile obj3.o ...

Как выполнить эти задачи параллельно с не более чем 6 задачами, выполняемыми одновременно с использованием Ksh и Perl? (Java или Python недоступны :-()

+0

Существует ли зависимости между задачами? – alex 2008-10-29 20:45:45

+0

какая платформа у вас работает? – warren 2008-10-29 20:50:18

ответ

5

В Perl вы должны посмотреть Parallel::ForkManager. Вы могли бы сделать что-то вроде этого:

my @make_obj = qw(
    obj1.o 
    obj2.o 
    obj3.o 
    ... 
); 

my $fm = $pm = new Parallel::ForkManager(6); 
foreach my $obj (@make_obj) { 
    $fm->start and next; 
    system("make -f Makefile $make_obj"); 
    $fm->finish(); 
} 
-1

Если ОС должным образом обрабатывает межпроцессорную связь и планирование, вы должны просто убрать все составляющие в фоновые процессы, если нет взаимозависимостей.

Если все они независимы, я бы выдаю ряд команд, как это:

make -f Makefile obj1.o & 
make -f Makefile obj2.o & 
... 
make -f Makefile objn.o & 

с зависимостями, строка их с двойным амперсандом (&&) так, что зависимый элемент не начинается до тех пор, его «родитель» завершен.

Я понимаю, что это не совсем то решение, которое вы просили, но так я бы напал на проблему :)

4

Альтернативой forking является запуск каждого make в своей собственной нити.

use threads; 

my $max_threads = 5; 

my @targets = qw(obj1.o obj2.o obj3.o ...); 
while(@targets) { 
    my $num_threads = threads->list(threads::running); 
    if($num_threads < $max_threads) { 
     my $target = shift @targets; 
     threads->create(sub { return system "make $target" }); 
    } 
} 

Я, к сожалению, вручную размахивает вокруг двух бит. Во-первых, заставляя петлю ждать, пока поток не закончится. Я считаю, что это достигается с помощью threads :: shared's cond_wait() и переменной семафора.

Второе получает возвращаемое значение от make, поэтому вы знаете, что что-то не удалось, и остановить сборку. Для этого вам нужно будет присоединиться() к каждому потоку, чтобы получить результат системы(), код завершения процесса.

Извините за поспешный ответ. Надеемся, что сообщество заполнит все остальное.