Алгоритми для обчислення FFT паралельно


12

Я намагаюся паралелізувати обчислення FFT на файлах сигналів розміром терабайт. Наразі така FFT, що використовує бібліотеку з відкритим кодом, займає багато годин, навіть працює через CUDA на найшвидшому графічному процесорі. Основою, яку я намагаюся адаптувати до цього процесу, є Hadoop. По суті, Hadoop розподіляє проблему на будь-яку кількість вузлів сервера таким чином:

• Ви розділите вхідний файл на (ключ, значення) пари.
• Ці пари подаються в алгоритм "Map", який перетворює ваші (ключ, значення) пари в деякі інші (ключ, значення) пари на основі того, що ви помістили всередину Map.
• Рамка потім збирає всі (ключ, значення) виводи з Карт і сортує їх за клавішами, а також агрегує значення з одним ключем до однієї пари, так що ви закінчуєте (ключ, список (значення1, значення2, ..)) пари
• Ці пари потім подаються в алгоритм «Зменшити», який, у свою чергу, виводить більше (ключ, значення) пар як ваш кінцевий результат (записується у файл).

Існує багато застосувань для цієї моделі в таких практичних речах, як обробка журналів серверів, але мені важко застосовувати рамки для подрібнення FFT на завдання "map" та "reduction", тим більше, що я не дуже знайомий з DSP.

Я не буду заважати вам мамбо програмуванням, оскільки це DSP Q&A. Я, однак, розгублений у тому, які алгоритми існують для обчислення FFT паралельно; Завдання "Зробити карту" та "Зменшити" не можуть (технічно) говорити між собою, тому FFT необхідно розділити на незалежні проблеми, з яких результати можна якось рекомбінувати наприкінці.

Я запрограмував просту реалізацію Cooley-Tukey Radix 2 DIT, яка працює на невеликих прикладах, але використовувати її для рекурсивного обчислення непарних / парних показників DFT на мільярд байтів не вийде. Я витратив кілька тижнів на читання багатьох статей, у тому числі й на алгоритмі MapReduce FFT (написаний Tsz-Wo Sze як частина його статті про множення SSA, я не можу пов’язати більше двох гіперпосилань) та «чотиришагової FFT» ( тут і тут), які схожі між собою і на те, що я намагаюся досягти. Однак я безнадійно поганий у математиці, і застосовуючи будь-який із цих методів вручну до простого набору чогось типу {1,2, 3, 4, 5, 6, 7, 8} (з усіма уявними компонентами 0) мені дико невірні результати. Чи може хтось пояснити мені ефективний паралельний алгоритм FFT простою англійською мовою (той, який я пов’язав чи будь-який інший), щоб я міг спробувати запрограмувати його?

Редагувати: Джим Клей та хтось інший, хто може бути збентежений моїм поясненням, я намагаюся зробити один FFT з терабайтного файлу. Але я хочу вміти робити це одночасно на декількох серверах, щоб прискорити процес.


1
Що саме ви намагаєтеся досягти? Ви хочете зробити один FFT файлу сигналу терабайт або кілька менших FFT кожного файлу?
Джим Клей

Відповіді:


13

Я думаю, що ваша основна проблема - це не паралельний алгоритм (який насправді можна зробити), а чисельна точність. Великі ЗПТ великого розміру чисельно досить складні. Коефіцієнти FFT мають вигляд і якщо N дуже великий, розрахунок коефіцієнта стає галасливим. Скажімо, у вас і ви використовуєте 64-бітну арифметику з подвійною точністю. Перші 1000 коефіцієнтів мають справжню частину, яка є саме єдністю (хоча це не повинно бути таким), тому вам знадобиться математика з більшою точністю, яка дуже неефективна і громіздка у використанні. N=240ej2πkNN=240

Ви також наберете безліч помилок округлення та обрізання, оскільки велика кількість операцій, що входять в одне вихідне число, теж дуже велика. Зважаючи на характер "кожного виходу залежить від кожного вхідного сигналу" FFT, поширення помилок поширюється.

Я не знаю про простий спосіб подолати це. Ваш запит незвичний. Більшість застосунків, які роблять спектральний аналіз великих наборів даних, роблять аналіз роботи, де у вас немає такої проблеми. Можливо, якщо ви можете охарактеризувати свою заявку, але це обмежує, але більше, ми можемо вказати на більш підходяще рішення.


Цілком справедливий пункт .. Мені доведеться більше подумати над цим. Можливо, я вдадуся до "аналізу бігу" врешті-решт, як ви кажете.
Філіп

Я знаю, що я дуже спізнююсь, але ви, випадково, маєте джерело того, як це можна зробити, оскільки ви згадали, що це можна зробити?
Клаудіо Брассер

4

Замість того, щоб намагатися переписати FFT, ви можете спробувати використовувати існуючу реалізацію FFT (наприклад, наприклад FFTW ) і застосовувати її повторно по довжині сигналу (незалежно від того, наскільки він великий) через перекриття, додавання або перекриття- зберегти методи. Це можливо, виразивши FFT як згортку .

Цим короткометражним FFT не потрібно спілкуватися один з одним, і вся схема відповідає крокам зменшення карти.

Взагалі, ви б хотіли це зробити, щоб ваш сигнал X розділився на більш дрібні сегменти, які також можуть перетинатися (наприклад, X [0:10], X [5:15], X [10:20] ... .). Виконайте FFT на цих невеликих сегментах і рекомбінуйте їх наприкінці, щоб отримати остаточний. Це дуже добре поєднується з операторами зменшення карт.

Під час "карти" ви можете генерувати (ключ, значення) пари, при цьому "ключ" є деяким послідовним ідентифікатором кожного сегмента (0,1,2,3,4,5, ....), а "значення" є INDEX (або позиція файлу) першого значення сегмента у файлі вашого сигналу. Так, наприклад, якщо у вашому файлі повно INT32, то індекс другого сегмента (вище) розміром 5 * (INT32). (Або якщо він у будь-якому іншому форматі, у вас може бути ліб)

Тепер кожен працівник отримує (ключ, значення), відкриває файл, шукає потрібну точку, зчитує з нього M-зразки (де M вище 10), виконує FFT і зберігає його у файл з деяким іменем, наприклад " RES_ [INKEY] .dat "і повертає пару (ключ, значення). У цьому випадку "ключем" буде INDEX ("значення" вхідного (ключ, значення) кортежу), а "значення" - це ім'я файлу, який містить результати FFT. (ми повернемося до цього)

У межах "зменшити" тепер можна реалізувати або перекриття-додавання, або перекриття-збереження, приймаючи (ключ, значення) від кроку "карта", відкриваючи цей файл, завантажуючи результати FFT, виконуючи або oa або os, а потім зберігаючи їх у правильний INDEX у вихідному файлі. (Дивіться псевдокод у цьому (або цьому ) кроці "map" паралельно обробляє "yt = ...", а крок "зменшення" обробляє частину "y (i, k) = ...".)

Тут може знадобитися деяке жонглювання файлами для зменшення трафіку в мережі або завантаження сервера, який може містити фактичний файл даних.


1
Я не впевнений у валідності перекриття-додавання та перекриття-збереження для комбінування менших фрагментів для отримання FFT більшого розміру - наскільки я знаю, для цього потрібен другий пропуск FFT (DFT розміром N = AB може бути розбита на A DFT розміром B, додатком множини фактора, а потім B DFT розміром A). Це може спрацювати, якщо ми хочемо вивести меншу роздільну здатність ...
pichenettes

Привіт, піценетки, дякую за це, що я мав на увазі, це це ( Engineeringproductivitytools.com/stuff/T0001/PT11.HTM ), яке я включу у відповідь.
A_A

2

Припустимо , що розмір даних . Прокладка з нулями в іншому випадку. У вашому випадку, оскільки ви згадуєте розміри "Терабайт-шкала", ми візьмемо N = 40.2N

Оскільки є великим, але абсолютно розумним для однієї машини розміром FFT, я пропоную вам зробити лише одну єдину ітерацію Кулі-Тукі радіусом , а потім дозволити належну бібліотеку FFT (як FFTW) виконайте роботу на кожній машині для меншого розміру .2N/2N/22N/2

Якщо бути більш чітким, не потрібно використовувати MR протягом усієї рекурсії, це буде справді неефективно. Ваша проблема може бути розбита на мільйон мегабайтних внутрішніх і зовнішніх FFT, і ці мегабайтні FFT можуть бути ідеально обчислені за допомогою FFTW тощо. ЗМ буде просто нести відповідальність за контроль переміщення даних та рекомбінацію даних, а не фактичні обчислення FFT ...

Моя сама перша ідея полягала б у наступній, але я підозрюю, що це можна зробити за допомогою одного ЗМ із розумнішим представленням даних.

Нехай - ваш вхідний сигнал,sR=2N/2

Перший ЗМ: внутрішній FFT

Карта: виконуйте децимацію в часі, групуйте зразки в блоки для внутрішнього FFT

вхід: де - індекс вибірки в ; значення, прийняте(k,v)k0..2N1vs[k]

випромінюють: - де% являє собою поділ за модулем та / цілим числом.(k%R,(k/R,v))

Зменшити: обчислити внутрішній FFT

вхід: де - індекс блоку; і - перелік пар пар(k,vs)kvs(i,v)

заповнити вектор розмірі таким чином, що для всіх значень в списку.inRin[i]=v

виконати розмір FFT на , щоб отримати вектор розміруRinoutR

для в , випромінюємоi0..R1(k,(i,out[i]))

Другий ЗМ: зовнішній FFT

Карта: групуйте зразки для зовнішнього ффта та застосуйте подвійні коефіцієнти

вхід: де - індекс блоку, вибірка внутрішньої FFT для цього блоку.(k,(i,v))k(i,v)

випромінювати(i,(k,v×exp2πjik2N))

Скорочення: виконайте зовнішній FFT

вхід: де - індекс блоку; і - перелік пар парk v s ( i , v )(k,vs)kvs(i,v)

заповнити вектор розмірі таким чином, що для всіх значень в списку.R i n [ i ] = vinRin[i]=v

виконати розмір FFT на , щоб отримати вектор розміруi n o u t RRinoutR

для в , випромінюємо0 . . R - 1 ( i × R + k , o u t [ i ] ) )i0..R1(i×R+k,out[i]))

Тут підтверджується концепт-код пітона.

Як бачимо, Картографи лише змішують порядок даних, тож за такими припущеннями:

  • децимація в часі (Mapper 1) може бути виконана на попередньому кроці (наприклад, програмою, яка перетворює дані у потрібний формат введення).
  • ваша рамка MR підтримує запис редукторів на ключ, відмінний від клавіші введення (у реалізації Google редуктори можуть виводити дані лише в той самий ключ, що і вони отримали, я думаю, це пов'язано з тим, що SSTable використовується як вихідний формат).

Все це можна зробити за один єдиний МР, внутрішній FFT в картографі, зовнішній FFT в редукторі. Доказ концепції тут .


Ваша реалізація здається багатообіцяючою, і я зараз переживаю це, але у внутрішньому редукторі FFT ви пишете "виконати розмір 2 ^ R FFT, щоб отримати вектор з розміром 2 ^ R". Якщо R дорівнює 2 ^ (N / 2), чи не був би цей FFT розміром 2 ^ (2 ^ N / 2), і, отже, невірно? Ви мали на увазі FFT розміром R?
Філіп

Так, схоже, я змішав і в кількох місцях ... відредаговано. Зауважте, що коментар Гільмара стосується мого підходу - вам доведеться використовувати більш високу точність, ніж подвійну в іншому випадку, деякі чинники подвійності ( ) матимуть реальну роль з 1, поки їх не повинно бути - це призводить до числових неточностей. 2 R exp - 2 π j i kR2Rexp2πjik2N
пікенети

0

Якщо ваш сигнал багатовимірний, то паралелізація FFT може бути здійснена досить легко; зберігайте один вимір безперервно в процесі MPI, виконайте FFT і перемістіть (altoall) для роботи над наступним виміром. FFTW робить це.

Якщо дані 1D, проблема набагато складніше. Наприклад, FFTW не записав 1D FFT за допомогою MPI. Якщо використовується алгоритм децимації частоти радіації-2, то перші кілька етапів можна виконати як наївний DFT, що дозволяє використовувати 2 або 4 вузли без втрати точності (це пояснюється тим, що коріння єдності для перші етапи або -1, або я, які добре працювати з ними).

До речі, що ви плануєте робити з даними, як тільки ви їх трансформували? Це може зробити щось, якщо хтось знає, що відбувається з виходом (тобто згортка, фільтр низьких частот тощо).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.