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

<channel>
	<title>Danny Thorpe &#187; make</title>
	<atom:link href="http://dannythorpe.com/tag/make/feed/" rel="self" type="application/rss+xml" />
	<link>http://dannythorpe.com</link>
	<description>Dream &#38; Deliver</description>
	<lastBuildDate>Tue, 07 Feb 2012 17:50:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Parallel Make: Using Build Stages to Prevent Pileups</title>
		<link>http://dannythorpe.com/2008/10/06/parallel-make-using-build-stages-to-prevent-pileups/</link>
		<comments>http://dannythorpe.com/2008/10/06/parallel-make-using-build-stages-to-prevent-pileups/#comments</comments>
		<pubDate>Tue, 07 Oct 2008 04:54:28 +0000</pubDate>
		<dc:creator>Danny Thorpe</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[concurrent]]></category>
		<category><![CDATA[make]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[parallel]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://dannythorpe.com/2008/10/06/parallel-make-using-build-stages-to-prevent-pileups/</guid>
		<description><![CDATA[A reader responded to my March article on Parallel Make in Win32 with a question: I’m trying to get the *.idl files to compile while using the -j flag. I’m having a problem when you run make -j and the idl compiler compiles the *.idl files (that works just fine), but right after that, it <a href='http://dannythorpe.com/2008/10/06/parallel-make-using-build-stages-to-prevent-pileups/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>A reader responded to my March article on <a href="http://dannythorpe.com/2008/03/06/parallel-make-in-win32/">Parallel Make in Win32</a> with a question:</p>
<blockquote><p>I’m trying to get the *.idl files to compile while using the -j flag. I’m having a problem when you run make -j and the idl compiler compiles the *.idl files (that works just fine), but right after that, it tries to run the g++ compiler and if certain files are not created before this command is run, then you get errors saying that there are missing files.</p></blockquote>
<p>It has been several months since I last worked with make (<a href="http://dannythorpe.com/2008/05/28/into-the-maelstrom-again/">I left Cooliris in May</a>) and since then most of what I had rediscovered about make has returned to its &#8216;maker&#8217;.  I&#8217;ve learned and forgotten make&#8217;s obscure rites more times than I care to remember.  There may well be a way to declare that the .h files required by some .cpp files are dependent upon certain .idl files, but the specific details escape me.</p>
<p>However, even if there is not a silver bullet dependency declaration available, you can use a partitioning technique to solve your problem:  Partition your makefile (build process) into stages.  Each stage can run its internal tasks in parallel, but executes sequentially with the other stages.</p>
<p> Here&#8217;s how to do that: </p>
<ol>
<li>Set up your makefile so that you have one target (rule) that processes your *.idl files.  Let&#8217;s call it IDLCompile</li>
<li>Set up another target that compiles your C++ code, including the C++ code that requires the *.idl output.  Let&#8217;s call it CppCompile.</li>
<li>Set up a third target which runs make recursively, passing different target params on each invocation.  I usually make this the default target as well.  Like this: (pseudo code)</li>
</ol>
<pre>default:
    make -j IDLcompile 
    make -j CppCompile
    make etc</pre>
<p>You can have all three targets in the same makefile that recursively invokes itself with different arguments. If that gives you a headache you can put the three targets in separate makefiles and invoke make with an additional makefile file argument.  It doesn&#8217;t make any difference to make, as each invocation is a separate process anyway.</p>
<p>Now, when you run make with no arguments for a typical build, it will run the steps in the default target sequentially (because you haven&#8217;t specified -j).  The stages execute sequentially to each other, but the tasks within each stage can execute in parallel if desired.  You still have parallelism where it counts.</p>
<p>Having make invoke each build stage separately and explicitly gives you simpler, clearer control over what gets built and when than by using traditional file dependency rules. With the topmost make process running in sequential mode, each stage must fully complete before the next stage can begin.  Within each stage, multiple targets can be spun up in parallel, but between stages is a strict serial execution sequence.</p>
<p>It will be very interesting to see how build processes and techniques evolve as distributed computing becomes more and more mainstream thanks to the combination of multicore processors and &#8220;elastic computing&#8221; in the cloud. Make has served us well for decades across a variety of hardware configurations, including clusters and peer networks, but &#8220;clear&#8221;, &#8220;simple&#8221;, and &#8220;easy&#8221; are never heard in the vicinity of &#8220;make&#8221;.  There&#8217;s room for improvement.</p>
<div style="text-align:center;width:100%;"><div style="margin:0px 0px 0px 0px;"><script type="text/javascript"><!--
google_ad_client = "ca-pub-0861479594738165";
/* End of Post */
google_ad_slot = "6510912161";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div></div><p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://dannythorpe.com/2008/10/06/parallel-make-using-build-stages-to-prevent-pileups/" data-text="Parallel Make: Using Build Stages to Prevent Pileups"></a><a class="a2a_button_google_plusone addtoany_special_service" data-annotation="none" data-href="http://dannythorpe.com/2008/10/06/parallel-make-using-build-stages-to-prevent-pileups/"></a><a class="a2a_button_facebook_like addtoany_special_service" data-href="http://dannythorpe.com/2008/10/06/parallel-make-using-build-stages-to-prevent-pileups/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fdannythorpe.com%2F2008%2F10%2F06%2Fparallel-make-using-build-stages-to-prevent-pileups%2F&amp;title=Parallel%20Make%3A%20Using%20Build%20Stages%20to%20Prevent%20Pileups" id="wpa2a_4">Share/Bookmark</a></p>]]></content:encoded>
			<wfw:commentRss>http://dannythorpe.com/2008/10/06/parallel-make-using-build-stages-to-prevent-pileups/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parallel Make in Win32</title>
		<link>http://dannythorpe.com/2008/03/06/parallel-make-in-win32/</link>
		<comments>http://dannythorpe.com/2008/03/06/parallel-make-in-win32/#comments</comments>
		<pubDate>Thu, 06 Mar 2008 10:44:34 +0000</pubDate>
		<dc:creator>Danny Thorpe</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[concurrent]]></category>
		<category><![CDATA[gnu]]></category>
		<category><![CDATA[make]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[parallel]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://dannythorpe.com/2008/03/06/parallel-make-in-win32/</guid>
		<description><![CDATA[I found myself in a lull between storms a few days ago, so I decided to do some housecleaning in our makefile before the next code rush hit.  And therein lies a story&#8230; We use one makefile to build all versions of PicLens for all browsers on all platforms.  It&#8217;s loosely patterned after the Google Gears project <a href='http://dannythorpe.com/2008/03/06/parallel-make-in-win32/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>I found myself in a lull between storms a few days ago, so I decided to do some housecleaning in our makefile before the next code rush hit.  And therein lies a story&#8230;</p>
<p>We use one makefile to build all versions of <a href="http://www.piclens.com">PicLens</a> for all browsers on all platforms.  It&#8217;s loosely patterned after the Google Gears project makefile &#8211; all source files are listed in one place, and <strong>make</strong> recursively invokes itself with different params to work its way through the various phases of the build process &#8211; checking dependencies, compiling source to obj, building the install bundles, etc.  We use Gnu <strong>make</strong> to run the build as it is available on all the platforms we need &#8211; and then some!</p>
<p>As the number of PicLens source files has grown rapidly over the past few months our build times have been getting longer and longer, and burning away a lot of our development productivity.  It was time to quit whining about it and just fix it!</p>
<p>One data point that bugged me about our build was CPU utilization &#8211; or lack thereof.  We all have multicore CPUs, but during the C++ compile phase the average CPU load was rarely more than one core (50% on dual core, 25% on quad).  This may be partly because gcc and msvc compilers are not aggressively multithreaded, and partly a reflection of the fact that C++ source compilation is largely disk I/O bound rather than CPU bound.</p>
<p>If you&#8217;ve got a lot of independent work items to do and spare CPU cores sitting idle, then you need to work on more than one item at a time.  One tantalizing prospect to improve build times was the Gnu <strong>make</strong> -j option. <strong>Make</strong> defaults to issuing one operation (invoke the compiler to compile this source file) at a time, and then waits for that to finish before issuing another operation.  With -j, you can tell <strong>make</strong> to issue multiple operations simultaneously as parallel processes. The idea is, if one instance of your compiler is only making use of one CPU core, then running two instances of the compiler to compile different source files should make use of two CPU cores, and finish compiling the two files in about the time it would take to compile just one file.</p>
<p>We added -j to our makefile for the source compilation phase, and with our first build test on an OSX Mac saw a nice 40% reduction in build time (dual core)! However, when we ran the build test on a Windows PC, we got a snippy little remark from <strong>make</strong>:</p>
<blockquote><p>make: Do not specify -j or &#8211;jobs if sh.exe is not available.<br />
make: Resetting make for single job mode.</p></blockquote>
<p>Well!  How rude!</p>
<p>Consulting the Gnu <strong>make</strong> docs, I found <a href="http://www.gnu.org/software/make/manual/make.html#Choosing-the-Shell">section 5.3.1 Choosing the Shell</a>, conveniently located right next to <a href="http://www.gnu.org/software/make/manual/make.html#Parallel">section 5.4 Parallel Execution</a>. Unfortunately, the Gnu docs state right up front:</p>
<blockquote><p>On MS-DOS, the `<samp><span class="samp">-j</span></samp>&#8216; option has no effect, since that system doesn&#8217;t support multi-processing.</p></blockquote>
<p>Well that&#8217;s a bummer.  And a little confusing, since Windows has been doing multi-processing for a very long time. I chose to ignore the docs as possibly outdated (MS-DOS!  How quaint!) and pressed on.</p>
<p>&#8220;<a href="http://www.gnu.org/software/make/manual/make.html#Choosing-the-Shell">Choosing the Shell</a>&#8221; talks a lot about <strong>make</strong> wanting a Unix style shell, like sh.exe.  It also talks a lot about how special and delicate the shell selection process is for &#8220;MS-DOS and Windows,&#8221; including checks for the COMSPEC environment variable.</p>
<p>We have a basket of Unix utils built for Win32 in our toolbox, and one of them is named zsh.exe.  It looks like a Bash shell, it smells like a Bash shell, but it doesn&#8217;t fork processes like a Bash shell.  Configuring <strong>make</strong> to use zsh as its shell sent it crashing to the floor. Hmm.  Not much better with the msys shell, and don&#8217;t get me started about cygwin.</p>
<p>I scoured the Internet looking for clues.  Lots of articles about Gnu <strong>make</strong> and -j, but nothing about how to make it work in Windows.  Then purely by chance, I stumbled into <a href="http://www.steve.org.uk/Software/make/">this page at steve.org.uk</a> which offered a solution to a different <strong>make</strong> problem:  set <strong>make</strong>&#8216;s SHELL environment variable to CMD.EXE, the Win32 shell, to resolve a &#8220;CreateProcess() failed&#8221; error.</p>
<p>SHELL=CMD.EXE?</p>
<p>Could it be that simple?</p>
<p>Yes! Telling <strong>make</strong> to use the Win32 shell magically enables <strong>make</strong> to fork processes and execute multiple compiler instances in parallel!</p>
<p>Now my question is this: Why is this setting needed at all?  cmd.exe is the default Win32 shell, has been for decades, and it&#8217;s the shell from which make is invoked.  Why doesn&#8217;t make figure this out on its own?  Having to set the SHELL variable in <strong>make</strong> seems so ridiculously redundant and deliberately obtuse.  &#8220;Hey Mr Make, I&#8217;d like you to drive my bus.  Yes, this bus.  The bus you rode in on.  The bus you&#8217;re still standing in.  Yes, that bus.&#8221;</p>
<p>What-<em>ever</em>.</p>
<p> I&#8217;ll take the 40% faster build times and leave the drama, thanks.</p>
<h3>Concurrency Notes</h3>
<p>Set the number of concurrent jobs equal to or less than the number of execution cores on your system.  Trying to bake 5 cakes in 4 pans at the same time is just silly.</p>
<p>How many cores do you have?  In Win32, it&#8217;s reported in the NUMBER_OF_PROCESSORS environment variable.  make -j $(NUMBER_OF_PROCESSORS) will do the trick (from within the makefile spawning a recursive make). </p>
<p>Just as with adding multithreading to existing source code, don&#8217;t expect your existing makefile logic to work on the first try after adding -j concurrency to your build.  Sequential <strong>make</strong> can hide implicit dependencies that will break when everything happens at once.</p>
<p>For example: if you use precompiled headers, you know that you should build the precompiled header target before you build any source files that use it.  For a sequential <strong>make</strong>, it&#8217;s enough to just put your precompiled header build instruction in the makefile in front of your source code build instruction.  For parallel <strong>make</strong>, though, that will simply start the precompiled header compile in one CPU core and spin up a source compile in another core, and they&#8217;ll soon collide. </p>
<p>For parallel <strong>make</strong>, you need to be more explicit about dependencies and flows than seqential <strong>make</strong> will let you get by with - you need to tell <strong>make</strong> that the precompiled header output is a prerequisite of all source files, for example. <strong>Make</strong> is smart enough to know that it can&#8217;t generate A and B concurrently if B depends upon the output of A.</p>
<p>Besides the .PCH, we discovered we had been lax is specifying the dependencies for some of our .RES resource files.  We had an IDL producing a .TLB, and a .RC including the .TLB to produce a .RES.  This worked fine for ages as a sequential process, but ran into trouble when parallel <strong>make</strong> tried to start compiling the .RC before MIDL was finished generating the TLB from the IDL.  (we have now exhausted our TLA quota)  Fixed by listing the TLB as a prerequisite of the .RES, which it should have been all along anyway.</p>
<p>Be careful about processes that write to shared files.  If A appends a message to log.txt and B appends a message to log.txt, A and B are likely to collide when executed in parallel unless they are careful to use appropriate file locking.</p>
<p>An example of that is compiler error output.  If you&#8217;ve got a syntax error in a header file used by A and B, then the compile processes for A and B will both fail and both report the syntax error to stderr.  More often than not, you&#8217;ll see the text output of compile process A interlaced letter by letter with B.  When each process is reporting the same error, it looks quite comical &#8211; your compiler has acquired a stutter, or perhaps is shivering with cold!</p>
<p>To get coherent error messages, temporarily set your jobs count to one.  Shortcut:  &#8220;make NUMBER_OF_PROCESSORS=1&#8243;.  Command line arguments take precedence over environment variables.</p>
<p>I&#8217;ve heard nebulous stories that msvc++ doesn&#8217;t work with parallel <strong>make</strong> &#8211; that outputting debug symbols to a shared .PDB file will result in a corrupted .PDB.  I&#8217;ve looked for evidence of such corruption, but after a month of building a project with 10MBs of PDB symbol info I have yet to find any PDB corruption. Consider that a myth busted.</p>
<p><a class="a2a_button_twitter_tweet addtoany_special_service" data-count="none" data-url="http://dannythorpe.com/2008/03/06/parallel-make-in-win32/" data-text="Parallel Make in Win32"></a><a class="a2a_button_google_plusone addtoany_special_service" data-annotation="none" data-href="http://dannythorpe.com/2008/03/06/parallel-make-in-win32/"></a><a class="a2a_button_facebook_like addtoany_special_service" data-href="http://dannythorpe.com/2008/03/06/parallel-make-in-win32/"></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fdannythorpe.com%2F2008%2F03%2F06%2Fparallel-make-in-win32%2F&amp;title=Parallel%20Make%20in%20Win32" id="wpa2a_8">Share/Bookmark</a></p>]]></content:encoded>
			<wfw:commentRss>http://dannythorpe.com/2008/03/06/parallel-make-in-win32/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  dannythorpe.com/tag/make/feed/ ) in 0.45285 seconds, on May 21st, 2012 at 5:57 pm UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on May 21st, 2012 at 6:57 pm UTC -->
