2015-02-10 2 views
0

У меня есть программа на C++, которая порождает процессы. Пользователь сообщает мне, сколько ядер мы должны работать, и сколько задач они хотели бы запустить.Установка ограничения на количество процессов, которые может вызвать моя программа

Скажите, что пользователь говорит мне, что у них есть 8 ядер для работы, и им нужно выполнить 20 наших задач. Затем я запускаю 8 задач изначально, и по мере того как каждый из них заканчивается, я создаю новую задачу, пока мы не закончим 20 задач.

Моя программа работает с Windows (MSVC 11) и Linux (GCC 4.8), поэтому реализации различаются для этих платформ, но в целом я использую семафоры для отслеживания порожденных процессов.

Мой вопрос: какой разумный способ ограничить количество ядер, которые может использовать пользователь? Я хотел бы сделать ошибку в начале программы, если пользователь сообщает нам о некотором количестве ядер, с которыми невозможно работать. Но я не уверен, как получить конкретное число, поскольку оно зависит от машины пользователя и платформы.

Например, я знаю, что для Windows, я использую WaitForMultipleObjects() и поэтому я ограничен MAXIMUM_WAIT_OBJECTS = 64 процессов, я могу ждать (см here). Но есть ли что-то подобное для Linux? Или даже другие «gotchas», подобные этому в Windows?

Я думаю, что я ищу некоторые стандартные рекомендации по настройке такого предела.

Спасибо.

+1

[This] (http://stackoverflow.com/questions/150355/programmatically-find-the-number-of-cores-on-a-machine) может быть полезным. – lcs

+0

@cocarin: спасибо, это очень полезно для расчета количества доступных сердечников. Тем не менее, я не уверен, что могу просто взять количество ядер в качестве предела ... например, если у пользователя есть 128 ядер на своей Windows-машине, они все равно не смогут использовать их все из-за ограничения из 64 процессов, которые мы можем ждать. –

ответ

0

WaitForMultipleObjects приятно, но это не единственный способ сделать что-то. Существуют и другие способы ожидания нескольких потоков или процессов. Например, вы можете обернуть задачу в поток, который выполняет задачу, а затем помещает результат (или просто уведомление) в очередь и отключает обычное событие ручного сброса. Процесс нереста ждет этого события ручного сброса и когда он отключается, опустошает очередь. Таким образом, вы никогда не будете ждать более одного события, и вы можете иметь неограниченное количество одновременных задач (в соответствии с аппаратными ограничениями, конечно).

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

В зависимости от того, что именно делает ваше приложение, вы также можете его перестроить так, чтобы вы создали N потоков (N - количество используемых ядер), и каждый поток удаляет задачи по очереди из общей очереди. Это было бы примерно так:

QueueOfTasks // at global scope 

// each thread proc 
while (Queue of tasks is not empty) 
{ 
    Dequeue task 
    Execute task 
    Do whatever post-task processing is necessary 
} 

Там вам не нужны никакие ручки ожидания. У вас есть N постоянных потоков, которые читаются из общей очереди. Никакой оркестровки не требуется.

Мне особенно нравится это последнее решение, потому что оно связано с гораздо менее специфичным для платформы кодом.

Смежные вопросы