<?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=%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2+%D0%AE%D1%80%D0%B8%D0%B9</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=%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2+%D0%AE%D1%80%D0%B8%D0%B9"/>
	<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/%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9"/>
	<updated>2026-10-22T19:39:41Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18631</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18631"/>
		<updated>2016-11-20T18:50:46Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Sleo}}&lt;br /&gt;
Авторы: [[U:Бугаков Юрий|Бугаков Юрий]] (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
То есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Blue Gene&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых  параметров запуска реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1, 2, 4, 8,..., 1024] ;&lt;br /&gt;
*	размер матрицы [2, 4, 8,..., 2048].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.0121%;&lt;br /&gt;
*	максимальная эффективность реализации 3.3003%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации построение матрицы Адамара в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:Prois1.jpg|thumb|center|700px|Рис.5 Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file:Effec1.jpg|thumb|center|700px|Рис.5 Изменение эффективности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации:&lt;br /&gt;
* При увеличении числа процессов производительность на рассмотренной области изменений параметров запуска увеличивается практически линейно. В следствии этого эффективность реализации, как видно по графику, перестает изменяться при увеличении числа процессоров и равна примерно 1,7%.&lt;br /&gt;
* При увеличении размера матрицы производительность на рассмотренной области изменений параметров запуска увеличивается логарифмически. Это связанно с тем, что количество операций зависит от количества единиц после бинарного произведения. Поэтому наиболее влияет порядок степени &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; размера матрицы &amp;lt;math&amp;gt;N=2^{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;
&lt;br /&gt;
Примеры вычислительных пакетов, содержащих функции генерации матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
# [http://www.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18630</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18630"/>
		<updated>2016-11-20T18:48:26Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Sleo}}&lt;br /&gt;
Авторы: [[U:Бугаков Юрий|Бугаков Юрий]] (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
То есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Blue Gene&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых  параметров запуска реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1, 2, 4, 8,..., 1024] ;&lt;br /&gt;
*	размер матрицы [2, 4, 8,..., 2048].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.0121%;&lt;br /&gt;
*	максимальная эффективность реализации 3.3003%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации построение матрицы Адамара в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:Prois1.jpg|thumb|center|700px|Рис.5 Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file:Effec1.jpg|thumb|center|700px|Рис.5 Изменение эффективности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации:&lt;br /&gt;
* При увеличении числа процессов производительность на рассмотренной области изменений параметров запуска увеличивается практически линейно. В следствии этого эффективность реализации, как видно по графику, перестает изменяться при увеличении числа процессоров и равна примерно 1,7%.&lt;br /&gt;
* При увеличении размера матрицы производительность на рассмотренной области изменений параметров запуска увеличивается логарифмически. Это связанно с тем, что количество операций зависит от количества единиц после бинарного произведения. Поэтому наиболее влияет порядок степени &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; размера матрицы &amp;lt;math&amp;gt;N=2^{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;
&lt;br /&gt;
Примеры вычислительных пакетов, содержащих функции генерации матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
# [http://www.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18628</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18628"/>
		<updated>2016-11-20T18:38:51Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Sleo}}&lt;br /&gt;
Авторы: [[U:Бугаков Юрий|Бугаков Юрий]] (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
То есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Blue Gene&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых  параметров запуска реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1, 2, 4, 8,..., 1024] ;&lt;br /&gt;
*	размер матрицы [2, 4, 8,..., 2048].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.0121%;&lt;br /&gt;
*	максимальная эффективность реализации 3.3003%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации построение матрицы Адамара в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:Prois1.jpg|thumb|center|700px|Рис.5 Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file:Effec1.jpg|thumb|center|700px|Рис.5 Изменение эффективности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации:&lt;br /&gt;
* При увеличении числа процессов производительность на рассмотренной области изменений параметров запуска увеличивается практически линейно. В следствии этого эффективность реализации, как видно по графику, перестает изменяться при увеличении числа процессоров и равна примерно 1,7%.&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;.   Эффективность возрастает тем быстрее, чем большее число процессов используется для выполнения. Это подтверждает предположение о том, что размер задачи сильно влияет на эффективность выполнения приложения. Оценка показывает, что с ростом размера задачи эффективность на рассмотренной области значений параметров запуска сильно увеличивается. Также, учитывая разницу максимальной и минимальной эффективности в 2,5%, можно сделать вывод, что рост эффективности при увеличении размера задачи наблюдается на большей части рассмотренной области значений.&lt;br /&gt;
По двум направлениям: 0,000403. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая. В совокупности с тем фактом, что разница между максимальной и минимальной эффективностью на рассмотренной области значений параметров небольшая, эффективность с увеличением масштабов возрастает, но медленно и с небольшими перепадами.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18625</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18625"/>
		<updated>2016-11-20T18:37:31Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Sleo}}&lt;br /&gt;
Авторы: [[U:Бугаков Юрий|Бугаков Юрий]] (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
То есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Blue Gene&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых  параметров запуска реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1, 2, 4, 8,..., 1024] ;&lt;br /&gt;
*	размер матрицы [2, 4, 8,..., 2048].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.0121%;&lt;br /&gt;
*	максимальная эффективность реализации 3.3003%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации построение матрицы Адамара в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:Prois1.jpg|thumb|center|700px|Рис.5 Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file:Effec1.jpg|thumb|center|700px|Рис.5 Изменение эффективности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации:&lt;br /&gt;
* При увеличении числа процессов производительность на рассмотренной области изменений параметров запуска увеличивается практически линейно. В следствии этого эффективность реализации, как видно по графику, перестает изменяться при увеличении числа процессоров и равна примерно 1,7%.&lt;br /&gt;
* При увеличении размера матрицы производительность на рассмотренной области изменений параметров запуска увеличивается логарифмически. Это связанно с тем, что количество операций зависит от количества единиц после бинарного произведения. Поэтому наиболее влияет порядок n степени размера матрицы.   Эффективность возрастает тем быстрее, чем большее число процессов используется для выполнения. Это подтверждает предположение о том, что размер задачи сильно влияет на эффективность выполнения приложения. Оценка показывает, что с ростом размера задачи эффективность на рассмотренной области значений параметров запуска сильно увеличивается. Также, учитывая разницу максимальной и минимальной эффективности в 2,5%, можно сделать вывод, что рост эффективности при увеличении размера задачи наблюдается на большей части рассмотренной области значений.&lt;br /&gt;
По двум направлениям: 0,000403. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая. В совокупности с тем фактом, что разница между максимальной и минимальной эффективностью на рассмотренной области значений параметров небольшая, эффективность с увеличением масштабов возрастает, но медленно и с небольшими перепадами.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18617</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18617"/>
		<updated>2016-11-20T18:15:04Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Sleo}}&lt;br /&gt;
Авторы: [[U:Бугаков Юрий|Бугаков Юрий]] (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
То есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Blue Gene&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых  параметров запуска реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1, 2, 4, 8,..., 1024] ;&lt;br /&gt;
*	размер матрицы [2, 4, 8,..., 2048].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.0121%;&lt;br /&gt;
*	максимальная эффективность реализации 3.3003%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации построение матрицы Адамара в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:Prois1.jpg|thumb|center|700px|Рис.5 Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file:Effec1.jpg|thumb|center|700px|Рис.5 Изменение эффективности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации:&lt;br /&gt;
* При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска уменьшается, однако в целом уменьшение не очень быстрое. Малая интенсивность изменения объясняется крайне низкой общей эффективностью работы приложения с максимумом в 2,65%, и значение эффективности на рассмотренной области значений быстро доходит до десятых долей процента. Это свидетельствует о том, что на большей части области значений нет интенсивного снижения эффективности. Это объясняется также тем, что с ростом вычислительной сложности падение эффективности становится не таким быстрым. Уменьшение эффективности на рассмотренной области работы параллельной программы объясняется быстрым ростом накладных расходов на организацию параллельного выполнения. С ростом вычислительной сложности задачи эффективность снижается так же быстро, но при больших значениях числа процессов. Это подтверждает предположение о том, что накладные расходы начинают сильно превалировать над вычислениями.&lt;br /&gt;
По размеру задачи: 0,06017. При увеличении размера задачи эффективность возрастает. Эффективность возрастает тем быстрее, чем большее число процессов используется для выполнения. Это подтверждает предположение о том, что размер задачи сильно влияет на эффективность выполнения приложения. Оценка показывает, что с ростом размера задачи эффективность на рассмотренной области значений параметров запуска сильно увеличивается. Также, учитывая разницу максимальной и минимальной эффективности в 2,5%, можно сделать вывод, что рост эффективности при увеличении размера задачи наблюдается на большей части рассмотренной области значений.&lt;br /&gt;
По двум направлениям: 0,000403. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая. В совокупности с тем фактом, что разница между максимальной и минимальной эффективностью на рассмотренной области значений параметров небольшая, эффективность с увеличением масштабов возрастает, но медленно и с небольшими перепадами.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18614</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18614"/>
		<updated>2016-11-20T18:03:50Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Sleo}}&lt;br /&gt;
Авторы: [[U:Бугаков Юрий|Бугаков Юрий]] (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
То есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Blue Gene&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых  параметров запуска реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1, 2, 4, 8,..., 1024] ;&lt;br /&gt;
*	размер матрицы [2, 4, 8,..., 2048].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.0121%;&lt;br /&gt;
*	максимальная эффективность реализации 3.3003%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации построение матрицы Адамара в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:Prois.jpg|thumb|center|700px|Рис.5 Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file:Effec.jpg|thumb|center|700px|Рис.5 Изменение эффективности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18613</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18613"/>
		<updated>2016-11-20T18:03:23Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Sleo}}&lt;br /&gt;
Авторы: [[U:Бугаков Юрий|Бугаков Юрий]] (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
То есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Blue Gene&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых  параметров запуска реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1, 2, 4, 8,..., 1024] ;&lt;br /&gt;
*	размер матрицы [2, 4, 8,..., 2048].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.0121%;&lt;br /&gt;
*	максимальная эффективность реализации 3.3003%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации построение матрицы Адамара в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:Pr.jpg|thumb|center|700px|Рис.5 Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file:Ef.jpg|thumb|center|700px|Рис.5 Изменение эффективности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18612</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18612"/>
		<updated>2016-11-20T18:02:23Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Sleo}}&lt;br /&gt;
Авторы: [[U:Бугаков Юрий|Бугаков Юрий]] (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
То есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Blue Gene&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых  параметров запуска реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1, 2, 4, 8,..., 1024] ;&lt;br /&gt;
*	размер матрицы [2, 4, 8,..., 2048].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.0121%;&lt;br /&gt;
*	максимальная эффективность реализации 3.3003%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации построение матрицы Адамара в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:Pr.png|thumb|center|700px|Рис.5 Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file:Ef.png|thumb|center|700px|Рис.5 Изменение эффективности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18611</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18611"/>
		<updated>2016-11-20T18:00:34Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Sleo}}&lt;br /&gt;
Авторы: [[U:Бугаков Юрий|Бугаков Юрий]] (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
То есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Blue Gene&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых  параметров запуска реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1, 2, 4, 8,..., 1024] ;&lt;br /&gt;
*	размер матрицы [2, 4, 8,..., 2048].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.0121%;&lt;br /&gt;
*	максимальная эффективность реализации 3.3003%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации построение матрицы Адамара в зависимости от изменяемых параметров запуска.&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18610</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=18610"/>
		<updated>2016-11-20T17:59:57Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Sleo}}&lt;br /&gt;
Авторы: [[U:Бугаков Юрий|Бугаков Юрий]] (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
То есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Blue Gene&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых  параметров запуска реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1, 2, 4, 8,..., 1024] ;&lt;br /&gt;
*	размер матрицы [2, 4, 8,..., 2048].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.0121%;&lt;br /&gt;
*	максимальная эффективность реализации 3.3003%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации разложения Холецкого в зависимости от изменяемых параметров запуска.&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14323</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14323"/>
		<updated>2016-10-28T09:49:54Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
Авторы: Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
То есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14322</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14322"/>
		<updated>2016-10-28T09:48:16Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
Авторы: Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14260</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14260"/>
		<updated>2016-10-27T19:12:58Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
Авторы: Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14259</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14259"/>
		<updated>2016-10-27T19:11:26Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
Авторы: Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14255</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14255"/>
		<updated>2016-10-27T19:05:44Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
Авторы: Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</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:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9&amp;diff=14229</id>
		<title>Обсуждение участника:Бугаков Юрий</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:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9&amp;diff=14229"/>
		<updated>2016-10-27T14:21:37Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Замечания к оформлению статьи:&lt;br /&gt;
&lt;br /&gt;
1. в первой строке указать авторов и их вклад в статью.&lt;br /&gt;
&lt;br /&gt;
2. в пункте 1.6 перенесите Т(n) в одну строку с концом предложения.&lt;br /&gt;
&lt;br /&gt;
3. в пункте 1.9 указать чему соответствуют разные входные и выходные данные. Иначе непонятно будет человеку, который первый раз на сайте.&lt;br /&gt;
&lt;br /&gt;
4. в пункте 2.7 убрать многоточия или заменить их на другие реализации&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14228</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14228"/>
		<updated>2016-10-27T14:20:27Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Авторы: Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: натуральное число &amp;lt;math&amp;gt; n \in \N &amp;lt;/math&amp;gt; - размерность матрицы Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (натуральное число &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;h_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;, где &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;
Одним из трудных мест параллельной реализации является правильный выбор количества процессов. Рассматривается некоторое фиксированное число процессов &amp;lt;math&amp;gt;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</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:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9&amp;diff=14217</id>
		<title>Обсуждение участника:Бугаков Юрий</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:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9&amp;diff=14217"/>
		<updated>2016-10-27T14:04:20Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Замечания к оформлению статьи:&lt;br /&gt;
&lt;br /&gt;
1. в первой строке указать авторов и их вклад в статью.&lt;br /&gt;
&lt;br /&gt;
2. в пункте 1.6 перенесите Т(n) в одну строку с концом предложения.&lt;br /&gt;
&lt;br /&gt;
3. в пункте 1.9 указать чему соответствуют разные входные и выходные данные. Иначе непонятно будет человеку, который первый раз на сайте.&lt;br /&gt;
&lt;br /&gt;
4. в пункте 2.7 убрать многоточия или заменить их на другие реализации&lt;br /&gt;
&lt;br /&gt;
Замечания 1, 2, 4 учтены. Непонятен 3 пункт.&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14216</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14216"/>
		<updated>2016-10-27T14:02:46Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Авторы: Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14215</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14215"/>
		<updated>2016-10-27T14:02:10Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Авторы: Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.9, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8;&lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14214</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14214"/>
		<updated>2016-10-27T14:01:09Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Авторы: Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8, 1.9;&lt;br /&gt;
* Совместное обсуждение и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14213</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14213"/>
		<updated>2016-10-27T14:00:40Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Авторы: Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа).&lt;br /&gt;
&lt;br /&gt;
Бугаков Юрий: &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.1, 1.2, 1.10, 2.1, 2.7; &lt;br /&gt;
* Совместное обсуждения и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
Кужамалиев Ернур &lt;br /&gt;
&lt;br /&gt;
* Пункты 1.3, 1.4, 1.5, 1.6, 1.7 (рисунки авториские), 1.8, 1.9;&lt;br /&gt;
* Совместное обсуждения и работа (подредактирование) над всей статьей в целом с другим автором.&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14206</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14206"/>
		<updated>2016-10-27T13:41:40Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма &amp;lt;math&amp;gt; T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}. &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;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14205</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14205"/>
		<updated>2016-10-27T13:40:43Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом: &amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14204</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=14204"/>
		<updated>2016-10-27T13:38:42Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave].&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13287</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13287"/>
		<updated>2016-10-20T17:41:26Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13286</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13286"/>
		<updated>2016-10-20T17:40:33Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13285</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13285"/>
		<updated>2016-10-20T17:39:50Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Особенности реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллелинной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13283</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13283"/>
		<updated>2016-10-20T17:38:00Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Особенности реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода построения матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллеливанной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13282</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13282"/>
		<updated>2016-10-20T17:37:12Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллеливанной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13281</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13281"/>
		<updated>2016-10-20T17:35:22Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллеливанной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13280</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13280"/>
		<updated>2016-10-20T17:35:00Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллеливанной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13279</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13279"/>
		<updated>2016-10-20T17:30:27Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O( \left[ \frac{n}{4}\right]\,2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллеливанной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13278</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13278"/>
		<updated>2016-10-20T17:28:48Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(\frac{n}{4}\right]^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&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;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллеливанной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13275</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13275"/>
		<updated>2016-10-20T17:27:38Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Построение матрицы Адамара&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(m2^{2m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(2^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;2^{2n}&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллеливанной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13273</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13273"/>
		<updated>2016-10-20T17:24:33Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Особенности реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у распараллеливанной adamar_not_recursion (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13272</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13272"/>
		<updated>2016-10-20T17:22:22Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,P)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13271</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=13271"/>
		<updated>2016-10-20T17:22:01Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11928</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11928"/>
		<updated>2016-10-15T20:45:18Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара будет следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11585</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11585"/>
		<updated>2016-10-15T19:56:07Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара будет следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right).&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11579</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11579"/>
		<updated>2016-10-15T19:54:59Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будут рассматриваться только такие случаи. Переопределение матрицы Адамара будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right).&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11571</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11571"/>
		<updated>2016-10-15T19:53:16Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будут рассматриваться только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right).&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11544</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11544"/>
		<updated>2016-10-15T19:48:25Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right).&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</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=11538</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=11538"/>
		<updated>2016-10-15T19:46:45Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&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;
Статья: [[Нечеткий_алгоритм_С_средних]]&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;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0&amp;diff=11507</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольного размера</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0&amp;diff=11507"/>
		<updated>2016-10-15T19:40:04Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: Бугаков Юрий переименовал страницу Участника: Бугаков Юрий, Кужамалиев Ернур/Построение матрицы Адамара произвольного размера в [[Обс…&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right).&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11503</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольной размерности</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=11503"/>
		<updated>2016-10-15T19:39:29Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right).&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0&amp;diff=11487</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольного размера</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0&amp;diff=11487"/>
		<updated>2016-10-15T19:37:40Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: Бугаков Юрий переименовал страницу Построение матрицы Адамара произвольного размера в [[Участника: Бугаков Юрий, Кужамалиев Ернур/Пос…&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right).&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0&amp;diff=11464</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольного размера</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0&amp;diff=11464"/>
		<updated>2016-10-15T19:33:14Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,P)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right).&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0&amp;diff=11459</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольного размера</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0&amp;diff=11459"/>
		<updated>2016-10-15T19:32:12Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,p)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right).&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0&amp;diff=11440</id>
		<title>Участник:Бугаков Юрий/Построение матрицы Адамара произвольного размера</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D1%83%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2_%D0%AE%D1%80%D0%B8%D0%B9/%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80%D0%B0_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0&amp;diff=11440"/>
		<updated>2016-10-15T19:30:59Z</updated>

		<summary type="html">&lt;p&gt;Бугаков Юрий: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Важную роль в алгебре и комбинаторике играют матрицы Адамара, которые впервые были введены в математический обиход в конце прошлого века одним из крупнейших французских математиков [https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%B0%D0%BC%D0%B0%D1%80,_%D0%96%D0%B0%D0%BA Жаком Адамаром (1865-1963)]. Их применение в науке и технике посвящены тысячи публикаций. Они предоставляют эффективные возможности для организации хранения, обработки и передачи информации.&lt;br /&gt;
&lt;br /&gt;
Квадратная матрица Н порядка &#039;&#039;m&#039;&#039; с элементами ±1 называется матрицей Адамара, если выполняется условие&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; H_m\,H_m^T = m\,E_m &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что различные строки матрицы Адамара попарно ортогональны [1]. Также, можно увидеть из определения, что m четно и&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
H_{2m} =&lt;br /&gt;
\begin{pmatrix}&lt;br /&gt;
H_{m} &amp;amp;  H_{m}\\&lt;br /&gt;
H_{m} &amp;amp; -H_{m}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С матрицами Адамара связан ряд нерешенных проблем, одна из которых состоит в следующем. Мы уже видели, что порядок &#039;&#039;m&#039;&#039; матрицы Адамара при &#039;&#039;m&#039;&#039; ≥ 3 может быть лишь четным. Более того, при &#039;&#039;m&#039;&#039; ≥ 4 порядок обязан делиться на 4. До сих пор остается открытым вопрос: для любого ли &#039;&#039;m&#039;&#039;, кратного 4, существует матрица Адамара порядка m? Неизвестно, в частности, существует ли матрица Адамара порядка 268 (это наименьший порядок, кратный 4, для которого матрица Адамара еще не построена).&lt;br /&gt;
&lt;br /&gt;
Часто матрицу Адамара нормализуют и рассматривают размерности степени 2 (например [2],[3] и [4]). В дальнейшем будем рассматривать только такие случаи. Переопределим матрицу Адамара следующим образом:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Матрица Адамара &#039;&#039;H&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sub&amp;gt;  - это матрица размера 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;, для которой справедливо равенство&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;H_n = H_{1} \otimes H_{n-1}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   &amp;amp;\begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&#039;&#039;&#039;где &amp;lt;math&amp;gt; \otimes &amp;lt;/math&amp;gt; представляет собой [https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BD%D0%B7%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 тензорное произведение].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Представим некоторые частные примеры матриц Адамара:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
    H_0 = +1,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_1 = \frac{1}{\sqrt2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rr}&lt;br /&gt;
    1 &amp;amp; 1\\&lt;br /&gt;
    1 &amp;amp; -1&lt;br /&gt;
   \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_2 = \frac{1}{2}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  H_3 = \frac{1}{2^{\frac{3}{2}}}&lt;br /&gt;
   \begin{pmatrix}\begin{array}{rrrrrrrr}&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1 &amp;amp; 1 &amp;amp;  1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; 1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; 1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp; 1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1 &amp;amp; -1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp;  1 &amp;amp; -1 &amp;amp;  1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1\\&lt;br /&gt;
    1 &amp;amp; -1 &amp;amp; -1 &amp;amp;  -1 &amp;amp; -1 &amp;amp;  1 &amp;amp;  1 &amp;amp; -1\\&lt;br /&gt;
    \end{array}\end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основой алгоритма является тот факт, что любую матрицу Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;, размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt; можно вычислить поэлементно ([3], [4]):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &#039;&#039;k&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; и &#039;&#039;l&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;j&#039;&#039;&amp;lt;/sub&amp;gt; коэффициенты двоичного разложения чисел &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039; (1 или 0):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;k = \sum^{n}_{i=0} {k_i 2^i} = k_{n} 2^{n} + k_{n-1} 2^{n-1} + \cdots + k_1 2 + k_0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и&lt;br /&gt;
: &amp;lt;math&amp;gt;l = \sum^{n}_{i=0} {l_i 2^i} = l_{n} 2^{n} + l_{n-1} 2^{n-1} + \cdots + l_1 2 + l_0&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;h_{k,l} = \frac{1}{2^\frac{n}{2}} (-1)^{\sum_j k_j l_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основную часть метода составляют вычисления значений степени -1 для каждого элемента:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;math&amp;gt;\sum_{j=0}^n k_j l_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как видно по формуле, получаемое значение равна количеству единиц в двоичной записи результата побитового умножения &#039;&#039;k&#039;&#039; и &#039;&#039;l&#039;&#039;. Существует эффективный метод вычисления количества единиц , сложность которого равна &#039;&#039;m&#039;&#039; операций вычитания и &#039;&#039;m&#039;&#039; операций побитового умножения, где &#039;&#039;m&#039;&#039;-искомое количество единиц.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая:&lt;br /&gt;
&lt;br /&gt;
1. Побитовое умножение &amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt;;  &lt;br /&gt;
&lt;br /&gt;
2. Вычисление количества единиц двоичной записи;&lt;br /&gt;
&lt;br /&gt;
3. Определение знака элемента по степени.&lt;br /&gt;
&lt;br /&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;N^2&amp;lt;/math&amp;gt; побитовых умножений &#039;&#039;k&amp;amp;l&#039;&#039;.&lt;br /&gt;
Во втором шаге, как говорилось выше, сложность метода вычисления количества единиц  числа в двоичном представлении равна удвоенному количеству единиц. В наихудшем случае сложность равна &amp;lt;math&amp;gt;2log_2N&amp;lt;/math&amp;gt;, при &#039;&#039;k=l=N-1&#039;&#039;, а в наилучшем 0. Для нахождения  степени всех элементов матрицы потребуются &amp;lt;math&amp;gt; 2N^2\left[\frac{log_2N}{4}\right]&amp;lt;/math&amp;gt; операций. В третьем шаге для определения знака потребуется &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt; операций, то есть сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
T(n) = 2\,(1+\left[\frac{n}{4}\right])\,2^{2n}.&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;
*&amp;lt;math&amp;gt;k\&amp;amp;l&amp;lt;/math&amp;gt; - операция побитового умножения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; соответствующие координаты элемента &amp;lt;math&amp;gt;h_{kl}&amp;lt;/math&amp;gt;;&lt;br /&gt;
* OP - вычисление количества единиц числа в двоичной системе. Состоит из последовательного применения операций вычитания и побитового умножения;&lt;br /&gt;
* SGN - определение знака соответствующего элемента. Если результат предыдущего шага четное, то знак положительный, иначе отрицательный.  &lt;br /&gt;
&lt;br /&gt;
[[file:Hadamar.png|thumb|center|1400px|Рисунок 1. Граф алгоритма.]]&lt;br /&gt;
[[file:OP3.png|thumb|center|1400px|Рисунок 2. Граф OP.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для построения матрицы порядка &amp;lt;math&amp;gt;N=2^n&amp;lt;/math&amp;gt; требуется последовательно выполнить следующие шаги:&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  вычислений побитового умножения,&lt;br /&gt;
* для каждого элемента от &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; операций вычитания и побитового умножения, в зависимости от результата предыдущего шага,&lt;br /&gt;
* &amp;lt;math&amp;gt;N^2&amp;lt;/math&amp;gt;  для определения знака значения элемента.&lt;br /&gt;
 &lt;br /&gt;
Таким образом для построения необходимы лишь простые операции вычитания и побитового умножения выполняемые с целыми положительными числами. Стоит заметить что вычисления для каждого элемента не зависят друг от друга. Также можно воспользоваться либо симметричностью матрицы Адамара либо закономерностью областей показанная в пункте 1.1.&lt;br /&gt;
Таким образом, основной вклад в высотe ЯПФ вносит операция вычисления количества единиц. Ширина ЯПФ будет равна O(n^2).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: n - размерность матрицы &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: 1 (число n).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица Адамара &amp;lt;math&amp;gt;H_n&amp;lt;/math&amp;gt; размерностью &amp;lt;math&amp;gt;2^n\times 2^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2^{2n}&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;P\in \mathbb{N}&amp;lt;/math&amp;gt;. Считается, что каждый процесс &#039;&#039;P&#039;&#039; обрабатывает не более чем &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; элементов. Тогда качественная формула может быть записана таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T(n,p)=2\,(1+\left[ \frac{n}{4} \right])\,\frac{2^{2n}}{P}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неравенство &amp;lt;math&amp;gt;\left[\frac{2^{2n}}{P}\right]\geq 1&amp;lt;/math&amp;gt; можно переписать, как &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Легко увидеть, что минимум функции &#039;&#039;T(n,P)&#039;&#039; будет при максимально возможном &#039;&#039;P&#039;&#039; : &amp;lt;math&amp;gt;log_2\,\sqrt{P}\leq n&amp;lt;/math&amp;gt;. Такое &#039;&#039;P&#039;&#039; будет оптимальным числом процессов для алгоритма. В частности, для &amp;lt;math&amp;gt;P=2^p,\,p\in\mathbb{N}&amp;lt;/math&amp;gt; оптимальное &amp;lt;math&amp;gt;P = 2^{2n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{T(n)}{T(n,p)}=P&amp;lt;/math&amp;gt;.&lt;br /&gt;
то есть, отношение последовательной и параллельной сложности будет &#039;&#039;линейно&#039;&#039; зависеть от &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Вычислительная мощность&#039;&#039; алгоритма построения матрицы Адамара, как отношение числа операций к суммарному объему входных и выходных данных: &lt;br /&gt;
:&amp;lt;math&amp;gt;\,\frac{2^{2n}(2+[\frac{n}{4}])}{1+2^{2n}}\left( \sim [\frac{n}{4}],\,n\to+\infty \right).&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;не детерминированным&#039;&#039;, так как число операций меняется в зависимости от входных данных (числа n, которое формирует матрицу размерности 2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;times;&amp;amp;nbsp;2&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
* Степень исхода вершины информационного графа равна 1;&lt;br /&gt;
&lt;br /&gt;
* Алгоритм построения матрицы Адамара является &#039;&#039;сбалансированным&#039;&#039;. Так как количество вершин на разных процессорах одинаково, то алгоритм является сбалансированным по числу операций на каждом процессоре.&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;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2); // h - нормализующий множитель&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
&lt;br /&gt;
    for(i=0;i&amp;lt;N;++i) &lt;br /&gt;
    {&lt;br /&gt;
	for(j=0;j&amp;lt;N;++j)&lt;br /&gt;
	{&lt;br /&gt;
		ij = i &amp;amp; j;&lt;br /&gt;
    		for (l=0;ij;++l) ij&amp;amp;=ij-1; // l - количество единиц бинарного представления ij&lt;br /&gt;
		if(l%2==0) H[i][j] = h;&lt;br /&gt;
		else H[i][j] = -h;&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также существует рекурсивная реализация метода генерации матрицы Адамара&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_recursion(int** H, int N, int i, int j, int h) // h - нормализующий множитель&lt;br /&gt;
{&lt;br /&gt;
    if(n==1) H[i][j] = h;&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        adamar(H, N/2, i, j, h);&lt;br /&gt;
        adamar(H, N/2, i, N/2+j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, j, h);&lt;br /&gt;
        adamar(H, N/2, N/2+i, N/2+j, -h);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или эквивалентный безрекурсивный вариант:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void adamar_not_recursion(int** H, int n) // N = 2^n - размерность матрицы&lt;br /&gt;
{     &lt;br /&gt;
    int i,j,N;&lt;br /&gt;
    float h;&lt;br /&gt;
    h = pow(1/2,n/2);&lt;br /&gt;
    N = pow(2,n);&lt;br /&gt;
    k=2;&lt;br /&gt;
    H[0][0] = h;&lt;br /&gt;
	&lt;br /&gt;
    while(k&amp;lt;=N)&lt;br /&gt;
    {&lt;br /&gt;
	for (i=0; i&amp;lt;k; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		for (j=0; j&amp;lt;k; ++j)&lt;br /&gt;
		{&lt;br /&gt;
			if (i&amp;lt;k/2 &amp;amp;&amp;amp; j&amp;lt;k/2)&lt;br /&gt;
			{&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				if(i&amp;gt;=k/2 &amp;amp;&amp;amp; j&amp;gt;=k/2)&lt;br /&gt;
				{&lt;br /&gt;
					H[i][j] = -(H[i-k/2][j-k/2]);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					if (i&amp;gt;j)&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i-k/2][j];&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						H[i][j] = H[i][j-k/2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
		&lt;br /&gt;
        k=k*2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для данного случая, рекурсия является менее эффективной для генерации матрицы Адамара ([https://habrahabr.ru/post/256351/ Хабрахабр. О бедной рекурсии замолвите слово, или всё, что вы не знали и не хотите о ней знать.]). С точки зрения последовательной реализации, генерация матрицы Адамара с помощью adamar_not_recursion будет выигрывать у adamar, так как adamar_not_recursion будет выполнять меньшее количество операций. С точки зрения параллельной реализации adamar имеет 100% парализацию и при определенных условиях будет выигрывать по времени у последовательной (пусть в adamar и будет выполняться большее количество операций, но они являются [https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 битовыми операциями]).&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Задача данного раздела - показать пределы [[глоссарий#Масштабируемость|&#039;&#039;масштабируемости&#039;&#039;]] алгоритма на различных платформах. Очень важный раздел. Нужно выделить, описать и оценить влияние точек барьерной синхронизации, глобальных операций, операций сборки/разборки данных, привести оценки или провести исследование [[глоссарий#Сильная масштабируемость|&#039;&#039;сильной&#039;&#039;]] и [[глоссарий#Слабая масштабируемость|&#039;&#039;слабой&#039;&#039;]] масштабируемости алгоритма и его реализаций.&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма определяет свойства самого алгоритма безотносительно конкретных особенностей используемого компьютера. Она показывает, насколько параллельные свойства алгоритма позволяют использовать возможности растущего числа процессорных элементов. Масштабируемость параллельных программ определяется как относительно конкретного компьютера, так и относительно используемой технологии программирования, и в этом случае она показывает, насколько может вырасти реальная производительность данного компьютера на данной программе, записанной с помощью данной технологии программирования, при использовании бóльших вычислительных ресурсов (ядер, процессоров, вычислительных узлов).&lt;br /&gt;
&lt;br /&gt;
Ключевой момент данного раздела заключается в том, чтобы показать &#039;&#039;реальные параметры масштабируемости программы&#039;&#039; для данного алгоритма на различных вычислительных платформах в зависимости от числа процессоров и размера задачи  [4]. При этом важно подобрать такое соотношение между числом процессоров и размером задачи, чтобы отразить все характерные точки в поведении параллельной программы, в частности, достижение максимальной производительности, а также тонкие эффекты, возникающие, например, из-за блочной структуры алгоритма или иерархии памяти.&lt;br /&gt;
&lt;br /&gt;
На рис.5. показана масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи. На графике хорошо видны области с большей производительностью, отвечающие уровням кэш-памяти.&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рис.5 Масштабируемость классического алгоритма умножения плотных матриц в зависимости от числа процессоров и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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.exponenta.ru/soft/matlab/potemkin/book2/chapter5/hadamard.asp MATLAB];&lt;br /&gt;
# [https://reference.wolfram.com/language/ref/HadamardMatrix.html WOLFRAM];&lt;br /&gt;
# [http://pydoc.net/Python/rogues/0.3.0/rogues.matrices.hadamard/ Python];&lt;br /&gt;
# [http://www.obihiro.ac.jp/~suzukim/masuda/octave/html3/octave_97.html Octave];&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что во многих вычислительных пакетах встроена операция тензорного произведения матриц, которая позволяет строить матрицу Адамара по определению. Этот факт позволяет использовать матрицу Адамара в этих вычислительных пакетах: &lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Maple MAPLE];&lt;br /&gt;
# [https://ru.wikipedia.org/wiki/Mathcad MATCATH]; &lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[1] Мак-Вильямс Ф.Дж., Слоэн Н.Дж.А. Теория кодов, исправляющих ошибки: Пер. с англ. — М: Связь, 1979. — 744 с.&lt;br /&gt;
&lt;br /&gt;
[2] Кронберг, Ю.И. Ожигов, А.Ю. Чернявский — Алгебраический аппарат квантовой информатики 2&lt;br /&gt;
&lt;br /&gt;
[3] Kunz H.O.. On the Equivalence Between One-Dimensional Discrete Walsh-Hadamard and Multidimensional Discrete Fourier Transforms. IEEE Transactions on Computers. 28 (3): 267–8. [https://en.wikipedia.org/wiki/Digital_object_identifier doi]:[http://ieeexplore.ieee.org/document/1675334/ 10.1109/TC.1979.1675334]&lt;br /&gt;
&lt;br /&gt;
[4] Википедия – свободная энциклопедия [Электронный ресурс]. -  https://en.wikipedia.org/wiki/Hadamard_transform. - (дата обращения: 15.10.2016).&lt;br /&gt;
&lt;br /&gt;
[5] Воеводин В.В.. Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&lt;br /&gt;
&lt;br /&gt;
[6] Воронцов К.В.. Математические методы обучения по прецедентам (теория обучения машин)&lt;/div&gt;</summary>
		<author><name>Бугаков Юрий</name></author>
	</entry>
</feed>