#parallel-processing #cuda #opencl #gpgpu
#параллельная обработка #cuda #opencl #gpgpu
Вопрос:
У нас есть миллионы небольших файлов, которые должны обрабатываться некоторыми программами.
Точная программа не важно и варьируется также с точной задачей. Тем не менее, это программы на C меньшего размера, и у нас есть исходный код, но они не являются внутренне распараллеливаемыми.
Обработка одного небольшого файла занимает около 15 секунд при использовании одного среднего ядра процессора (Intel серии i7). И для этого требуется около 200 МБ оперативной памяти во время работы программы.
Мы хотим распараллелить это на графических процессорах и запустить на каждом графическом ядре (например, Cuda-core) по одному экземпляру программы. Таким образом, если GPU имеет 3000 CUDA-ядер, то мы хотели бы запустить 3000 экземпляров параллельно. Если возможно, мы хотим использовать общую фреймворковую обработку, такую как OpenCL (а не Cuda, но если Cuda необходима для этого случая, это будет приемлемо).
Прямо сейчас мы пытаемся оценить, будет ли это возможно (у нас пока нет большого опыта в программировании на GPGPU). Основная проблема, которую мы представляем, — это память. Если мы запустим, например, 3000 экземпляров параллельно, и для каждого экземпляра потребуется 200 МБ видеопамяти, то нам потребуется 600 ГБ памяти.
Графические карты, которые мы в первую очередь имеем в виду, — это высококачественные карты Geforce, которые обычно имеют от 8 до 11 ГБ памяти. И у нас есть рабочие станции с графическим процессором с 4 картами на корпус / материнскую плату, которые мы хотели бы использовать для этого сначала (но позже, возможно, также на других системах с графическим процессором, поэтому мы предпочитаем общую платформу, такую как OpenCL).
Какие существуют способы решения этой проблемы?
Комментарии:
1. Не станет ли пропускная способность / задержка памяти узким местом всего после 3-5 экземпляров? Вам понадобится псевдо-malloc внутри ядра, такой, чтобы он возвращал только «объединенную» группу адресов для всех запрашивающих потоков (на тот момент) из уже глобального буфера с cuda-malloced. Даже это может не сработать, если экземпляры не упорядочены таким образом, чтобы делать меньше ветвлений между собой. Лучший способ — распараллелить ваш алгоритм, запуская только достаточное количество экземпляров для перекрытия передачи данных, чтения файлов и вычислений.
2. Графические процессоры не предлагают ничего похожего на тот уровень детализации, который, по вашему мнению, вам нужен, поэтому нет, вы не можете этого сделать.
3. @huseyintugrulbuyukisik, спасибо за ваш комментарий. Я не могу ответить на ваш вопрос, но другие могут.
4. @talonmies: Если вы имеете в виду гранулярность механизма, который выполняет распараллеливание так, как мы хотим, такой код мы можем написать сами, если не существует модуля / пакета, который может нас здесь поддержать. Вопрос в том, выполнимо ли это, т. Е. разрешима ли проблема с памятью.
5. Вы не можете запустить полную программу на одном ядре GPU. Ближайшая вещь, которая полностью поддерживает один или несколько потоков выполнения, — это CUDA GPU SM, а не core.
Ответ №1:
Точная программа не важна
Это принятие желаемого за действительное. Проблема, которую вы пытаетесь решить, чрезвычайно важна; если бы это было так же просто, как перекомпиляция кода C в двоичные файлы шейдеров GPU, практически все программное обеспечение делало бы это для бесплатного повышения скорости.
Как правило, вы не сможете преобразовать всю программу C 1: 1 в ядро GPU, и даже если вам удастся это сделать, она будет работать крайне плохо. Вам действительно нужно будет приложить усилия по переосмыслению вашей проблемы с точки зрения операций типа SIMD, чтобы добиться чего-либо с помощью GPU.
В частности, у вас, похоже, создается впечатление, что каждое «ядро» GPU независимо. Это не тот случай, группы из них работают синхронно, поэтому, если ваш код перегружен ветвлениями, у вас будет очень плохое использование. Они также совместно используют шину памяти, поэтому, если каждый поток обращается к некоррелированным областям памяти, это значительно замедлит выполнение, и вы не сможете достаточно быстро передавать данные в ALU / FPU.
Память также является проблемой, но не только из-за общего объема видеопамяти, как вы указали, но и потому, что локальные переменные используют «частную» память, которая на самом деле является регистрами и которая является очень ограниченным ресурсом (измеряется в лучшем случае в килобайтах).
Я рекомендую ознакомиться с руководствами по оптимизации OpenCL, опубликованными всеми основными поставщиками графических процессоров. Это даст вам хорошее представление о том, какой код работает хорошо, а какой нет, и какие соображения следует учитывать при принятии решения, какой код выгружать на GPU и как.
Комментарии:
1. Большое спасибо за ваш ответ, это было очень полезно. Я исправил свой вопрос выше в соответствии с вашей информацией (т. е. вычеркнул утверждение о том, что программа не важна). Что касается вашего заявления «если бы это было как … практически все программы будут делать это для бесплатного повышения скорости «, возможно, здесь следует добавить, что все программы, которые выполняют большое количество независимых задач, могли бы это делать, но это не относится к большинству программ.
2. @Jadzia Многие части программного обеспечения могут быть адаптированы для ускорения GPU. Однако результирующий код обычно не похож на исходный, и во многих случаях алгоритмы должны быть радикально переработаны. Итак, я не уверен в вашем утверждении «большинство программ»; возможно, большинство программ в целом, но, вероятно, не большинство программ, привязанных к процессору. (Вы не предоставили достаточно подробностей о том, что вы делаете, чтобы я мог сказать, применимо ли это к вашему программному обеспечению. Даже некоторые традиционно последовательные рабочие нагрузки, такие как сжатие, часто могут выиграть от ускорения GPU, если хорошенько подумать.)