Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > FFT на CUDA


Автор: hawk3500 31.5.2012, 12:43
Доьрого времени суток.
Подскажите кто нибудь делал реализацию БПФ из комплексного в реальное на GPU?
Не могу разобраться.....у  меня на входе есть массив Complex.....а что делать дальше?
Подскажите пожалуйста кто знает.

С уважением,
hawk3500.
P.S.
SDK смотрел и пример от туда тоже...но по прежнему не совсем ясно.

Автор: W4FhLF 31.5.2012, 13:33
Что значит "реализация БПФ из комплексного в реальное"?

Автор: hawk3500 31.5.2012, 13:45
на входе есть массив состоящий из структур:
struct complex_z
{
double Re;
double Im;
}
собственно над ним надо совершить БПФ.

Автор: W4FhLF 31.5.2012, 13:54
Есть прямое и обратное преобразование Фурье. Частотный спектр всегда определен на комплексной плоскости. Вам, судя по тому, что числа комплексные, надо сделать обратное преобразование? Точность у вас двойная. 

Используйте библиотеку CUFFT. Она отлично документирована и идёт с примерами. В чём проблема?

Автор: borisbn 31.5.2012, 14:52
Цитата(hawk3500 @  31.5.2012,  12:43 Найти цитируемый пост)
Подскажите кто нибудь делал реализацию БПФ из комплексного в реальное

Результат БПФ - всегда комплексный. Если тебе нужно получить спектр мощности, то просто берёшь амплитуду каждого числа
Код
powerSpectr[ i ] = sqrt( complexSpectr[ i ].re * complexSpectr[ i ].re + complexSpectr[ i ].im * complexSpectr[ i ].im );

брать корень, в принципе, необязательно.

Цитата(W4FhLF @  31.5.2012,  13:54 Найти цитируемый пост)
судя по тому, что числа комплексные, надо сделать обратное преобразование

Почему так категорично ? Отсчёты сигнала тоже могут быть комплексными. Я, например, в большинстве случаев работаю именно с комплексным сигналом (он получается из вещественного путём конвертации и фильтрации спец. микросхемой. AD6634, например)

Автор: W4FhLF 31.5.2012, 15:12
Цитата(borisbn @  31.5.2012,  14:52 Найти цитируемый пост)
Почему так категорично ? Отсчёты сигнала тоже могут быть комплексными. Я, например, в большинстве случаев работаю именно с комплексным сигналом (он получается из вещественного путём конвертации и фильтрации спец. микросхемой. AD6634, например) 


Потому что автор сказал, что надо complex -> real, а вы говорите про complex -> complex fft

В общем, я просто предположил. 

Цитата(borisbn @  31.5.2012,  14:52 Найти цитируемый пост)
брать корень, в принципе, необязательно.


Почему? Вы записали вычисление абсолютного значения комплексного числа (расстояние от начала координат на комплексной плоскости), корень там обязателен. 

Автор: hawk3500 31.5.2012, 15:34
borisbn , да , я работаю именно с комплексным сигналом.
И хочу получить по средствам БПФ на CUDA получить огибающую, т.е. именно можность сигнала , по этому из комплексного в реальное.
Я примерчики смотрел на SDK nvidia , но вот что то не доконца понятно....хотелось бы увидеть просто пример альтернативной реализации либо же просто менее нагруженный и более понятный.

Автор: borisbn 31.5.2012, 15:47
Цитата(W4FhLF @  31.5.2012,  15:12 Найти цитируемый пост)
 Вы записали вычисление абсолютного значения комплексного числа (расстояние от начала координат на комплексной плоскости), корень там обязателен

Если речь идёт о спектре сигнала, то обычно в дальнейшем спектр мощности преобразовывают к децибелам. Формула для логарифмического спектра выглядит так
Код
logSpectr[ i ] = 10 * log10( spectrAmplitude[ i ] );

Это для случая, когда в массиве spectrAmplitude лежит амплитуда спектра, т.е. корень. Если же известно, что там лежит мощность спектра (корень не брали), т.е. так
Код
logSpectr[ i ] = 10 * log10( spectrAmplitude[ i ] ^ 2 );

то эту двойку можно вынести и получим
Код
logSpectr[ i ] = 20 * log10( spectrAmplitude[ i ] );


Цитата(hawk3500 @  31.5.2012,  15:34 Найти цитируемый пост)
И хочу получить по средствам БПФ на CUDA получить огибающую, т.е. именно можность сигнала

стоп! ты хочешь получить огибающую или мощность сигнала или спектра сигнала ?
Если первое, то просто делаешь
Код
envelope[ i ] = sqrt( samples[ i ].re * samples[ i ].re + samples[ i ].im * samples[ i ].im ); // для огибающей
power[ i ] = samples[ i ].re * samples[ i ].re + samples[ i ].im * samples[ i ].im; // для мощности

Если второе, то после БПФ ты получаешь массив с комплексными числами. Чтобы получить спектр мощности делаешь как я написал в своём первом сообщении.

Добавлено через 3 минуты и 15 секунд
P.S. Для получения мощности сигнала БПФ вообще не нужен (разве что нужно посчитать мощность в какой-то определённой полосе, а не во всей входной полосе сигнала)

Автор: hawk3500 31.5.2012, 16:00
Нужно получить именно спектр мощности в данном частотном диапозоне.
Т.е. получить спектр сигнала и построить график мощности по частоте.

Автор: borisbn 31.5.2012, 16:14
Цитата(hawk3500 @  31.5.2012,  16:00 Найти цитируемый пост)
Нужно получить именно спектр мощности

после cufftExecZ2Z на выходе получается массив cufftDoubleComplex. Это - комплексный спектр. Чтобы получить спектр мощности делаешь:
Код
cufftDoubleComplex * spectr = cudaMalloc( ...
cufftDoubleReal * powerSpectr = cudaMalloc( ...
cufftExecZ2Z( plan , samples , spectr , CUFFT_FORWARD ); // собственно FFT
for ( int i = 0; i < fftLength; i++ ) {
    powerSpectr[ i ] = spectr[ i ].re * spectr[ i ].re + spectr[ i ].im * spectr[ i ].im;
}


Добавлено через 32 секунды
я надеюсь, этот документ - http://developer.download.nvidia.com/compute/DevZone/docs/html/CUDALibraries/doc/CUFFT_Library.pdf - у тебя есть ?

Автор: hawk3500 31.5.2012, 18:20
Всем спасибо.
Вопрос решил.
Но вот осталась одна не ясность.
Кодна я получаю своего рода хэндл при вызове функции cudaMalloc в одном потоке и затем пытаюсь его использовать в другом потоке ,то ничего не выходит.Т.е. мне приходится в потоке где происходит обработка выделять каждый раз память в  GPU.
Подскажит епожалуйста кто нибудь с таким встречался?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)