<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-6248105557226342764</atom:id><lastBuildDate>Wed, 26 Oct 2011 09:45:00 +0000</lastBuildDate><category>bltoolkit</category><category>reflection</category><category>cpumem</category><category>bug</category><category>programming</category><category>boost</category><category>callgrind</category><category>expression-templates</category><category>nb</category><category>simd</category><category>links</category><category>asio</category><category>suxx</category><category>c#</category><category>hint</category><category>valgrind</category><category>python</category><category>sse</category><category>spirit</category><category>gcc</category><category>file processing</category><category>performance</category><category>kcachegrind</category><category>cpp</category><category>preprocessor</category><category>.NET</category><category>event-system</category><title>sergey miryanov</title><description /><link>http://sergey-miryanov.blogspot.com/</link><managingEditor>noreply@blogger.com (Sergey Miryanov)</managingEditor><generator>Blogger</generator><openSearch:totalResults>38</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/sergey-miryanov" /><feedburner:info uri="sergey-miryanov" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>sergey-miryanov</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-6474267813235067726</guid><pubDate>Mon, 29 Aug 2011 10:15:00 +0000</pubDate><atom:updated>2011-08-29T16:15:22.103+06:00</atom:updated><title>How I setup Jenkins to build haskell/network</title><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
Haskell/network is &lt;a class="ot-anchor" href="https://github.com/haskell/network"&gt;https://github.com/haskell/network&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;What I setup:&lt;br /&gt; * msysgit [1]. Installed to C:\Program Files (x86)\Git&lt;br /&gt; * MinGW [2]. Installed to C:\MinGW&lt;br /&gt; * ghc [3, 4, 5]. Installed to c:\ghc\*&lt;br /&gt; * cabal-install [6]. Installed to c:\ghc&lt;br /&gt; &lt;br /&gt;After this I updated SYSTEM PATH environment variable (not user!) in following way:&lt;br /&gt; * C:\MinGW\msys\1.0\bin&lt;br /&gt; * C:\MinGW\bin&lt;br /&gt; * C:\ghc&lt;br /&gt; * C:\ghc\ghc-6.10.4\bin&lt;br /&gt; * C:\ghc\ghc-6.12.3\bin&lt;br /&gt; * C:\ghc\ghc-7.0.3\bin&lt;br /&gt; * C:\Program Files (x86)\Git\cmd&lt;br /&gt; * C:\Program Files (x86)\Git\bin&lt;br /&gt;&lt;br /&gt;MinGW required to execute autoreconf.&lt;br /&gt;&lt;br /&gt;Jenkins
 service started with my windows user credentials. This allowed service 
to access cabal package database, because with default service APPDATA 
path it fails on cabal update.&lt;br /&gt;&lt;br /&gt;Also, maybe I did something wrong but 'cabal install &lt;s&gt;w ghc&lt;/s&gt;*.exe --only-dependencies --enable-tests' did not work, so I installed all deps manually.&lt;br /&gt;&lt;br /&gt;[1] Git-1.7.6-preview20110708.exe from &lt;a class="ot-anchor" href="http://code.google.com/p/msysgit/downloads/list"&gt;http://code.google.com/p/msysgit/downloads/list&lt;/a&gt;&lt;br /&gt;[2] &lt;a class="ot-anchor" href="http://sourceforge.net/projects/mingw/files/Automated%20MinGW%20Installer/mingw-get-inst"&gt;http://sourceforge.net/projects/mingw/files/Automa&lt;wbr&gt;&lt;/wbr&gt;ted%20MinGW%20Installer/mingw-get-inst&lt;/a&gt;&lt;br /&gt;[3] &lt;a class="ot-anchor" href="http://www.haskell.org/ghc/download_ghc_6_10_4"&gt;http://www.haskell.org/ghc/download_ghc_6_10_4&lt;/a&gt;&lt;br /&gt;[4] &lt;a class="ot-anchor" href="http://www.haskell.org/ghc/download_ghc_6_12_3"&gt;http://www.haskell.org/ghc/download_ghc_6_12_3&lt;/a&gt;&lt;br /&gt;[5] &lt;a class="ot-anchor" href="http://www.haskell.org/ghc/download_ghc_7_0_3"&gt;http://www.haskell.org/ghc/download_ghc_7_0_3&lt;/a&gt;&lt;br /&gt;[6] cabal.exe from &lt;a class="ot-anchor" href="http://www.haskell.org/cabal/download.html"&gt;http://www.haskell.org/cabal/download.html&lt;/a&gt;&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-6474267813235067726?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/_ZNu1RHN1Jc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/_ZNu1RHN1Jc/how-i-setup-jenkins-to-build.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2011/08/how-i-setup-jenkins-to-build.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-4016708328661934346</guid><pubDate>Fri, 10 Jul 2009 05:34:00 +0000</pubDate><atom:updated>2009-07-10T11:46:07.759+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">valgrind</category><category domain="http://www.blogger.com/atom/ns#">kcachegrind</category><category domain="http://www.blogger.com/atom/ns#">hint</category><category domain="http://www.blogger.com/atom/ns#">callgrind</category><title>valgrind, dlopen and debug info</title><description>Столкнулся сегодня с проблемой, что KCachegrind не отображает отладочную информацию для некоторых модулей.&lt;br /&gt;&lt;br /&gt;Покопавшись в интернетах наткнулся на этот баг (&lt;a href="http://bugs.kde.org/show_bug.cgi?id=142086"&gt;valgrind doesn't output debug info with dlopen'ed libraries &lt;/a&gt;) и вспомнил, что модули у нас загружаются динамически.&lt;br /&gt;&lt;br /&gt;Как сказано в последнем сообщение это все таки баг:&lt;br /&gt;&lt;blockquote&gt;The bug is still there.&lt;br /&gt;I did some debugging with Julian and we came to the conclusion that the problem is with chroot() after dlopen'ing the library.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Я проверил код, но явно chroot нигде не вызывается. &lt;br /&gt;&lt;br /&gt;Полез искать дальше и наткнулся на следующий баг (&lt;a href="http://bugs.kde.org/show_bug.cgi?id=79362"&gt;Debug info is lost for .so files when they are dlclose'd &lt;/a&gt;). Что навело меня на мысль не выгружать модули.&lt;br /&gt;&lt;br /&gt;И на самом деле помогло. &lt;br /&gt;&lt;br /&gt;Так, что если модули активно не загружаются и не выгружаются для профилирования можно отключить выгрузку модулей. Ну или пофиксить valgrind.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-4016708328661934346?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/K4TwDHvXWOI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/K4TwDHvXWOI/valgrind-dlopen-and-debug-info.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>1</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2009/07/valgrind-dlopen-and-debug-info.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-5639489494452665911</guid><pubDate>Sat, 28 Mar 2009 07:12:00 +0000</pubDate><atom:updated>2009-03-28T13:39:26.762+05:00</atom:updated><title>Domain-Specific Program Generation</title><description>А ни у кого случайно нет вот этой &lt;a href="http://books.google.com/books?hl=en&amp;lr=&amp;id=G6-YLrjVA_kC&amp;oi=fnd&amp;pg=PA107&amp;ots=CkyG2kZaaT&amp;sig=qPWpAXg7--oWHemamMyG3w7gpis#PPP1,M1"&gt;книги&lt;/a&gt; в электронном виде?&lt;br /&gt;&lt;br /&gt;upd:&lt;br /&gt;Уже не надо, помогли товарищи из стенфорда. Сейчас у меня есть статьи из нее:&lt;br /&gt; - Program Optimization in the Domain of High-Performance Parallelism&lt;br /&gt; - A Personal Outlook on Generator Research&lt;br /&gt; - PiLib: A Hosted Language for Pi-Calculus Style Concurrency&lt;br /&gt; - A Language and Tool for Generating Efficient Virtual Machine Interpreters&lt;br /&gt; - Optimizing Sequences of Skeleton Calls&lt;br /&gt; - Domain-Specific Optimizations of Composed Parallel Components&lt;br /&gt; - Runtime Code Generation in C++ as a Foundation for Domain-Specific Optimisation&lt;br /&gt; - Guaranteed Optimization for Domain-Specific Programming&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-5639489494452665911?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/Ceehwqu-bAo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/Ceehwqu-bAo/blog-post_28.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2009/03/blog-post_28.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-9051555958422921684</guid><pubDate>Tue, 24 Mar 2009 06:12:00 +0000</pubDate><atom:updated>2009-03-24T11:16:52.983+05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">hint</category><category domain="http://www.blogger.com/atom/ns#">cpp</category><title>ODR violation</title><description>Наткнулся сегодня на нарушение ODR (если я правильно понимаю). &lt;br /&gt;&lt;br /&gt;Суть в том, что если класс имеет __declspec specifier и, кроме того, имеется forward declaration и у этого forward declaration __declspec specifier не указан, то можно поиметь кучу проблем, например, с экспортом символов в dll - их может в dll просто не оказаться.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-9051555958422921684?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/iR4UI0bDSYc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/iR4UI0bDSYc/odr-violation.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2009/03/odr-violation.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-7928163023427209670</guid><pubDate>Sun, 22 Mar 2009 07:16:00 +0000</pubDate><atom:updated>2009-03-22T12:54:52.570+05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">event-system</category><category domain="http://www.blogger.com/atom/ns#">preprocessor</category><category domain="http://www.blogger.com/atom/ns#">boost</category><category domain="http://www.blogger.com/atom/ns#">cpp</category><title>Про систему событий</title><description>В свое время мне тоже надо было сделать какое-то подобие событийной системы, а так как я был увлечен BOOST_PP, то я нарисовал ее на нем.&lt;br /&gt;&lt;br /&gt;Для начала скажу, что если мы регистриуем события begin, end то такая система позволит писать нам this-&gt;on_begin () или this-&gt;on_end (), а не this-&gt;fire_event (begin_signal). К тому же, мы можем иметь любое количество параметров различных типов и проверка типов будет выполняться на этапе компиляции, т.е. например, this-&gt;on_begin (clock ()). &lt;br /&gt;&lt;br /&gt;Как это использовать:&lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;      &lt;font color="#000000"&gt;DECLARE_EVENT_LIST&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;reservoir_simulator&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt;&lt;br /&gt;                          &lt;font color="#000000"&gt;signal_params_t&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt;&lt;br /&gt;                          &lt;font color="#40B440"&gt;17&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt;&lt;br /&gt;                          &lt;font color="#C8003C"&gt;((&lt;/font&gt;&lt;font color="#000000"&gt;begin&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;clock_t&lt;/font&gt;&lt;font color="#C8003C"&gt;),&lt;/font&gt; &lt;font color="#40B440"&gt;1&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_initial_conditions&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_initial_conditions&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;begin_large_step&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_wells_process&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_grp_process&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_grp_process&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_low_skin_factor&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_low_skin_factor&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_large_step&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;begin_small_steps&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_small_steps&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_save_data&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_save_data&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_history_matching&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_history_macthing&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;end&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;clock_t&lt;/font&gt;&lt;font color="#C8003C"&gt;),&lt;/font&gt; &lt;font color="#40B440"&gt;1&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                          &lt;font color="#C8003C"&gt;));&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;Самое интересное здесь это:&lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;                          &lt;font color="#C8003C"&gt;((&lt;/font&gt;&lt;font color="#000000"&gt;begin&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;clock_t&lt;/font&gt;&lt;font color="#C8003C"&gt;),&lt;/font&gt; &lt;font color="#40B440"&gt;1&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_initial_conditions&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_initial_conditions&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;begin_large_step&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_wells_process&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_grp_process&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_grp_process&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_low_skin_factor&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_low_skin_factor&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_large_step&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;begin_small_steps&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_small_steps&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_save_data&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_save_data&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;before_history_matching&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;after_history_macthing&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;end&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;clock_t&lt;/font&gt;&lt;font color="#C8003C"&gt;),&lt;/font&gt; &lt;font color="#40B440"&gt;1&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;                          &lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;Это наш список событий - каждое событие описывается кортежом, состоящим из имени события, списка параметров (тоже кортеж) и количества параметров с списке.&lt;br /&gt;&lt;br /&gt;Итак:&lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="#0000C8"&gt;#define&lt;/font&gt; &lt;font color="#000000"&gt;DECLARE_EVENT_LIST&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;name_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;params_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;ts_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;t_&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;    &lt;font color="#0000FF"&gt;public&lt;/font&gt;&lt;font color="#C8003C"&gt;:&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;    &lt;font color="#000000"&gt;DECLARE_SIGNALS_ENUM&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;ts_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;t_&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;    &lt;font color="#000000"&gt;BOOST_PP_SEQ_FOR_EACH_I&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;UDECL_I&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;params_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;BOOST_PP_TUPLE_TO_SEQ&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;ts_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;t_&lt;/font&gt;&lt;font color="#C8003C"&gt;))&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;    &lt;font color="#000000"&gt;EXPORT_SIGNALS_ENUM&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;name_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;ts_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;t_&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;name_ - prefix, params_ - тип параметров, ts_ - количество событий в кортеже, t_ - кортеж событий. Про params_ я объясню позже.&lt;br /&gt;&lt;br /&gt;DECLARE_SIGNALS_ENUM(ts_, t_) - из кортежа событий делаем enum.&lt;br /&gt;BOOST_PP_SEQ_FOR_EACH_I(UDECL_I, params_, BOOST_PP_TUPLE_TO_SEQ(ts_, t_)) - создаем набор функций типа on_[event_name].&lt;br /&gt;EXPORT_SIGNALS_ENUM(name_, ts_, t_) - выгрузка этого дела в питон.&lt;br /&gt;&lt;br /&gt;Далее:&lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="#0000C8"&gt;#define&lt;/font&gt; &lt;font color="#000000"&gt;DECLARE_SIGNALS_ENUM&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;ts_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;t_&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;    &lt;font color="#0000FF"&gt;enum&lt;/font&gt; &lt;font color="#000000"&gt;signal_codes&lt;/font&gt; &lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;    &lt;font color="#000000"&gt;BOOST_PP_SEQ_FOR_EACH_I&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;DECLARE_SIGNAL_ENUM_I&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;BOOST_PP_TUPLE_TO_SEQ&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;ts_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;t_&lt;/font&gt;&lt;font color="#C8003C"&gt;))&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;  &lt;font color="#C8003C"&gt;};&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;BOOST_PP_TUPLE_TO_SEQ(ts_, t_) - делаем из кортежа событий последовательность.&lt;br /&gt;BOOST_PP_SEQ_FOR_EACH_I(DECLARE_SIGNAL_ENUM_I, _, BOOST_PP_TUPLE_TO_SEQ(ts_, t_)) - для каждого элемента последовательности применяем макрос DECLARE_SIGNAL_ENUM_I.&lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="#0000C8"&gt;#define&lt;/font&gt; &lt;font color="#000000"&gt;DECLARE_SIGNAL_ENUM_I&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;r&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;data&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;i&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;elem&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;    &lt;font color="#000000"&gt;BOOST_PP_CAT&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;BOOST_PP_TUPLE_ELEM&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#40B440"&gt;3&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt;&lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt;&lt;font color="#000000"&gt;elem&lt;/font&gt;&lt;font color="#C8003C"&gt;),&lt;/font&gt; &lt;font color="#000000"&gt;_signal&lt;/font&gt;&lt;font color="#C8003C"&gt;),&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3,0,elem), _signal) - т.к. событие у нас описывается кортежом и в данном макросе мы получили его в elem, то надо вытащить из него первые элемент, ну и добавить к нему префикс. На выходе получим нечто типа:&lt;br /&gt;enum {&lt;br /&gt;begin_signal, &lt;br /&gt;end_signal,&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Теперь нам надо создать функции on_[event_name].&lt;br /&gt;BOOST_PP_SEQ_FOR_EACH_I(UDECL_I, params_, BOOST_PP_TUPLE_TO_SEQ(ts_, t_)) - тоже самое, делаем последовательность и для каждого элемента применяем макрос UDECL_I.&lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="#0000C8"&gt;#define&lt;/font&gt; &lt;font color="#000000"&gt;DECL&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;type_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;name_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;t_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;ts_&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;    &lt;font color="#0000FF"&gt;void&lt;/font&gt; &lt;font color="#000000"&gt;BOOST_PP_CAT&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;on_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;name_&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;PARAM_LIST&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;BOOST_PP_TUPLE_TO_SEQ&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;ts_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;t_&lt;/font&gt;&lt;font color="#C8003C"&gt;),&lt;/font&gt; &lt;font color="#000000"&gt;ts_&lt;/font&gt;&lt;font color="#C8003C"&gt;))&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;    &lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;        &lt;font color="#000000"&gt;type_&lt;/font&gt; &lt;font color="#000000"&gt;params&lt;/font&gt;&lt;font color="#C8003C"&gt;;&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;        &lt;font color="#000000"&gt;PUSH_LIST&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;BOOST_PP_TUPLE_TO_SEQ&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;ts_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;t_&lt;/font&gt;&lt;font color="#C8003C"&gt;),&lt;/font&gt; &lt;font color="#000000"&gt;ts_&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;        &lt;font color="#0000FF"&gt;this&lt;/font&gt;&lt;font color="#C8003C"&gt;-&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;fire_signal&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;BOOST_PP_CAT&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;name_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;_signal&lt;/font&gt;&lt;font color="#C8003C"&gt;),&lt;/font&gt; &lt;font color="#000000"&gt;params&lt;/font&gt;&lt;font color="#C8003C"&gt;);&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;    &lt;font color="#C8003C"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000C8"&gt;#define&lt;/font&gt; &lt;font color="#000000"&gt;UDECL_I&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;r&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;data&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;i&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;elem&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;font color="#FFFFFF" style="background-color:#DCBEDC"&gt;\&lt;/font&gt;&lt;br /&gt;    &lt;font color="#000000"&gt;DECL&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;data&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;BOOST_PP_TUPLE_ELEM&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#40B440"&gt;3&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt;&lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt;&lt;font color="#000000"&gt;elem&lt;/font&gt;&lt;font color="#C8003C"&gt;),&lt;/font&gt; &lt;font color="#000000"&gt;BOOST_PP_TUPLE_ELEM&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#40B440"&gt;3&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt;&lt;font color="#40B440"&gt;1&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt;&lt;font color="#000000"&gt;elem&lt;/font&gt;&lt;font color="#C8003C"&gt;),&lt;/font&gt; &lt;font color="#000000"&gt;BOOST_PP_TUPLE_ELEM&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#40B440"&gt;3&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt;&lt;font color="#40B440"&gt;2&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt;&lt;font color="#000000"&gt;elem&lt;/font&gt;&lt;font color="#C8003C"&gt;))&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;Здесь тоже все просто - вытаскиваем из тупла, который описывает событие три элемента - имя, список параметров и количество параметров. Но так как не все прекрасно в датском королевстве, то полученные параметры нам надо упаковать в вектор и передать нижележащему слою. &lt;br /&gt;&lt;br /&gt;PUSH_LIST и PARAM_LIST у меня самописные (т.к. project-specif), но если разобраться как устроены некоторые BOOST_PP то можно подобрать аналог или написать свои, это на самом деле не сложно.&lt;br /&gt;&lt;br /&gt;Выгрузка в питон тоже не представляет интереса, т.к. делается по аналогии.&lt;br /&gt;&lt;br /&gt;Ну вроде все.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-7928163023427209670?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/HbdoLggSHWM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/HbdoLggSHWM/blog-post.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>2</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2009/03/blog-post.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-9064388605586915622</guid><pubDate>Sun, 22 Mar 2009 07:06:00 +0000</pubDate><atom:updated>2009-03-23T10:32:48.149+05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">spirit</category><category domain="http://www.blogger.com/atom/ns#">hint</category><category domain="http://www.blogger.com/atom/ns#">boost</category><category domain="http://www.blogger.com/atom/ns#">cpp</category><category domain="http://www.blogger.com/atom/ns#">expression-templates</category><title>template class overriding</title><description>Тут на днях выяснилось, что не все знают про один плюснутый трюк. Как известно, C++ не позволяют иметь шаблонные классы с одинаковым именем, но разным количеством шаблонных параметров. Т.е. код &lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="#0000FF"&gt;template&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#0000FF"&gt;typename&lt;/font&gt; &lt;font color="#000000"&gt;X&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000FF"&gt;struct&lt;/font&gt; &lt;font color="#000000"&gt;S&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;};&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000FF"&gt;template&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#0000FF"&gt;typename&lt;/font&gt; &lt;font color="#000000"&gt;X&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#0000FF"&gt;typename&lt;/font&gt; &lt;font color="#000000"&gt;Y&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000FF"&gt;struct&lt;/font&gt; &lt;font color="#000000"&gt;S&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;};&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;не является валидным. Но в некоторых случаях это ограничение можно обойти с помощью перегрузки функций:&lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="#0000FF"&gt;template&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#0000FF"&gt;typename&lt;/font&gt; &lt;font color="#000000"&gt;X&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000FF"&gt;struct&lt;/font&gt; &lt;font color="#000000"&gt;S_X&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;};&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000FF"&gt;template&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#0000FF"&gt;typename&lt;/font&gt; &lt;font color="#000000"&gt;X&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#0000FF"&gt;typename&lt;/font&gt; &lt;font color="#000000"&gt;Y&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000FF"&gt;struct&lt;/font&gt; &lt;font color="#000000"&gt;S_XY&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;};&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000FF"&gt;template&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#0000FF"&gt;typename&lt;/font&gt; &lt;font color="#000000"&gt;X&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#000000"&gt;S_X&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#000000"&gt;X&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#000000"&gt;S&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;i&gt;&lt;font color="#808080"&gt;/*params*/&lt;/font&gt;&lt;/i&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;br /&gt;  &lt;font color="#0000FF"&gt;return&lt;/font&gt; &lt;font color="#000000"&gt;S_X&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#000000"&gt;X&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;i&gt;&lt;font color="#808080"&gt;/*params*/&lt;/font&gt;&lt;/i&gt;&lt;font color="#C8003C"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000FF"&gt;template&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#0000FF"&gt;typename&lt;/font&gt; &lt;font color="#000000"&gt;X&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#0000FF"&gt;typename&lt;/font&gt; &lt;font color="#000000"&gt;Y&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#000000"&gt;S_XY&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#000000"&gt;X&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;Y&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#000000"&gt;S&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;i&gt;&lt;font color="#808080"&gt;/*params*/&lt;/font&gt;&lt;/i&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;br /&gt;  &lt;font color="#0000FF"&gt;return&lt;/font&gt; &lt;font color="#000000"&gt;S_XY&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#000000"&gt;X&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;Y&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;i&gt;&lt;font color="#808080"&gt;/*params*/&lt;/font&gt;&lt;/i&gt;&lt;font color="#C8003C"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;В первый раз я этот трюк использовал, когда &lt;a href="http://sergey-miryanov.blogspot.com/2008/03/blog-post.html"&gt;делал свой парсер а-ля boost::spirit&lt;/a&gt;. Также он используется при реализации техники &lt;a href="http://sergey-miryanov.blogspot.com/2008/07/expression-templates-sse.html"&gt;Expression Templates&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-9064388605586915622?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/k2I_7YNGUkM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/k2I_7YNGUkM/template-class-overriding.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2009/03/template-class-overriding.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-5233663758900872744</guid><pubDate>Tue, 06 Jan 2009 06:09:00 +0000</pubDate><atom:updated>2009-01-06T11:20:44.407+05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gcc</category><category domain="http://www.blogger.com/atom/ns#">bug</category><category domain="http://www.blogger.com/atom/ns#">cpp</category><title>GCC can't parse a non-parenthesized comma in a template-id within a default argument</title><description>Ковырялся вчера с нашим Ядром (тм) и наткнулся на баг в gcc (в Comeau Online компилится), гыгыгы :)&lt;br /&gt;Вот кусок кода, на котором можно протестить:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;template &amp;lt;typename T, bool F&amp;gt;&lt;br /&gt;struct sp&lt;br /&gt;{&lt;br /&gt;  sp ()&lt;br /&gt;  {&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;struct X&lt;br /&gt;{&lt;br /&gt;  typedef sp &amp;lt;X, true&amp;gt; sp_x;&lt;br /&gt;  //X (sp_x x = sp_x ())                      // OK&lt;br /&gt;  //X (sp &amp;lt;X, true&amp;gt; x = (sp &amp;lt;X, true&amp;gt; ()))    // OK&lt;br /&gt;  X (sp &amp;lt;X, true&amp;gt; x = sp &amp;lt;X, true&amp;gt; ())        // ERROR&lt;br /&gt;  {&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Баг в багзилле тоже нашел (&lt;a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57"&gt;#57&lt;/a&gt;) =)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-5233663758900872744?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/_FQznkfKKIE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/_FQznkfKKIE/gcc-cant-parse-non-parenthesized-comma.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2009/01/gcc-cant-parse-non-parenthesized-comma.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-2348199899619145749</guid><pubDate>Fri, 29 Aug 2008 17:54:00 +0000</pubDate><atom:updated>2008-08-29T23:57:58.680+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">programming</category><title /><description>&lt;blockquote&gt;Юра Бронников, известный своим переводом SICP на русский, &lt;a href="http://lj.rossia.org/users/gogabr/84420.html"&gt;взялся&lt;/a&gt; за &lt;a href="http://newstar.rinet.ru/~goga/tapl/"&gt;перевод&lt;/a&gt; отличной книги &lt;a href="http://www.cis.upenn.edu/%7Ebcpierce/tapl/"&gt;Types and Programming Languages&lt;/a&gt;. И он призывает учавствовать в вычитке. Книга планируется к изданию в бумажном виде.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;via &lt;a href="http://alexott-ru.blogspot.com/2008/08/blog-post_29.html"&gt;Alex Ott&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-2348199899619145749?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/lcNrirt6FwU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/lcNrirt6FwU/sicp-types-and-programming-languages.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>2</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/08/sicp-types-and-programming-languages.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-7130234012016706676</guid><pubDate>Thu, 24 Jul 2008 17:01:00 +0000</pubDate><atom:updated>2009-03-01T01:07:58.672+05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">hint</category><category domain="http://www.blogger.com/atom/ns#">python</category><category domain="http://www.blogger.com/atom/ns#">boost</category><title>boost::python hint</title><description>При выгрузке в питон классов с виртуальными функциями wrapper, который будет перенапралять вызовы должен хранить ссылку на питоновский объект. Но в бустовой &lt;a href="http://www.boost.org/doc/libs/1_35_0/libs/python/doc/v2/class.html#class_-spec"&gt;документации&lt;/a&gt; &lt;a href="http://www.boost.org/doc/libs/1_35_0/libs/python/doc/v2/call_method.html#examples"&gt;нигде не говорится&lt;/a&gt;, что у нее надо увеличивать счетчик. А делать, это желательно. Для этого нужно использовать &lt;a href="http://wiki.python.org/moin/boost.python/HowTo#head-424ccf31791b165173f04254cfe73cbaab133f7c"&gt;Py_INCREF/Py_DECREF&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-7130234012016706676?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/6SXu41cl__M" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/6SXu41cl__M/boostpyhon-hint.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>4</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/07/boostpyhon-hint.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-9188331978456688601</guid><pubDate>Sat, 05 Jul 2008 16:11:00 +0000</pubDate><atom:updated>2009-03-23T10:34:39.227+05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">performance</category><category domain="http://www.blogger.com/atom/ns#">simd</category><category domain="http://www.blogger.com/atom/ns#">cpp</category><category domain="http://www.blogger.com/atom/ns#">sse</category><category domain="http://www.blogger.com/atom/ns#">expression-templates</category><title>Эксперименты с expression templates и sse</title><description>Недавно узнал о новой для себя технике – &lt;a href="http://ubiety.uwaterloo.ca/~tveldhui/papers/Expression-Templates/exprtmpl.html"&gt;expression templates&lt;/a&gt;, это то знание, которого мне в свое время не хватило, когда &lt;a href="http://sergey-miryanov.blogspot.com/2008/03/blog-post.html"&gt;я писал парсер&lt;/a&gt; а-ля boost::spirit (нашел, кстати, &lt;a href="http://www.amergerzic.com/post/ExpressionTemplates.aspx"&gt;статью&lt;/a&gt;, в которой довольно подробно описано как устроен не весть, но часть boost::spirita).&lt;br /&gt;&lt;br /&gt;Недавно встала задача выполнения простейших арифметических операций над большими массивами данных. Конечно, это дело можно запрограммировать по старинке, но хочется, чтобы все было красиво и прозрачно – и тут я решил поискать, как, же все таки работает boost::spirit, оказалось, что в его основе лежит очень красивая и элегантная идея (и все менее слоупоки чем я с ней давно знакомы, я думаю). Идея в том, что операции над операндами выполняются не в момент, когда эти операции встречаются в выражении, а только в тот момент, когда результат данного выражения нужен. &lt;br /&gt;&lt;br /&gt;Как это делается? Для выражения на этапе компиляции строится дерево и для того, чтобы получить результат вычисления дерево просто обходится. Как это делается на плюсах? Основным строительным блоком является шаблонный оператор, состоящий из левого и правого операндов и операции между ними. Т.к. оператор шаблонный, то любой из операндов может быть точно таким же оператором (или любым типом, соответствующим требуемому интерфейсу).&lt;br /&gt;&lt;br /&gt;Я уже говорил, что я решил использовать эту технику для операций над массивами, и тут есть два варианта:&lt;br /&gt;- использовать готовую библиотеку (например, &lt;a href="http://tvmet.sourceforge.net/introduction.html"&gt;tvmet&lt;/a&gt;).&lt;br /&gt;- или написать свою примитивную.&lt;br /&gt;&lt;br /&gt;Во втором случае, либо вектора должны соответствовать нужному интерфейсу, либо надо сделать небольшой адаптер (в этом случае придется написать большую кучу операторов, это видно у меня в примере). Как видно я выбрал второй вариант.&lt;br /&gt;&lt;br /&gt;Набор классов для базовых операций (+, -, *, /) пишется за пол часа, ничего сложного нет.&lt;br /&gt;&lt;br /&gt;Набор классов позволит нам довольно наглядно описывать действия над массивами. Кроме того, эта техника позволит избавиться от временных переменных для хранения результатов конкретных операций. В случае, когда массивы имеют большую размерность это приятный бенефит. &lt;br /&gt;&lt;br /&gt;Второе, что я хотел сделать – это реализовать эти операции с использованием sse – во-первых хотелось наконец руками потрогать sse, во-вторых хотелось хоть не много сгладить потери в реализации, которые возможно (?) будут привнесены техникой.&lt;br /&gt;Для эффективной реализации алгоритмов с sse необходимо, чтобы данные были выровнены на границу 16-байтного слова. По умолчанию стандартный аллокатор не выравнивает память и необходимо либо написать свой, либо найти аллокатор, совместимый со стандартным, который бы выравнивал выделяемую память. Как оказалось, простой аллокатор с такой функциональностью сделать совсем не сложно. Что я, конечно, и сделал.&lt;br /&gt;&lt;br /&gt;Я сравнил что у меня получилось. Версия SSE2 обгоняет простую реализацию раза в полтора, а захардкоженная реализация тестового выражения обгоняет простую реализацию раза в два с половиной. Цифры:&lt;br /&gt;&lt;center&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fotki.yandex.ru/users/sergey-miryanov/view/62796/"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 393px;" src="http://img-fotki.yandex.ru/get/25/sergey-miryanov.1/0_f54c_2129b04c_XL" border="0" alt="" /&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Вот вроде и все. &lt;a href="http://www.everfall.com/paste/id.php?xt179xo4urak"&gt;Source code&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-9188331978456688601?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/GIicEClDYAI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/GIicEClDYAI/expression-templates-sse.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>1</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/07/expression-templates-sse.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-3941476662409063690</guid><pubDate>Sat, 05 Jul 2008 07:22:00 +0000</pubDate><atom:updated>2008-07-05T13:31:20.068+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">asio</category><title>asio 1.1.1</title><description>Между тем два дня назад &lt;a href="http://sourceforge.net/mailarchive/forum.php?thread_name=486CC064.80606%40kohlhoff.com&amp;forum_name=asio-users"&gt;вышла новая версия asio&lt;/a&gt;, в которой официально добавлен windows::basic_random_access_handle.&lt;br /&gt;&lt;br /&gt;На мой вопрос связанный с тем, почему &lt;a href="http://sergey-miryanov.blogspot.com/2008/06/asioasyncread-and-asiowindowsbasicstrea.html"&gt;не работает async_read&lt;/a&gt; Chris ответил что следует пользоваться async_read_at и соответственно windows::basic_random_access_handle (&lt;a href="http://www.everfall.com/paste/id.php?kkdnb015y082"&gt;пример&lt;/a&gt;, если кому-нибудь интересно).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-3941476662409063690?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/yEBZuTjeGr4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/yEBZuTjeGr4/asio-111.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/07/asio-111.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-5731124315718952027</guid><pubDate>Sun, 29 Jun 2008 18:35:00 +0000</pubDate><atom:updated>2008-06-30T00:49:18.178+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">asio</category><category domain="http://www.blogger.com/atom/ns#">file processing</category><title>Еще раз про asio и про мои тесты</title><description>У меня наконец то нашлось достаточно времени чтобы закончить начатые тесты с asio. Буду краток - asio это круто и очень удобно. Как всегда:&lt;br /&gt;&lt;center&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fotki.yandex.ru/users/sergey-miryanov/view/61584/"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px;" src="http://img-fotki.yandex.ru/get/54/sergey-miryanov.1/0_f090_c92c419d_XL" border="0" alt="" /&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;seq - seq - файл открыт для последовательного чтения и чтение производится последовательно&lt;br /&gt;seq - rnd - тоже самое, только чтение производится со случаным смещением&lt;br /&gt;rnd - seq - файл открыт для чтения с произвольным доступом, чтение производится последовательно&lt;br /&gt;rnd - rnd - это понятно&lt;br /&gt;seq_nb - rnd - файл открыт для последовательного чтения, без буфферизации, чтение производится со случайным смещением&lt;br /&gt;rnd_nb - rnd - файл открыт для чтения с произвольным доступом, без буфферизации, чтение производится со случайным смещением&lt;br /&gt;&lt;br /&gt;Как видно я все таки облажался в прошлом посте на тему, и чтение с произвольным смещением медленее, чем последовательное. Но при этом можно получить скорость доступа большую 10MB/s.&lt;br /&gt;&lt;br /&gt;Реализация asio круче чем моя собственная:&lt;br /&gt;&lt;center&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fotki.yandex.ru/users/sergey-miryanov/view/61585/"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px;" src="http://img-fotki.yandex.ru/get/25/sergey-miryanov.1/0_f091_a1b04f28_XL" border="0" alt="" /&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;Тут сравнивались только seq_nb/rnd_nb - rnd.&lt;br /&gt;&lt;br /&gt;&lt;font size="-2"&gt;По нижней оси как всегда размер буфера чтения.&lt;/font&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-5731124315718952027?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/wtVtFxlMrw4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/wtVtFxlMrw4/asio.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/06/asio.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-7095722212040420745</guid><pubDate>Wed, 25 Jun 2008 19:07:00 +0000</pubDate><atom:updated>2008-07-24T23:36:44.691+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">hint</category><category domain="http://www.blogger.com/atom/ns#">asio</category><title>asio::io_service::reset hint</title><description>Могу посоветовать перед каждым вызовом asio::io_service::run вызывать &lt;a href="http://asio.sourceforge.net/asio-1.0.0/doc/asio/reference/io_service/reset.html"&gt;asio::io_service::reset&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;This function must be called prior to any second or later set of invocations of the run(), run_one(), poll() or poll_one() functions when a previous invocation of these functions returned due to the io_service being stopped or running out of work. This function allows the io_service to reset any internal state, such as a "stopped" flag.&lt;/blockquote&gt; &lt;br /&gt;&lt;br /&gt;Это во многом облегчит жизнь начинающего asio-иста.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-7095722212040420745?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/DViEKmrMCEc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/DViEKmrMCEc/asioioservicereset-hint.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/06/asioioservicereset-hint.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-3568320736796429682</guid><pubDate>Tue, 24 Jun 2008 17:10:00 +0000</pubDate><atom:updated>2008-06-24T23:15:06.094+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">programming</category><category domain="http://www.blogger.com/atom/ns#">cpp</category><category domain="http://www.blogger.com/atom/ns#">asio</category><title>asio::windows::basic_stream_handle - 2</title><description>Если поковыряться, то можно придумать как запилить asio::windows::basic_stream_handle, чтобы он правильно (опять же на мой взгляд) читал из файлов. Запил на самом деле очень простой и я не вижу причин, почему разработчики не пошли по тому же пути.&lt;br /&gt;&lt;br /&gt;Запил - в файл win_iocp_handle_service.hpp после строки 691 добавить следующее:&lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="#000000"&gt;ptr&lt;/font&gt;&lt;font color="#C8003C"&gt;.&lt;/font&gt;&lt;font color="#000000"&gt;get&lt;/font&gt;&lt;font color="#C8003C"&gt;()-&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;Offset&lt;/font&gt; &lt;font color="#C8003C"&gt;=&lt;/font&gt; &lt;font color="#000000"&gt;boost&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;uint64_t&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;handler&lt;/font&gt;&lt;font color="#C8003C"&gt;.&lt;/font&gt;&lt;font color="#000000"&gt;total_transferred_&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;amp;&lt;/font&gt; &lt;b&gt;&lt;font color="#40B440"&gt;0x&lt;/font&gt;&lt;/b&gt;&lt;font color="#40B440"&gt;FFFFFFFF&lt;/font&gt;&lt;font color="#C8003C"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;font color="#000000"&gt;ptr&lt;/font&gt;&lt;font color="#C8003C"&gt;.&lt;/font&gt;&lt;font color="#000000"&gt;get&lt;/font&gt;&lt;font color="#C8003C"&gt;()-&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;OffsetHigh&lt;/font&gt; &lt;font color="#C8003C"&gt;=&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;boost&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;uint64_t&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;handler&lt;/font&gt;&lt;font color="#C8003C"&gt;.&lt;/font&gt;&lt;font color="#000000"&gt;total_transferred_&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;gt;&amp;gt;&lt;/font&gt; &lt;font color="#40B440"&gt;32&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;amp;&lt;/font&gt; &lt;b&gt;&lt;font color="#40B440"&gt;0x&lt;/font&gt;&lt;/b&gt;&lt;font color="#40B440"&gt;FFFFFFFF&lt;/font&gt;&lt;font color="#C8003C"&gt;;&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272" size="-2"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;diff'ы делать я еще не научился, сорри.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-3568320736796429682?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/gtBtVlrWZGM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/gtBtVlrWZGM/asiowindowsbasicstreamhandle-2.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>4</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/06/asiowindowsbasicstreamhandle-2.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-5508823314840731808</guid><pubDate>Tue, 24 Jun 2008 16:33:00 +0000</pubDate><atom:updated>2008-06-24T23:09:38.483+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">programming</category><category domain="http://www.blogger.com/atom/ns#">cpp</category><category domain="http://www.blogger.com/atom/ns#">asio</category><category domain="http://www.blogger.com/atom/ns#">file processing</category><title>asio::async_read and asio::windows::basic_stream_handle</title><description>Ковыряюсь тут с &lt;a href="http://asio.sourceforge.net/"&gt;asio&lt;/a&gt; на предмет ассинхронного чтения файлов. Как выяснилось последняя версия - 1.1.0 - не умеет правильно читать из файлов. Простой код (см. ниже) не работает. &lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="#000000"&gt;asio&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;windows&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;basic_stream_handle&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;lt;&amp;gt;&lt;/font&gt; &lt;font color="#000000"&gt;handle_&lt;/font&gt;&lt;font color="#C8003C"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;font color="#000000"&gt;asio&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;streambuf&lt;/font&gt; &lt;font color="#000000"&gt;buf_&lt;/font&gt;&lt;font color="#C8003C"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#000000"&gt;asio&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;async_read&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;stream_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;buf_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;complete_condition_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;handler_&lt;/font&gt;&lt;font color="#C8003C"&gt;);&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272" size="-2"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Ожидаемое (на мой взгляд) поведение - файл будет полностью считан в буфер buf_. Вместо этого буфер забивается блоком данных (по умолчанию 512b), считанных от начала файла и до тех пор пока размер буфера меньше размера файла.&lt;br /&gt;&lt;br /&gt;По совету &lt;a href="http://alexott-ru.blogspot.com/"&gt;Alex'a&lt;/a&gt; взял версию c cvs.sourceforge - там та же фигня с basic_stream_handle. Но зато появился basic_random_access_handle, на основе которого можно сделать свой поток и читать последовательно (или со случаным доступом) из файла. Поток можно сделать например таким:&lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="#0000FF"&gt;struct&lt;/font&gt; &lt;font color="#000000"&gt;random_handle_wrapper&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;br /&gt;  &lt;font color="#000000"&gt;random_handle_wrapper&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;asio&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;io_service&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;amp;&lt;/font&gt;&lt;font color="#000000"&gt;io_service&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;HANDLE&lt;/font&gt; &lt;font color="#000000"&gt;file&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;  &lt;font color="#C8003C"&gt;:&lt;/font&gt; &lt;font color="#000000"&gt;handle_&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;io_service&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;file&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;  &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;file_&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;file&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;  &lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;transfered_&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#40B440"&gt;0&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;  &lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;font color="#C8003C"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;font color="#0000FF"&gt;template&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#0000FF"&gt;typename&lt;/font&gt; &lt;font color="#000000"&gt;MutableBufferSequence&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#0000FF"&gt;typename&lt;/font&gt; &lt;font color="#000000"&gt;ReadHandler&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;  &lt;font color="#0000FF"&gt;void&lt;/font&gt; &lt;font color="#000000"&gt;async_read_some&lt;/font&gt;&lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#0000FF"&gt;const&lt;/font&gt; &lt;font color="#000000"&gt;MutableBufferSequence&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;amp;&lt;/font&gt; &lt;font color="#000000"&gt;buffers&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;ReadHandler&lt;/font&gt; &lt;font color="#000000"&gt;handler&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;  &lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;br /&gt;    &lt;font color="#000000"&gt;handle_&lt;/font&gt;&lt;font color="#C8003C"&gt;.&lt;/font&gt;&lt;font color="#000000"&gt;async_read_some_at&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;transfered_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;buffers&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;handler&lt;/font&gt;&lt;font color="#C8003C"&gt;);&lt;/font&gt;&lt;br /&gt;  &lt;font color="#C8003C"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;font color="#0000FF"&gt;void&lt;/font&gt; &lt;font color="#000000"&gt;move_fwd&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;size_t&lt;/font&gt; &lt;font color="#000000"&gt;transfered&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;  &lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;br /&gt;    &lt;font color="#000000"&gt;transfered_&lt;/font&gt; &lt;font color="#C8003C"&gt;+=&lt;/font&gt; &lt;font color="#000000"&gt;transfered&lt;/font&gt;&lt;font color="#C8003C"&gt;;&lt;/font&gt;&lt;br /&gt;  &lt;font color="#C8003C"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;font color="#000000"&gt;asio&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;windows&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;basic_random_access_handle&lt;/font&gt;&lt;font color="#C8003C"&gt;&amp;lt;&amp;gt;&lt;/font&gt; &lt;font color="#000000"&gt;handle_&lt;/font&gt;&lt;font color="#C8003C"&gt;;&lt;/font&gt;&lt;br /&gt;  &lt;font color="#000000"&gt;HANDLE&lt;/font&gt;            &lt;font color="#000000"&gt;file_&lt;/font&gt;&lt;font color="#C8003C"&gt;;&lt;/font&gt;&lt;br /&gt;  &lt;font color="#000000"&gt;boost&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;uint64_t&lt;/font&gt;   &lt;font color="#000000"&gt;transfered_&lt;/font&gt;&lt;font color="#C8003C"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;};&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272" size="-2"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Тогда read_handler примет примерно такой вид:&lt;br /&gt;&lt;table width = "100%" bgcolor="#F2F2F2"&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;&lt;font color="#0000FF"&gt;void&lt;/font&gt; &lt;font color="#000000"&gt;read_handler&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;asio&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;error_code&lt;/font&gt; &lt;font color="#000000"&gt;ec&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;size_t&lt;/font&gt; &lt;font color="#000000"&gt;transferred&lt;/font&gt;&lt;font color="#C8003C"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;{&lt;/font&gt;&lt;br /&gt;  &lt;font color="#000000"&gt;std&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;cout&lt;/font&gt; &lt;font color="#C8003C"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#000000"&gt;std&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;string&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;data_&lt;/font&gt;&lt;font color="#C8003C"&gt;.&lt;/font&gt;&lt;font color="#000000"&gt;c_array&lt;/font&gt;&lt;font color="#C8003C"&gt;(),&lt;/font&gt; &lt;font color="#000000"&gt;data_&lt;/font&gt;&lt;font color="#C8003C"&gt;.&lt;/font&gt;&lt;font color="#000000"&gt;c_array&lt;/font&gt;&lt;font color="#C8003C"&gt;()&lt;/font&gt; &lt;font color="#C8003C"&gt;+&lt;/font&gt; &lt;font color="#000000"&gt;transferred&lt;/font&gt;&lt;font color="#C8003C"&gt;);&lt;/font&gt;&lt;br /&gt;  &lt;font color="#000000"&gt;stream_&lt;/font&gt;&lt;font color="#C8003C"&gt;.&lt;/font&gt;&lt;font color="#000000"&gt;move_fwd&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;transferred&lt;/font&gt;&lt;font color="#C8003C"&gt;);&lt;/font&gt;&lt;br /&gt;  &lt;font color="#000000"&gt;asio&lt;/font&gt;&lt;font color="#C8003C"&gt;::&lt;/font&gt;&lt;font color="#000000"&gt;async_read&lt;/font&gt; &lt;font color="#C8003C"&gt;(&lt;/font&gt;&lt;font color="#000000"&gt;stream_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;buf_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;complete_condition_&lt;/font&gt;&lt;font color="#C8003C"&gt;,&lt;/font&gt; &lt;font color="#000000"&gt;handler_&lt;/font&gt;&lt;font color="#C8003C"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;font color="#C8003C"&gt;}&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;&lt;b&gt;&lt;i&gt;&lt;a href="http://dobrokot.nm.ru/WinnieColorizer.html"&gt;&lt;font color="#727272" size="-2"&gt;_Winnie C++ Colorizer&lt;/font&gt;&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;И так уже можно жить.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-5508823314840731808?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/CoIAf9niAmE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/CoIAf9niAmE/asioasyncread-and-asiowindowsbasicstrea.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/06/asioasyncread-and-asiowindowsbasicstrea.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-63701099158077000</guid><pubDate>Sat, 21 Jun 2008 16:52:00 +0000</pubDate><atom:updated>2008-06-21T22:55:26.947+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">nb</category><title /><description>30го числа я буду &lt;a href="http://www.t-platforms.ru/ru/news.php?zone=news&amp;id=85"&gt;здесь&lt;/a&gt;. Также во второй половине дня у меня будет не много свободного времени, буду рад с кем-либо из старых жж френдов увидиться.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-63701099158077000?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/qJB8OQFUyJY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/qJB8OQFUyJY/30.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/06/30.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-4495502367537650085</guid><pubDate>Mon, 16 Jun 2008 18:13:00 +0000</pubDate><atom:updated>2008-06-30T00:52:06.722+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">file processing</category><title>Вести из зазеркалья</title><description>&lt;a href="http://sergey-miryanov.blogspot.com/2008/06/asio.html"&gt;Данные результаты тестов официально признаются зафейлеными.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.gamedeff.com/?p=142"&gt;К разговору о:&lt;/a&gt; потестил чтение со случайным доступом, получил, на мой взгляд, странные результаты - в этом случае производительность оказалась даже выше &lt;a href="http://sergey-miryanov.blogspot.com/2008/06/blog-post.html"&gt;чем&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fotki.yandex.ru/users/sergey-miryanov/view/58315/"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px;" src="http://img-fotki.yandex.ru/get/2/sergey-miryanov.1/0_e3cb_468757d9_XL" border="0" alt="" /&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fotki.yandex.ru/users/sergey-miryanov/view/58316/"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px;" src="http://img-fotki.yandex.ru/get/53/sergey-miryanov.1/0_e3cc_f5371ae_XL" border="0" alt="" /&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;async (no buf, seq scan) - последовательное чтение - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | &lt;a href="http://support.microsoft.com/kb/98756"&gt;FILE_FLAG_SEQUENTIAL_SCAN&lt;/a&gt; | FILE_FLAG_NO_BUFFERING.&lt;br /&gt;&lt;br /&gt;async (no buf, rand) - случайное чтение - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING.&lt;br /&gt;&lt;br /&gt;async (no buf, seq scan, rand) - случайное чтение - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | &lt;a href="http://support.microsoft.com/kb/98756"&gt;FILE_FLAG_SEQUENTIAL_SCAN&lt;/a&gt; | FILE_FLAG_NO_BUFFERING.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-4495502367537650085?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/YAUldSktEWQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/YAUldSktEWQ/blog-post_17.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>3</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/06/blog-post_17.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-6422494856069763102</guid><pubDate>Thu, 05 Jun 2008 15:05:00 +0000</pubDate><atom:updated>2008-06-05T21:09:05.953+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">cpp</category><category domain="http://www.blogger.com/atom/ns#">links</category><title /><description>Кстати, если еще кто не читал, то рекомендую: &lt;a href="http://www.ddj.com/cpp/184403861"&gt;Assertions&lt;/a&gt;, &lt;a href="http://www.ddj.com/cpp/184403745"&gt;Enhancing Assertions&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Александреску рассказывает как делать Ассерты(тм).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-6422494856069763102?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/domty6Q_XpA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/domty6Q_XpA/assertions-enhancing-assertions.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/06/assertions-enhancing-assertions.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-8748166749764233777</guid><pubDate>Tue, 03 Jun 2008 15:22:00 +0000</pubDate><atom:updated>2008-06-03T22:00:23.064+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">programming</category><category domain="http://www.blogger.com/atom/ns#">cpp</category><category domain="http://www.blogger.com/atom/ns#">file processing</category><title>О том как с толком потратить время</title><description>В общем, по случаю тут тестировал загрузку больших файлов. Файлы – массив чисел с плавающей точкой, в текстовом виде.&lt;br /&gt;&lt;br /&gt;Тестировал на файле из 50М чисел, это примерно 700МB данных.&lt;br /&gt;&lt;br /&gt;Я начал с обычного sscanf, долго плясал вокруг него с бубном, подбирал размеры буфера. Пока не уперся в примерно 8MB/s. Думал, что это ограничение жесткого диска, как выяснилось - нет. Затем заменил sscanf на atof, скорости тоже не прибавило. Сделал memory mapped и async IO – это прибавило порядка 20% - для размера буфера, который я считал оптимальным. Но это тоже все не то. Попробовал выкинуть atof из внутреннего цикла – получил порядка 30+ MB/s. Круто. Нашел в интернете парочку быстрых функций – &lt;a href="http://www.jbox.dk/sanos/source/lib/strtod.c.html"&gt;strtod&lt;/a&gt; (у меня в тестах "fast" strtod) и &lt;a href="http://std.kku.ac.th/4730204657/Animation/source/Irrlicht/fast_atof.h"&gt;fast_atof&lt;/a&gt; от IrrLicht.&lt;br /&gt;&lt;br /&gt;По просьбе &lt;a href="http://timai-ru.blogspot.com/"&gt;трудящихся&lt;/a&gt;, так же включил boost::lexical_cast (он, кстати, показал самый стабильный результат).&lt;br /&gt;&lt;br /&gt;Тест с async IO no buffering включил по наводке с &lt;a href="http://entland.homelinux.com/blog/2006/10/25/reading-files-as-fas-as-possible/"&gt;сайта&lt;/a&gt;. Опять же на первоначальном размере буфера результаты были не лучшие, так что я его включил так, на всякий случай. Конечные результаты показали, что все таки не зря.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;Случай первый - стандартные С файлы - FILE.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fotki.yandex.ru/users/sergey-miryanov/view/54722/"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px;" src="http://img-fotki.yandex.ru/get/53/sergey-miryanov.1/0_d5c2_91641de2_XL" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;Случай второй - memory mapped файлы (win32)&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fotki.yandex.ru/users/sergey-miryanov/view/54721/"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px;" src="http://img-fotki.yandex.ru/get/53/sergey-miryanov.1/0_d5c1_5b94ed24_XL" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;Асинхронные файлы (win32)&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fotki.yandex.ru/users/sergey-miryanov/view/54719/"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px;" src="http://img-fotki.yandex.ru/get/53/sergey-miryanov.1/0_d5bf_5998e27d_XL" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;Чтение производится в два буфера - пока данные загружаются во второй буфер, данные из первого буфера обрабатываются. Проседание производительности для буфера с размером большим 32k, я могу объяснить тем, что прочитанный буфер обрабатывается дольше, чем загружается второй буфер чтения.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;Асинхронные файлы без буферизации (win32)&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fotki.yandex.ru/users/sergey-miryanov/view/54720/"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px;" src="http://img-fotki.yandex.ru/get/53/sergey-miryanov.1/0_d5c0_3eb2b0d3_XL" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;Сравнение "fast" strtod для различных типов чтения файлов&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fotki.yandex.ru/users/sergey-miryanov/view/54725/"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px;" src="http://img-fotki.yandex.ru/get/53/sergey-miryanov.1/0_d5c5_ffe14779_XL" border="0" alt="" /&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;Сравнение IrrLicht fast_atof для различных типов чтения файлов&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fotki.yandex.ru/users/sergey-miryanov/view/54724/"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px;" src="http://img-fotki.yandex.ru/get/3/sergey-miryanov.1/0_d5c4_6ed35b2b_XL" border="0" alt="" /&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Во всех случаях по оси Х - размер буфера чтения в байтах, по оси Y - data transfer rate, в MB/s. Для memory mapped файлов во всех случаях размер буфера - 64k. Почему "fast" strtod показал такие странные результаты - надо смотреть, а с этим по определенным причинам плохо.&lt;br /&gt;&lt;br /&gt;Да, «быстрые» версии не работают с локалями и прочим, но об этом можно подумать отдельно, если скорость загрузки критична.&lt;br /&gt;Да, тесты банальны – все и так знают, что стандартные функции чересчур медленные.&lt;br /&gt;&lt;br /&gt;Ну вот вроде и все.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-8748166749764233777?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/y5CcyPDAYUw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/y5CcyPDAYUw/blog-post.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>1</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/06/blog-post.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-912280005129869157</guid><pubDate>Sat, 17 May 2008 19:40:00 +0000</pubDate><atom:updated>2008-05-18T01:41:36.392+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">cpumem</category><category domain="http://www.blogger.com/atom/ns#">programming</category><title>Loop Stream Detector</title><description>&lt;blockquote&gt;There is another big advantage of small loops, at least on certain processors. The Intel Core 2 front end has a special feature called Loop Stream Detector (LSD). If a loop has no more than 18 instructions (none of which is a call to a subroutine), requires only up to 4 decoder fetches of 16 bytes, has at most 4 branch instructions, and is executed more than 64 times, than the loop is sometimes locked in the instruction queue and therefore more quickly available when the loop is used again. This applies, for instance, to small inner loops which are entered&lt;br /&gt;many times through an outer loop.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-912280005129869157?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/j_G0RlEeU2E" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/j_G0RlEeU2E/loop-stream-detector.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/05/loop-stream-detector.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-1810970278273740576</guid><pubDate>Sat, 17 May 2008 19:37:00 +0000</pubDate><atom:updated>2008-05-18T01:38:04.122+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">cpumem</category><category domain="http://www.blogger.com/atom/ns#">programming</category><title>Back to the future</title><description>Несколько слов о том, что нас ждет в будущем – в будущем нас ждет полный коммунизмЪ и всеобщее счастье. &lt;br /&gt;&lt;br /&gt;В статье приводится не большой пример конструирования lock-free стека. Затем ведется разговор о transactional memory. Про TM в основном на железячном уровне и по большей части на основе довольно старой статьи о HTM. Для HTM будет свой собственный кеш и следовательно данные, которые будут использоваться транзакциями следует отделять от остальных данных.&lt;br /&gt;&lt;br /&gt;Кроме того, чем дальше, тем больше будут расти задержки (latency) и тем важнее стоит обращать внимание на правильный префетчинг. Ну и на векторизацию тоже.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Список приложений&lt;/span&gt;&lt;br /&gt;Приложение А.1 – умножение матриц, с разворачиванием и векторизацией.&lt;br /&gt;Приложение А.2 – отладка статического предсказания переходов.&lt;br /&gt;Приложение А.3 – измерения шаринга кеш-линий.&lt;br /&gt;Приложение Б – подсказки по oprofile&lt;br /&gt;Приложение С – типы памяти&lt;br /&gt;Приложение D - libNUMA&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-1810970278273740576?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/IHDVtfa-Sdk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/IHDVtfa-Sdk/back-to-future.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/05/back-to-future.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-4256494382076403309</guid><pubDate>Sat, 17 May 2008 19:34:00 +0000</pubDate><atom:updated>2008-05-18T12:00:33.852+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">cpumem</category><category domain="http://www.blogger.com/atom/ns#">programming</category><title>How we can do it</title><description>Несколько групп инструментов:&lt;br /&gt;• Инструменты для профилирования работы с памятью&lt;br /&gt;• • oprofile&lt;br /&gt;• • • Можно получить только вероятностные и иногда неточные результаты&lt;br /&gt;• • pfmon&lt;br /&gt;• Инструменты для моделирования работы кешей&lt;br /&gt;• • valgrind --tool=cachegrind&lt;br /&gt;• Инструменты для подсчета используемой памяти&lt;br /&gt;• • valgrind --tool=massif&lt;br /&gt;• • • в случае если используется собственный аллокатор не возможно отследить использование памяти&lt;br /&gt;• • • если используется только обертка над обычными функциями, то можно указать название функции --alloc-fn=function&lt;br /&gt;• • memusage&lt;br /&gt;• Инструменты для профилирования нарушений доступа (page fault)&lt;br /&gt;• • Автор разработал собственную программу для valgrind’a – &lt;a href="http://people.redhat.com/drepper/pagein.html"&gt;pagein&lt;/a&gt;&lt;br /&gt;• Profile guided optimization &lt;br /&gt;• • gcc –fprofile-generate and -fprofile-use&lt;br /&gt;&lt;br /&gt;Те же советы – статическое предсказание переходов, увеличение размера страницы, правильный выбор аллокатора.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-4256494382076403309?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/gnW5j2AhNuI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/gnW5j2AhNuI/how-we-can-do-it.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>2</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/05/how-we-can-do-it.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-3956066719636429776</guid><pubDate>Sat, 17 May 2008 19:30:00 +0000</pubDate><atom:updated>2008-05-18T01:34:48.365+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">performance</category><category domain="http://www.blogger.com/atom/ns#">cpumem</category><category domain="http://www.blogger.com/atom/ns#">programming</category><title>What we can do</title><description>Это самое интересное. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;1. non-temporal write operations&lt;/span&gt;&lt;br /&gt;В случаях, когда обрабатывается большой набор данных, например, загружается с диска и выстраивается в памяти в какую-либо структуру для дальнейшей обработки, то можно отменить кеширование таких данных. Для этого используются streaming SIMD extensions.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2. seq vs rand&lt;/span&gt;&lt;br /&gt;Способ обращения к памяти тоже важен. Последовательный доступ более эффективен, чем случайный или по колонкам (например, в матрицах). Если правильно подготовить данные, чтобы обработка выполнялась последовательно, то можно получить очень хороший прирост производительности.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;3. loop unrolling&lt;/span&gt;&lt;br /&gt;Можно вручную разворачивать циклы, в которых производится обработка больших наборов данных. Делать это стоит для того, чтобы максимально использовать кеш-линию. Под размер кеш-линии можно подстраиваться динамически (sysconf (_SC_LEVEL1_DCACHE_LINESIZE)), либо статически.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;4. vectorization&lt;/span&gt;&lt;br /&gt;Чтобы выжать максимальную производительность в дополнение к перечисленному, стоит воспользоваться векторизованными операциями (SIMD, SSE).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;5. padding&lt;/span&gt;&lt;br /&gt;Данные стоит выравнивать и избегать padding’а. Можно сказать gcc --reorganize чтобы он перетасовал данные, чтобы уменьшить padding. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;6. critical words&lt;/span&gt;&lt;br /&gt;Наиболее часто используемые данные стоит размещать в начале структуры. Если способ доступа (access pattern) заранее не известен, то лучше обращаться к элементам структуры в том порядке, в котором они объявлены.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;7. structure cache line alignment&lt;/span&gt;&lt;br /&gt;В случае если структура большая (больше кеш-линии), то элементы следует выравнивать по кеш-линии, с учетом правила critical word.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;8. alignment &lt;/span&gt;&lt;br /&gt;Код и данные должны быть выровнены. В случае если выравнивание отсутствует, то можно получить большие пенальти при работе с памятью.&lt;br /&gt;Отсюда же вытекает, что стек должен быть выровнен. В большинстве случаев компилятор знает размер стека для каждой функции, соответственно он может выравнивать функции. Функции с переменным числом параметров и alloca лишают компилятор такой возможности.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;9. code linearization&lt;/span&gt;&lt;br /&gt;Переходы плохо предсказываются статически и могут привести к большему количеству промахов в кеш.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;10. L1i&lt;/span&gt;&lt;br /&gt;Для того чтобы лучше использовать L1i нужно обратить внимание на:&lt;br /&gt;• Уменьшение объема кода.&lt;br /&gt;• Выравнивание кода.&lt;br /&gt;• И линейное выполнение кода (linear code execution without bubbles). Это сложно и автор отсылает к чтению документов по processor design.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;11. code inlining&lt;/span&gt;&lt;br /&gt;При подстановке функций результирующий код может оказаться больше одной кеш-линии и вполне может оказаться, что этот кусок без инлайна, но умещающийся в кеш-линии будет эффективнее. За этим тоже стоит следить. Компилятору можно об этом сказать, используя always_inline и noinline.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;12. Статическое предсказание переходов&lt;/span&gt;&lt;br /&gt;В случаях, когда какое-либо условие в большинстве случаев имеет одно значение, компилятору можно сказать об этом. В этом случае, он сможет сгенерировать более эффективный код, за счет размещения реже выполняемой ветки кода за чаще используемой веткой кода. gcc об этом можно сказать с помощью __builtin_expect и флагом –freorder-blocks.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;13. small loops&lt;/span&gt;&lt;br /&gt;Процессоры умеют определять циклы в коде, если цикл удовлетворяет определенным условиям, то он может быть locked in the instruction queue и поэтому доступ к нему будет происходить быстрее.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;14. reduce working set size&lt;/span&gt;&lt;br /&gt;Желательно уменьшать размер рабочей области, чтобы она помещалась в L2 кеш и за счет этого уменьшилось общее количество промахов в кеш.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;15. TLB usage optimization&lt;/span&gt;&lt;br /&gt;Первое – увеличить размер страниц, второе – уменьшить распределение диапазонов адресов. Про первое уже говорилось, про второе тоже, стоит добавить, что существует такая штука как ASLR. ASLR случайным образом распределяет в памяти DSO, стек, кучу и прочее, чтобы предотвратить некоторые атаки. Если производительность выше безопасности то следует ASLR отключать.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;16. hardware prefetching&lt;/span&gt;&lt;br /&gt;Hardware prefetching работает в границах одной страницы. Насколько я понял, в некоторых ситуациях это может создавать проблемы. Чтобы управлять префетчингом или вообще его отключить существуют MSR регистры.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;17. software prefetching&lt;/span&gt;&lt;br /&gt;Самое главное правило – сначала профилирование, затем оптимизация, затем снова профилирование. Стоит смотреть на количество промахов в кеш, выделять проблемные места и пробовать их префетчить и затем снова смотреть на количество промахов. Если количество промахов не уменьшилось, то инструкции префетчинга лучше убрать.&lt;br /&gt;gcc умеет префетчить доступ к массивам, обрабатываемым в цикле. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;18. speculative load&lt;/span&gt;&lt;br /&gt;Процессоры умеют выполнять несколько инструкций одновременно. В некоторых ситуациях код не может быть разделен на конвейеры из-за определенного порядка инструкций и из-за то, что не может быть предсказано содержимое памяти или регистров. Код можно перегруппировать, вынеся команды загрузки данных за команду, которая реально их использует. Для этого используется speculative load – данные загружаются в регистр, далее в том месте где эти данные используются выполняется проверка (либо она делается раньше и автоматически) что данные не изменились в памяти. Если не изменились – загружаются из регистра, если изменились – из памяти. &lt;br /&gt;Корявенько, но надеюсь смысл понятен. В статье более понятный пример.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;19. prefetcher thread&lt;/span&gt;&lt;br /&gt;Для префетчинга данных можно использовать второй поток, который будет заниматься только префетчингом. У автора на тестах такой вариант оказался производительнее, чем вариант с простым префетчингом.&lt;br /&gt;Недостатком способа является необходимость синхронизировать основной и вспомогательные потоки.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Multi-threading optimizations&lt;/span&gt;&lt;br /&gt;Три основных вопроса, которые стоит рассматривать в связи с:&lt;br /&gt;• Конкурентность&lt;br /&gt;• Атомарный доступ&lt;br /&gt;• Пропускная способность&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Конкурентный доступ к данным&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;20. divide modified data&lt;/span&gt;&lt;br /&gt;Наилучший случай – потоки работаю с совершенно различными участками памяти (это не относится к hyperthread’ам). &lt;br /&gt;В случае если потоки пишут(!) в перекрывающиеся регионы памяти, может произойти «false sharing» - когда одна и та же кеш-линии из-за RFO постоянно перемещается из кеша одного процессора в кеш другого процессора. Это можно привести к серьезному уменьшению производительности. Этого можно избежать либо полностью разделив данные, либо добавляя padding между элементами структуры, чтобы каждый элемент или группа элементов, обрабатываемых потоком находилась в различных кеш-линиях.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;21. group const vars&lt;/span&gt;&lt;br /&gt;В противоположность модифицируемым данным константы вполне можно и нужно разделять, поэтому лучше все константы сгруппировать в единый блок.&lt;br /&gt;&lt;br /&gt;Можно выделить 4 группы, на которые можно разбивать данные:&lt;br /&gt;• read-only&lt;br /&gt;• read-write&lt;br /&gt;• read-mostly&lt;br /&gt;• per-thread (можно пометить __thread, тогда будет использоваться TLS, но следует иметь в виду, если данные используются только одним потоком, то в других потоках эти данные будут просто занимать данные, кроме того, указатели на данные в TLS не валидные в других потоках, со всеми вытекающими отсюда).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Атомарность доступа&lt;/span&gt;&lt;br /&gt;Существует несколько распространенных типов атомарного доступа к данным:&lt;br /&gt;• Bit test&lt;br /&gt;• Load Lock / Store Conditional (LL/SC)&lt;br /&gt;• CAS&lt;br /&gt;• Atomic arithmetic &lt;br /&gt;Операции атомарной арифметики выполняются эффективнее, чем CAS. Хотя последний является более простым.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Пропускная способность&lt;/span&gt;&lt;br /&gt;На многопроцессорной машине пропускная способность шины данных может оказаться потолком в достижении максимально возможной производительности. Единственное что стоит с этим делать – следить, чтобы каждый процессор работал со своей памятью (не с памятью, другого процессора).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Еще раз NUMA&lt;/span&gt;&lt;br /&gt;Несколько советов:&lt;br /&gt;• Реплицировать данные&lt;br /&gt;• Группировать данные по процессорам узла&lt;br /&gt;• Обрабатывать данные блоками на разных процессорах, результат сливать&lt;br /&gt;• Писать данные в локальную память&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-3956066719636429776?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/DcL2mN4x33E" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/DcL2mN4x33E/what-we-can-do.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>7</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/05/what-we-can-do.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-5668842388889909886</guid><pubDate>Sat, 17 May 2008 19:22:00 +0000</pubDate><atom:updated>2008-05-18T01:30:44.124+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">cpumem</category><category domain="http://www.blogger.com/atom/ns#">programming</category><title>Let Mortal Kombat begin</title><description>&lt;a href="http://people.redhat.com/drepper/cpumemory.pdf"&gt;What every programmer should know about memory&lt;/a&gt; - это очень большая и интересная статья о работе с памятью. Уверен, что тем, кому приходилось заниматься обработкой больших наборов данных или писать критический к производительности код сталкивались или знают о вещах, о которых говориться в статье.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Память&lt;/span&gt;&lt;br /&gt;Итак, в современных компьютерах используется два типа памяти – статическая и динамическая. Статическая память очень быстрая, но очень сложная, поэтому ее очень мало. Динамическая память проще в устройстве, поэтому ее можно сделать больше, поэтому в современных компьютерах ее много. Ну, «много». Простота устройства имеет свои отрицательные стороны. Если при обращении к статической памяти мы моментально получаем ответ (запись или чтение слова), то при обращении к динамической памяти имеет различные задержки и синхронизации. Подробнее про циклы синхронизации написано в статье.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Кеш&lt;/span&gt;&lt;br /&gt;Это объясняют, почему доступ к памяти имеет задержки на программном уровне. Чтобы скрыть эти задержки были введены аппаратные кеши – L1, L2 и где то L3. По нарастающей - эти кеши имеют большую емкость и большее время доступа. L1 может быть реализован статической или динамической полно-ассоциативной памятью. L2-кеши как правило реализуются в виде 4- или 8- ассоциативной памяти. В статье довольно подробно рассказано про то, какая бывает память и как она устроена. Нарисованы интересные таблички и графики по времени доступа, в зависимости от размера кеша и ассоциативности L2-кеша. Зависимость между размером кеша и ассоциативностью имеет нелинейный характер (в некоторых источниках указывают, что при увеличении ассоциативности вдвое также вдвое увеличивается «размер» кеша, это неверно в общем случае).&lt;br /&gt;&lt;br /&gt;Введение hyperthreading’а означает уменьшение размера кеша вдвое, чтобы компенсировать это можно ввести 16-ассоциативный кеш. Но на самом деле он довольно сложен в организации, поэтому, как правило, добавляют еще один уровень кеша (L3 получается также 4- или 8- ассоциативный), а L2 шарят между ядрами.&lt;br /&gt;&lt;br /&gt;На все это стоит обращать внимание при выборе процессора.&lt;br /&gt;&lt;br /&gt;L1 кешей сущестует два – для инструкций и для памяти – L1i и L1d. В кеше инструкций хранятся уже декодированные команды, а не просто куски чистой памяти, как в L1d.&lt;br /&gt;&lt;br /&gt;L1 кеш обычно per core. Поэтому его будут разделять все процессы. Это следует иметь в виду при создании многопоточных приложений. Ну и hyperthreading тоже разделяет этот кеш и его емкость по сути уменьшается вдвое.&lt;br /&gt;&lt;br /&gt;L2 обычно разделяется между ядрами.&lt;br /&gt;&lt;br /&gt;Кеши выстроены в иерархию L1(I,d)-&gt;L2-&gt;L3-&gt;main memory. При обращении к памяти слово, а точнее кеш-линия попадает в кеш. Если в кеше нет места для новой кеш-линии может произойти следующее:&lt;br /&gt;• Если у процессора exclusive cache, например в AMD, то кеш-линия присутствует только в одном кеше. Соответственно, когда заканчивается место в кеше она выталкивается в кеш на уровень выше.&lt;br /&gt;• У Intel’a inclusive cache. И кеш-линия присутствует во всех (L1, L2) кешах, соответственно при выталкивании нет необходимости помещать кеш-линию в кеш на уровень выше, так как она уже там находиться. Соответственно inclusive caches оперативнее выталкивают линии из кеша. &lt;br /&gt;&lt;br /&gt;Эти вещи также стоит учитывать при выборе процессора.&lt;br /&gt;&lt;br /&gt;На SMP машинах процессоры имеют доступ ко всей памяти и поэтому кеши ядер не могут работать независимо друг от друга, т.к. у разных процессоров в кеше может оказаться одна и та же кеш-линия. Поддержание процессорами состояния своих кешей в не противоречивом состоянии называется cache coherency. Для этого кеш-линии, в которые производилась запись, помечаются dirty-флагом. Если другой процессор обращается кеш-линии другого процессора, которая помечена этим флагом, то происходит запись кеш-линии в память и загрузка ее в кеш другого процессора. При этом кеш-линии непомеченные данным флагом могут присутствовать в кешах нескольких процессоров.&lt;br /&gt;&lt;br /&gt;Если эти два правила – помеченные линии находятся только в одном кеше и непомеченные могут находиться во многих кешах – соблюдаются, то работа с кешами может быть реализована эффективно.&lt;br /&gt;&lt;br /&gt;Для поддержания памяти в целостном состоянии были разработаны различные протоколы и один из них это MESI (и самый распространенный). M – Modified, E – Exclusive, S – Shared, I – Invalid. Опять же с этим практически не приходиться сталкиваться в обычной жизни, но знать об этом стоит.&lt;br /&gt;&lt;br /&gt;Изначально все кеш-линии помечены как Invalid. При записи в кеш-линию она помечается M, при чтении – либо S, либо E, смотря сколько процессоров читают из кеш-линии одновременно. При попытке чтения кеш-линии в состоянии M другим процессором, она будет записана в память и затем передана в кеш другого процессора. Этот процесс называется RFO – Request For Ownership. Также перемещение потока на другой процессор может вызвать RFO. Не смотря на то, что MESI предназначен для эффективной реализации кешей, одного его не достаточно. В SMP на производительность оказывает влияние и пропускная способность шины (FSB) и необходимость синхронизации.&lt;br /&gt;&lt;br /&gt;В статье приведена таблица, сколько примерно тактов занимает доступ к кешу и памяти:&lt;br /&gt;• Registers  &lt;= 1&lt;br /&gt;• L1d   ~ 3&lt;br /&gt;• L2   ~ 14&lt;br /&gt;• Main memory  ~240.&lt;br /&gt;&lt;br /&gt;Но это все в идеальном случае. На практике чаще всего получается все сильно хуже.&lt;br /&gt;&lt;br /&gt;Также в идеальном случае затраты могут быть еще уменьшены за счет того, что современные процессоры умеют выполнять многие инструкции параллельно.&lt;br /&gt;&lt;br /&gt;Существенным является размер рабочей области – working set size – в том случае, когда этот размер превышает размер какого-либо кеша, то начинаются пенальти, и заметно снижается скорость доступа. &lt;br /&gt;&lt;br /&gt;Имеет значение характер работы с памятью. При этом можно использовать различные префетчи. При большом размере рабочей области на производительность будут оказывать влияние промахи в TLB кеш.&lt;br /&gt;&lt;br /&gt;При больших размерах рабочей области и при последовательном доступе существенным будет и размер кеша, как L1 так и L2. Чем больше размер, тем выше производительность. При случайном доступе преимущество большого кеша будет не так явно заметно.&lt;br /&gt;&lt;br /&gt;Для записи обычно существует несколько стратегий (write-through, write-back), но с ними обычно приходиться иметь дело на уровне ядра.&lt;br /&gt;&lt;br /&gt;В случае параллельной обработки можно добиться 2 и 4 кратного увеличения производительности для 2 и 4 потоков, но только если размер рабочей области не превышает размеры кеша (в данном случае кеша L2) и только в случаях, когда потоки не выполняются независимо. Это в случае «чистых» потоков, в случае hyperthreading’а все не много по-другому, так как они разделяют все кеши и память. Приводится формула и график, рассчитанный на ее основе. По графику можно заключить, что если программа имеет небольшое число удачных попаданий в кеш (hit-rates), то использование нескольких потоков выгодно. В случае если программа имеет высокий уровень попаданий, то получить прирост производительности для нескольких потоков довольно сложно. &lt;br /&gt;&lt;br /&gt;Кеш инструкций, с ним все просто. Простые правила – генерируйте небольшой код и помогайте процессору предсказывать переходы, не делайте модификацию кода, процессор этого не любит, так как ему приходится сбрасывать кеш инструкций из-за этого.&lt;br /&gt;&lt;br /&gt;Процессор загружает в кеш память блоками, называемыми кеш-линиями.  Для загрузки одной кеш-линии процессору необходимо выполнить несколько операций чтения данных. Это привносит свои задержки. Чтобы их скрыть процессор умеет загружать и предоставлять доступ к запрошенному слову, а остальную часть кеш-линии загружать в фоне. Данное слово называется критическим (critical word). Желательно, чтобы это критическое слово находилось в начале кеш-линии.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Виртуальная память&lt;/span&gt;&lt;br /&gt;Процессор имеет подсистему виртуальной памяти. Для обеспечения доступа к ней операционная система хранит таблицы страниц. При доступе к какой-либо памяти ОС транслирует виртуальный адрес в физический с помощью этих таблиц. Эти таблицы располагаются в основной памяти поэтому доступ к ним желательно также оптимизировать. Для этого процессор имеет TLB кеш (Translation Look-Aside Buffer). L1TLB кеш очень маленький и поэтому очень быстрый. TLB кеш имеет несколько уровней и L1TLB разделен на кеш инструкций и данных. &lt;br /&gt;&lt;br /&gt;TLB кеш также можно префетчить, но не явно, а за счет префетчинга код и данных.&lt;br /&gt;&lt;br /&gt;Таблица страниц для каждого процесса своя, от распределения используемых диапазонов адресов зависит количество уровней таблиц, и соответственно время доступа. Если имеется такая возможность, то желательно распределение адресов уменьшить. Также количество и размер таблиц страниц зависит от размера страницы. В случаях с большим размером страницы можно получить прирост производительности. Говорят, что в мире больших БД это нормальная практика увеличивать размер страницы. &lt;br /&gt;&lt;br /&gt;Чтобы использовать страницы большего размера в линуксе необходимо использовать hugetlbfs.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;NUMA&lt;/span&gt;&lt;br /&gt;Non Uniform Memory Access. Имеется куча процессоров, к каждому их которых подсоединена своя память. Но все процессоры имеют доступ ко всей, общей, памяти. Это создает отдельные трудности, т.к. обращение к чужой памяти требует, чтобы процессор-владелец передал запрошенную память (кеш-линию) другому процессору. Это вносит задержки, которые есть и с которыми надо как то бороться, или как то скрывать. Что можно сделать – уменьшить количество запросов к чужой памяти, это можно делать через affinity mask. Кроме того, DSO объекты могут быть общими для всех процессов, выполняющихся на разных процессорах. Обращение к DSO приведет к доступу в чужую память и к потере производительности. С этим тоже можно бороться (на уровне приложений или ОС?) с помощью зеркалирования  DSO. В линуксе информацию о доступной NUMA-памяти и кешах можно получить через sysfs (/sys/devices/system/cpu/cpu*/cache).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-5668842388889909886?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/wPwG0Yqfvxo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/wPwG0Yqfvxo/let-mortal-kombat-begin.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/05/let-mortal-kombat-begin.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6248105557226342764.post-1927799779270922349</guid><pubDate>Fri, 02 May 2008 18:12:00 +0000</pubDate><atom:updated>2008-05-03T00:19:16.375+06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">performance</category><category domain="http://www.blogger.com/atom/ns#">links</category><title /><description>&lt;a href="http://softwarecommunity.intel.com/isn/downloads/graphics/GDC/Optimizing%20DirectX%20on%20Multi-core%20Architectures.ppt"&gt;Вы можете лучше управлять потоками DX&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Ну и чтобы два раза не вставать: &lt;a href="http://softwarecommunity.intel.com/isn/downloads/Ext_Optimizing_Memory_Traffic.pdf"&gt;не большой пример с интересными цифрами&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6248105557226342764-1927799779270922349?l=sergey-miryanov.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/sergey-miryanov/~4/UPelSDKsmdE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/sergey-miryanov/~3/UPelSDKsmdE/dx.html</link><author>noreply@blogger.com (Sergey Miryanov)</author><thr:total>0</thr:total><feedburner:origLink>http://sergey-miryanov.blogspot.com/2008/05/dx.html</feedburner:origLink></item></channel></rss>

