2015-06-18 2 views
3

фона:Возможно ли выполнить несколько экземпляров программы CUDA на многопроцессорной машине?

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

Вопрос:

Я бег моего кода на машине Linux с 4 GPU и хотел бы использовать все 4 графические процессоры, запустив 4 экземпляров моей программы (1 на GPU). Возможно ли, чтобы программа выбрала графический процессор, который не используется другим приложением CUDA для запуска? Я не хочу жестко кодировать все, что могло бы вызвать проблемы в будущем, когда программа запускается на другом оборудовании с большим или меньшим количеством графических процессоров.

+0

http://www.nvidia.com/docs/IO/116711/sc11-multi-gpu.pdf - это лучший хит google ваш вопрос. Решает ли ваша проблема? – Yakk

+0

Не совсем, что адреса, использующие несколько графических процессоров в одном приложении CUDA, я прошу о запуске нескольких программ CUDA одновременно на нескольких графических процессорах (но еще 1 GPU на один экземпляр). Это потребует значительного переписывания для моего кода для обработки нескольких партий в одном экземпляре. – aseal

+0

Вы делаете асинхронные звонки? Разделите группу на подгруппы N (где N - количество графических процессоров), отправьте каждую подгруппу на другой графический процессор, а затем соберете их снова? – Yakk

ответ

5

environment variableCUDA_VISIBLE_DEVICES является вашим другом.

Я предполагаю, что у вас так много терминалов, как у вас есть графические процессоры. Допустим, ваше приложение называется myexe

Затем в одном терминале, вы могли бы сделать:

CUDA_VISIBLE_DEVICES="0" ./myexe 

В следующем терминале:

CUDA_VISIBLE_DEVICES="1" ./myexe 

и так далее.

Тогда первый экземпляр будет запущен на первом графическом процессоре, указанном CUDA. Второй экземпляр будет работать на втором графическом процессоре (только) и так далее.

Предполагая Баш, и для данного сеанса терминала, вы можете сделать это «постоянный», экспортируя переменную:

export CUDA_VISIBLE_DEVICES="2" 

после этого, все приложения CUDA работать в этой сессии будет наблюдать лишь третий перечисляемого GPU (перечисление начинается с 0), и они будут наблюдать, что GPU , как если бы это было устройство 0 в их сеансе.

Это означает, что вам не нужно вносить какие-либо изменения в приложение для этого метода, при условии, ваше приложение использует GPU по умолчанию или GPU 0.

Вы также можете расширить это сделать несколько графических процессоров доступны, например, :

export CUDA_VISIBLE_DEVICES="2,4" 

означает графические процессоры, которые обычно перечислять как 2 и 4 теперь будет только графические процессоры «видны» в этой сессии, и они будут перечислять в 0 и 1.

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

  1. нам нужно определение «в использовании»
  2. ГПУ, использовавшееся в определенный момент времени не может быть в использовании сразу же после того, как что
  3. Самое главное, что графический процессор, который не используется, может быть «использован» асинхронно, что означает, что вы подвергаетесь условиям гонки.

Таким образом, лучший совет (IMO) - это управлять графическими процессорами явно. В противном случае вам понадобится какая-то форма планировщика заданий (вне сферы действия этого вопроса, IMO), чтобы иметь возможность запрашивать неиспользуемые графические процессоры и «резервировать» их до того, как другое приложение попытается сделать это упорядоченным образом.

+0

Интересно - вам известно, поддерживает ли OCL аналогичную функцию? –

+0

Похоже, что [AMD имеет нечто подобное] (http://stackoverflow.com/questions/14380927/restrict-number-of-gpus-for-amd-opencl). Я не знаю, существует ли общий метод для устройств OpenCL. –

+1

Я тестировал программу OpenCL на графических процессорах NVIDIA, и мне удалось выбрать графический процессор, который будет выполняться при использовании 'CUDA_VISIBLE_DEVICES', поэтому кажется, что эта переменная среды работает и для OpenCL (на графических процессорах NVIDIA), но я не знайте, что это указано где угодно. Это просто мое наблюдение. –

0

Существует лучший (более автоматический) способ, который мы используем в PIConGPU, который запускается на огромных (и разных) кластерах. См реализации здесь: https://github.com/ComputationalRadiationPhysics/picongpu/blob/909b55ee24a7dcfae8824a22b25c5aef6bd098de/src/libPMacc/include/Environment.hpp#L169

В основном: Call cudaGetDeviceCount, чтобы получить число графических процессоров, итерацию над ними и называют cudaSetDevice установить это в качестве текущего устройства и проверьте, если это работало. Эта проверка может включать тестовое создание потока из-за некоторой ошибки в CUDA, которая сделала setDevice успешной, но все последующие вызовы не удались, поскольку устройство действительно использовалось. Примечание. Возможно, вам придется установить GPU в эксклюзивный режим, чтобы GPU мог использовать только один процесс. Если у вас недостаточно данных одной «партии», вам может потребоваться обратное: несколько процессов отправляют работу на один графический процессор. Так что настройтесь в соответствии с вашими потребностями.

Другие идеи: Запустите MPI-приложение с таким же количеством процессов за ранг, как и графические процессоры, и используйте тот же номер устройства, что и номер локального ранга. Это также помогло бы в таких приложениях, как ваши, у которых есть разные наборы данных для распространения. Таким образом, вы можете, например, имеют MPI ранг 0 длина процесса1-данные и MPI ранг 1 длина процесса2-данные и т. д.

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