2012-06-23 3 views
5

Cuda - это потрясающе, и я использую его как сумасшедший, но я не использую ее полный потенциал, потому что у меня проблема с передачей памяти, и мне было интересно, есть ли лучший способ получить переменный объем памяти. В основном я отправляю массив массивов 65535 в Cuda, и Cuda анализирует каждый элемент данных примерно на 20 000 различных способов, и если в моей логике программ есть совпадение, тогда он сохраняет список 30 int в результате. Подумайте о моей логике анализа каждой другой комбинации, а затем посмотрите на общую сумму, и если сумма равна числу, которое я ищу, тогда он сохраняет результаты (что представляет собой список 30 int для каждого анализируемого элемента).Передача большого переменного объема памяти от Cuda

Проблема 65535 (блоки/элементы в массиве данных) * 20000 (общее количество проверенных комбинаций элементов) = 1,310,700,000. Это означает, что мне нужно создать массив такого размера, чтобы иметь дело с тем, что все данные будут иметь положительный результат (что крайне маловероятно, а создание int output[1310700000][30] кажется сумасшедшим для памяти). Я был вынужден сделать его меньше и отправлять меньше блоков для обработки, потому что я не знаю, как Cuda может эффективно писать связанный список или список с динамическим размером (при таком подходе он записывает вывод в память хоста с помощью блока * number_of_different_way_tests).

Есть ли лучший способ сделать это? Может ли Cuda как-то писать в свободную память, которая не является производной от блокады? Когда я тестирую этот процесс на процессоре, менее 10% массива элементов имеют положительное совпадение, поэтому крайне маловероятно, что я буду использовать так много памяти каждый раз, когда отправляю работу на ядро.

p.s. Я смотрю выше, и хотя это именно то, что я делаю, если его запутывает, тогда другой способ думать об этом (не совсем то, что я делаю, но достаточно хорошо, чтобы понять проблему), я отправляю 20 000 массивов (каждый из них содержат 65 535 элементов) и добавление каждого элемента со своим партнером в других массивах, и если общее число равно числу (скажем, 200-210), то я хочу знать числа, которые он добавил, чтобы получить соответствующий результат. Если числа очень широко варьируются, то не все будут совпадать, но, используя мой подход, я вынужден malloc этот огромный объем памяти. Могу ли я получить результаты с меньшим объемом памяти? Мой текущий подход к malloc настолько, насколько я свободен, но я вынужден запускать меньше блоков, которые неэффективны (я хочу запускать как можно больше блоков и потоков, потому что мне нравится, как Cuda организует и запускает блоки) , Есть ли какие-нибудь Cuda или C трюки, которые я могу использовать для этого, или я застрял в mallocing максимальных возможных результатах (и покупке большего количества памяти)?

+0

Как насчет нескольких строк кода? – wallyk

+0

Если положительных совпадений мало, альтернативная процедура, описанная мной в [этом ответе] (http://stackoverflow.com/q/11148860/442006), может быть хорошей. Вы увеличивали бы индекс на 30 каждый раз. –

+0

эй @wallyk Есть ли что-то непонятное, что я могу объяснить больше? или если вы чувствуете, что код нужен, я могу работать над созданием выборки спермы (поскольку моя фактическая кодовая база довольно большая и зависит от других файлов, я чувствовал, что это будет более запутанным, а затем полезным). – Lostsoul

ответ

0

As Per Roger Dahl's great answer: Функциональность, которую вы ищете, называется уплотнением потока.

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

Однако, учитывая более распространенную ситуацию, когда имеется множество результатов, лучшим решением будет выполнение операции уплотнения в виде отдельного шага. Один из способов сделать это - с помощью thrust :: copy_if. См. Этот вопрос для получения дополнительной информации.

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