2013-07-30 3 views
1

Мне нужно предварительно выполнить несколько сверток с малыми матрицами и ядрами, и я надеялся, что использование многих процессоров GPU позволит мне как можно быстрее.Наилучший подход для свертки множества малых матриц с использованием CUDA

Проблема заключается в следующем: у меня много матриц (от 1000 до 10000) или относительно небольших размеров (~ 15x15 до 1x1 - как в скалярном) и определенное количество сверточных масок (от 20 до 1) , Мне нужна свертка всех матриц с каждой сверткой маской примера:

A; %5,000 matrices of size 10x10, A(i) = a 10x10 matrix 
B; 10 matrices of size 5x5, B(k) = a 5x5 matrix 
res(j)=conv(A,B(1)); %res(j) is the result of convolving all 5,000 
%matrices in A by the j'th kernel B(j) 

целью является вычислительным Рез (1), ..., Рез (10) как можно быстрее

Я хотел бы услышать предложения о том, как реализовать наиболее эффективный алгоритм. Свертка на основе FFT, вероятно, будет слишком медленной.

Каждая реализация, которую я видел до сих пор, предназначена для 2-й свертки, предназначенной для свертки двух больших матриц, в то время как мне нужно свертывать множество маленьких матриц.

Я знаю очень мало о программировании CUDA прямо сейчас, но я в процессе обучения.

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

Спасибо!

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

+0

Эта проблема не идеальна для графического процессора из-за небольшого размера матриц. Из опыта внедрения пакетных решателей для небольших матриц на GPU я бы рекомендовал использовать один блок потока для каждой матрицы для больших матриц и один поток на матрицу для действительно маленьких матриц. Вам нужно было бы найти точку переключения между двумя подходами экспериментально, это, вероятно, между размером 7 и размером 10. – njuffa

+0

Спасибо. Я думал, что почти никто не нуждается в этом, но я рад видеть, что, по крайней мере, кто-то осуществил это. Вы случайно не знаете, где я могу найти очень быструю реализацию CUDA для такой проблемы? Я смотрел и ничего не мог найти, но если там будет очень хорошая реализация, было бы здорово. Я не ожидаю, что мой код будет таким же быстрым, как у более опытных программистов CUDA (и сейчас я почти не знаю этой темы, поэтому кто-то был бы более опытным, чем я ...) – user1999728

+0

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

ответ

2

Я не претендую на то, чтобы дать окончательный ответ на ваш вопрос, но я бы просто хотел указать из нескольких вещей:

  1. Как вы упомянули, первой возможностью было бы использовать подход БПФ. Проблема в этой строке заключается в том, что (исправьте меня, если я ошибаюсь) библиотека cuFFT в первую очередь предназначена для работы с большими матрицами, поэтому для плодотворного использования этого подхода будут разработаны алгоритмы FFT, эффективные для небольших матриц. Я просто хочу указать, что есть некоторые алгоритмы такого рода, см., Например, статью: Small Discrete Fourier Transforms on GPUs. У меня нет прямого опыта работы с БПФ CUDA на небольших матрицах указанного типа, но, возможно, это может быть интересно для вас, так как матрицы масок находятся в малом количестве (10), и поэтому вы можете «перерабатывать» свои БПФ для большое количество сверток (5000).
  2. Если вы решили не использовать подход FFT, то, если у вас есть архитектура графического процессора с вычислительной способностью >=3.5, то динамический параллелизм может быть хорошим кандидатом для вычисления сверток. Если рассматривать оценку каждого свертка матричного элемента как интерполяция, то вы будете иметь интерполяционные проблемы размера 15x15 и динамического параллелизма может помочь, увидеть сообщение: Benefit of splitting a big CUDA kernel and using dynamic parallelism
0

Один подход заключается в использовании ArrayFire-х GFOR loop, который я работа над.

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

array x = randu(5);  // the input 
array y = randu(m,5); // the output 
array f = constant(1,3); // the kernel 
gfor (array k, 0, m-1) { 
    y(span,k) = convolve(x,f); 
} 

Удачи!

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

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