2012-05-14 4 views
2

Я новичок в CUDA и пытаюсь выполнить некоторую обработку большого количества массивов. Каждый массив представляет собой массив из примерно 1000 символов (а не строку, просто сохраненную как символы), и их может быть до 1 миллиона из них, поэтому около 1 gb данных, которые будут переданы. Эти данные уже загружены в память, и у меня есть указатель на каждый массив, но я не думаю, что могу полагаться на все последовательные данные в памяти, поэтому я не могу просто передать все это одним вызовом.Как лучше перенести большое количество массивов символов на GPU?

В настоящее время я сделал первый шаг с ним с помощью тяги и основал свое решение на this message ... Я создал структуру со статическим вызовом, которая выделяет всю память, а затем каждый отдельный конструктор копирует этот массив и У меня есть вызов преобразования, который принимает структуру с указателем на массив устройств.

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

this question (вопрос в основном не связан, но я думаю, что пользователь пытается сделать что-то подобное). Talonmies предлагает, чтобы они пытались использовать zip-итератор, но я не вижу, как это поможет передать большое количество массивы.

Я также только что узнал о cudaMemcpy2DToArray и cudaMemcpy2D при написании этого вопроса, так что, возможно, это ответ, но я не вижу сразу, как они будут работать, поскольку ни один из них не считает указатели указателями в качестве входных данных ...

Любые предложения приветствуются ...

+1

Если вам не нужна вся эта память в вашем ядре немедленно.Вы можете скопировать только часть его с синхронизированной операцией копирования и другой частью в асинхронной копии. Можете ли вы применить алгоритм для этого механизма копирования? – geek

+0

Ум, я не уверен, алгоритм работает так, что каждый массив может обрабатываться независимо, поэтому я пытаюсь распараллелить его на графическом процессоре. Я думаю, это зависит от того, какое максимальное количество потоков доступно на графическом процессоре, а потом да, я могу просто перенести это множество массивов, а затем скопировать других, пока они обрабатываются. – JSoet

+0

Я решил решить, что лучшим методом было просто не использовать толчок вообще и просто переустановить память (что означает, что я должен сделать ее копию) в смежный массив, который можно перенести сразу. Спасибо тем, кто ответил. – JSoet

ответ

1

Один из способов сделать это, как marina.k предложил, дозирование ваших переводов только по мере необходимости. Поскольку вы сказали, что каждый массив содержит только около 1000 символов, вы можете назначить каждому символу поток (так как на Fermi мы можем выделить 1024 потока на блок) и каждый массив обрабатывается одним блоком. В этом случае вы можете перенести все массивы на один «раунд» за один вызов - можете ли вы использовать стиль FORTRAN, где вы делаете один гигантский массив и получать 5-й элемент «третьего» массива символов 1000, который вы бы перейти:

third_array[5] = big_array[5 + 2*1000] 

так, что первый 1000 голец массив составляет первые 1000 элементов big_array, второй 1000 гольца массива составляет вторые 1000 элементов big_array и т.д.? В этом случае ваши символы будут непрерывными в памяти, и вы можете перенести набор, который вы собираетесь обрабатывать, с одним запуском ядра только в одной memcpy. Затем, как только вы запустите одно ядро, вы пополняете big_array на стороне процессора и скопируете его асинхронно на GPU.

Внутри каждого ядра вы можете просто обрабатывать каждый массив в пределах 1 блока, чтобы блок N обрабатывал (N-1) -thousandth элемент до N-тысячной d_big_array (где вы копировали все эти символы).

+0

Хм, я думаю, что, возможно, я был недостаточно ясен, но обработка должна выполняться на основе каждого массива, поэтому я думаю, что для каждого массива требуется 1 поток. Что касается 1 гигантского массива, да, в идеале я бы это сделал, проблема в том, что эти массивы уже загружены в память, когда я делаю эту обработку, и они не загружаются так ... И я действительно не хочу дублировать их, так как это около 1 ГБ памяти ... но я думаю, похоже, что мне, возможно, придется изменить способ загрузки изначально, чтобы они загружались как один большой массив. – JSoet

1

Вы пытались прикрепить память? Это может обеспечить значительное ускорение некоторых конфигураций оборудования.

1

взять попробовать из асинхронном, вы можете назначить ту же работу в разных потоках, каждый технологический поток небольшая часть даты, сделать Tranfer и вычисление одновременно
здесь код
cudaMemcpyAsync (inputDevPtr + я * размер , hostPtr + i * размер, размер, cudaMemcpyHostToDevice, поток [i]); MyKernel < < < 100, 512, 0, stream [i] >>> (outputDevPtr + i * size, inputDevPtr + i * размер, размер); cudaMemcpyAsync (hostPtr + i * size, outputDevPtr + i * размер, размер, cudaMemcpyDeviceToHost, поток [i]);

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

  • Нет связанных вопросов^_^