<?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=Kisel+dv</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=Kisel+dv"/>
	<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/Kisel_dv"/>
	<updated>2026-10-23T07:48:26Z</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=24002</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=24002"/>
		<updated>2017-11-16T22:42:00Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
[[File:InfographDNS.png|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Серым на графе помечен этап, в котором происходит считывание матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; и их запись в &amp;quot;смежные грани куба&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Далее как бы проецируем каждый блок матрицы на каждую плоскость куба из процессов(на каждую плоскость, параллельную рассматриваемой матрице, см.рисунок выше), таким образом в каждом из них будет выполняться свое умножение уникальной комбинации блоков(&amp;quot;синий&amp;quot; этап).&lt;br /&gt;
&lt;br /&gt;
Зеленым обозначен этап суммирования и вывода результата - матрицы &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DNS1.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Размер блоков, на которые разбивается матрица, выбирается по оптимальному принципу: целая часть от &amp;lt;math&amp;gt;\frac{N}{q^{\frac{1}{3}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N, q&amp;lt;/math&amp;gt;, соответственно, размер матрицы и количество процессов.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Приблизительно одинаковые результаты по времени на количестве процессов, равном 8 и 16, обусловлены равным числом по факту используемых процессов в программе, поскольку деление в данных двух случаях будет происходить на равные блоки(выше указана оптимальная формула для количества блоков).&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
3d-график:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph3.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23993</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23993"/>
		<updated>2017-11-16T20:04:13Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Масштабируемость алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DNS1.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Размер блоков, на которые разбивается матрица, выбирается по оптимальному принципу: целая часть от &amp;lt;math&amp;gt;\frac{N}{q^{\frac{1}{3}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N, q&amp;lt;/math&amp;gt;, соответственно, размер матрицы и количество процессов.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Приблизительно одинаковые результаты по времени на количестве процессов, равном 8 и 16, обусловлены равным числом по факту используемых процессов в программе, поскольку деление в данных двух случаях будет происходить на равные блоки(выше указана оптимальная формула для количества блоков).&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
3d-график:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph3.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23992</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23992"/>
		<updated>2017-11-16T20:03:23Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Масштабируемость алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DNS1.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Размер блоков, на которые разбивается матрица, выбирается по оптимальному принципу: целая часть от &amp;lt;math&amp;gt;\frac{N}{q^{\frac{1}{3}}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Приблизительно одинаковые результаты по времени на количестве процессов, равном 8 и 16, обусловлены равным числом по факту используемых процессов в программе, поскольку деление в данных двух случаях будет происходить на равные блоки(выше указана оптимальная формула для количества блоков).&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
3d-график:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph3.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23991</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23991"/>
		<updated>2017-11-16T20:02:16Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Масштабируемость алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DNS1.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Размер блоков, на которые разбивается матрица, выбирается по оптимальному принципу: &amp;lt;math&amp;gt;\left[\frac{N}{q^{\frac{1}{3}}\right]}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Приблизительно одинаковые результаты по времени на количестве процессов, равном 8 и 16, обусловлены равным числом по факту используемых процессов в программе, поскольку деление в данных двух случаях будет происходить на равные блоки(выше указана оптимальная формула для количества блоков).&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
3d-график:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph3.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23990</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23990"/>
		<updated>2017-11-16T20:01:57Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Масштабируемость алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DNS1.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Размер блоков, на которые разбивается матрица, выбирается по оптимальному принципу: &amp;lt;math&amp;gt;[\frac{N}{q^{\frac{1}{3}}]}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Приблизительно одинаковые результаты по времени на количестве процессов, равном 8 и 16, обусловлены равным числом по факту используемых процессов в программе, поскольку деление в данных двух случаях будет происходить на равные блоки(выше указана оптимальная формула для количества блоков).&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
3d-график:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph3.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23989</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23989"/>
		<updated>2017-11-16T19:49:45Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DNS1.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
3d-график:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph3.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23988</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23988"/>
		<updated>2017-11-16T19:49:25Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
3d-график:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph3.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23981</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23981"/>
		<updated>2017-11-16T19:10:21Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Масштабируемость алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
[[File:DNS1.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
3d-график:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph3.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23980</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23980"/>
		<updated>2017-11-16T18:06:11Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
[[File:DNS1.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23979</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23979"/>
		<updated>2017-11-16T17:46:35Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
[[File:DNS1.PNG|thumb|center|1000px|]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG|thumb|center|1000px|]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23978</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23978"/>
		<updated>2017-11-16T17:46:21Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
[[File:DNS1.PNG]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg|thumb|center|500px|]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23977</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23977"/>
		<updated>2017-11-16T17:28:15Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
[[File:DNS1.PNG]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph2.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем данные графиком:&lt;br /&gt;
&lt;br /&gt;
[[File: DNS_graph1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Очевидно, что система хорошо масштабируема.&lt;br /&gt;
&lt;br /&gt;
=== Характеристики программно-аппаратной среды ===&lt;br /&gt;
&lt;br /&gt;
Все вычисления были произведены на суперкомпьютере &amp;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6, реализация MPI: Intel MPI 4.0.3.&lt;br /&gt;
При компиляции использована опция -lm (подключение библиотеки math).&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23976</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23976"/>
		<updated>2017-11-16T17:17:25Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
[[File:DNS1.PNG]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&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;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6.&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23957</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23957"/>
		<updated>2017-11-14T22:24:17Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
[[File:DNS1.PNG]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&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;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6.&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23956</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23956"/>
		<updated>2017-11-14T22:14:15Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&lt;br /&gt;
&lt;br /&gt;
При классификации по последовательной сложности, таким образом, алгоритм умножения матриц относится к алгоритмам &#039;&#039;с кубической сложностью&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
[[File:DNS1.PNG]]&lt;br /&gt;
&lt;br /&gt;
[[File:DNS2.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&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;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6.&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23955</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23955"/>
		<updated>2017-11-14T22:11:49Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&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;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6.&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23950</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23950"/>
		<updated>2017-11-14T21:30:46Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Масштабируемость алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&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;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 2000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.976&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|6.012&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|18.012&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|18.153&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|162.214&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|495.675&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|2.245&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.814&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.232&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.094&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.027&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;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6.&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23949</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23949"/>
		<updated>2017-11-14T20:22:01Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&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;
Рассматривались квадратные матрицы размерностью  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;500\leqslant N \leqslant 2000&amp;lt;/math&amp;gt;, а число процессов изменялось от  &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;128&amp;lt;/math&amp;gt;. Для примера посмотрим как изменялось время выполнения программы в зависимости от числа процессов (здесь берутся матрицы размера &amp;lt;math&amp;gt;N = 1000&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Число процессов&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|128&lt;br /&gt;
|0.234&lt;br /&gt;
|-&lt;br /&gt;
|64&lt;br /&gt;
|0.24&lt;br /&gt;
|-&lt;br /&gt;
|32&lt;br /&gt;
|0.248&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|0.254&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|0.272&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|0.29&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|0.323&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
А теперь посмотрим на зависимость времени выполнения программы от размера матриц. Число процессов зафиксируем равным &amp;lt;math&amp;gt;64&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Размер матриц&lt;br /&gt;
! Время (с)&lt;br /&gt;
|-&lt;br /&gt;
|2000&lt;br /&gt;
|0.248&lt;br /&gt;
|-&lt;br /&gt;
|1500&lt;br /&gt;
|0.254&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|0.272&lt;br /&gt;
|-&lt;br /&gt;
|750&lt;br /&gt;
|0.29&lt;br /&gt;
|-&lt;br /&gt;
|500&lt;br /&gt;
|0.323&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;quot;Ломоносов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Для компиляции был использован компилятор языка C++ GNU 4.4.6.&lt;br /&gt;
&lt;br /&gt;
Вычисления производились в очереди test. Ограничений на лимит времени на узел наложено не было.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23948</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23948"/>
		<updated>2017-11-14T20:09:20Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Свойства и структура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&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;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23947</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23947"/>
		<updated>2017-11-14T20:08:35Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Программная реализация алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&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;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23754</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23754"/>
		<updated>2017-11-04T13:48:45Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;2n^2&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23706</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23706"/>
		<updated>2017-11-01T12:26:59Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на блочном разделении данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;.  [[#Ресурс параллелизма алгоритма|Далее]] данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;mn+nl&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;ml&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23683</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23683"/>
		<updated>2017-10-31T04:46:51Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на разделении промежуточных данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;. Далее данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;A_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;mn+nl&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;ml&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23540</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23540"/>
		<updated>2017-10-24T17:32:35Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на разделении промежуточных данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;. Далее данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с элементами &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;mn+nl&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;ml&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23526</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23526"/>
		<updated>2017-10-24T15:56:28Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на разделении промежуточных данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;. Далее данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с элементами &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;mn+nl&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;ml&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DNS алгоритм не очень распространен в Интернете, сравнительно просто отыскать лишь текстовое описание данного способа умножения матриц. Чуть более трудной, однако выполнимой задачей будет нахождение его реализации, например, на [https://github.com/ github].&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23485</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23485"/>
		<updated>2017-10-24T14:19:29Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на разделении промежуточных данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;. Далее данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с элементами &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Для умножение данных матриц в последовательном варианте требуется по &amp;lt;math&amp;gt; n^3 &amp;lt;/math&amp;gt;&amp;amp;nbsp; умножений и сложений.&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;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;mn+nl&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;ml&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23483</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23483"/>
		<updated>2017-10-24T14:05:24Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на разделении промежуточных данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;. Далее данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с элементами &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{k=0}^{n-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассматриваем матрицы размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитые на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков размера &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
Тогда сложность алгоритма&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;m^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;, разбитых на &amp;lt;math&amp;gt;m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp; блоков. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; m \times m \times m&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; A_{ik}B_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; m) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, m-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; C_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(m) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&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;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;mn+nl&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;ml&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23482</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23482"/>
		<updated>2017-10-24T13:17:01Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на разделении промежуточных данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;. Далее данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с элементами &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Рассмотрим блоки матриц: &amp;lt;math&amp;gt;A_{ij}, B_{ij},&lt;br /&gt;
 C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;. В цикле выполним последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{m=0}^{n-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;n^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; n \times n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; a_{ik}b_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; n) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, n-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; c_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; c_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(n) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23481</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23481"/>
		<updated>2017-10-24T13:15:16Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на разделении промежуточных данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;. Далее данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с элементами &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;,&lt;br /&gt;
где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;&amp;amp;nbsp; - количество блоков матрицы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS состоит из вычислений всех элементов блоков матрицы-результата: процедур вычислений умножения блоков матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на блоки матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{m-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad i \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; произведение блоков матриц &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Далее в цикле выполняется последовательное умножение блоков матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_{ij} = \sum_{m=0}^{n-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;n^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; n \times n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; a_{ik}b_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; n) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, n-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; c_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; c_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(n) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23480</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23480"/>
		<updated>2017-10-24T13:01:55Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на разделении промежуточных данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;. Далее данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с элементами &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с блоками &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=0}^{n-1} A_{ik} B_{kj} \quad i \in [0, m-1], \quad j \in [0, m-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;, где  &amp;lt;math&amp;gt; m \times m &amp;lt;/math&amp;gt;*nbsp; - количество блоков матриц.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS можно составить из множественных скалярных произведений строк матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на столбцы матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj} \quad i \in [1, n], \quad i \in [1, n]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; скалярное произведение векторов(строк матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на столбцы матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;) &amp;lt;math&amp;gt;\sum_{k=0}^{n-1} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Далее в цикле выполняется последовательное умножение элементов матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{ij} = \sum_{k=0}^{n-1} a_{ik} b_{kj} \quad i \in [0, n-1], \quad j \in [0, n-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;n^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; n \times n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; a_{ik}b_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; n) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, n-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; c_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; c_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(n) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23479</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23479"/>
		<updated>2017-10-24T12:53:07Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на разделении промежуточных данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;. Далее данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с элементами &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с элементами &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{ij} = \sum_{k=0}^{n-1} a_{ik} b_{kj} \quad i \in [0, n-1], \quad j \in [0, n-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS можно составить из множественных скалярных произведений строк матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на столбцы матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj} \quad i \in [1, n], \quad i \in [1, n]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; скалярное произведение векторов(строк матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на столбцы матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;) &amp;lt;math&amp;gt;\sum_{k=0}^{n-1} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Обнулим матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, предназначенную для записи полученного результата произведения &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Далее в цикле выполняется последовательное умножение элементов матриц операндов и суммирование результатов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{ij} = \sum_{k=0}^{n-1} a_{ik} b_{kj} \quad i \in [0, n-1], \quad j \in [0, n-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
В результате получаем матрицу &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp;, равную произведению матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;n^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; n \times n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; a_{ik}b_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; n) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, n-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; c_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; c_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(n) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv&amp;diff=23420</id>
		<title>Участник:Kisel dv</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:Kisel_dv&amp;diff=23420"/>
		<updated>2017-10-23T19:26:52Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Кисель Дмитрий Владимирович, студент 4 курса ВМК МГУ, кафедры системного анализа.&lt;br /&gt;
&lt;br /&gt;
[[Участник:Kisel dv/DNS алгоритм умножения матриц]]&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23418</id>
		<title>Участник:Kisel dv/DNS алгоритм умножения матриц</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:Kisel_dv/DNS_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86&amp;diff=23418"/>
		<updated>2017-10-23T19:25:35Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: Новая страница: «Автор: Д.В.Кисель  = Свойства и структура алгоритма =  == Общее описание алг…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: [[Участник:Kisel dv|Д.В.Кисель]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма = &lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм DNS(Dekel, Nassimi, Sahni - назван по фамилиям создателей) является одним из блочных алгоритмов решения задачи &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; перемножения двух матриц. Для данного алгоритма мы не используем какие-либо свойства матриц &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
DNS основан на разделении промежуточных данных, его преимуществом является временная сложность &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;&amp;amp;nbsp; при вычислительной сложности &amp;lt;math&amp;gt;O(\frac{n^3}{log(n)})&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Достигается это за счет 3d-секционирования(англ. partitioning), в отличие от альтернатив, использующих 2d-секционирование(например, алгоритм Кэннона). Тем самым, алгоритм DNS представим в виде куба, где матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp;, &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; и матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; ортогональны друг другу&amp;lt;ref&amp;gt;E. Dekel, D. Nassimi, and S. Sahni, “Parallel Matrix and Graph Algorithms,” SIAM, Journal on Computing, vol. 10, no. 4, Nov. 1981, pp. 657-675.&amp;lt;/ref&amp;gt;. Далее данное описание будет рассмотрено подробнее.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&amp;amp;nbsp; с элементами &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp; и &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;, соответственно.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&amp;amp;nbsp; с элементами &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Используемые формулы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{ij} = \sum_{k=0}^{n-1} a_{ik} b_{kj} \quad i \in [0, n-1], \quad j \in [0, n-1]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения матриц методом DNS можно составить из множественных скалярных произведений строк матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на столбцы матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{k=1}^{n} a_{ik} b_{kj} \quad i \in [1, n], \quad i \in [1, n]  &amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В алгоритме используется:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; скалярное произведение векторов(строк матрицы &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt;&amp;amp;nbsp; на столбцы матрицы &amp;lt;math&amp;gt; B &amp;lt;/math&amp;gt;&amp;amp;nbsp;) &amp;lt;math&amp;gt;\sum_{k=0}^{n-1} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Рассмотрим &amp;lt;math&amp;gt;n^3&amp;lt;/math&amp;gt;&amp;amp;nbsp; процессов, доступных для умножения двух матриц размером &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;. Представим их в виде трехмерного массива &lt;br /&gt;
&amp;lt;math&amp;gt; n \times n \times n&amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; Процессы именованы согласно их расположению в массиве, соответственно, вычисление произведения &amp;lt;math&amp;gt; a_{ik}b_{kj} &amp;lt;/math&amp;gt;&amp;amp;nbsp; присвоено процессу с координатами &amp;lt;math&amp;gt; [i, j, k] (0 \leq i,j,k &amp;lt; n) &amp;lt;/math&amp;gt;&amp;amp;nbsp;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \cdot &amp;lt;/math&amp;gt;&amp;amp;nbsp; После того, как каждый процесс завершил умножение, результаты процессов &amp;lt;math&amp;gt; [i, j, 0], [i, j, 1], ..., [i, j, n-1] &amp;lt;/math&amp;gt;&amp;amp;nbsp; суммируются в &amp;lt;math&amp;gt; c_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp;. Суммирование всех &amp;lt;math&amp;gt; c_{ij} &amp;lt;/math&amp;gt;&amp;amp;nbsp; может выполняться одновременно за &amp;lt;math&amp;gt; log(n) &amp;lt;/math&amp;gt;&amp;amp;nbsp; шагов. &amp;lt;ref&amp;gt;http://parallelcomp.uw.hu/ch08lev1sec2.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Kisel dv</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:Kisel_dv&amp;diff=23379</id>
		<title>Участник:Kisel dv</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:Kisel_dv&amp;diff=23379"/>
		<updated>2017-10-23T15:13:14Z</updated>

		<summary type="html">&lt;p&gt;Kisel dv: Новая страница: «Кисель Дмитрий Владимирович, студент 4 курса ВМК МГУ, кафедры системного анализа.»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Кисель Дмитрий Владимирович, студент 4 курса ВМК МГУ, кафедры системного анализа.&lt;/div&gt;</summary>
		<author><name>Kisel dv</name></author>
	</entry>
</feed>