CUFFT

218 views
Skip to first unread message

Алексей Вахтин

unread,
Aug 13, 2011, 3:30:57 PM8/13/11
to CUDA.CS.MSU.SU
Кто-нибудь использовал библиотеку CUFFT? Где можно найти примеры?
Интересуют как классический CUDA C, так и .Net. Мне не понятно, зачем
нужен параметр batch? nx, как я понимаю, число элементов в массиве.

Dmitry N. Mikushin

unread,
Aug 13, 2011, 3:46:41 PM8/13/11
to cudac...@googlegroups.com
Примеры можно найти в CUFFT_Library.pdf - документации, идущей с CUDA Toolkit.

CUFFT никак не связан с .NET, но в C# Вы можете импортировать всё что
угодно с помощью dllimport, по кр. мере в 2.0 так было.

Batch - это количество рядов. Нарпример, если Вам нужно сделать прямое
преобразование над несколькими одномерными рядами одинаковой длины. В
этом случае, их можно либо преобразовывать по отдельности, либо можно
расположить их один за другим и обработать за один вызов cufft, указав
batch=<количество рядов>. Второй способ может дать бОльшую
производительность. Вообще cufft немного похож на fftw. В терминах
fftw batch - это many.

- Д.

13 августа 2011 г. 23:30 пользователь Алексей Вахтин
<alva...@gmail.com> написал:


> Кто-нибудь использовал библиотеку CUFFT? Где можно найти примеры?
> Интересуют как классический CUDA C, так и .Net. Мне не понятно, зачем
> нужен параметр batch? nx, как я понимаю, число элементов в массиве.
>

> --
> Вы получили это сообщение, поскольку подписаны на группу CUDA.CS.MSU.SU.
>
> Чтобы добавлять сообщения в эту группу, отправьте письмо по адресу cudac...@googlegroups.com.
> Чтобы отменить подписку на эту группу, отправьте сообщение по адресу cudacsmsusu...@googlegroups.com.
> О дополнительных функциях можно узнать в группе по адресу http://groups.google.com/group/cudacsmsusu?hl=ru.
>
>

Алексей Вахтин

unread,
Aug 14, 2011, 1:52:43 AM8/14/11
to cudac...@googlegroups.com

CUFFT никак не связан с .NET, но в C# Вы можете импортировать всё что
угодно с помощью dllimport, по кр. мере в 2.0 так было.

Batch - это количество рядов. Нарпример, если Вам нужно сделать прямое
преобразование над несколькими одномерными рядами одинаковой длины. В
этом случае, их можно либо преобразовывать по отдельности, либо можно
расположить их один за другим и обработать за один вызов cufft, указав
batch=<количество рядов>. Второй способ может дать бОльшую
производительность. Вообще cufft немного похож на fftw. В терминах
fftw batch - это many.

Большое спасибо. CUFFT реализован в CUDA .Net в виде классов CUFFT и CUFTDriver, но запустить его пока что не получилось. В документации по CUDA .Net очень мало информации. Спасибо за подсказку про dllimport, попробую пойти другим путем.

Vladislav Galas

unread,
Aug 14, 2011, 12:03:44 PM8/14/11
to cudac...@googlegroups.com
Встраивал вычислительное ядро (трёхмерная свёрка + доп. обвеска) в программу на С++.
Если есть конкретные вопросы, то спрашивайте :)


13 августа 2011 г. 23:30 пользователь Алексей Вахтин <alva...@gmail.com> написал:
Кто-нибудь использовал библиотеку CUFFT? Где можно найти примеры?

Алексей Вахтин

unread,
Aug 16, 2011, 7:13:50 AM8/16/11
to CUDA.CS.MSU.SU
Что-то я не совсем пойму как работает CUFFT.

Вот мой код:

void cufwtExec(double* &data, int N)
{
cufftHandle plan;
cufftDoubleComplex *out_data;
cufftDoubleReal *in_data;

cutilSafeCall(cudaMalloc((void**)&in_data, sizeof(double) * N));
cutilSafeCall(cudaMemcpy(in_data, data, sizeof(double) * N,
cudaMemcpyHostToDevice));

cutilSafeCall(cudaMalloc((void**)&out_data, sizeof(cufftComplex) *
N));

cufwtCheckError(cufftPlan1d(&plan, N, CUFFT_D2Z, 1));

cufwtCheckError(cufftExecD2Z(plan, in_data, out_data));

cufftDoubleComplex *res = new cufftDoubleComplex[N];
cutilSafeCall(cudaMemcpy(res, out_data, sizeof(cufftComplex) * N,
cudaMemcpyDeviceToHost));
for (int I = 0; I < N; I++)
{
data[I] = res[I].x;
};
delete[] res;

cufwtCheckError(cufftDestroy(plan));

cutilSafeCall(cudaFree(in_data));
cutilSafeCall(cudaFree(out_data));
}

Задаю дельтафункцию: 192 элемента нулевые, на 50-м месте - единица. В
результате получаю первые 96 элементов немного похожи на реальную
часть фурье, но, мне кажется, не совсем точное, а остальные 96
элементов - вообще не затронуты, просто мусор. Почему? Что-то не так с
параметрами? Я уже и с коэффициентами в cufftPlan1d пытался поработать
- все равно, считает на половину почему-то.

Сергей Козлов

unread,
Aug 16, 2011, 7:24:10 AM8/16/11
to cudac...@googlegroups.com
Может cufftDoubleComplex и cufftComplex размером отличаются?

16 августа 2011 г. 14:13 пользователь Алексей Вахтин <alva...@gmail.com> написал:

Vitaliy Chernov

unread,
Aug 16, 2011, 7:27:09 AM8/16/11
to cudac...@googlegroups.com
Так и должно быть. Это преобразование "real-to-complex",
соответственно, "недостающие" элементы - это комплексно-сопряжённые 96
полученных элементов. В мануале "CUFFT Library" пишут:

For real‐to‐complex FFTs, the output array holds only the nonredundant
complex coefficients. So for an N‐element transform, the output array
holds N/2+1 cufftComplex terms.

16 августа 2011 г. 15:13 пользователь Алексей Вахтин
<alva...@gmail.com> написал:

Сергей Козлов

unread,
Aug 16, 2011, 7:30:37 AM8/16/11
to cudac...@googlegroups.com
Тогда ошибка здесь:
cutilSafeCall(cudaMemcpy(res, out_data, sizeof(cufftComplex) * N,
cudaMemcpyDeviceToHost));

Должно быть

cutilSafeCall(cudaMemcpy(res, out_data, sizeof(cufftDoubleComplex) * N,
cudaMemcpyDeviceToHost));


16 августа 2011 г. 14:27 пользователь Vitaliy Chernov <vitaliy...@gmail.com> написал:

Vitaliy Chernov

unread,
Aug 16, 2011, 7:48:40 AM8/16/11
to cudac...@googlegroups.com
Мне кажется, немного не так. Ведь на выходе будет (N/2+1) элементов типа double complex, поэтому:

// при выделении памяти для выходного массива:
cutilSafeCall(cudaMalloc((void**)&out_data, sizeof(cufftDoubleComplex) *(N/2+1)));

// при записи в память хоста:
cutilSafeCall(cudaMemcpy(res, out_data, sizeof(cufftDoubleComplex) * (N/2+1), cudaMemcpyDeviceToHost));


Алексей Вахтин

unread,
Aug 16, 2011, 7:31:11 AM8/16/11
to cudac...@googlegroups.com


16 августа 2011 г. 15:24 пользователь Сергей Козлов <kozlov.sergey....@gmail.com> написал:

Может cufftDoubleComplex и cufftComplex размером отличаются?
 
Да, они размером отличаются, так как cufftComplex - основан на float, а cufftDoubleComplex - на double. Но я посмотрел код, вроде везде используется double и cufftDoubleComplex. Константа в функцию cufftPlan1d передается CUFFT_D2Z - double в DoubleComplex, используется функция cufftExecD2Z. Врде так все. или где-то есть подвох? 

Алексей Вахтин

unread,
Aug 16, 2011, 8:08:58 AM8/16/11
to cudac...@googlegroups.com
Тогда ошибка здесь:
cutilSafeCall(cudaMemcpy(res, out_data, sizeof(cufftComplex) * N,
cudaMemcpyDeviceToHost));

Должно быть

cutilSafeCall(cudaMemcpy(res, out_data, sizeof(cufftDoubleComplex) * N,
cudaMemcpyDeviceToHost));

Да, здесь действительно ошибка. 

Сергей Козлов, спасибо за подсказку.

Сергей Козлов

unread,
Aug 16, 2011, 8:09:48 AM8/16/11
to cudac...@googlegroups.com
Везде должно быть ufftDoubleComplex или ufftComplex, в зависимости от того, что возвращает cufftExecD2Z.

16 августа 2011 г. 14:31 пользователь Алексей Вахтин <alva...@gmail.com> написал:


16 августа 2011 г. 15:24 пользователь Сергей Козлов <kozlov.sergey....@gmail.com> написал:

Может cufftDoubleComplex и cufftComplex размером отличаются?
 
Да, они размером отличаются, так как cufftComplex - основан на float, а cufftDoubleComplex - на double. Но я посмотрел код, вроде везде используется double и cufftDoubleComplex. Константа в функцию cufftPlan1d передается CUFFT_D2Z - double в DoubleComplex, используется функция cufftExecD2Z. Врде так все. или где-то есть подвох? 

--

Алексей Вахтин

unread,
Aug 16, 2011, 8:51:35 AM8/16/11
to cudac...@googlegroups.com
Как я понял, в CUFFT число элементов должно быть степенью двойки. Всем откликнувшимся спасибо. Все работает )))

Vitaliy Chernov

unread,
Aug 16, 2011, 8:56:48 AM8/16/11
to cudac...@googlegroups.com
Не обязательно. Но на степенях двойки (а также когда размер входного массива делится нацело на 2, 3, 5, 7) достигается максимальная производительность.
Reply all
Reply to author
Forward
0 new messages