<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>З.П.И. &#187; C#</title>
	<atom:link href="http://wiki.dodex.org/tag/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://wiki.dodex.org</link>
	<description>Что-то новое пришедшее в голову или интересное, найденное в интернете</description>
	<lastBuildDate>Tue, 08 Nov 2011 10:16:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Parallel Extensions для .net 3.5</title>
		<link>http://wiki.dodex.org/2008/11/28/parallel-extensions-%d0%b4%d0%bb%d1%8f-net-35/</link>
		<comments>http://wiki.dodex.org/2008/11/28/parallel-extensions-%d0%b4%d0%bb%d1%8f-net-35/#comments</comments>
		<pubDate>Fri, 28 Nov 2008 16:57:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[потоки]]></category>

		<guid isPermaLink="false">http://wiki.dodex.org/?p=419</guid>
		<description><![CDATA[Количество ядер у процессоров растет год от года. Но многие программы до сих пор умеют использовать только одно. В небольшой заметке хочу рассказать о дополнении к библиотеке System.Threading, которое называется Parallel Extensions. Это дополнение позволяет на высоком уровне выполнять задачи на всех доступных ядрах/процессорах. Данная статья является лишь кратким вводным обзором в Parallel Extensions. Так [...]]]></description>
			<content:encoded><![CDATA[<p><!-- Тело записи --><a href="http://wiki.dodex.org/wp-content/uploads/2008/11/001_19_contrast.jpg"><img class="size-full wp-image-420 alignleft" title="001_19_contrast" src="http://wiki.dodex.org/wp-content/uploads/2008/11/001_19_contrast.jpg" alt="" width="150" height="74" /></a>Количество ядер у процессоров растет год от года. Но многие программы до сих пор умеют использовать только одно. В небольшой заметке хочу рассказать о дополнении к библиотеке <code>System.Threading</code>, которое называется <em>Parallel Extensions</em>. Это дополнение позволяет на высоком уровне выполнять задачи на всех доступных ядрах/процессорах.</p>
<p>Данная статья является лишь кратким вводным обзором в <em>Parallel Extensions</em>. Так же в конце статьи вы найдете ссылки на ресурсы, которые раскрывают тему во всех деталях.</p>
<p>Если интересно, то смело ныряем под кат.</p>
<p><span id="more-419"></span></p>
<p><strong>Немного истории</strong></p>
<p>Библиотека <em>Parallel Extensions</em> (PE) — совместный проект команды .net и Microsoft Research — впервые увидела свет 29 ноября 2007 года. Она создана для того, чтобы разработчики могли пользоваться современными многоядерными архитектурами, не утруждая себя трудоемким управлением потоками. Программы, написанные с применением библиотеки, автоматически используют все доступные ядра системы. Если же программа будет запущена на старом одноядерном компьютере, то выполнение будет происходить последовательно, практически без потерь в производительности. Таким образом, использование PE раскрывает все преимущества многоядерных технологий, сохраняя работоспособность на одноядерных системах.</p>
<p>Последнее обновление библиотеки было в июне 2008 года. Сейчас она имеет статус <em>Community Technology Preview</em> и, скорее всего, войдет в 4 версию .net.</p>
<p><strong>Состав библиотеки</strong></p>
<p>PE состоит из трех основных компонентов:</p>
<ul>
<li>Task Parallel Library (TPL) — предоставляет такие императивные методы, как <code>Parallel.For</code>, <code>Parallel.Foreach</code> и <code>Parallel.Invoke</code> для выполнения параллельных вычислений. Вся работа по созданию и завершению потоков, в зависимости от имеющихся процессоров выполняется библиотекой автоматически.</li>
<li>Parallel LINQ (PLINQ) — надстройка над LINQ to Objects и LINQ to XML, позволяющая выполнять параллельные запросы. В большинстве случаев достаточно в начале запроса написать <code>AsParallel()</code> для того, чтобы все последующие операторы выполнялись параллельно. Внутренне использует TPL.</li>
<li>Coordination Data Structures (CDS) — набор структур, который используется для синхронизации и координации выполнения параллельных задач. Ее мы рассматривать в этой статье не будем.</li>
</ul>
<p>Хочу предупредить, что эта библиотека не решает вопросов, связанных с потоковой безопасностью объектов. Если вы используете не <em>ThreadSafe</em> объекты, то сами должны следить за тем, чтобы объект использовался только одним потоком.</p>
<p><strong>Что будем делать</strong></p>
<p>В качестве примера предлагаю взять поиск простых чисел от 2 до заданного предела. Будем все числа из этого интервала проверять следующим статическим методом:</p>
<blockquote><p><code><span style="color: black;"><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> Prime<br />
{<br />
<span style="color: #008000;">/// &lt;summary&gt;</span><br />
<span style="color: #008000;">/// Determines whether the specified candidate is prime.</span><br />
<span style="color: #008000;">/// &lt;/summary&gt;</span><br />
<span style="color: #008000;">/// &lt;param name="candidate"&gt;The candidate.&lt;/param&gt;</span><br />
<span style="color: #008000;">/// &lt;returns&gt;</span><br />
<span style="color: #008000;">///   &lt;c&gt;true&lt;/c&gt; if the specified candidate is prime; otherwise, &lt;c&gt;false&lt;/c&gt;.</span><br />
<span style="color: #008000;">/// &lt;/returns&gt;</span><br />
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">bool</span> IsPrime(<span style="color: #0000ff;">int</span> candidate)<br />
{<br />
<span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> d = 2; d &lt;= candidate/2; d++)<br />
{<br />
<span style="color: #0000ff;">if</span>(candidate%d == 0)<br />
<span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span>;<br />
}<br />
<span style="color: #0000ff;">return</span> candidate &gt; 1;<br />
}<br />
}</span></code></p></blockquote>
<p>Для удобства создадим интерфейс:</p>
<blockquote><p><code><span style="color: black;"> <span style="color: #0000ff;">interface</span> IPrimeFinder<br />
{<br />
<span style="color: #008000;">/// &lt;summary&gt;</span><br />
<span style="color: #008000;">/// Finds primes up to the specified limit.</span><br />
<span style="color: #008000;">/// &lt;/summary&gt;</span><br />
<span style="color: #008000;">/// &lt;param name="limit"&gt;The limit.&lt;/param&gt;</span><br />
<span style="color: #008000;">/// &lt;returns&gt;List of primes&lt;/returns&gt;</span><br />
<span style="color: #2b91af;">List</span>&lt;<span style="color: #0000ff;">int</span>&gt; Find ( <span style="color: #0000ff;">int</span> limit );<br />
}</span></code></p></blockquote>
<p><strong>Эталонный расчет</strong></p>
<p>В качестве эталона будем считать простой цикл for от 2 до <code>limit</code>:</p>
<blockquote><p><code><span style="color: black;"><span style="color: #0000ff;">public</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #0000ff;">int</span>&gt; Find(<span style="color: #0000ff;">int</span> limit)<br />
{<br />
<span style="color: #0000ff;">var</span> result = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #0000ff;">int</span>&gt;();</span></code></p>
<p><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i = 2; i &lt; limit; i++)<br />
{<br />
<span style="color: #0000ff;">if</span>(Prime.IsPrime(i))<br />
result.Add(i);<br />
}</p>
<p><span style="color: #0000ff;">return</span> result;<br />
}</p></blockquote>
<p>Если мы запустим нашу программу, то увидим примерно следующий график загрузки процессора при поиске всех простых чисел до 200 000:</p>
<p><a href="http://wiki.dodex.org/wp-content/uploads/2008/11/halfcpu.png"><img class="alignnone size-full wp-image-421" title="halfcpu" src="http://wiki.dodex.org/wp-content/uploads/2008/11/halfcpu.png" alt="" width="486" height="101" /></a></p>
<p>Процессор работает только в пол силы. Попробуем это исправить.</p>
<p><strong>Parallel.For</strong></p>
<p>Большое преимущество этой библиотеки в том, что для создания многопоточного код а требуется минимум изменений. В нашем случае метод <code>Parallel.For()</code> принимает три параметра: начало интервала, конец и делегат для выполнения. Заметьте, что модификация не затрагивает тело цикла:</p>
<blockquote><p><code><span style="color: black;"><span style="color: #0000ff;">public</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #0000ff;">int</span>&gt; Find(<span style="color: #0000ff;">int</span> limit)<br />
{<br />
<span style="color: #0000ff;">var</span> result = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #0000ff;">int</span>&gt;();</span></code></p>
<p>Parallel.For(2,    <span style="color: #008000;">//start from</span><br />
limit, <span style="color: #008000;">//up to</span><br />
i =&gt;  <span style="color: #008000;">//action variable</span><br />
{<br />
<span style="color: #0000ff;">if</span>(Prime.IsPrime(i))<br />
result.Add(i);<br />
});</p>
<p><span style="color: #0000ff;">return</span> result;<br />
}</p></blockquote>
<p>Изменения минимальны, но давайте посмотрим, на график загрузки процессора:</p>
<p><a href="http://wiki.dodex.org/wp-content/uploads/2008/11/fullcpu.png"><img class="alignnone size-full wp-image-422" title="fullcpu" src="http://wiki.dodex.org/wp-content/uploads/2008/11/fullcpu.png" alt="" width="486" height="101" /></a></p>
<p>Используются оба ядра. И время выполнения сократилось почти в два раза (одна клетка — 5 секунд). Стоит заметить, что <code>List&lt;T&gt;</code> позволяет добавлять элементы в разных потоках. А вот если бы мы попытались пройтись по с списку с помощью foreach, то получили бы ошибку. Вся работа с синхронизацией так и лежит на пользователе.</p>
<p><strong>AsParallel()</strong></p>
<p>Одним из моих самых любимых новшеств в .net стал LINQ. Он позволяет сократить многие конструкции до одной строчки. Вот как будет выглядеть наш пример, записанный с помощью LINQ:</p>
<blockquote><p><code><span style="color: black;">Enumerable.Range ( 2, limit - 1 ).Where ( Prime.IsPrime ).ToList ( );</span></code></p></blockquote>
<p>Коротко и ясно. Для того, чтобы сделать этот запрос параллельным нужно дописать всего одно слово <code>AsParallel()</code>:</p>
<blockquote><p><code><span style="color: black;">Enumerable.Range(2, limit - 1).AsParallel().Where(Prime.IsPrime).ToList();</span></code></p></blockquote>
<p>Все, что записано после <code>AsParallel()</code> будет выполнено в параллельных потоках, используя все процессоры. Как видно и в случае LINQ никаких изменений, затрагивающих содержание исходного кода, не потребовалось. Более того этот вариант более безопасен с точки зрения потоков: в данном случаем PLINQ сам синхронизирует выполнение. Можно так же использовать и агрегирующие функции.</p>
<p><strong>Parallel.Invoke()</strong></p>
<p><code>Parallel.Invoke()</code> в основном используется для выполнения разноплановых задач. В нашем варианте мы разобьем все числа из диапазона на 10 частей и выполним расчет в виде параллельных задач. Для этого создадим дополнительный метод помощник, который в качестве аргументов получает верхнюю границу, количество поддиапазонов и номер поддиапазона для расчета:</p>
<blockquote><p><code><span style="color: black;"><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #0000ff;">int</span>&gt; CheckRange(<span style="color: #0000ff;">int</span> n, <span style="color: #0000ff;">int</span> limit, <span style="color: #0000ff;">int</span> factor)<br />
{<br />
<span style="color: #0000ff;">var</span> local_result = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #0000ff;">int</span>&gt;();<br />
<span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i = n*(limit/factor); i &lt; (n + 1)*(limit/factor); i++)<br />
{<br />
<span style="color: #0000ff;">if</span>(Prime.IsPrime(i))<br />
local_result.Add(i);<br />
}<br />
<span style="color: #0000ff;">return</span> local_result;<br />
}</span></code></p></blockquote>
<p>В качестве аргумента <code>Parallel.Invoke()</code> в нашем случае принимает массив делегатов. Новый код будет выглядеть так:</p>
<blockquote><p><code><span style="color: black;"><span style="color: #0000ff;">public</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #0000ff;">int</span>&gt; Find(<span style="color: #0000ff;">int</span> limit)<br />
{<br />
<span style="color: #0000ff;">var</span> result = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #0000ff;">int</span>&gt;();<br />
Parallel.Invoke(() =&gt; result.AddRange(CheckRange(0, limit, 10)),<br />
() =&gt; result.AddRange(CheckRange(1, limit, 10)),<br />
() =&gt; result.AddRange(CheckRange(2, limit, 10)),<br />
() =&gt; result.AddRange(CheckRange(3, limit, 10)),<br />
() =&gt; result.AddRange(CheckRange(4, limit, 10)),<br />
() =&gt; result.AddRange(CheckRange(5, limit, 10)),<br />
() =&gt; result.AddRange(CheckRange(6, limit, 10)),<br />
() =&gt; result.AddRange(CheckRange(7, limit, 10)),<br />
() =&gt; result.AddRange(CheckRange(8, limit, 10)),<br />
() =&gt; result.AddRange(CheckRange(9, limit, 10)));</span></code></p>
<p><span style="color: #0000ff;">return</span> result;<br />
}</p></blockquote>
<p>Мы, конечно, сильно изменили код, но это не типичная ситуация.</p>
<p><strong>Немного статистики</strong></p>
<p>Для наглядности привожу график скорости выполнения:</p>
<p><a href="http://wiki.dodex.org/wp-content/uploads/2008/11/graph.png"><img class="alignnone size-full wp-image-423" title="graph" src="http://wiki.dodex.org/wp-content/uploads/2008/11/graph.png" alt="" width="486" height="278" /></a></p>
<p>И график загрузки процессора (немного растянул):</p>
<p><a href="http://wiki.dodex.org/wp-content/uploads/2008/11/cpu.png"><img class="alignnone size-full wp-image-424" title="cpu" src="http://wiki.dodex.org/wp-content/uploads/2008/11/cpu.png" alt="" width="486" height="102" /></a></p>
<p>На графике загрузки хорошо видны паттерны из трех методов, использующих параллельные вычисления и одного эталонного.</p>
<p>Даже при маленьком количестве вычислений, когда процессоры загружены не полностью, использование PE дает практически двукратный прирост скорости. Существует небольшой оверхеад при первом обращении к библиотеке. Выбор же типа параллельных вычислений на скорость практически не влияет.</p>
<p><strong>Дайте два!</strong></p>
<ol>
<li>Страница загрузки <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=348F73FD-593D-4B3C-B055-694C50D2B0F3&amp;displaylang=en">Parallel Extensions</a></li>
<li>Исходные коды примера: <a href="http://img.3fonov.ru/2008/11/pe/Look4Prime.zip">Look4Prime</a></li>
</ol>
<p><strong>И это все ?!?</strong></p>
<p>Нет, не все. Вот ссылки для более углубленного изучения:</p>
<ul>
<li>Подразделение <a href="http://msdn.microsoft.com/en-us/concurrency/default.aspx">Parallel Computing</a></li>
<li><a href="http://blogs.msdn.com/pfxteam/">Parallel FX Team Blog</a></li>
<li><a href="http://en.wikipedia.org/wiki/Parallel_FX_Library">Parallel FX Library</a> в Википедии</li>
<li><a href="http://msdn.microsoft.com/en-us/magazine/cc163329.aspx">Running Queries On Multi-Core Processors</a></li>
</ul>
<p>Взято с Хабра.  <a title="http://habrahabr.ru/blogs/net/45732/" href="http://habrahabr.ru/blogs/net/45732/" target="_blank">http://habrahabr.ru/blogs/net/45732/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://wiki.dodex.org/2008/11/28/parallel-extensions-%d0%b4%d0%bb%d1%8f-net-35/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ClickOnce</title>
		<link>http://wiki.dodex.org/2008/11/11/clickonce/</link>
		<comments>http://wiki.dodex.org/2008/11/11/clickonce/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 19:04:51 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[ClickOnce]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[VisualStudio]]></category>
		<category><![CDATA[Развертывание]]></category>
		<category><![CDATA[Установка]]></category>

		<guid isPermaLink="false">http://wiki.dodex.org/?p=5</guid>
		<description><![CDATA[Столкнувшись с задачей установки програмного обеспечения у клиента, набрел на интересную технологию &#8211; ClickOnce. Из описания: Что такое развертывание ClickOnce? ClickOnce – это технология развертывания, позволяющая создавать приложения Windows с возможностью самообновления, которые могут устанавливаться и запускаться с минимальным вмешательством пользователя. Развертывание ClickOnce разрешает три основные проблемы развертывания. Всю остальную инфу нетрудно получить поиском в [...]]]></description>
			<content:encoded><![CDATA[<p>Столкнувшись с задачей установки програмного обеспечения у клиента, набрел на интересную технологию &#8211; ClickOnce. Из описания:</p>
<p><strong>Что такое развертывание ClickOnce?</strong><br />
ClickOnce – это технология развертывания, позволяющая создавать приложения Windows с возможностью самообновления, которые могут устанавливаться и запускаться с минимальным вмешательством пользователя. Развертывание ClickOnce разрешает три основные проблемы развертывания.</p>
<p>Всю остальную инфу нетрудно получить <a href="http://www.google.ru/search?q=Clickonce" target="_blank">поиском в Google</a>, по фразе ClickOnce.</p>
]]></content:encoded>
			<wfw:commentRss>http://wiki.dodex.org/2008/11/11/clickonce/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

