<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Блоги Intel® Software Network &#187; Параллельное программирование</title>
	<atom:link href="http://software.intel.com/ru-ru/blogs/category/parallel/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/ru-ru/blogs</link>
	<description></description>
	<pubDate>Thu, 19 Nov 2009 08:48:22 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.5</generator>
	<language>en</language>
			<item>
		<title>Будьте аккуратны с директивой atomic</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/11/18/atomic/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/11/18/atomic/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 08:11:04 +0000</pubDate>
		<dc:creator>Andrey Karpov</dc:creator>
		
		<category><![CDATA[Параллельное программирование]]></category>

		<category><![CDATA[Разработка софта]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[openmp]]></category>

		<category><![CDATA[PVS-Studio]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/11/18/atomic/</guid>
		<description><![CDATA[Хочется рассказать об одной ошибке, которую легко может допустить человек еще мало знакомый с технологией OpenMP. Ошибка связана с неверным представлением о работе директивы atomic.]]></description>
			<content:encoded><![CDATA[<p>Хочется рассказать об одной ошибке, которую легко может допустить человек еще мало знакомый с технологией <a href="http://www.viva64.com/terminology/OpenMP_rus.html">OpenMP</a>. Ошибка связана с неверным представлением о работе директивы atomic. Директива atomic работает быстрее, чем критические секции, так как некоторые атомарные операции могут быть напрямую заменены командами процессора. И поэтому ее удобно использовать при вычислении различных выражений. Но следует помнить, что atomic никак не влияет на вызов функций, используемых в выражении. Рассмотрим это на примере:</p>
<pre name="code" class="cpp">class Example
{
public:
  unsigned m_value;

  Example() : m_value(0) {}

  unsigned GetValue()
  {
    return ++m_value;
  }

  unsigned GetSum()
  {
    unsigned sum = 0;
    #pragma omp parallel for
    for (ptrdiff_t i = 0; i &lt; 100; i++)
    {
      #pragma omp atomic
      sum += GetValue();
    }
    return sum;
  }
};</pre>
<p>Данный пример содержит ошибку <a href="http://www.viva64.com/terminology/Race_condition_rus.html">состояния гонки</a> (Race condition), и возвращаемое ей значение может меняться от запуска к запуску.  Если вы попробуете приведенный пример, и результат все время будет верен, то можете изменить функцию GetValue, как показано ниже, чтобы ошибка проявлялась более четко:</p>
<pre name="code" class="cpp">unsigned GetValue()
{
  Sleep(0);
  m_value++;
  Sleep(0);
  return m_value;
}</pre>
<p>В коде с помощью директивы atomic защищено увеличение переменной "sum". Но директива atomic не оказывает влияние на вызов функции GetValue(). Вызовы происходят в параллельных потоках, что приводит к ошибкам при выполенения операции "++m_value" внутри функции GetValue.</p>
<p>Помните, что функции, используемые в выражениях, к которым применяется директива atomic, должны быть потоко-безопасными (thread-safe). Директива atomic распространяется только на операции следующего вида:</p>
<ul>
<li>x binop= expr</li>
<li>x++</li>
<li>++x</li>
<li>x--</li>
<li>--x</li>
</ul>
<p>Здесь х - скалярная переменная, expr - выражение со скалярными типами, в котором не присутствует переменная х, binop - не перегруженный оператор +, *, -, /, &amp;, ^, |, &lt;&lt;, or &gt;&gt;. Во всех остальных случаях применять директиву atomic нельзя.</p>
<p>В приведенном примере директива atomic обезопасит операцию "sum +=", но не обезопасит вызов функции GetValue. Для исправления показанной ошибки необходимо использовать критическую секцию или иные способы для защиты переменной m_value.</p>
<p>Обнаружить подобные ошибки может помочь, такой инструмент как VivaMP, входящий в состав <a href="http://www.viva64.com/ru/pvs-studio/">PVS-Studio</a>. В данном случае, он диагностирует ошибку следующим образом: Error <a href="http://www.viva64.com/content/PVS-Studio-help-ru/V1205.html">V1205</a>: Data race risk. Unprotected concurrent operation with the ‘m_value’ variable. При этом ошибку можно обнаружить еще на этапе написания кода, так как VivaMP представляет собой статический анализатор кода и не требует запуска приложения.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/11/18/atomic/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Использование суперкомпьютеров в промышленности</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/11/18/2002566/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/11/18/2002566/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 07:10:50 +0000</pubDate>
		<dc:creator>ialexander</dc:creator>
		
		<category><![CDATA[Академическое сообщество]]></category>

		<category><![CDATA[Параллельное программирование]]></category>

		<category><![CDATA[Разработка софта]]></category>

		<guid isPermaLink="false">http://origin-software.intel.com/ru-ru/blogs/2009/11/18/2002566/</guid>
		<description><![CDATA[В соседней записи Долой летнее время обсуждается пара вопросов поднятых Дмитрием Медведевым в своем Послании федеральному собранию. В этом послании поднимается и другая более близкая нам тема об использовании суперкмопьютеров:
И, наконец, пятая приоритетная задача - развитие стратегических и информационных технологий. В России должен быть в полном объёме задействован потенциал суперкомпьютеров, суперкомпьютерных систем, которые объединены высокоскоростными [...]]]></description>
			<content:encoded><![CDATA[<p>В соседней записи <a href="http://software.intel.com/ru-ru/blogs/2009/11/13/2002532/">Долой летнее время</a> обсуждается пара вопросов поднятых Дмитрием Медведевым в своем <a href="http://www.kremlin.ru/transcripts/5979">Послании федеральному собранию</a>. В этом послании поднимается и другая более близкая нам тема об использовании суперкмопьютеров:</p>
<blockquote><p>И, наконец, пятая приоритетная задача - развитие стратегических и информационных технологий. В России должен быть в полном объёме задействован потенциал суперкомпьютеров, суперкомпьютерных систем, которые объединены высокоскоростными каналами передачи данных. С их помощью уже в пятилетней перспективе станет возможным проектирование новейших самолётов и космических аппаратов, автомобилей и ядерных реакторов. Ведь сложная техника, не прошедшая суперкомпьютерного моделирования, что называется, не положенная в цифру, через несколько лет просто не будет востребована рынком. И для завоевания здесь конкурентных позиций мы обязаны настойчиво работать.</p></blockquote>
<p>Как это ни печально осознавать, но использование суперкомпьютеров в нашей промышленности находится на очень низком уровне. Медведев уже не в первый раз говорит об этом, но особых подвижек пока нет.</p>
<p>Можно говорить о том, что наш наши КБ и НИИ безинициативны и не делают использовать доступные вычислительные мощности. Но вот вам обратный пример: <a href="http://www.jinr.ru/default.asp?language=rus">Институт объединенных ядерных исследований</a> при выполнении зарубежных заказов по проектированию циклотронов был вынужден использовать обычный персональный компьютер, неизвестно, чем бы завершились проекты, но ребятам удалось использовать видеоадаптер для значительного ускорения вычислений в рамках проекта "CBDA: Cyclotron Beam Dynamics Analysis". С другой стороны университетские кластеры просто простаивают. К примеру, кластер МГТУ им. Баумана загружен всего на несколько процентов, по словам инсайдеров.</p>
<p>В России есть отдельные проекты, которые пытаются решить эту задачу, например, <a href="http://caebeans.susu.ru/">CAEBeans</a> под руководством проф. Л.Б. Соколинского, ЮУрГУ. Другой пример: проект <a href="http://dcs.isa.ru/wiki/staff/taras/projects/mathcloud">MathCloud</a> Алексея Тарасова из ИСА РАН.</p>
<p>Но все эти проекты как-то разрознены, нет единой системы, они как капля в море и ситуации не меняют. Может быть, для прорыва в этой области требуется некоторая критическая масса таких проектов. А может уже сегодня сильные мира сего могут предпринять шаги по созданию системы, объединяющией проекты, созданию единого информационного пространства в этой области. Ведь не секрет, что представители промышленности не слишком часто посещают научные конференции по параллельным вычислениям и не могут знать о такого рода проектах, и что, вообще, ведутся работы.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/11/18/2002566/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Тридцать три шага назад!? – часть II</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/11/17/ii-2/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/11/17/ii-2/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 11:24:10 +0000</pubDate>
		<dc:creator>vlubch</dc:creator>
		
		<category><![CDATA[Параллельное программирование]]></category>

		<category><![CDATA[Разработка софта]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/11/17/ii-2/</guid>
		<description><![CDATA[В 50-е годы прошлого века Алан Тьюринг в своей знаменитой работе «Могут ли машины мыслить?»  предложил  игру в имитацию. Суть в том, что в одну  комнату помещают машину, в другую человека, и если нельзя распознать, кто где, то дается положительный ответ на заданный вопрос. А можем ли мы по аналогии ответить, какая машина, параллельная или последовательная, находится в комнате?]]></description>
			<content:encoded><![CDATA[<p>В 50-е годы прошлого века Алан Тьюринг в своей знаменитой работе «Могут ли машины мыслить?»  предложил  игру в имитацию. Суть в том, что в одну  комнату помещают машину, в другую человека, и если нельзя распознать, кто где, то дается положительный ответ на заданный вопрос. А можем ли мы по аналогии ответить, какая машина, параллельная или последовательная, находится в комнате?</p>
<p>При анализе библиотеки TBB ей были заданы «вопросы» в форме разных алгоритмов вычисляющих числа Фибоначчи. В результате было высказано предположение, что TBB не делает алгоритм параллельным. И это, несмотря использование ядер? Парадоксально? Странное на первый взгляд утверждение базируется на том, что параллельный рекурсивный алгоритм, созданный на базе аналогичного последовательного алгоритма, должен иметь вычислительную сложность, выражаемую линейной зависимостью - O(n). Но с какой такой бухты-барахты мы это взяли? …</p>
<p>Создадим модели императивного и рекурсивного последовательных алгоритмов, вычисляющих числа Фибоначчи, и убедимся, что они эквивалентны по поведению исходным алгоритмам. Это докажет, что выбранная вычислительная модель и процедура перехода к ней не искажают свойств моделируемых алгоритмов. Затем, применив эту же методику для параллельных алгоритмов, мы уже по свойствам моделей будем судить о свойствах анализируемого алгоритма.</p>
<p>На рис.1 приведена блок-схема императивного алгоритма вычисления чисел Фибоначчи, исходный код которого на языке С++ приведен в листинге 1. Для построения эквивалентной модели в форме конечного автомата проведем процедуру разметки блок-схемы точно так же, как это было показано в первой части для параллельного рекурсивного алгоритма. Сама разметка показана там же на рис.1, а граф эквивалентного автомата на рис.2.  На рис.3 приведен граф автомата, который эквивалентен последовательному рекурсивному алгоритму.</p>
<pre name="code" class="cpp">
float fib (int n)
{
  int i;
  float y, fib1, fib2;
  if (n <= 1) return y=1;
  for (fib1 = fib2 = 1, i=2; i <=n; i++)
  {
    y = fib1+fib2; fib1 = fib2; fib2 = y;
  }
  return (y);
}
// Листинг 1. Программа для вычисления чисел Фибоначчи
</pre>
<div id="attachment_2002557" class="wp-caption alignnone" style="width: 310px"><a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d1811-d0b1d181-d0bfd0bed181d0bbd0b8d0bcd0bfd0b5d180d0b0d182d0b8d0b2d0bdd18bd0b93.jpg"><img class="size-medium wp-image-2002557" src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d1811-d0b1d181-d0bfd0bed181d0bbd0b8d0bcd0bfd0b5d180d0b0d182d0b8d0b2d0bdd18bd0b93-300x285.jpg" alt="Рис. 1. Блок-схема размеченного императивного алгоритма вычисления чисел Фибоначчи" width="300" height="285" /></a><p class="wp-caption-text">Рис. 1. Блок-схема размеченного императивного алгоритма вычисления чисел Фибоначчи</p></div>
<div id="attachment_2002559" class="wp-caption alignnone" style="width: 271px"><a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d1812-d0b0d0b2d182d0bed0bcd0b0d182-d0bfd0bed181d0bbd0b8d0bcd0b5d180d0b0d182d0b8d0b2d0bdd18bd0b91.jpg"><img class="size-medium wp-image-2002559" src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d1812-d0b0d0b2d182d0bed0bcd0b0d182-d0bfd0bed181d0bbd0b8d0bcd0b5d180d0b0d182d0b8d0b2d0bdd18bd0b91-261x300.jpg" alt="Рис.2. Граф автомата императивного алгоритма" width="261" height="300" /></a><p class="wp-caption-text">Рис.2. Граф автомата императивного алгоритма</p></div>
<div id="attachment_2002560" class="wp-caption alignnone" style="width: 289px"><a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d1813-d0b0d0b2d182d0bed0bcd0b0d182-d0bfd0bed181d0bbd180d0b5d0bad183d180d181d0b8d18f1.jpg"><img class="size-medium wp-image-2002560" src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d1813-d0b0d0b2d182d0bed0bcd0b0d182-d0bfd0bed181d0bbd180d0b5d0bad183d180d181d0b8d18f1-279x300.jpg" alt="Рис.3. Граф автомата последовательного рекурсивного алгоритма" width="279" height="300" /></a><p class="wp-caption-text">Рис.3. Граф автомата последовательного рекурсивного алгоритма</p></div>
<p>Теперь у нас есть две обычных программы и две автоматных модели. Доказательство того, что вычислительная сложность в результате перехода от одной модели к другой не претерпела изменений, сводится к демонстрации того, что дискретное время автоматных моделей  изменяется по тому же закону, что и реальное время работы эквивалентных обычных программ.</p>
<p>В таблицу 1 сведены результаты тестирования обычных и автоматных алгоритмов. В ее первой строке – номер числа в ряду Фибоначчи, в следующих двух - реальное время работы обычных алгоритмов, а в четвертой и пятой - дискретное время их автоматных аналогов. Графики эффективности, приведенные к времени 20-го числа обычного императивного алгоритма (первое значение во второй строке таблицы) показаны на рис.4. Из их полного совпадения следует, что выбранная модель и методика построения эквивалентных моделей не влияют на его вычислительную сложность. Напомним, что под вычислительной сложностью понимается зависимость времени работы алгоритма от значения входных данных.</p>
<blockquote><p><code>Таблица 1<br />
20       21       22       23       24       25       26       27       28<br />0,002    0,002    0,002    0,003    0,003    0,003    0,003    0,003    0,003<br />0,572    0,931    1,499    2,427    3,948    6,376    10,307   16,636   26,997<br />79       83       87       91       95       99       103      107      111<br />65672    106262   171638   278204   450146   728354   1178504  1906862  3085370<br />
</code></p></blockquote>
<blockquote><p><code>Таблица 2<br />
20       21       22       23       24       25       26       27       28<br />0,002    0,002    0,002    0,003    0,003    0,003    0,003    0,003    0,003<br />0,572    0,931    1,499    2,427    3,948    6,376    10,307   16,636   26,997<br />59       62       65       68       71       74       77       80       83<br />
</code></p></blockquote>
<p>В целях наглядности включим в новую таблицу времена обычных алгоритмов из таблицы 1 и дискретное время работы параллельного рекурсивного алгоритма. Графики вычислительной сложности, приведенные ко времени императивного алгоритма, по данным таблицы 2, представлены на рис. 5. Их вид убеждает, что вычислительная сложность параллельного алгоритма имеет тот же вид, что и вычислительная сложность последовательного императивного алгоритма. Просто параллельный алгоритм в абсолютном выражении тратит на вычисление меньше времени. В данном случае условного времени – дискретного.</p>
<div id="attachment_2002562" class="wp-caption alignnone" style="width: 310px"><a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d1814-d0b3d180d0b0d184d0b8d0bad0b8-d18dd184d184d0b5d0bad182d0b8d0b2d0bdd0bed181d182d0b8-d0b0d0bbd0b3d0bed180d0b8d182d0bcd0be1.jpg"><img class="size-medium wp-image-2002562" src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d1814-d0b3d180d0b0d184d0b8d0bad0b8-d18dd184d184d0b5d0bad182d0b8d0b2d0bdd0bed181d182d0b8-d0b0d0bbd0b3d0bed180d0b8d182d0bcd0be1-300x186.jpg" alt="Рис. 4. Графики эффективности алгоритмов (Ряд 1,2 – обычные, Ряд 3,4 – автоматные)" width="300" height="186" /></a><p class="wp-caption-text">Рис. 4. Графики эффективности алгоритмов (Ряд 1,2 – обычные, Ряд 3,4 – автоматные)</p></div>
<div id="attachment_2002563" class="wp-caption alignnone" style="width: 310px"><a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d1815-d0b3d180d0b0d184d0b8d0bad0b8-d18dd184d184d0b5d0bad182d0b8d0b2d0bdd0bed181d182d0b8-d0b0d0bbd0b3d0bed180d0b8d182d0bcd0be.jpg"><img class="size-medium wp-image-2002563" src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d1815-d0b3d180d0b0d184d0b8d0bad0b8-d18dd184d184d0b5d0bad182d0b8d0b2d0bdd0bed181d182d0b8-d0b0d0bbd0b3d0bed180d0b8d182d0bcd0be-300x189.jpg" alt="Рис.5. Графики вычислительной сложности алгоритмов (Ряд 1, 2 – обычные, Ряд 3 – параллельный рекурсивный)" width="300" height="189" /></a><p class="wp-caption-text">Рис.5. Графики вычислительной сложности алгоритмов (Ряд 1, 2 – обычные, Ряд 3 – параллельный рекурсивный)</p></div>
<p>Из совпадения вычислительной сложности алгоритмов следует, что, не зная какой алгоритм – рекурсивный или императивный реализует «черный ящик», сложно определить устройство внутренностей «ящика». Можно было бы судить по реальному времени, т.к. параллельный по идее должен быть быстрее. Но, это еще, как говорится, не факт! Может быть, правда, пока? <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> Однако, если известно точно, что «ящик» реализует рекурсивный алгоритм, то линейный характер вычислительной сложности говорит о том, что oн параллельный, а если экспоненциальный (аппроксимация с помощью функции СТЕПЕНЬ(число; степень из Excel приводит к зависимости – O(2^(N/1,44))  – последовательный.</p>
<p>… Но если вернутся к цели нашего исследования – анализу вычислительной сложности алгоритмов, то проблема, безусловно, не в том, что TBB замедлила в данном конкретном случае работу алгоритмов в реальном времени. В теории анализ алгоритмов не связывают с реальным временем, а рассматривают условное время. Например, когда «зернистость» будет соответствовать требованиям TBB (в пределах 1000 инструкций на такт условного времени), то, скорее всего, время работы уменьшится и возможно даже, как в случае с числами Фибоначчи, пропорционально числу ядер. Проблема в другом: свойства алгоритма, как показало тестирование, остались прежними – последовательными! Но смысл введения множества ядер не только и не столько в простом увеличении скорости работы программ, а в увеличение скорости за счет качественно иного программирования – параллельного. А последнее, если верить теории, должно привести к изменению его вычислительной сложности. Пока мы этого не наблюдаем (или не можем увидеть?).</p>
<p>Так может ли речь идти о параллельном алгоритме, если его свойства остаются последовательными? Для внешнего наблюдателя, играющего, например, в упомянутую выше имитацию, подобное «распараллеливание» эквивалентно простому увеличению тактовой частоты «ящика» – при увеличении скорости его работы, и уменьшении – при увеличении времени работы. Напомним, что в случае TBB скорость для однопоточной параллельной версии сначала уменьшилась в 66 раз, а потом для двух ядер увеличилась в два раза, т.е. в конечном итоге уменьшилась в 33 раза при сохранении вычислительной сложности (?).</p>
<p>Но тогда, если следовать правилам «игры» или, что точнее, теории алгоритмов, речь должна идти скорее о неких ухищрениях, в каких-то случаях повышающих, а в большинстве, как можно предположить, скорее понижающих,  скорость работы  программ. При этом сама причина уменьшения скорости в том, что под упомянутые требования зернистости подпадает лишь малая часть параллельных алгоритмов.<br />
Оценивая результаты тестирования алгоритмов, можно также возразить – просто мало ядер! Настолько мало, что их число никак не сказывается на свойствах алгоритма. Но будет ли достаточно 4-х, 8-ми и т.д. ядер? И, действительно, для параллельного рекурсивного алгоритма почти любое доступное их число сейчас и даже предполагаемое в будущем – капля в море, т.к. речь должна идти о сотнях тысяч ядер!</p>
<p>Оценку вычислительной сложности параллельного алгоритма можно и даже нужно выполнять исходя из понятия виртуального параллелизма. В этом случае и время должно быть виртуальным или условным. В автоматной модели условное/виртуальное время – это дискретное время. А как узнать виртуальное время (в теории, напомним, чаще говорят об относительном времени) работы многопоточного  алгоритма? Подсчитывать число инструкций, в том числе и выполняемых параллельно?...</p>
<p>PS: Тестирование параллельного рекурсивного алгоритма на MC# убеждает, что и  он имеет вычислительную сложность, как и у последовательного рекурсивного алгоритма.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/11/17/ii-2/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Первый взгляд на Go</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/11/17/go/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/11/17/go/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 09:57:46 +0000</pubDate>
		<dc:creator>ialexander</dc:creator>
		
		<category><![CDATA[Параллельное программирование]]></category>

		<category><![CDATA[Разработка софта]]></category>

		<category><![CDATA[Язык программирования Go]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/11/17/go/</guid>
		<description><![CDATA[Итак, что интересного, хорошего и плохого нашел я в этом языке, просидев с ним несколько дней?]]></description>
			<content:encoded><![CDATA[<p>Выход Go похож на дурную шутку. Сначала Google выпустил браузер Chrome, который работает только под Windows, теперь новый язык Go, компилятор которого есть под Linux и Mac OS X, но никак не под Windows. Оно, конечно, понятно, что есть хорошее оправдание - команда маленькая, и все охватить не могут, но тем не менее факт остается фактом.<br />
Выход этого языка - плохая новость для Microsoft, отнюдь не из-за того, что Google проигнорировал Windows, но из-за того, что он начал вторжение в святая святых MS - разработка средств разработки. Теперь Балмеру, чтобы исправить ситуацию придется прыгать в 2 раза выше и кричать в 2 раза чаще: "Developers! Developers! Developers!".<br />
Итак, что интересного, хорошего и плохого нашел я в этом языке, просидев с ним несколько дней.</p>
<p>Первое, что бросается в глаза, в этом якобы Си-подобном языке, это объявления переменных и типов. Здесь добавлены новые ключевые слова и все перевернуто с ног на голову, команда Go, утверждает, что так удобнее. Но поначалу такое нововведение вызывает только раздражение. Теперь, чтобы объявить переменную i типа int, придется выдать конструкцию:</p>
<blockquote>
<pre>var i int;</pre>
</blockquote>
<p>Другие примеры:</p>
<blockquote>
<pre>var p *int; //указатель
var str string; //строка</pre>
</blockquote>
<p>Да, да все верно. В Go строки поддерживаются самим языком, мало того, как и в C# они неизменяемые. А значит, при работе с ними придется быть крайне внимательным, чтобы не наплодить кучу строковых объектов.</p>
<p>Арифметике указателей, напротив, придется сказать "до свидания". Гуглы решили, что так безопаснее, да еще и проще будет реализовать сборщик мусора. Ага, в Go появилось и это чудо. Гугл декларирует Go как быстрый язык поддерживающий параллельное программирование. Как сборщик мусора будет сочетаться с этими декларациями? Весьма, весьма интересно. Одно правда, для ряда параллельных задач сборщик мусора упрощает дело. Бывает так, что приходится писать пользовательские менеджеры памяти, только, чтобы память можно было освобождать в условиях общей памяти и многопоточности. С другой стороны, сборщик мусора может серьезно сказаться на эффективности. Задачи дискретной оптимизации, к примеру, весьма активно используют память и сборщик мусора тут может сыграть дурную шутку. Но пока это лишь предположения.</p>
<p>Разработчики Go так и не смогли обойтись без синтаксического сахара в объявлениях переменных, следующие 2 объявления равнозначны:</p>
<blockquote>
<pre>var i int = 0;
i := int(0);</pre>
</blockquote>
<p>Оператор := позволяет задавать тип переменной, исходя из типа присваиваемого значения.</p>
<p>Для констант также не нужно задавать тип константы, он определяется по типу значения:</p>
<blockquote>
<pre>const NewLine = "\n";</pre>
</blockquote>
<p>Можно объединить определения нескольких констант следующим образом:</p>
<blockquote>
<pre>const (
	NewLine = "\n";
	MagicNumber = int(7);
)</pre>
</blockquote>
<p>У языка Go настоящая беда с точками с запятой, правило где их нужно ставить, а где необязательно весьма запутаны, так, что я предпочитаю ставить и везде, так спокойнее.</p>
<p>Функции в Go достаточно интересны. Они выдерживают общий стиль объявления новых типов, и на этот раз ключевым словом является func:</p>
<blockquote>
<pre>func lisa(grade int) {...} // по правилам Си: void foo(int i) {...}
func bart(shorts string) string {...} //const char *bart(const char *str) {...}</pre>
</blockquote>
<p>Все это конечно замечательно, но есть одно дополнение, которое позволит обходится без boost::tuple в качестве возвращаемого значения:</p>
<blockquote>
<pre>func homer(beer string) (int, double) {...} //аналог в Си: эээ...
		//int homer(const char *beer, double *result) {...}</pre>
</blockquote>
<p>В общем, несколько возвращаемых значений не новинка и поддерживаются в том же Руби, но какого их нет в таком вроде новом языке как C#? И в C++ их тоже не хватает. Стандартная ситуация: возврат кода ошибки и основного результата.</p>
<p>Пожалуй не буду дальше испытывать ваше терпение, и некоторые более интересные типы вроде исключений и определений новых типов я оставлю до следующей записи.<br />
P.S.:Для тех, кто как и я страдает без подсветки синтаксиса в Go, могу предложить файл определений для библиотеки <a href="http://projects.gnome.org/gtksourceview/">GtkSourceView-2.x</a>, если вы скопируете его в папку /usr/share/gtksourceview-2.0/language-specs/ (путь может меняться в зависимости от дистрибутива Linux), то такие приложения как gedit, будут поддерживать подсветку синтаксиса Go: <a href="http://software.intel.com/file/23751">go.lang</a>.</p>
<ul>
<li><a href="http://golang.org">Сайт языка программирования Go</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/11/17/go/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Go, Go, Google, Go!</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/11/12/go-go-google-go/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/11/12/go-go-google-go/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 08:31:28 +0000</pubDate>
		<dc:creator>vilianov</dc:creator>
		
		<category><![CDATA[Открытый код]]></category>

		<category><![CDATA[Параллельное программирование]]></category>

		<category><![CDATA[Google Go]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/11/12/go-go-google-go/</guid>
		<description><![CDATA[Я начал подозревать неладное, когда появился онлайновый почтовый клиент и сервер одновременно Gmail. Подозрения усилились с запуском онлайновых офиса и переводчика. После анонса "андроида" не спал всю ночь, думал о виртуальном Big Brother'е. Браузер Chrome поставил на компьютер в первый же день, потому что все уже было понятно. Выход Google Wave воспринял, как грубые ласки перед массовой виртуальной лоботомией...]]></description>
			<content:encoded><![CDATA[<p>Ну что, свершилось... Я начал подозревать неладное, когда появился онлайновый почтовый клиент и сервер одновременно Gmail. Подозрения усилились с запуском онлайновых офиса и переводчика. После анонса "андроида" не спал всю ночь, думал о виртуальном Big Brother'е. Браузер Chrome поставил на компьютер в первый же день, потому что все уже было понятно. Выход Google Wave воспринял, как грубые ласки перед массовой виртуальной лоботомией...</p>
<p>И вот - гран финале. Сегодня Google объявила о выходе собственного языка программирования Go. Начался обратный отсчет времени до тотального покорения галактики.</p>
<p>Я сейчас сижу на сайте <a href="http://golang.org/">http://golang.org/</a>, читаю документацию и паралелльно общаюсь со знатоками. Не скрою, мне трудно, потому что никакой я не программист  - так, тестировщик. Пока на вид ничего страшного: в FAQ много уклончивых формулировок и маркетингового бла-бла, и по соседству признается, что даже в самой великой и ужасной Google до массового использования мегаязыка пока не дошло.</p>
<p>И вот вроде всего первый день пошел, а отзывов в Интернете уже пруд пруди. Кто-то называет странным плодом любви Python с C++. Кто-то придумал имя для людей, программирующих на нем - Goпники. Есть голоса, предрекающие кончину во младенчестве, а есть и оптимисты, гарантирующие скорый переход на Go 99,9 процентов всех программистов мира. Не 100, потому что этих фортранщиков все равно не переубедить. Они переживут даже ядерную зиму.</p>
<p>Скептики могут сказать, что существует несколько тысяч языков программирования, и одним больше, одним меньше - не повод тратить виртуальные чернила. Но тут ведь как в известном анекдоте: "я не знаю, кто в машине, но шофер у него Брежнев". Людские и финансовые возможности Google таковы, что если в компании решат - Go попрет стремительным домкратом. Коллеги по бизнесу сначала посмеются, потом помолчат, а потом запрутся в маленьких комнатках и начнут бояться любого звука. Помните, как хихикали над Microsoft, когда корпорация вышла на рынок приставок? Вот, недавно вышло исследование - на долю Xbox приходится уже 49% отечественного рынка, да и на мировом одни сплошные поводы для оптимизма. В общем, главное - захотеть.</p>
<p>Но захочет ли Google? Чтобы понять это, язык  <span style="line-through;">врага</span> надо знать и понимать немного лучше, чем это под силу экс-тестировщику. Поэтому обращаюсь к вам, уважаемые коллеги. Каковы первые впечатления? Насколько доработан язык на сегодняшний день? Правда ли, что он заточен исключительно под серверные приложения, а остальным просьба не беспокоится? Что может заставить лично вас серьезно сесть на Go? И - главное - нужен ли индустрии новый язык программирования? И нужен ли ей Go?</p>
<p>Меня пока порадовало вот что. В беседе с одним из экспертов, автором нескольких серьезных книг по программированию, который пока решил остаться неизвестным, первым делом был озвучен интерес -насколько применение Go облегчает распараллеливание?</p>
<p>Дорогой Дмитрий Оганезов! Даже если Big Brother нас таки заглотит, мы будем знать, что идея пошла в массы, и если бы не он - все бы у нас получилось. Но может еще и получится, а?</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/11/12/go-go-google-go/feed/</wfw:commentRss>
		</item>
		<item>
		<title>По теплым следам онлайн семинара "Intel(R) Parallel Studio workflow"</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/11/09/intelr-parallel-studio-workflow/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/11/09/intelr-parallel-studio-workflow/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 14:48:36 +0000</pubDate>
		<dc:creator>Kirill Mavrodiev (Intel)</dc:creator>
		
		<category><![CDATA[Intel Software Network]]></category>

		<category><![CDATA[Академическое сообщество]]></category>

		<category><![CDATA[Конкурсы и мероприятия]]></category>

		<category><![CDATA[Параллельное программирование]]></category>

		<category><![CDATA[Parallel Studio]]></category>

		<category><![CDATA[Tachyon]]></category>

		<category><![CDATA[онлайн семинар]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/11/09/intelr-parallel-studio-workflow/</guid>
		<description><![CDATA[Хочу поделиться своими впечатлениями о первом в русскоязычном сообществе онлайн-семинаре от Intel. Вебинар назывался “Intel® Parallel Studio workflow” и был посвящен одному из подходов к распараллеливанию и оптимизации последовательных приложений, на примере трассировщика лучей Tachyon.]]></description>
			<content:encoded><![CDATA[<p>Хочу поделиться своими впечатлениями о первом в русскоязычном сообществе онлайн-семинаре от Intel. Вебинар назывался “Intel® Parallel Studio workflow” и был посвящен одному из подходов к распараллеливанию и оптимизации последовательных приложений, на примере трассировщика лучей Tachyon.</p>
<p>Данный подход называют “Распараллеливание черного ящика”. Он состоит из 4х основных шагов:</p>
<ul>
<li>этап поиска мест, где параллелизм наиболее эффективен;</li>
<li>этап программной реализации распараллеливания;</li>
<li>этап отладки работы уже параллельного приложения;</li>
<li>этап повышения эффективности распараллеливания.</li>
</ul>
<p>Для каждого этапа я использовал один из компонентов инструментария Intel® Parallel Studio: <em>Parallel Amplifier</em> – Hotspots, <em>Parallel Composer</em>, <em>Parallel Inspector</em> и <em>Parallel Amplifier</em> – Concurrency и Lock and Waits, соответственно. Первому шагу я уже посвятил один из своих блогов: <a href="http://software.intel.com/ru-ru/blogs/2009/10/26/2002338/">http://software.intel.com/ru-ru/blogs/2009/10/26/2002338/</a>. Я планирую опубликовать блоги по оставшимся этапам. Так что у вас будет возможность задать вопросы, которые вы не задали на семинаре.</p>
<p>Теперь о моих впечатлениях: Не хочу обидеть Нижегородцев, но я очень рад тому, что география аудитории онлайн-семинара оказалась довольно обширной: начиная дальним востоком России и заканчивая средней Европой. Попытаюсь объяснить почему. В силу своего географического расположения, студенты Нижнего Новгорода имеют возможность как минимум 1 раз в квартал посещать технические семинары, которые проводят инженеры компании Intel «в живую». У студентов других городов такой возможности, к сожалению, нет. Мне самому повезло, так как во время учебы я принимал участие (приезжал из Уфы) в Зимней школе 2005 и в Летней школе 2007 от компании Интел, которые проходили в Нижнем Новгороде. Таким образом, к окончанию учебы я уже знал, какие знания и какой опыт от меня будит требовать работодатель.</p>
<p>Вести онлайн семинар оказалось гораздо труднее, чем в живую. Во-первых, во время семинара я не мог понять, насколько интересно и понятно содержание презентации и демонстраций, т.к. нет ран-тайм общения с аудиторией. К примеру, когда я вижу, что большая часть засыпает или нет вообще никаких вопросов со стороны слушателей, то я стараюсь повернуть русло в другую сторону и попытаться заинтересовать аудиторию. Если это не в 8-9 утра, конечно :). Во-вторых, это задержка видео и звукового сигнала. Когда логически переходишь к новому слайду или картинке, но аудитория еще не видит ее, это порой сбивает с мысли. Этот список можно продолжать. Но, как говорится, ”Первый блин комом”. Мы постараемся учесть все ошибки, и следующий “вебинарь” получится лучше с технической точки зрения. Предлагаю обсудить ваши впечатления. Пользуясь случаем, хочу задать вопрос: какие онлайн семинары вы бы хотели посетить?. Стоит заметить, что я уже получил запросы на подробное описание Advanced Vector Extension (AVX) и Intel® Parallel Debugger Extension (PDE).</p>
<p>Я думаю, что мы найдем специалистов, которые поделятся с вами своими знаниями и опытом. Надеюсь на то, что встречаться с вами на онлайн семинарах станет хорошей традицией.</p>
<p>Спасибо Вам, Спасибо Диме и Маше!</p>
<blockquote><p>Add-on от <a href="http://software.intel.com/ru-ru/blogs/author/dmitry-oganezov/">Дмитрия</a>:</p>
<p>Да пожалуйста! :). Пользуясь правами администратора ISN, я беспардонно влезу в эту запись чтобы еще раз поблагодарить Кирилла :). Кирилл, ты у нас первопроходец! И не только в плане самого что ни на есть первого русского вебинара. Я внимательно посмотрел на вебинары наших зарубежных коллег, и вот что оказалось: мы первые, кто показывает на вебинаре case study: не просто презентацию, а живые демки. Впрочем, довольно петь друг другу дифирамбы: недостатков тоже хватало! Как уже сказал Кирилл, ваши отзывы и пожелания принимаются в виде комментариев к этой записи. Заранее спасибо.</p></blockquote>
<p>Ссылки по теме:<br />
Посмотреть вебинар в записи можно <a href="http://intelwebinars.na6.acrobat.com/p45462250/">здесь</a> (извините, первые минут 5 «потерялись»).<br />
Исходники проекта Tachyon на разных стадиях оптимизации лежат <a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/tachyon-parallelstudio.zip">здесь</a>.<br />
<a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/tachyon-step-by-step.doc">Описание</a> процесса сборки Tachyon.<br />
Скачать триальную версию Intel® Parallel Studio можно <a href="http://software.intel.com/sites/products/irc/StudioEvalForm6.html">здесь</a>.</p>
<p>Всем удачи!</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/11/09/intelr-parallel-studio-workflow/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Миллион шагов на месте</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/11/08/2002466/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/11/08/2002466/#comments</comments>
		<pubDate>Sun, 08 Nov 2009 01:24:53 +0000</pubDate>
		<dc:creator>Alexey Kukanov (Intel)</dc:creator>
		
		<category><![CDATA[Параллельное программирование]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/11/08/2002466/</guid>
		<description><![CDATA[Задавшись в комментариях к записи "33 шага назад" вопросом, каким образом введение параллелизма может поменять асимптотические характеристики алгоритма, я должен был быстрее догадаться, каков правильный ответ. ]]></description>
			<content:encoded><![CDATA[<p>Для тех, кто не в курсе, о чём пойдёт речь, попробую сделать краткое вступление.</p>
<p>В своей записи на здешней блог-площадке Вячеслав Любченко привёл графики времени работы параллельного рекурсивного алгоритма нахождения чисел Фибоначчи в зависимости от порядкового номера числа в последовательности. И в случае реализации алгоритма на TBB время росло экспоненциально, а у реализации, где структура алгоритма описана при помощи конечных автоматов (КА) - линейно!</p>
<p>В чём тут дело, я должен был догадаться раньше, почти сразу. Никакой параллелизм не способен перевести экспоненциальную сложность исходного алгоритма в линейную, кроме ... экспоненциально растущего :) </p>
<p>Исполнение рекурсивного алгоритма определения числа Фибоначчи суть есть обход двоичного дерева с подсчётом его листьев. Последовательное исполнение - обход в глубину, параллельное - обход в ширину. Глубина дерева - N-1, где N - порядковый номер искомого числа Фибоначчи (рассматриваем N&gt;1, считая, что для N&lt;=1 решение известно). Для идеально сбалансированного двоичного дерева на каждом ярусе глубины d содержится 2 в степени d (2^d) узлов; соответственно, количество листьев - 2^(N-1). В нашей задаче дерево не сбалансировано; но можно показать, что и в нашем случае максимальное количество узлов на одном ярусе, как и общее количество узлов, имеет асимптотическую оценку O(2^N). </p>
<p>В КА реализации у Вячеслава каждому узлу дерева соответствует один конечный автомат, а в самой простой реализации на TBB - одна "задача", то есть объект класса, унаследованного от tbb::task. Все автоматы, как и все задачи, могут работать/исполняться независимо друг от друга. Так откуда же разница в поведении?</p>
<p>А разница, на самом деле, в применённых методиках измерения. При оценке поведения КА реализации Вячеслав использовал дискретное время. За один такт дискретного времени все автоматы осуществляют переход из одного состояния в другое, причём их количество на дискретное время не влияет. По сути, время оценивается <em>до</em> этапа отображения (mapping) возможного параллелизма на конкретную аппаратную платформу.</p>
<p>При получении же графиков для TBB и MC# использовалось время "настенное" (wall clock time), измеренное <em>после</em> отображения возможного параллелизма на реальную платформу, в которой фактическая степень параллелизма равна 2 и постоянна. Чуда не случится, от добавления второго (4-го, 32-го) ядра асимптотическое поведение алгоритма не изменится.</p>
<p>Чтобы поведение алгоритма, предсказанное в дискретном времени, совпадало с поведением во времени реальном, необходима такая же степень реального (аппаратного) параллелизма, какова была степень параллелизма при получении оценки. То есть, для достижения асимптотического поведения О(N) необходим аппаратный параллелизм порядка O(2^N). Подумаешь, всего какой-то миллион или около того ядер для вычисления 30-го числа Фибоначчи <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> Причём, если зафиксировать аппаратный параллелизм даже на этом уровне и продолжить увеличивать N, то асимптотическое поведение быстро вернётся к экспоненциальному; для сохранения линейности алгоритма необходимо и дальше экспоненциально наращивать мощность. Представьте себе компьютер, в котором сколь угодно много вычислителей добавляются динамически по мере надобности и сразу же встраиваются в работу программы. Это, конечно, классно, но боюсь, ещё долго останется нереальным.</p>
<p>Чтобы избежать сравнения яблок с томатами, можно для КА реализации алгоритма построить график зависимости <em>реального</em> времени от N. Поскольку переходы для всех автоматов обсчитываются последовательно на одном ядре, реальное время, соответствующее одному дискретному такту, будет сильно разным для моделей из десятка и из миллиона автоматов, а в результате на графике будет та же экспонента (что Вячеслав и подтвердил в комментариях).</p>
<p>Справедливости ради замечу, что Вячеслав предпринял попытку привести измеренное реальное время в форму, пригодную для сравнения с дискретным. Но это, на мой взгляд, невозможно. Его идея об использовании времени работы итеративного алгоритма в качестве нормирующего фактора явно не работает. Докажу от противного: если такое преобразование приводит реальное время в форму, сопоставимую с дискретным, то это должно быть истинно и для КА модели. Реальное время T работы КА программы растёт как O(2^N), при нормировании константой получим время T'=T*O(1), то есть растущее по тому же закону. Соответствия поведению дискретного времени DT ~ О(N) мы не получили, значит, преобразование не достигает желаемой цели.</p>
<p>Стало быть, выводы, которые Вячеслав сделал о TBB как параллельной модели, некорректны, так как исходили из ложных посылок.</p>
<p>В завершение замечу, что TBB и другие модели, которые умеют отображать потенциальный параллелизм на реально присутствующий аппаратный, для задач с рекурсивным параллелизмом будут выдавать решение, масштабируемое с ростом количества доступных ядер - в отличие от последовательной реализации КА модели у Вячеслава, которая, сколько ядер не добавь, будет пока что топтаться на месте. Всеми миллионами конечных автоматов, в ритме дискретного времени :)</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/11/08/2002466/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Тридцать три шага назад!?</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/11/06/2002442/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/11/06/2002442/#comments</comments>
		<pubDate>Fri, 06 Nov 2009 11:29:04 +0000</pubDate>
		<dc:creator>vlubch</dc:creator>
		
		<category><![CDATA[Параллельное программирование]]></category>

		<category><![CDATA[TBB]]></category>

		<category><![CDATA[Фибоначчи]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/11/06/2002442/</guid>
		<description><![CDATA[Если доверять классикам, то иногда нужно сделать шаг назад, чтобы потом - два шага вперед. А что же в параллельном программировании? Куда мы шагаем, что и в чем выигрываем? Чтобы легче было шагать, нам в помощь дадены разнообразные средства для параллельного программирования – языки, библиотеки и т.п. Обратим свой взгляд на библиотеку Intel® TBB (Intel® Threading Building Blocks) и посмотрим, куда она нас приведет.]]></description>
			<content:encoded><![CDATA[<p>На мою просьбу написать рекурсивный параллельный алгоритм на базе TBB так никто и не откликнулся. Алексей Куканов – молчит, прошу прощения, как рыба, несмотря на мои неоднократные обращения к нему лично, у остальных – свои проблемы и, видимо, интересы. Но, как мне представляется, интересы у нас одни – параллельное программирование, а потому нужен все же диалог. Хотя бы… ну хоть кто-нибудь намекнул, что данный алгоритм приведен в документации к Intel® TBB (Intel® Threading Building Blocks)! Или, может, Алексей не следит за блогами, а остальные не знакомы с ее описанием? И то и другое достаточно удивительно, если не сказать странно! <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> Тем не менее, к вящей радости проблема нашла свое решение – сам нашел! <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Но – к делу! Если доверять классикам, то иногда нужно сделать шаг назад, чтобы потом - два шага вперед. А что же в параллельном программировании? Куда мы шагаем, что и в чем выигрываем? Чтобы легче было шагать, нам в помощь дадены разнообразные средства для параллельного программирования – языки, библиотеки и т.п. Обратим свой взгляд на библиотеку Intel® TBB (Intel® Threading Building Blocks) и посмотрим, куда она нас приведет. Будет ли наш «параллельный путь» легче и/или быстрее.</p>
<p>Собираясь в дальний путь, настоятельно рекомендуется проверить средства передвижения. В противном случае – это халатность, граничащая с безрассудством. Целям проверки в дистрибутиве TBB служат ее тестовые примеры. Выберем из множества примеров, имеющихся в составе дистрибутива, один из самых простых и наглядных – вычисление чисел Фибоначчи. Это проект fibonacci из дистрибутива TBB.</p>
<p>Числа Фибоначчи нам известны, или должны быть известны, с юных лет (см., например, «Энциклопедический словарь юного математика»). Результаты тестовых прогонов для чисел в диапазоне от 20-го до 28-го числа по обычным алгоритмам – императивному и рекурсивному и параллельному аналогу рекурсивного алгоритма сведены в таблицу 1.</p>
<blockquote><p><code>Таблица 1.<br />
20       21       22       23       24       25      26       27       28<br />0,002033 0,002187 0,002333 0,002502 0,002678 0,00282 0,002978 0,003184 0,003376<br />0,5717   0,9314   1,499674 2,427057 3,948402 6,3763  10,30745 16,63595 26,99721<br />38,277   61,795   100,736  162,243  264,04   427,75  691,78   1119,94  1808,8<br />19,626   32,397   50,981   82,236   132,24   214,11  344,99   557,68   903,44</code></p></blockquote>
<p>В ней первая строка соответствует номеру числа, вторая - реальному времени работы императивного алгоритма, третья - рекурсивного, четвертая и пятая – однопоточной и двухпоточной версиям рекурсивного алгоритма на базе TBB. Рекурсивный алгоритм заимствован из документа Tutoril комплекта документации к TBB, используемый процессор - Intel® Core™2 CPU 6400 @ 2,13 GHz.</p>
<p>Поскольку тестирование проводилось на двухядерном процессоре, то время работы «двухядерного» варианта меньше ровно в два раза. Эффект от многоядерности налицо! Однако, если мы сравним время работы алгоритмов во второй строке и в четвертой, то имеем замедление работы более чем в тридцать три раза (на первую строку лучше не смотреть!). Или, другими словами, чтобы достичь скорости исходного алгоритма, запрограммированного обычным способом и на одном ядре, нам нужно будет минимум шестьдесят шесть (!) ядер, чтобы хотя бы приблизиться к нему по производительности. Глядя на таблицу и вспоминая вопрос Сергея Вильянова – «Есть ли реальная польза от многоядерных процессоров?», напрашивается один ответ – нет, т.к. медленно!</p>
<p>При такой скорости многоядерности сложно быть «торопливым» (см. <a href="http://software.intel.com/ru-ru/blogs/2009/02/12/2000639/">http://software.intel.com/ru-ru/blogs/2009/02/12/2000639/</a>). Мечталось-то, ведь, совсем о другом! Но если серьезно, то подобные факты не способствуют оптимизму, т.к. желаемое и в этот раз только отодвинулось, причем на достаточно большое расстояние, т.к. о более чем шестидесятиядерном процессоре сейчас, думаю, даже мечтать нельзя, хотя и ходят разговоры о тысячах ядер!</p>
<p>Но проблема-то, как это ни удивительно, не в скорости. Скорость - это как раз поправимо. Проблема глубже. Если мы немного «пошаманим» с таблицей, то вдруг выясняется, что параллелизма как такового библиотека TBB в приложение не добавляет. Скрытое становится явным, если мы посмотрим на графики алгоритмов, которые приведены к времени вычисления императивного алгоритма (к вычислению 20-го числа).</p>
<p>На рис. 1 графики обычного рекурсивного алгоритма и его параллельных аналогов совпадают идеально, имея экспоненциальный характер роста зависимости скорости работы от номера числа в ряду Фибоначчи. А вот скорость императивного алгоритма, как легко видеть, представляет собой линейную функцию (см. ряд 1 на рис.1).</p>
<p><a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d181-11.jpg"><img class="size-medium wp-image-2002441 alignnone" src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d180d0b8d181-11-300x169.jpg" alt="" width="300" height="169" /><br />
</a><em>Рис.1. График зависимости скорости работы программы от n</em></p>
<p>Но, может, так оно и должно быть? Т.е. если мы имеем обычный рекурсивный алгоритм и его эквивалентный параллельный аналог, то и характер их поведения должен быть похожим в силу свойств алгоритма? Но зачем тогда параллелизм? Тем более, как можно видеть, мы только усугубляем ситуацию, усложняя программирование (см. на код с TBB) да еще и многократно замедляя работу программ.</p>
<p>Но, слава Богу (или – нам?), можно показать, что ситуация не столь уж удручающая. Параллельным программированием заниматься можно и нужно. Так, для нашего случая зависимость скорости расчета от номера числа у параллельного рекурсивного алгоритма должна быть столь же линейна, как и у последовательного императивного алгоритма. Уже только это - источник большого оптимизма. Важно переломить тенденцию, т.к. скорость увеличить достаточно просто (правда, до известных пределов, которых мы, к сожалению, уже фактически достигли). Ну а о том, что это возможно, в следующем блоге.</p>
<p>Весьма важное замечание. Сейчас мы в поиске надежных, эффективных и адекватных средств и/или моделей параллельных вычислений. В этом смысле параллельный рекурсивный алгоритм оказался «лакмусовой бумажкой» тестирования библиотеки на адекватность параллелизму. Пока, как показало испытание, несмотря на заявленный параллелизм, ТВВ не влияет качественно на свойства алгоритма (скажем осторожно – в данном случае). Да, отдавая ей должное, TBB использует множество ядер (см. таблицу 1), но при этом не добавляет параллельных свойств алгоритму. Что делать? Это уже вопрос, наверное, к … Алексею. Если, конечно, он не отмолчится в очередной раз <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>И еще. Сороковое число обычный рекурсивный алгоритм считает почти за 9 сек, параллельный двухпоточный – за 290 сек! Все то же сакральное - «тридцать три». Параллелизм – полный! <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>А интересно, какую зависимость получим, протестировав параллельный рекурсивный алгоритм на MC#? Этого я, честно, пока не знаю. Вот выяснением этого и займусь. Проблема только в одном – мне известно, что уже на 16-м/17-м числе программа на MC# аварийно завершает свою работу. Значит, нужно выбирать другой диапазон…</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/11/06/2002442/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Сверхлинейное ускорение</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/11/04/2002434/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/11/04/2002434/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 12:29:54 +0000</pubDate>
		<dc:creator>ialexander</dc:creator>
		
		<category><![CDATA[Параллельное программирование]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/11/04/2002434/</guid>
		<description><![CDATA[Мы привыкли слышать утверждения, что параллельные методы показывают плохую эффективность, а хорошие последовательные алгоритмы плохо распараллеливаются. Доказываем обратное на примере задачи коммивояжёра с отсечением по методу ветвей и границ.]]></description>
			<content:encoded><![CDATA[<p>Неприятной особенностью многих задач дискретной оптимизации является то, что точное решение можно получить только перебором. А другой особенностью является то, что количество решений растет экспоненциально с размером задачи, и задачу достаточно небольшой размерности при полном переборе можно решать дольше времени жизни вселенной. К примеру, число решений задачи коммивояжёра с 60 городами больше, чем число молекул во вселенной, а это считается весьма небольшой задачей. Поэтому единственным возможным вариантом найти оптимальное решение является ограниченный перебор.<br />
Одним из таких алгоритмов является метод ветвей и границ. Его ключевой идеей является разбиение по некоторым формальным критериям множества решений на подмножества, затем делается попытка доказать, что в конкретном подмножестве не содержится оптимальных решений. Как правило, это делается с помощью процедуры граничной оценки подмножества, которая дает оценку наилучшего возможного решения подмножества и сравнение полученного значения с рекордом - лучшего известного решения. В случае, если удастся доказать, что подмножество не содержит оптимальных решений, оно удаляется из дальнейшего рассмотрения, "отсеивается". В противном случае само подмножество разбивается, и для каждого нового подмножества применяется процедура оценки. Ветвление продолжается до тех пор пока все подмножества не будут отсеяны; если в подмножестве остается только одно решение, и оно лучше рекорда, последний обновляется новым полученным значением.</p>
<p>Рекорд, оставшийся после отсева всех подмножеств, является оптимальным решением.<br />
Первоначальное значение рекорда может быть получено с помощью какой-нибудь эвристики (генетические алгоритмы, алгоритмы муравьиных колоний и др.).<br />
Критически важными здесь являются качество процедуры оценки и значение рекорда. Лучше всего, если оно равно оптимальному решению, в этом случае отсев будет происходить максимально быстро.</p>
<p>Итак после краткого введения в специфику решаемых задач рассмотрим результаты одного вычислительного эксперимента решения задачи коммивояжёра на МВС-100К:</p>
<table border="1" cellspacing="0">
<tbody>
<tr>
<td>Число  Процессоров</td>
<td>Время (сек)</td>
<td>Ускорение</td>
<td>Число  ветвлений</td>
</tr>
<tr>
<td>1</td>
<td>664,83</td>
<td>1</td>
<td>3299763</td>
</tr>
<tr>
<td>2</td>
<td>96,9</td>
<td>6,86</td>
<td>1331230</td>
</tr>
<tr>
<td>4</td>
<td>34,49</td>
<td>19,28</td>
<td>900641</td>
</tr>
<tr>
<td>8</td>
<td>42,03</td>
<td>15,82</td>
<td>1939826</td>
</tr>
<tr>
<td>16</td>
<td>26,14</td>
<td>25,43</td>
<td>2374063</td>
</tr>
<tr>
<td>32</td>
<td>21,81</td>
<td>30,48</td>
<td>3225846</td>
</tr>
<tr>
<td>48</td>
<td>8,52</td>
<td>78,03</td>
<td>2038415</td>
</tr>
<tr>
<td>64</td>
<td>4,11</td>
<td>161,76</td>
<td>1325692</td>
</tr>
<tr>
<td>96</td>
<td>2,9</td>
<td>229,25</td>
<td>1194724</td>
</tr>
</tbody>
</table>
<p>В столбце "Ускорение" задано ускорение по сравнению с последовательным (однопроцессорном) вариантом. Как легко заметить, практически во всех строках мы наблюдаем сверхлинейное ускорение, кроме строки с числом процессоров равным 32. Мало того, здесь наблюдается еще одна интересная аномалия: задача на 4-х процессорах решается быстрее, чем на 8. Объяснение этой аналомалии мне уже приходилось давать:</p>
<blockquote><p>Процесс решения задачи методом ветвей и  границ можно представить как  обход дерева, в каждой вершине  которого по соотношению между оценкой и рекордом определяется, подлежит ли эта вершина дальнейшему ветвлению. Очевидно, что число ветвлений (вершин дерева ветвления) зависит от того, в каком порядке обходится это дерево. Можно очень быстро получить оптимальное или близкое к нему решение и затем уже отсеять оставшиеся вершины. При этом число ветвлений сильно зависит от числа используемых процессоров, определяющего распределение множества вершин между собой и, следовательно, порядок обхода дерева. Чтобы нивелировать влияние порядка обхода, перед началом ветвлений рекорду присваиваем оптимальное значение. Тогда порядок обхода дерева становится несущественным, так как оптимальное решение уже известно, и производится лишь отсев вершин (т.е. доказательство оптимальности).</p></blockquote>
<p>В цитате еще раз напоминается о важности хорошего рекорда. Похоже, что в варианте с 4 процессорами кости легли так, что хороший рекорд очень быстро находится. В этом легко убедиться посмотрев на столбец "Число ветвлений". В варианте с 4 процессорами ветвлений меньше миллиона, в то время как в варианте с 8 процессорами их почти 2 миллиона.</p>
<p><em>UPDATE</em>: В следующей таблице представлены результаты эксперимента с заранее заданным рекордом, равным оптимальному решению, т.е. эффект быстрого нахождения хорошего рекорда нивелирован.</p>
<table border="1" cellspacing="0">
<tbody>
<tr>
<td>Число  процессоров</td>
<td>Время (сек)</td>
<td>Ускорение</td>
</tr>
<tr>
<td>1</td>
<td>56,53</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>28,31</td>
<td>2</td>
</tr>
<tr>
<td>4</td>
<td>14,14</td>
<td>4</td>
</tr>
<tr>
<td>8</td>
<td>7,83</td>
<td>7,22</td>
</tr>
<tr>
<td>16</td>
<td>4,59</td>
<td>12,32</td>
</tr>
<tr>
<td>32</td>
<td>2,64</td>
<td>21,41</td>
</tr>
<tr>
<td>48</td>
<td>1,72</td>
<td>32,87</td>
</tr>
<tr>
<td>64</td>
<td>1,6</td>
<td>35,33</td>
</tr>
<tr>
<td>96</td>
<td>1,7</td>
<td>33,25</td>
</tr>
</tbody>
</table>
<p>Мы можем видеть, что ни о каком сверхлинейном ускорении и речи быть не может.</p>
<p>Тем не менее, в качестве выводов хотелось бы сделать следующее замечание. В данном примере параллельный метод решения задачи показал большую эффективность, нежели последовательный. И теперь идеи параллельного решения можно попробовать использовать для улучшения последовательного. Мы же привыкли слышать другие утверждения, параллельные методы показывают худшую эффективность, а хорошие последовательные плохо распараллеливаются.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/11/04/2002434/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Grand Central Dispatch от Apple</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/11/03/grand-central-dispatch-apple/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/11/03/grand-central-dispatch-apple/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 08:11:26 +0000</pubDate>
		<dc:creator>ialexander</dc:creator>
		
		<category><![CDATA[Параллельное программирование]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/11/03/grand-central-dispatch-apple/</guid>
		<description><![CDATA[Лично для меня из новинок в Mac OS X 10.6 Snow Leopard наиболее интересна задаче-ориентированная (во, загнул) технология параллельного программирования Grand Central Dispatch (GDC).
GCD предлагает разделять весь выполняемый код на независимые задачи (tasks) и помещать их в очереди, откуда они запускаются при наличии свободных ресурсов. Если в числе свободных у нас числятся 4 ядра, то одновременно [...]]]></description>
			<content:encoded><![CDATA[<p>Лично для меня из новинок в Mac OS X 10.6 Snow Leopard наиболее интересна задаче-ориентированная (во, загнул) технология параллельного программирования Grand Central Dispatch (GDC).<br />
GCD предлагает разделять весь выполняемый код на независимые задачи (tasks) и помещать их в очереди, откуда они запускаются при наличии свободных ресурсов. Если в числе свободных у нас числятся 4 ядра, то одновременно у нас будет выполняться 4 потока.</p>
<p>Перед тем, как привести пример работы технологии, придется рассказать о недавно добавленной поддержке замыканий в C/C++/Objective-C под называнием "блоки". Блоки объявляются с помощью нового оператора ^:</p>
<pre name="code" class="cpp">int i = 5;
testb = ^(char *s) { printf("string is %s, number is %d\n", s, i); };
testb("hello");</pre>
<p>Результатом вызова в 3-й строке будет:</p>
<blockquote><p>string is hello, number is 5</p></blockquote>
<p>Подробнее о блоках мы можете почитать в википедии: <a href="http://ru.wikipedia.org/wiki/%D0%91%D0%BB%D0%BE%D0%BA%D0%B8_%28%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0_%D0%A1%D0%B8%29">Блоки (расширение языка Си)</a>.<a href="http://ru.wikipedia.org/wiki/%D0%91%D0%BB%D0%BE%D0%BA%D0%B8_%28%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0_%D0%A1%D0%B8%29"><br />
</a></p>
<p>Итак, на входе у нас имеется следующий последовательный код:</p>
<pre name="code" class="cpp">for (i = 0; i &lt; count; i++) {
      results[i] = do_work(data, i);
}
total = summarize(results, count);</pre>
<p>При условии, что функция do_work не изменяет какие-либо глобальные переменные, мы можем распараллелить с помощью OpenMP:</p>
<pre name="code" class="cpp">#pragma omp parallel for
for (i = 0; i &lt; count; i++) {
      results[i] = do_work(data, i);
}
total = summarize(results, count);</pre>
<p>А при использовании GDC код будет выглядеть так:</p>
<pre name="code" class="cpp">dispatch_apply(count, dispatch_get_global_queue(0, 0), ^(size_t i){
     results[i] = do_work(data, i);
    });
total = summarize(results, count);</pre>
<p>Почувствуйте, что называется разницу. На самом деле разница, конечно, есть. Технология Apple имеет более широкое применение, к примеру, задачи мы можем запускать не только параллельно, но и асинхронно (dispatch_async), а также запускать в определенное время (dyspatch_after). Таким образом, GDC поддерживает не только параллельные вычисления, но обеспечивает новый способ добавления асинхронности в приложения. Притом этот способ действительно выглядит весьма прозрачным и простым, как утверждает Apple. Мало того, Apple обещает, что создание и запуск задачи будет требовать очень мало ресурсов, намного меньшие чем создание и запуск потока.</p>
<p>В целом, Grand Central Dispatch выглядит неплохо, предлагает новый подход к созданию параллельных приложений и асинхронных вызовов (хотя концепция задачи отнюдь не нова, она давно витает в воздухе), но на революцию совсем не тянет. Т. к. основная задача распараллеливания - выделение независимых участков кода, которые могут выполняться параллельно, все равно остается на разработчике.</p>
<p>Что интересно, Apple выпустила GCD под открытой лицензией Apache, и в данный момент эта технология уже портирована на FreeBSD (см. [1]).</p>
<p>Ссылки:</p>
<ol>
<li><a href="http://libdispatch.macosforge.org/">libdispatch</a></li>
<li><a href="http://ru.wikipedia.org/wiki/Grand_Central_Dispatch">Wikipedia: Grand Central Dispatch</a></li>
<li><a href="http://ru.wikipedia.org/wiki/%D0%91%D0%BB%D0%BE%D0%BA%D0%B8_%28%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0_%D0%A1%D0%B8%29">Wikipedia: Блоки (расширение языка Си)</a></li>
<li><a href="http://habrahabr.ru/blogs/macosxdev/66632/">Поддержка замыканий в Snow Leopard</a></li>
</ol>
<p>P.S. По этой теме я перевел 2 статьи англоязычной википедии про GCD и Blocks, и понятное дело, разместил их перевод в русской википедии. В ходе перевода пришлось сделать ряд допущений, к примеру, Blocks перевел как блоки, а Task Parallelism - параллелизм задач (есть вариант параллелизм заданий). В общем, я усиленно намекаю что, критика перевода и особенно его улучшение приветствуются.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/11/03/grand-central-dispatch-apple/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
