<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Weasel</id>
	<title>Алговики - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Weasel"/>
	<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/ru/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Weasel"/>
	<updated>2026-10-22T21:00:08Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Chachba.A&amp;diff=18667</id>
		<title>Обсуждение участника:Chachba.A</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Chachba.A&amp;diff=18667"/>
		<updated>2016-11-20T22:37:34Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Замечания к статье &amp;quot;Быстрое дискретное преобразование Фурье&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к статье ==&lt;br /&gt;
&lt;br /&gt;
* п.п. 1.8, 1.9 не раскрыты--[[Участник:IgorS|IgorS]] ([[Обсуждение участника:IgorS|обсуждение]]) 14:57, 25 октября 2016 (MSK)&lt;br /&gt;
** исправлено&lt;br /&gt;
* не указан конкретный вклад каждого автора--[[Участник:IgorS|IgorS]] ([[Обсуждение участника:IgorS|обсуждение]]) 14:57, 25 октября 2016 (MSK)&lt;br /&gt;
** исправлено&lt;br /&gt;
* в п.п. 2.4 следует добавить описание компьютерной платформы, текст исследуемой программы.--[[Участник:IgorS|IgorS]] ([[Обсуждение участника:IgorS|обсуждение]]) 13:41, 16 ноября 2016 (MSK)&lt;br /&gt;
** сделано&lt;br /&gt;
&lt;br /&gt;
== Замечания к статье &amp;quot;Быстрое дискретное преобразование Фурье&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
* Перенесите пожалуйста статью в личное пространство [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK) &lt;br /&gt;
** а как это сделать? У нас нет прав на это, похоже&lt;br /&gt;
*** пункт 1 на этой странице, надо написать модератору: [[Алговики:Студенческие работы]]&lt;br /&gt;
**** написал запрос на перенос в личное пространство&lt;br /&gt;
* Раздел 1.1 - в самом первом абзаце стоит вставить обозначения двух фунций - f и f с крышкой, чтобы было ясно, что куда отображается. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK) &lt;br /&gt;
** Done&lt;br /&gt;
* В общее описание алгоритма нужно вставить слова именно об алгоритме, а не только о математической задаче. В чем быстрота, за счет чего она достигается и т.д. Тут, в отличие от математического описания, не стоит увлекаться формулами. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;br /&gt;
* Раздел 1.2 - существует обозначение части формулы через эпсилон, однако в следующей формуле он не встречается, странно. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;br /&gt;
* Нужно пояснение, что происходит, когда N не представимо в виде произведения: применим ли алгоритм и в каких изменениях он нуждается. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;br /&gt;
*** Обратите внимание на то, что объяснение других участников другое: [[Участник:Ivanov.kir.m/Быстрое дискретное преобразование Фурье]]&lt;br /&gt;
**** Сделано&lt;br /&gt;
* Нет данных о глубине рекурсии, написать об этом явно, скорее всего, в разделе &amp;quot;вычислительное ядро алгоритма&amp;quot;. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;br /&gt;
&lt;br /&gt;
* Все хорошо, кроме переноса статьи (написал об этом) и дописывания разделов про программную реализацию алгоритма [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 12:43, 18 ноября 2016 (MSK)&lt;br /&gt;
** Дополнено&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=18666</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=18666"/>
		<updated>2016-11-20T22:36:06Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; {{Assignment|IgorS}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] &lt;br /&gt;
&lt;br /&gt;
[[Участник:Chachba.A|Чачба А.Н.]] заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, [[Участник:Weasel|Костоев Р.С.]] написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; вещественной переменной, называемой таргетным сигналом, с другой функцией &amp;lt;math&amp;gt;\hat{f}&amp;lt;/math&amp;gt; вещественной переменной, называемой образом Фурье, или спектром исходной функции, по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, есть аналог непрерывного преобразования Фурье, но для дискретного сигнала, содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяется в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Такая скорость достигается благодаря применению схемы «разделяй и властвуй». Общий вид преобразования позволяет разделить массив на несколько частей таким образом, что, применяя преобразование Фурье к отдельным его частям и объединяя специальным образом результаты (при помощи поворотных множителей и повторного применения преобразования), получать на выходе образ исходного вектора. Но благодаря разделению массива исходного размера на части суммарная асимптотическая сложность алгоритма уменьшается.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{\varepsilon_{N}^{(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;. Так как рекурсия применяется каждый раз при отщеплении одного множителя, то можно заключить, что глубина рекурсии алгоритма составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; — число множителей в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В свою очередь, если число &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; не факторизуется в произведение простых множителей (то есть &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — простое число), то данный алгоритм напрямую не применим. На замену ему приходит алгоритм Радера, который в некотором смысле сводит задачу размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; к подзадаче задаче размерности &amp;lt;math&amp;gt;N\pm 1&amp;lt;/math&amp;gt; вычисления свертки, в которой допустимо и увеличение размерности до составных в том числе.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Все запуски программы[http://pastebin.com/raw/xajKb9JN] проводились на с/к Blue Gene/P с использованием библиотеки Intel MKL.&lt;br /&gt;
&lt;br /&gt;
IBM Blue Gene/P — массивно-параллельная вычислительная система, которая состоит из двух стоек, включающих 2048 четырехъядерных вычислительных узлов, с пиковой производительностью 27,9 терафлопс.&lt;br /&gt;
&lt;br /&gt;
Характеристики системы:&lt;br /&gt;
* две стойки с вычислительными узлами и узлами ввода-вывода&lt;br /&gt;
* 1024 четырехъядерных вычислительных узла в каждой из стоек&lt;br /&gt;
* 16 узлов ввода-вывода в стойке (в текущей конфигурации активны 8, т.е. одна I/O-карта на 128 вычислительных узлов)&lt;br /&gt;
* программирование с использованием MPI, OpenMP/pthreads, POSIX I/O&lt;br /&gt;
* высокая энергоэффективность: ∼ 372 MFlops/W&lt;br /&gt;
&lt;br /&gt;
Вычислительный узел включает в себя четырехъядерный процессор, 2 ГБ общей памяти и сетевые интерфейсы.&lt;br /&gt;
&lt;br /&gt;
Вычислительной узел:&lt;br /&gt;
* четыре микропроцессорных ядра PowerPC 450 (4-way SMP)&lt;br /&gt;
* пиковая производительность: 4 ядра x 3,4 GFlop/sec на ядро = 13,6 GFlop/sec&lt;br /&gt;
* пропускная способность памяти: 13,6 GB/sec&lt;br /&gt;
* 2 ГБ общей памяти&lt;br /&gt;
* 2 x 4 МБ кэш-памяти 2-го уровня (в документации по BG/P носит название L3)&lt;br /&gt;
* легковесное ядро (compute node kernel, CNK), представляющее собой Linux-подобную операционную систему, поддерживающую значительное подмножество Linux-совместимых системных вызовов&lt;br /&gt;
* асинхронные операции межпроцессорных обменов (выполняются параллельно с вычислениями)&lt;br /&gt;
* операции ввода-вывода перенаправляются I/O-картам через сеть коллективных операций&lt;br /&gt;
&lt;br /&gt;
[[Файл:Time.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 2.&#039;&#039;&#039; Время выполнения параллельной реализации БПФ в секундах. Size - число элементов массива. Р - число использованных процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Efff.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 3.&#039;&#039;&#039; Эффективность параллельной реализации БПФ. Size - число элементов массива. Р - число использованных процессоров. Эффективность в пределах от 0 до 1.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из графика, эффективность параллельной реализации резко падает с ростом количества используемых процессоров, связано это с увеличением количества накладных расходов.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Википедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lineprinter&amp;diff=18664</id>
		<title>Обсуждение участника:Lineprinter</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lineprinter&amp;diff=18664"/>
		<updated>2016-11-20T22:10:50Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Перенос ==&lt;br /&gt;
Статья: [[Участник:Бобцов Борис/Вычисление определенного интеграла с использованием адаптивно сгущающейся сетки]]&lt;br /&gt;
Выполняет: [[Участник:Бобцов Борис| Бобцов Борис]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Вычисление определенного интеграла с использованием адаптивно сгущающейся сетки]]&lt;br /&gt;
Выполняют: [[Участник:Greno4ka| Устинов Григорий ]] и [[ Лиджиев Данир ]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Кластеризация сетями Кохонена]]&lt;br /&gt;
Выполняют: [[Участник:Kravtsovkirill| Кравцов Кирилл]] и [[Участник:Emaksimov| Максимов Егор]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нахождение собственных чисел квадратной матрицы методом QR разложения (2)]]&lt;br /&gt;
Выполняют: Баев Олег и Шевелев Александр&lt;br /&gt;
&lt;br /&gt;
Статья: [[Стабилизированный метод биспоряженных градиентов (BiCGSTAB)]]&lt;br /&gt;
Выполняют: Гаврилов Алексей и Новиков Александр&lt;br /&gt;
&lt;br /&gt;
Статья: [[Участники: Бобошко А., Юмакаева А./Решение начальной задачи Коши для системы ОДУ методом Рунге-Кутта 4-го порядка]];&lt;br /&gt;
Выполняют: Бобошко Алексей и Юмакаева Алина&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на сетях Кохоннена]];&lt;br /&gt;
Выполняют:  Логвиненко Александра и Адиев Тохтар&lt;br /&gt;
&lt;br /&gt;
Статья: [[Ортогонализация Грама-Шмидта]];&lt;br /&gt;
Выполняют: [[Участник:KibAndrey| Кибанов Андрей]] и Аджиева Татьяна&lt;br /&gt;
&lt;br /&gt;
Статья: [[Самоорганизующиеся карты Кохонена]];&lt;br /&gt;
Выполняет: [[Участник:Anton goy| Гой Антон]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[ЕМ-алгоритм_(Тематическое_моделирование)]];&lt;br /&gt;
Выполняют: Мурат Апишев и Андрей Заночкин&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_Ланцоша_с_полной_переортогонализацией]];&lt;br /&gt;
Выполняет:[[Участник:Sfedotov| Федотов С.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_k-средних]]&lt;br /&gt;
Выполняют: [[Участник:Error2407|Богомазов Евгений]], [[Участник:Илья_Егоров|Егоров Илья]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм k-means]]&lt;br /&gt;
Выполняют: [[Участник:Бротиковская Данута|Данута Бротиковская]] и [[Участник:DennZo1993|Денис Зобнин]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Partitioning Around Medoids (Алгоритм)]]&lt;br /&gt;
Выполняют: [[Участник:Denemmy| Галеев Данил]] и [[Участник:Ivan.Z| Запутляев Иван]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий_алгоритм_С_средних]]&lt;br /&gt;
Выполняют: [[Участник:Demon smd|Д.А.Гуськов]], [[Участник:marina abramenkova|М.А.Абраменкова]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Решение_задачи_Коши_для_системы_ОДУ_методом_Рунге-Кутты_4_порядка]];&lt;br /&gt;
Выполняют: [[Участник:Алимов_Дамир_Алиевич|Алимов Дамир]] и [[Участник:Anlesnichiy|Антон Лесничий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Строгий_алгоритм_С_средних_(Hard_C-Means,_HCM)]];&lt;br /&gt;
Выполняют: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]] и [[Участник:Юрий_Комаров|Комаров Юрий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на минимальном остовном дереве]];&lt;br /&gt;
Выполняет: [[Участник:Astandrik | Стандрик Антон Сергеевич]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Умножение разреженной матрицы на вектор]];&lt;br /&gt;
Выполняет: [[Участник:Lexaloris | Новоселов Алексей]], Выполняет: [[Участник:kochet|П.А. Кочетков]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нахождение_собственных_чисел_квадратной_матрицы_методом_QR_разложения_(3)|Нахождение собственных чисел квадратной матрицы методом QR разложения (3)]];&lt;br /&gt;
Выполняют: [[Участник:Смирнова_Александра|Смирнова А.С.]], [[Участник:Александра_Киямова|Киямова А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод_Якоби_вычисления_сингулярных_чисел_и_векторов]];&lt;br /&gt;
Выполняют: [[Участница:Почернина_Елена| Почернина Елена]] и [[Участница:Светлана|Костюкова Светлана]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод_Ньютона_для_решения_систем_нелинейных_уравнений(2)]];&lt;br /&gt;
Выполняют: [[Участник:Oleggium|Гирняк О.Р.]], [[Участник:Dimx19|Васильков Д.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_кластеризации_с_использованием_представлений]];&lt;br /&gt;
Выполняют: [[Участник:Cookie|Шатков С.А.]], [[Участница:JuliaA|Антохина Ю.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Быстрое_преобразование_Фурье_(FFT)|Быстрое преобразование Фурье (FFT)]];&lt;br /&gt;
Выполняют: [[Участник:Victoria_Stepanischeva|Степанищева Виктория]] и [[Участник:Igor_Munkin|Мунькин Игорь]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Быстрое_дискретное_преобразование_Фурье|Быстрое_дискретное_преобразование_Фурье]];&lt;br /&gt;
Выполняют: [[Участник:ivanov.kir.m | К.М.Иванов]], [[Участник:Pumpkin | А.C.Сапин]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_k_средних]]&lt;br /&gt;
Выполняют: [[Участник:Parkhomenko|Пархоменко Павел]], [[Участник:ivan.mashonskiy|Машонский Иван]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[EM-алгоритм_кластеризации]]&lt;br /&gt;
Выполняет: [[Участник:Noite|Зинченко Дмитрий]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_k_means]]&lt;br /&gt;
Выполняют: [[Участник:IanaV| Валуйская Яна]], [[Участник:GlotovES| Глотов Евгений]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Якоби вычисления собственных значений симметричной матрицы ЗП |Метод Якоби вычисления собственных значений симметричной матрицы ЗП]];&lt;br /&gt;
Выполняют: [[Участник:Зиновьев Владимир|Зиновьев В.С.]], [[Участник:Пронин Андрей|Пронин А.М.]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_кластеризации,_основанный_на_минимальном_покрывающем_дереве]]&lt;br /&gt;
Выполняет: [[Участник:Kanast74|Дмитриева Анастасия]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Нахождение_собственных_чисел_квадратной_матрицы_методом_QR_разложения_(4)]]&lt;br /&gt;
Выполняют: [[Участник:F-morozov|Морозов Ф. В.]], [[Участник:Nataliya|Пащенко Н. Ф.]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Хранение_ненулевых_элементов_разреженных_матриц._Умножение_разреженной_матрицы_на_вектор]];&lt;br /&gt;
Выполняют: [[Участник:Trrufina|Третьякова Р.М.]] и [[Участник:Екатерина_Буторина|Буторина Е.В.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_кластеризации_с_использованием_представлений2]];&lt;br /&gt;
Выполняет: [[Участник:Лукьянова Анна|Лукьянова А.Я.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Якоби вычисления собственных значений симметричной матрицы]];&lt;br /&gt;
Выполняют: [[Участник: Galkina|Галкина А.С.]], [[Участник: Игорь|Плахов И.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод рекурсивной координатной бисекции]];&lt;br /&gt;
Выполняют: [[Участник: Obirvalger|Гордеев Михаил]], [[Участник: KolmakovEA|Колмаков Евгений]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Итерационный метод решения системы линейных алгебраических уравнений GMRES (обобщенный метод минимальных невязок)]];&lt;br /&gt;
Выполняют: [[Участник: Эльвира Ахиярова|Ахиярова Эльвира]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Хранение ненулевых элементов разреженной матрицы. Умножение разреженной матрицы на вектор]];&lt;br /&gt;
Выполняют: [[Участник: Janyell|Сычева Евгения]], [[Участник: Ahahalin|Хахалин Анатолий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Построение матрицы Адамара произвольного размера]];&lt;br /&gt;
Выполняют: [[Участник: Бугаков Юрий|Бугаков Юрий]], Кужамалиев Ернур&lt;br /&gt;
&lt;br /&gt;
Статья: [[Вычисление определенного интеграла с использованием адаптивно сгущающейся сетки (1)]]&lt;br /&gt;
Выполняют: [[Участница:Sannikovats| Санникова Татьяна Сергеевна]], [[Участник:Plukshin| Лукшин Петр Андреевич]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на построении каркаса]];&lt;br /&gt;
Выполняют: [[Участник:SenderovichNikita| Сендерович Никита]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на максимизации ожидания]];&lt;br /&gt;
Выполняют: Готман Мария, Лукашкина Юлия&lt;br /&gt;
&lt;br /&gt;
Статья: [[Partitioning_Around_Medoids_(PAM)]]&lt;br /&gt;
Выполняют: [[Участник:Avasilenko|А.Э.Василенко]], [[Участник:Anastasia|А.В.Тузикова]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий алгоритм С-средних (Fuzzy C-means)]]&lt;br /&gt;
Выполняют: [[Участник:Nikmedoed|Н.А. Муромцев]], [[Участник:illusive_mike|М.С. Дворецкий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий алгоритм C средних]]&lt;br /&gt;
Выполняют: [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Плотностный алгоритм кластеризации DBSCAN]]&lt;br /&gt;
Выполняют: [[Участник:Elena777mc|Малахова Е.С.]], [[Участник:Жаннат_Сагиолданова|Сагиолданова Ж.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Кластеризация Partitioning Around Medoids (PAM)]]&lt;br /&gt;
Выполняют:[[ Участник:Тодуа Антон| Тодуа Антон]], [[Участник:Гусева Юлия| Гусева Юлия]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Участник:Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа)/Построение матрицы Адамара произвольной размерности]]&lt;br /&gt;
Выполняют:[[ Участник:Бугаков Юрий| Бугаков Юрий]], [[Участник:Кужамалиев Ернур| Кужамалиев Ернур]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Участник:Nikita/Построение_матрицы_Адамара|Построение матрицы Адамара]]&lt;br /&gt;
Выполняют: [[Участник:Nikita|Иванов Никита]], [[Участник:Tsyganov Nikita|Цыганов Никита]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Ньютона для решения систем нелинейных уравнений]]&lt;br /&gt;
Выполняют: [[Участник:Александр Чернышев|Александр Чернышев]], [[Участник:Захаров Никита|Захаров Никита]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[BIRCH|Сбалансированный итеративный алгоритм редукции и кластеризации с использованием иерархий&lt;br /&gt;
(BIRCH)]]&lt;br /&gt;
Выполняют: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Плотностный_алгоритм_кластеризации|Плотностный_алгоритм_кластеризации]], Выполняют: [[Участник:Ramon93i7|Шемякин Роман]], [[Участник:Dadrik|Вашуров Илья]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм CLOPE кластеризации категориальных данных]].&lt;br /&gt;
Выполняют: [[Участник:Артем_Карпухин|Карпухин Артем]], [[Участник:Артем_Желтков|Желтков Артем]].&lt;br /&gt;
&lt;br /&gt;
Статья: [[Участник:Борис/Алгоритм_Рунге-Кутты]]&lt;br /&gt;
Выполняет: [[Участник:Борис| Савков Борис]] и Степанов Евгений.&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_кластеризации_категориальных_данных_CLOPE]].&lt;br /&gt;
Выполняют: [[Участник:Андрей_Туманов|А.Л.Туманов]], [[Участник:Александр_Александров|А.В.Александров]].&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)]].&lt;br /&gt;
Выполняет: [[Участник:AleksLevin|А.Д.Левин]].&lt;br /&gt;
&lt;br /&gt;
Статья: [[Быстрое дискретное преобразование Фурье (БПФ)]].&lt;br /&gt;
Выполняет: [[ Участник:Chachba.A| Чачба Алан]], [[Участник:Weasel| Костоев Руслан]].&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17826</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17826"/>
		<updated>2016-11-16T22:11:21Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] &lt;br /&gt;
&lt;br /&gt;
[[Участник:Chachba.A|Чачба А.Н.]] заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, [[Участник:Weasel|Костоев Р.С.]] написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; вещественной переменной, называемой таргетным сигналом, с другой функцией &amp;lt;math&amp;gt;\hat{f}&amp;lt;/math&amp;gt; вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, есть аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяется в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Такая скорость достигается благодаря применению схемы &amp;quot;разделяй и властвуй&amp;quot;. Общий вид преобразования позволяет разделить массив на несколько частей таким образом, что, применяя преобразование Фурье к отдельным его частям и объединяя специальным образом результаты (при помощи поворотных множителей и повторного применения преобразования), получать на выходе образ исходного вектора. Но благодаря разделению массива исходного размера на части суммарная асимптотическая сложность алгоритма уменьшается.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{\varepsilon_{N}^{(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;. Так как рекурсия применяется каждый раз при отщеплении одного множителя, то можно заключить, что глубина рекурсии алгоритма составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;-число множителей в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В свою очередь, если число &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; не факторизуется в произведение простых множителей (то есть &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - простое число), то данный алгоритм не применим. На замену ему приходит алгоритм Радера, имеющий худшую асимптотику, нежели обычный БПФ, но лучшую чем &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;. Также алгоритм Радера потребует дополнительного взаимодействия процессоров, что приведет к ухудшению эффективности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Все запуски программы[http://pastebin.com/raw/xajKb9JN] проводились на с/к Blue Gene/P с использованием библиотеки Intel MKL.&lt;br /&gt;
&lt;br /&gt;
IBM Blue Gene/P — массивно-параллельная вычислительная система, которая состоит из двух стоек, включающих 2048 четырехъядерных вычислительных узлов, с пиковой производительностью 27,9 терафлопс.&lt;br /&gt;
&lt;br /&gt;
Характеристики системы:&lt;br /&gt;
* две стойки с вычислительными узлами и узлами ввода-вывода&lt;br /&gt;
* 1024 четырехъядерных вычислительных узла в каждой из стоек&lt;br /&gt;
* 16 узлов ввода-вывода в стойке (в текущей конфигурации активны 8, т.е. одна I/O-карта на 128 вычислительных узлов)&lt;br /&gt;
* программирование с использованием MPI, OpenMP/pthreads, POSIX I/O&lt;br /&gt;
* высокая энергоэффективность: ∼ 372 MFlops/W&lt;br /&gt;
&lt;br /&gt;
Вычислительный узел включает в себя четырехъядерный процессор, 2 ГБ общей памяти и сетевые интерфейсы.&lt;br /&gt;
&lt;br /&gt;
Вычислительной узел:&lt;br /&gt;
* четыре микропроцессорных ядра PowerPC 450 (4-way SMP)&lt;br /&gt;
* пиковая производительность: 4 ядра x 3,4 GFlop/sec на ядро = 13,6 GFlop/sec&lt;br /&gt;
* пропускная способность памяти: 13,6 GB/sec&lt;br /&gt;
* 2 ГБ общей памяти&lt;br /&gt;
* 2 x 4 МБ кэш-памяти 2-го уровня (в документации по BG/P носит название L3)&lt;br /&gt;
* легковесное ядро (compute node kernel, CNK), представляющее собой Linux-подобную операционную систему, поддерживающую значительное подмножество Linux-совместимых системных вызовов&lt;br /&gt;
* асинхронные операции межпроцессорных обменов (выполняются параллельно с вычислениями)&lt;br /&gt;
* операции ввода-вывода перенаправляются I/O-картам через сеть коллективных операций&lt;br /&gt;
&lt;br /&gt;
[[Файл:Time.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 2.&#039;&#039;&#039; Время выполнения параллельной реализации БПФ в секундах. Size - число элементов массива. Р - число использованных процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Efff.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 3.&#039;&#039;&#039; Эффективность параллельной реализации БПФ. Size - число элементов массива. Р - число использованных процессоров. Эффективность в пределах от 0 до 1.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из графика, эффективность параллельной реализации резко падает с ростом количества используемых процессоров, связано это с увеличением количества накладных расходов.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Википедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17825</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17825"/>
		<updated>2016-11-16T22:10:07Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] &lt;br /&gt;
&lt;br /&gt;
[[Участник:Chachba.A|Чачба А.Н.]] заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, [[Участник:Weasel|Костоев Р.С.]] написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; вещественной переменной, называемой таргетным сигналом, с другой функцией &amp;lt;math&amp;gt;\hat{f}&amp;lt;/math&amp;gt; вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, есть аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяется в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Такая скорость достигается благодаря применению схемы &amp;quot;разделяй и властвуй&amp;quot;. Общий вид преобразования позволяет разделить массив на несколько частей таким образом, что, применяя преобразование Фурье к отдельным его частям и объединяя специальным образом результаты (при помощи поворотных множителей и повторного применения преобразования), получать на выходе образ исходного вектора. Но благодаря разделению массива исходного размера на части суммарная асимптотическая сложность алгоритма уменьшается.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{\varepsilon_{N}^{(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;. Так как рекурсия применяется каждый раз при отщеплении одного множителя, то можно заключить, что глубина рекурсии алгоритма составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;-число множителей в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В свою очередь, если число &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; не факторизуется в произведение простых множителей (то есть &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - простое число), то данный алгоритм не применим. На замену ему приходит алгоритм Радера, имеющий худшую асимптотику, нежели обычный БПФ, но лучшую чем &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;. Также алгоритм Радера потребует дополнительного взаимодействия процессоров, что приведет к ухудшению эффективности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Все запуски программы[http://pastebin.com/raw/xajKb9JN] проводились на с/к Blue Gene/P.&lt;br /&gt;
&lt;br /&gt;
IBM Blue Gene/P — массивно-параллельная вычислительная система, которая состоит из двух стоек, включающих 2048 четырехъядерных вычислительных узлов, с пиковой производительностью 27,9 терафлопс.&lt;br /&gt;
&lt;br /&gt;
Характеристики системы:&lt;br /&gt;
* две стойки с вычислительными узлами и узлами ввода-вывода&lt;br /&gt;
* 1024 четырехъядерных вычислительных узла в каждой из стоек&lt;br /&gt;
* 16 узлов ввода-вывода в стойке (в текущей конфигурации активны 8, т.е. одна I/O-карта на 128 вычислительных узлов)&lt;br /&gt;
* программирование с использованием MPI, OpenMP/pthreads, POSIX I/O&lt;br /&gt;
* высокая энергоэффективность: ∼ 372 MFlops/W&lt;br /&gt;
&lt;br /&gt;
Вычислительный узел включает в себя четырехъядерный процессор, 2 ГБ общей памяти и сетевые интерфейсы.&lt;br /&gt;
&lt;br /&gt;
Вычислительной узел:&lt;br /&gt;
* четыре микропроцессорных ядра PowerPC 450 (4-way SMP)&lt;br /&gt;
* пиковая производительность: 4 ядра x 3,4 GFlop/sec на ядро = 13,6 GFlop/sec&lt;br /&gt;
* пропускная способность памяти: 13,6 GB/sec&lt;br /&gt;
* 2 ГБ общей памяти&lt;br /&gt;
* 2 x 4 МБ кэш-памяти 2-го уровня (в документации по BG/P носит название L3)&lt;br /&gt;
* легковесное ядро (compute node kernel, CNK), представляющее собой Linux-подобную операционную систему, поддерживающую значительное подмножество Linux-совместимых системных вызовов&lt;br /&gt;
* асинхронные операции межпроцессорных обменов (выполняются параллельно с вычислениями)&lt;br /&gt;
* операции ввода-вывода перенаправляются I/O-картам через сеть коллективных операций&lt;br /&gt;
&lt;br /&gt;
[[Файл:Time.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 2.&#039;&#039;&#039; Время выполнения параллельной реализации БПФ в секундах. Size - число элементов массива. Р - число использованных процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Efff.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 3.&#039;&#039;&#039; Эффективность параллельной реализации БПФ. Size - число элементов массива. Р - число использованных процессоров. Эффективность в пределах от 0 до 1.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из графика, эффективность параллельной реализации резко падает с ростом количества используемых процессоров, связано это с увеличением количества накладных расходов.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Википедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Chachba.A&amp;diff=17824</id>
		<title>Обсуждение участника:Chachba.A</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Chachba.A&amp;diff=17824"/>
		<updated>2016-11-16T22:08:46Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Замечания к статье */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к статье ==&lt;br /&gt;
&lt;br /&gt;
* п.п. 1.8, 1.9 не раскрыты--[[Участник:IgorS|IgorS]] ([[Обсуждение участника:IgorS|обсуждение]]) 14:57, 25 октября 2016 (MSK)&lt;br /&gt;
** исправлено&lt;br /&gt;
* не указан конкретный вклад каждого автора--[[Участник:IgorS|IgorS]] ([[Обсуждение участника:IgorS|обсуждение]]) 14:57, 25 октября 2016 (MSK)&lt;br /&gt;
** исправлено&lt;br /&gt;
* в п.п. 2.4 следует добавить описание компьютерной платформы, текст исследуемой программы.--[[Участник:IgorS|IgorS]] ([[Обсуждение участника:IgorS|обсуждение]]) 13:41, 16 ноября 2016 (MSK)&lt;br /&gt;
** сделано&lt;br /&gt;
&lt;br /&gt;
== Замечания к статье &amp;quot;Быстрое дискретное преобразование Фурье&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
* Перенесите пожалуйста статью в личное пространство [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK) &lt;br /&gt;
** а как это сделать? У нас нет прав на это, похоже&lt;br /&gt;
* Раздел 1.1 - в самом первом абзаце стоит вставить обозначения двух фунций - f и f с крышкой, чтобы было ясно, что куда отображается. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK) &lt;br /&gt;
** Done&lt;br /&gt;
* В общее описание алгоритма нужно вставить слова именно об алгоритме, а не только о математической задаче. В чем быстрота, за счет чего она достигается и т.д. Тут, в отличие от математического описания, не стоит увлекаться формулами. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;br /&gt;
* Раздел 1.2 - существует обозначение части формулы через эпсилон, однако в следующей формуле он не встречается, странно. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;br /&gt;
* Нужно пояснение, что происходит, когда N не представимо в виде произведения: применим ли алгоритм и в каких изменениях он нуждается. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;br /&gt;
* Нет данных о глубине рекурсии, написать об этом явно, скорее всего, в разделе &amp;quot;вычислительное ядро алгоритма&amp;quot;. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17823</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17823"/>
		<updated>2016-11-16T22:08:13Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] &lt;br /&gt;
&lt;br /&gt;
[[Участник:Chachba.A|Чачба А.Н.]] заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, [[Участник:Weasel|Костоев Р.С.]] написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; вещественной переменной, называемой таргетным сигналом, с другой функцией &amp;lt;math&amp;gt;\hat{f}&amp;lt;/math&amp;gt; вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, есть аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяется в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Такая скорость достигается благодаря применению схемы &amp;quot;разделяй и властвуй&amp;quot;. Общий вид преобразования позволяет разделить массив на несколько частей таким образом, что, применяя преобразование Фурье к отдельным его частям и объединяя специальным образом результаты (при помощи поворотных множителей и повторного применения преобразования), получать на выходе образ исходного вектора. Но благодаря разделению массива исходного размера на части суммарная асимптотическая сложность алгоритма уменьшается.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{\varepsilon_{N}^{(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;. Так как рекурсия применяется каждый раз при отщеплении одного множителя, то можно заключить, что глубина рекурсии алгоритма составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;-число множителей в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В свою очередь, если число &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; не факторизуется в произведение простых множителей (то есть &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - простое число), то данный алгоритм не применим. На замену ему приходит алгоритм Радера, имеющий худшую асимптотику, нежели обычный БПФ, но лучшую чем &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;. Также алгоритм Радера потребует дополнительного взаимодействия процессоров, что приведет к ухудшению эффективности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Все запуски программы[http://pastebin.com/raw/xajKb9JN] проводились на с/к Blue Gene/P.&lt;br /&gt;
&lt;br /&gt;
IBM Blue Gene/P — массивно-параллельная вычислительная система, которая состоит из двух стоек, включающих 2048 четырехъядерных вычислительных узлов, с пиковой производительностью 27,9 терафлопс.&lt;br /&gt;
&lt;br /&gt;
Характеристики системы:&lt;br /&gt;
* две стойки с вычислительными узлами и узлами ввода-вывода&lt;br /&gt;
* 1024 четырехъядерных вычислительных узла в каждой из стоек&lt;br /&gt;
* 16 узлов ввода-вывода в стойке (в текущей конфигурации активны 8, т.е. одна I/O-карта на 128 вычислительных узлов)&lt;br /&gt;
* программирование с использованием MPI, OpenMP/pthreads, POSIX I/O&lt;br /&gt;
* высокая энергоэффективность: ∼ 372 MFlops/W&lt;br /&gt;
&lt;br /&gt;
Вычислительный узел включает в себя четырехъядерный процессор, 2 ГБ общей памяти и сетевые интерфейсы.&lt;br /&gt;
&lt;br /&gt;
Вычислительной узел:&lt;br /&gt;
* четыре микропроцессорных ядра PowerPC 450 (4-way SMP)&lt;br /&gt;
* пиковая производительность: 4 ядра x 3,4 GFlop/sec на ядро = 13,6 GFlop/sec&lt;br /&gt;
* пропускная способность памяти: 13,6 GB/sec&lt;br /&gt;
* 2 ГБ общей памяти&lt;br /&gt;
* 2 x 4 МБ кэш-памяти 2-го уровня (в документации по BG/P носит название L3)&lt;br /&gt;
* легковесное ядро (compute node kernel, CNK), представляющее собой Linux-подобную операционную систему, поддерживающую значительное подмножество Linux-совместимых системных вызовов&lt;br /&gt;
* асинхронные операции межпроцессорных обменов (выполняются параллельно с вычислениями)&lt;br /&gt;
* операции ввода-вывода перенаправляются I/O-картам через сеть коллективных операций&lt;br /&gt;
&lt;br /&gt;
[[Файл:Time.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 2.&#039;&#039;&#039; Время выполнения параллельной реализации БПФ в секундах. Size - число элементов массива. Р - число использованных процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Efff.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 3.&#039;&#039;&#039; Эффективность параллельной реализации БПФ. Size - число элементов массива. Р - число использованных процессоров. Эффективность в пределах от 0 до 1.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из графика, эффективность параллельной реализации резко падает с ростом количества используемых процессоров, связано это с увеличением количества накладных расходов.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Википедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17134</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17134"/>
		<updated>2016-11-14T21:24:35Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] &lt;br /&gt;
&lt;br /&gt;
[[Участник:Chachba.A|Чачба А.Н.]] заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, [[Участник:Weasel|Костоев Р.С.]] написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; вещественной переменной, называемой таргетным сигналом, с другой функцией &amp;lt;math&amp;gt;\hat{f}&amp;lt;/math&amp;gt; вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, есть аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяется в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Такая скорость достигается благодаря применению схемы &amp;quot;разделяй и властвуй&amp;quot;. Общий вид преобразования позволяет разделить массив на несколько частей таким образом, что, применяя преобразование Фурье к отдельным его частям и объединяя специальным образом результаты (при помощи поворотных множителей и повторного применения преобразования), получать на выходе образ исходного вектора. Но благодаря разделению массива исходного размера на части суммарная асимптотическая сложность алгоритма уменьшается.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{\varepsilon_{N}^{(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;. Так как рекурсия применяется каждый раз при отщеплении одного множителя, то можно заключить, что глубина рекурсии алгоритма составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;-число множителей в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В свою очередь, если число &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; не факторизуется в произведение простых множителей (то есть &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - простое число), то данный алгоритм не применим. На замену ему приходит алгоритм Радера, имеющий худшую асимптотику, нежели обычный БПФ, но лучшую чем &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;. Также алгоритм Радера потребует дополнительного взаимодействия процессоров, что приведет к ухудшению эффективности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
[[Файл:Time.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 2.&#039;&#039;&#039; Время выполнения параллельной реализации БПФ в секундах. Size - число элементов массива. Р - число использованных процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Efff.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 3.&#039;&#039;&#039; Эффективность параллельной реализации БПФ. Size - число элементов массива. Р - число использованных процессоров. Эффективность в пределах от 0 до 1.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из графика, эффективность параллельной реализации резко падает с ростом количества используемых процессоров, связано это с увеличением количества накладных расходов.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Википедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17130</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17130"/>
		<updated>2016-11-14T20:59:59Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] &lt;br /&gt;
&lt;br /&gt;
[[Участник:Chachba.A|Чачба А.Н.]] заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, [[Участник:Weasel|Костоев Р.С.]] написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; вещественной переменной, называемой таргетным сигналом, с другой функцией &amp;lt;math&amp;gt;\hat{f}&amp;lt;/math&amp;gt; вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, есть аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяется в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Такая скорость достигается благодаря применению схемы разделяй и властвуй. Общий вид преобразования позволяет разделить массив на несколько частей таким образом, что, применяя преобразование Фурье к отдельным его частям и объединяя специальным образом результаты (при помощи поворотных множителей и повторного применения преобразования), получать на выходе образ исходного вектора. Но благодаря разделению массива исходного размера на части суммарная асимптотическая сложность алгоритма уменьшается.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{\varepsilon_{N}^{(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;. Так как рекурсия применяется каждый раз при отщеплении одного множителя, то можно заключить, что глубина рекурсии алгоритма составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;-число множителей в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В свою очередь, если число &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; не факторизуется в произведение простых множителей (то есть &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - простое число), то данный алгоритм не применим. На замену ему приходит алгоритм Радера, имеющий худшую асимптотику, нежели обычный БПФ, но лучшую чем &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;. Также алгоритм Радера потребует дополнительного взаимодействия процессоров, что приведет к ухудшению эффективности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
[[Файл:Time.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 2.&#039;&#039;&#039; Время выполнения параллельной реализации БПФ в секундах. Size - число элементов массива. Р - число использованных процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Efff.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 3.&#039;&#039;&#039; Эффективность параллельной реализации БПФ. Size - число элементов массива. Р - число использованных процессоров. Эффективность в пределах от 0 до 1.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из графика, эффективность параллельной реализации резко падает с ростом количества используемых процессоров, связано это с увеличением количества накладных расходов.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Википедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Chachba.A&amp;diff=17129</id>
		<title>Обсуждение участника:Chachba.A</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Chachba.A&amp;diff=17129"/>
		<updated>2016-11-14T20:59:48Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Замечания к статье &amp;quot;Быстрое дискретное преобразование Фурье&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к статье ==&lt;br /&gt;
&lt;br /&gt;
* п.п. 1.8, 1.9 не раскрыты--[[Участник:IgorS|IgorS]] ([[Обсуждение участника:IgorS|обсуждение]]) 14:57, 25 октября 2016 (MSK)&lt;br /&gt;
** исправлено&lt;br /&gt;
* не указан конкретный вклад каждого автора--[[Участник:IgorS|IgorS]] ([[Обсуждение участника:IgorS|обсуждение]]) 14:57, 25 октября 2016 (MSK)&lt;br /&gt;
** исправлено&lt;br /&gt;
&lt;br /&gt;
== Замечания к статье &amp;quot;Быстрое дискретное преобразование Фурье&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
* Перенесите пожалуйста статью в личное пространство [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK) &lt;br /&gt;
** а как это сделать? &lt;br /&gt;
* Раздел 1.1 - в самом первом абзаце стоит вставить обозначения двух фунций - f и f с крышкой, чтобы было ясно, что куда отображается. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK) &lt;br /&gt;
** Done&lt;br /&gt;
* В общее описание алгоритма нужно вставить слова именно об алгоритме, а не только о математической задаче. В чем быстрота, за счет чего она достигается и т.д. Тут, в отличие от математического описания, не стоит увлекаться формулами. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;br /&gt;
* Раздел 1.2 - существует обозначение части формулы через эпсилон, однако в следующей формуле он не встречается, странно. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;br /&gt;
* Нужно пояснение, что происходит, когда N не представимо в виде произведения: применим ли алгоритм и в каких изменениях он нуждается. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;br /&gt;
* Нет данных о глубине рекурсии, написать об этом явно, скорее всего, в разделе &amp;quot;вычислительное ядро алгоритма&amp;quot;. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 13:31, 11 ноября 2016 (MSK)&lt;br /&gt;
** Done&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17128</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17128"/>
		<updated>2016-11-14T20:59:18Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|IgorS}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] &lt;br /&gt;
&lt;br /&gt;
[[Участник:Chachba.A|Чачба А.Н.]] заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, [[Участник:Weasel|Костоев Р.С.]] написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; вещественной переменной, называемой таргетным сигналом, с другой функцией &amp;lt;math&amp;gt;\hat{f}&amp;lt;/math&amp;gt; вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, есть аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяется в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Такая скорость достигается благодаря применению схемы разделяй и властвуй. Общий вид преобразования позволяет разделить массив на несколько частей таким образом, что, применяя преобразование Фурье к отдельным его частям и объединяя специальным образом результаты (при помощи поворотных множителей и повторного применения преобразования), получать на выходе образ исходного вектора. Но благодаря разделению массива исходного размера на части суммарная асимптотическая сложность алгоритма уменьшается.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{\varepsilon_{N}^{(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;. Так как рекурсия применяется каждый раз при отщеплении одного множителя, то можно заключить, что глубина рекурсии алгоритма составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;-число множителей в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В свою очередь, если число &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; не факторизуется в произведение простых множителей (то есть &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - простое число), то данный алгоритм не применим. На замену ему приходит алгоритм Радера, имеющий худшую асимптотику, нежели обычный БПФ, но лучшую чем &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;. Также алгоритм Радера потребует дополнительного взаимодействия процессоров, что приведет к ухудшению эффективности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
[[Файл:Time.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 2.&#039;&#039;&#039; Время выполнения параллельной реализации БПФ в секундах. Size - число элементов массива. Р - число использованных процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Efff.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 3.&#039;&#039;&#039; Эффективность параллельной реализации БПФ. Size - число элементов массива. Р - число использованных процессоров. Эффективность в пределах от 0 до 1.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из графика, эффективность параллельной реализации резко падает с ростом количества используемых процессоров, связано это с увеличением количества накладных расходов.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Википедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17120</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=17120"/>
		<updated>2016-11-14T20:05:39Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|IgorS}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] &lt;br /&gt;
&lt;br /&gt;
[[Участник:Chachba.A|Чачба А.Н.]] заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, [[Участник:Weasel|Костоев Р.С.]] написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, есть аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяется в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
[[Файл:Time.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 2.&#039;&#039;&#039; Время выполнения параллельной реализации БПФ в секундах. Size - число элементов массива. Р - число использованных процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Efff.PNG|center|thumb|640px|&#039;&#039;&#039;Рисунок 3.&#039;&#039;&#039; Эффективность параллельной реализации БПФ. Size - число элементов массива. Р - число использованных процессоров. Эффективность в пределах от 0 до 1.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из графика, эффективность параллельной реализации резко падает с ростом количества используемых процессоров, связано это с увеличением количества накладных расходов.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Вкипедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14361</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14361"/>
		<updated>2016-10-28T12:00:20Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] &lt;br /&gt;
&lt;br /&gt;
[[Участник:Chachba.A|Чачба А.Н.]] заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, [[Участник:Weasel|Костоев Р.С.]] написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Вкипедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14041</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14041"/>
		<updated>2016-10-26T14:47:31Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] &lt;br /&gt;
&lt;br /&gt;
[[Участник:Chachba.A|Чачба А.Н.]] заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, [[Участник:Weasel|Костоев Р.С.]] написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Вкипедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Chachba.A&amp;diff=14040</id>
		<title>Обсуждение участника:Chachba.A</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Chachba.A&amp;diff=14040"/>
		<updated>2016-10-26T14:45:12Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Замечания к статье */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к статье ==&lt;br /&gt;
&lt;br /&gt;
* п.п. 1.8, 1.9 не раскрыты--[[Участник:IgorS|IgorS]] ([[Обсуждение участника:IgorS|обсуждение]]) 14:57, 25 октября 2016 (MSK)&lt;br /&gt;
** исправлено&lt;br /&gt;
* не указан конкретный вклад каждого автора--[[Участник:IgorS|IgorS]] ([[Обсуждение участника:IgorS|обсуждение]]) 14:57, 25 октября 2016 (MSK)&lt;br /&gt;
** исправлено&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14039</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14039"/>
		<updated>2016-10-26T14:44:43Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] &lt;br /&gt;
&lt;br /&gt;
[[Участник:Chachba.A|Чачба А.Н.]] заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, [[Участник:Weasel|Костоев Р.С.]] написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Вкипедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14038</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14038"/>
		<updated>2016-10-26T14:43:44Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]] Чачба А.Н. заполнил половину всех заполненных пунктов (а именно 1.1, 1.2, 1.6, 1.8, 1.9) и построил информационный граф алгоритма, Костоев Р.С. написал программу и провел серию запусков на суперкомпьютере и заполнил вторую половину пунктов. Оба после заполнения исправляли найденные ошибки во всех пунктах.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Вкипедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14030</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14030"/>
		<updated>2016-10-26T14:32:42Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексным полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору:&lt;br /&gt;
&amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; - исходные сигналы. Обозначим &amp;lt;math&amp;gt;z = x + iy&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;F(k, x)&amp;lt;/math&amp;gt; - это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ый коэффициент образа Фурье вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - F(k, \bar z)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая, что &amp;lt;math&amp;gt;F(k, \bar z) = \overline{F(N - k, z)}&amp;lt;/math&amp;gt;, получаем:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, x) = \frac{F(k, z) + \overline{F(N-k, z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;F(k, y) = -i\frac{F(k, z) - \overline{F(N-k,z)}}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такой способ позволяет приблизительно в два раза уменьшить количество вычислений.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел - спектр исходного сигнала.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Вкипедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14020</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=14020"/>
		<updated>2016-10-26T14:07:35Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
В силу независимости всех рекурсивных вызовов и того факта, что путь максимальной длины в графе (так называемый критический путь) имеет порядок &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;, можно утверждать, что параллельная сложность алгоритма составит &amp;lt;math&amp;gt;O(\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Замечание&#039;&#039;: формально основание логарифма на каждом рекурсивном шаге зависит от множителя в факторизации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, потому использована О-символика.&lt;br /&gt;
&lt;br /&gt;
При условии ограниченности количества доступных вычислительных узлов рекомендуется выбирать множители в разложении числа $N$ близкими к числу доступных узлов, таким образом доступные ресурсы будут использованы максимально эффективно.&lt;br /&gt;
&lt;br /&gt;
Итого алгоритм относится к логарифмическому классу алгоритмов по параллельной сложности.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексым полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору.&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Вкипедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=9157</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=9157"/>
		<updated>2016-10-15T10:51:07Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Литература */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Пусть имеется неограниченное число процессоров, тогда учитывая схему алгоритма БПФ, максимальное число одновременно работающих процессоров может составлять &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, тогда сложность алгоритма на &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; процессорах составит &amp;lt;math&amp;gt;\log{N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексым полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору.&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Вкипедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=9152</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=9152"/>
		<updated>2016-10-15T10:50:50Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Пусть имеется неограниченное число процессоров, тогда учитывая схему алгоритма БПФ, максимальное число одновременно работающих процессоров может составлять &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, тогда сложность алгоритма на &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; процессорах составит &amp;lt;math&amp;gt;\log{N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексым полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору.&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
* Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&lt;br /&gt;
* Описание алгоритма на Вкипедии: [https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5 Быстрое преобразование Фурье]&lt;br /&gt;
* Материалы лекций по &amp;quot;Алгоритмам и структурам данных&amp;quot; Школы Анализа Данных Яндекса ()&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=9099</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=9099"/>
		<updated>2016-10-15T10:41:57Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
В последовательном варианте можно бороться за улучшение константы сложности, предподсчитав значения соответствующих коэффициентов.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Пусть имеется неограниченное число процессоров, тогда учитывая схему алгоритма БПФ, максимальное число одновременно работающих процессоров может составлять &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, тогда сложность алгоритма на &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; процессорах составит &amp;lt;math&amp;gt;\log{N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексым полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору.&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=9009</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=9009"/>
		<updated>2016-10-15T10:23:58Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;{k}&amp;lt;/math&amp;gt; рекурсий на первом этапе и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; на последнем этапе, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Пусть имеется неограниченное число процессоров, тогда учитывая схему алгоритма БПФ, максимальное число одновременно работающих процессоров может составлять &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, тогда сложность алгоритма на &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; процессорах составит &amp;lt;math&amp;gt;\log{N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексым полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору.&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=8974</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=8974"/>
		<updated>2016-10-15T10:12:50Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;O(N{k})&amp;lt;/math&amp;gt; уровней рекурсии, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Пусть имеется неограниченное число процессоров, тогда учитывая схему алгоритма БПФ, максимальное число одновременно работающих процессоров может составлять &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, тогда сложность алгоритма на &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; процессорах составит &amp;lt;math&amp;gt;\log{N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексым полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору.&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* Самая популярная библиотека для работы с преобразованиями Фурье это [http://www.fftw.org FFTW]&lt;br /&gt;
* Реализация от Intel в рамках [//software.intel.com/en-us/intel-mkl Math Kernel Library]&lt;br /&gt;
* Реализация ДПФ на графических картах от NVidia - [//developer.nvidia.com/cufft cuFFT]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7759</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7759"/>
		<updated>2016-10-14T16:19:37Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;O(N{k})&amp;lt;/math&amp;gt; уровней рекурсии, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Алгоритм состоит из трех этапов, следовательно если &amp;lt;math&amp;gt;N = \prod_{i = 1}^np_i&amp;lt;/math&amp;gt;, то общая сложность составляет порядка &amp;lt;math&amp;gt;O(N\sum_{i=1}^np_i)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Пусть существует некоторое фиксированное число &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, такое что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
p_i \leq P \quad \forall i = 1...n,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
тогда, учитывая, что &amp;lt;math&amp;gt;n \leq \log_{P}{N}&amp;lt;/math&amp;gt;, сложность алгоритма можно записать в виде &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Пусть имеется неограниченное число процессоров, тогда учитывая схему алгоритма БПФ, максимальное число одновременно работающих процессоров может составлять &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, тогда сложность алгоритма на &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; процессорах составит &amp;lt;math&amp;gt;\log{N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;:&lt;br /&gt;
Чаще всего для обработки сигналов в качестве входных данных для БПФ подается вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вещественных элементов. Но БПФ работает и для случая элементов над комплексым полем. Таким образом, например, можно экономить на количестве применений БПФ в некоторой конкретной задаче путем приведения двух векторов вещественных чисел к одному вектору комплексных чисел с вещественной частью равной первому вектору и комплексной частью равной второму вектору.&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;:&lt;br /&gt;
Вектор размерности &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; комплексных чисел.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Матрица Вандермонда преобразования &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt; такая, что:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
A^{-1} = \frac{1}{N}A^*&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом обратное преобразование Фурье с точностью до нормирующего множителя и сопряжения элементов матрицы совпадает с прямым.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7409</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7409"/>
		<updated>2016-10-14T12:04:59Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;O(N{k})&amp;lt;/math&amp;gt; уровней рекурсии, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура БПФ для случая &amp;lt;math&amp;gt;N = km&amp;lt;/math&amp;gt; описывается рекурсивно:&lt;br /&gt;
# &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; независимых преобразований векторов меньшей размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
#Умножение элементов на поворотные коэффициенты (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; умножений)&lt;br /&gt;
# &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обратных преобразований векторов размерностей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7407</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7407"/>
		<updated>2016-10-14T11:57:40Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;O(N{k})&amp;lt;/math&amp;gt; уровней рекурсии, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем же случае, когда &amp;lt;math&amp;gt;N = \prod_{i=1}^np_i&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt; O(N(\sum_{i=1}^np_i))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7404</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7404"/>
		<updated>2016-10-14T11:54:27Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Пусть, для простоты &amp;lt;math&amp;gt; N = km&amp;lt;/math&amp;gt;, тогда рекурсивная реализация преобразования Фурье, за счет &amp;lt;math&amp;gt;O(N{k})&amp;lt;/math&amp;gt; уровней рекурсии, имеет суммарную сложность &amp;lt;math&amp;gt;O(Nk + Nm + km) = O(N(k + m))&amp;lt;/math&amp;gt;. В случае, например &amp;lt;math&amp;gt;N = 2^n&amp;lt;/math&amp;gt; сложность БПФ составляет &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7371</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7371"/>
		<updated>2016-10-14T11:30:46Z</updated>

		<summary type="html">&lt;p&gt;Weasel: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph2.png|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7354</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=7354"/>
		<updated>2016-10-14T11:13:23Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод для случая &amp;lt;math&amp;gt;N = 2^k&amp;lt;/math&amp;gt;, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[Файл:FourierGraph.svg|center|thumb|640px|&#039;&#039;&#039;Рисунок 1.&#039;&#039;&#039; Информационный граф преобразования Кули-Тьюки для &amp;lt;math&amp;gt;N = km = 25, k = 5, m = 5&amp;lt;/math&amp;gt;. Желтые вершины - умножение на поворотные множители.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=6069</id>
		<title>Быстрое дискретное преобразование Фурье (БПФ)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%B4%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5_(%D0%91%D0%9F%D0%A4)&amp;diff=6069"/>
		<updated>2016-10-12T20:39:43Z</updated>

		<summary type="html">&lt;p&gt;Weasel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Chachba.A|Чачба А.Н.]], [[Участник:Weasel|Костоев Р.С.]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Быстрое преобразование Фурье (БПФ)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N \log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Преобразование Фурье - взаимно однозначное отображение одной функции вещественной, называемой таргетным сигналом, с другой функцией вещественной переменной, называемой образом Фурье или спектром исходной функции по формуле:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\hat{f}(\omega)=\frac{1}{\sqrt{2\pi}}\int\limits_{-\infty}^{\infty}f(x)e^{-ix\omega}\,dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Дискретное преобразование Фурье, в свою очередь, если аналог непрерывного преобразования Фурье, но для дискретного сигнала содержащего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; отсчетов.&lt;br /&gt;
Широко применяет в цифровой обработке сигналов, теории вероятностей, криптографии и акустике.&lt;br /&gt;
Преобразование Фурье обратимо, причем обратное преобразование имеет практически ту же форму, что и прямое.&lt;br /&gt;
Преобразование Фурье имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;, но существует быстрый вариант преобразование Фурье со сложностью &amp;lt;math&amp;gt;O(N\log{N})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Пусть исходный сигнал имеет значения &amp;lt;math&amp;gt;x_n,\quad n = 0,\dots,N-1&amp;lt;/math&amp;gt;, тогда дискретное прямое преобразование Фурье (ДПФ) имеет вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
X_k = \sum_{n=0}^{N-1}x_ne^{-\frac{2\pi i}{N}kn},\quad k = 0, \dots, N-1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Обозначим &amp;lt;math&amp;gt; \varepsilon_{N} = e^{-\frac{2\pi i}{N}}&amp;lt;/math&amp;gt;, тогда ДПФ можно перезаписать в матричной форме:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\bar X = A\bar x&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где матрица &amp;lt;math&amp;gt;A = \{e^{-\frac{2\pi i}{N}(i - 1)(j - 1)}\}_{i,j=1}^{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Рекурсивный метод, без оптимизации на C++:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;complex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
typedef complex&amp;lt;double&amp;gt; cd;&lt;br /&gt;
typedef vector&amp;lt;cd&amp;gt; vcd;&lt;br /&gt;
&lt;br /&gt;
vcd fft(const vcd &amp;amp;as) { &lt;br /&gt;
  int n = as.size();&lt;br /&gt;
  if (n == 1) return vcd(1, as[0]);&lt;br /&gt;
&lt;br /&gt;
  vcd w(n); // Calculate roots&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
    double alpha = 2 * M_PI * i / n;&lt;br /&gt;
    w[i] = cd(cos(alpha), sin(alpha));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  vcd A(n / 2), B(n / 2);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n / 2; i++) {&lt;br /&gt;
    A[i] = as[i * 2];&lt;br /&gt;
    B[i] = as[i * 2 + 1];&lt;br /&gt;
  }&lt;br /&gt;
  vcd Av = fft(A);&lt;br /&gt;
  vcd Bv = fft(B);&lt;br /&gt;
  vcd res(n);&lt;br /&gt;
  for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    res[i] =   Av[i % (n / 2)] +&lt;br /&gt;
        w[i] * Bv[i % (n / 2)];&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Weasel</name></author>
	</entry>
</feed>