<?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>Michael George Hart</title>
	<atom:link href="http://michael-george-hart.com/2010-11-27/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://michael-george-hart.com/2010-11-27</link>
	<description>This is my personal notebook that hopeful maybe of some use to you.</description>
	<lastBuildDate>Fri, 23 Dec 2011 15:30:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Is there any Justification for this web page?</title>
		<link>http://michael-george-hart.com/2010-11-27/2011/12/23/is-there-any-justification-for-this-web-page/</link>
		<comments>http://michael-george-hart.com/2010-11-27/2011/12/23/is-there-any-justification-for-this-web-page/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 15:30:40 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://michael-george-hart.com/2010-11-27/?p=459</guid>
		<description><![CDATA[I love my iPad, it is the perfect tool that I have been waiting for since the invention of the Apple Newton in 1993. Given that so much of what I desire instanous access to is now on my iPad &#8230; <a href="http://michael-george-hart.com/2010-11-27/2011/12/23/is-there-any-justification-for-this-web-page/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I love my iPad, it is the perfect tool that I have been waiting for since the invention of the Apple Newton in 1993. Given that so much of what I desire instanous access to is now on my iPad duplicating what I now have on this blog. I now need to seriously consider the value of these Pages to me?</p>
]]></content:encoded>
			<wfw:commentRss>http://michael-george-hart.com/2010-11-27/2011/12/23/is-there-any-justification-for-this-web-page/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8216;You&#8217;ve got to find what you love,&#8217; Jobs says</title>
		<link>http://michael-george-hart.com/2010-11-27/2011/12/01/youve-got-to-find-what-you-love-jobs-says/</link>
		<comments>http://michael-george-hart.com/2010-11-27/2011/12/01/youve-got-to-find-what-you-love-jobs-says/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 20:53:58 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://michael-george-hart.com/2010-11-27/?p=456</guid>
		<description><![CDATA[Ripped from the pages of Stanford UNIVERSITY. As story that I have always tried to live &#8216;You&#8217;ve got to find what you love,&#8217; Jobs says This is a prepared text of the Commencement address delivered by Steve Jobs, CEO of &#8230; <a href="http://michael-george-hart.com/2010-11-27/2011/12/01/youve-got-to-find-what-you-love-jobs-says/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ripped from the pages of Stanford UNIVERSITY. As story that I have always tried to live</p>
<h1>&#8216;You&#8217;ve got to find what you love,&#8217; Jobs says</h1>
<p>This is a prepared text of the Commencement address delivered by Steve Jobs, CEO of Apple Computer and of Pixar Animation Studios, on June 12, 2005.</p>
<div>
<div>
<div>
<p><a href="http://www.youtube.com/embed/UF8uR6Z6KLc?hl=en&amp;fs=1&amp;autoplay=0&amp;hd=1&amp;showinfo=0&amp;rel=0">Video of the Commencement address.</a></p>
</div>
</div>
<p>I am honored to be with you today at your commencement from one of the finest universities in the world. I never graduated from college. Truth be told, this is the closest I&#8217;ve ever gotten to a college graduation. Today I want to tell you three stories from my life. That&#8217;s it. No big deal. Just three stories.</p>
<p>The first story is about connecting the dots.</p>
<p>I dropped out of Reed College after the first 6 months, but then stayed around as a drop-in for another 18 months or so before I really quit. So why did I drop out?</p>
<p>It started before I was born. My biological mother was a young, unwed college graduate student, and she decided to put me up for adoption. She felt very strongly that I should be adopted by college graduates, so everything was all set for me to be adopted at birth by a lawyer and his wife. Except that when I popped out they decided at the last minute that they really wanted a girl. So my parents, who were on a waiting list, got a call in the middle of the night asking: &#8220;We have an unexpected baby boy; do you want him?&#8221; They said: &#8220;Of course.&#8221; My biological mother later found out that my mother had never graduated from college and that my father had never graduated from high school. She refused to sign the final adoption papers. She only relented a few months later when my parents promised that I would someday go to college.</p>
<p>And 17 years later I did go to college. But I naively chose a college that was almost as expensive as Stanford, and all of my working-class parents&#8217; savings were being spent on my college tuition. After six months, I couldn&#8217;t see the value in it. I had no idea what I wanted to do with my life and no idea how college was going to help me figure it out. And here I was spending all of the money my parents had saved their entire life. So I decided to drop out and trust that it would all work out OK. It was pretty scary at the time, but looking back it was one of the best decisions I ever made. The minute I dropped out I could stop taking the required classes that didn&#8217;t interest me, and begin dropping in on the ones that looked interesting.</p>
<p>It wasn&#8217;t all romantic. I didn&#8217;t have a dorm room, so I slept on the floor in friends&#8217; rooms, I returned coke bottles for the 5¢ deposits to buy food with, and I would walk the 7 miles across town every Sunday night to get one good meal a week at the Hare Krishna temple. I loved it. And much of what I stumbled into by following my curiosity and intuition turned out to be priceless later on. Let me give you one example:</p>
<p>Reed College at that time offered perhaps the best calligraphy instruction in the country. Throughout the campus every poster, every label on every drawer, was beautifully hand calligraphed. Because I had dropped out and didn&#8217;t have to take the normal classes, I decided to take a calligraphy class to learn how to do this. I learned about serif and san serif typefaces, about varying the amount of space between different letter combinations, about what makes great typography great. It was beautiful, historical, artistically subtle in a way that science can&#8217;t capture, and I found it fascinating.</p>
<p>None of this had even a hope of any practical application in my life. But ten years later, when we were designing the first Macintosh computer, it all came back to me. And we designed it all into the Mac. It was the first computer with beautiful typography. If I had never dropped in on that single course in college, the Mac would have never had multiple typefaces or proportionally spaced fonts. And since Windows just copied the Mac, it&#8217;s likely that no personal computer would have them. If I had never dropped out, I would have never dropped in on this calligraphy class, and personal computers might not have the wonderful typography that they do. Of course it was impossible to connect the dots looking forward when I was in college. But it was very, very clear looking backwards ten years later.</p>
<p>Again, you can&#8217;t connect the dots looking forward; you can only connect them looking backwards. So you have to trust that the dots will somehow connect in your future. You have to trust in something — your gut, destiny, life, karma, whatever. This approach has never let me down, and it has made all the difference in my life.</p>
<p>My second story is about love and loss.</p>
<p>I was lucky — I found what I loved to do early in life. Woz and I started Apple in my parents garage when I was 20. We worked hard, and in 10 years Apple had grown from just the two of us in a garage into a $2 billion company with over 4000 employees. We had just released our finest creation — the Macintosh — a year earlier, and I had just turned 30. And then I got fired. How can you get fired from a company you started? Well, as Apple grew we hired someone who I thought was very talented to run the company with me, and for the first year or so things went well. But then our visions of the future began to diverge and eventually we had a falling out. When we did, our Board of Directors sided with him. So at 30 I was out. And very publicly out. What had been the focus of my entire adult life was gone, and it was devastating.</p>
<p>I really didn&#8217;t know what to do for a few months. I felt that I had let the previous generation of entrepreneurs down &#8211; that I had dropped the baton as it was being passed to me. I met with David Packard and Bob Noyce and tried to apologize for screwing up so badly. I was a very public failure, and I even thought about running away from the valley. But something slowly began to dawn on me — I still loved what I did. The turn of events at Apple had not changed that one bit. I had been rejected, but I was still in love. And so I decided to start over.</p>
<p>I didn&#8217;t see it then, but it turned out that getting fired from Apple was the best thing that could have ever happened to me. The heaviness of being successful was replaced by the lightness of being a beginner again, less sure about everything. It freed me to enter one of the most creative periods of my life.</p>
<p>During the next five years, I started a company named NeXT, another company named Pixar, and fell in love with an amazing woman who would become my wife. Pixar went on to create the worlds first computer animated feature film, <em>Toy Story</em>, and is now the most successful animation studio in the world. In a remarkable turn of events, Apple bought NeXT, I returned to Apple, and the technology we developed at NeXT is at the heart of Apple&#8217;s current renaissance. And Laurene and I have a wonderful family together.</p>
<p>I&#8217;m pretty sure none of this would have happened if I hadn&#8217;t been fired from Apple. It was awful tasting medicine, but I guess the patient needed it. Sometimes life hits you in the head with a brick. Don&#8217;t lose faith. I&#8217;m convinced that the only thing that kept me going was that I loved what I did. You&#8217;ve got to find what you love. And that is as true for your work as it is for your lovers. Your work is going to fill a large part of your life, and the only way to be truly satisfied is to do what you believe is great work. And the only way to do great work is to love what you do. If you haven&#8217;t found it yet, keep looking. Don&#8217;t settle. As with all matters of the heart, you&#8217;ll know when you find it. And, like any great relationship, it just gets better and better as the years roll on. So keep looking until you find it. Don&#8217;t settle.</p>
<p>My third story is about death.</p>
<p>When I was 17, I read a quote that went something like: &#8220;If you live each day as if it was your last, someday you&#8217;ll most certainly be right.&#8221; It made an impression on me, and since then, for the past 33 years, I have looked in the mirror every morning and asked myself: &#8220;If today were the last day of my life, would I want to do what I am about to do today?&#8221; And whenever the answer has been &#8220;No&#8221; for too many days in a row, I know I need to change something.</p>
<p>Remembering that I&#8217;ll be dead soon is the most important tool I&#8217;ve ever encountered to help me make the big choices in life. Because almost everything — all external expectations, all pride, all fear of embarrassment or failure &#8211; these things just fall away in the face of death, leaving only what is truly important. Remembering that you are going to die is the best way I know to avoid the trap of thinking you have something to lose. You are already naked. There is no reason not to follow your heart.</p>
<p>About a year ago I was diagnosed with cancer. I had a scan at 7:30 in the morning, and it clearly showed a tumor on my pancreas. I didn&#8217;t even know what a pancreas was. The doctors told me this was almost certainly a type of cancer that is incurable, and that I should expect to live no longer than three to six months. My doctor advised me to go home and get my affairs in order, which is doctor&#8217;s code for prepare to die. It means to try to tell your kids everything you thought you&#8217;d have the next 10 years to tell them in just a few months. It means to make sure everything is buttoned up so that it will be as easy as possible for your family. It means to say your goodbyes.</p>
<p>I lived with that diagnosis all day. Later that evening I had a biopsy, where they stuck an endoscope down my throat, through my stomach and into my intestines, put a needle into my pancreas and got a few cells from the tumor. I was sedated, but my wife, who was there, told me that when they viewed the cells under a microscope the doctors started crying because it turned out to be a very rare form of pancreatic cancer that is curable with surgery. I had the surgery and I&#8217;m fine now.</p>
<p>This was the closest I&#8217;ve been to facing death, and I hope it&#8217;s the closest I get for a few more decades. Having lived through it, I can now say this to you with a bit more certainty than when death was a useful but purely intellectual concept:</p>
<p>No one wants to die. Even people who want to go to heaven don&#8217;t want to die to get there. And yet death is the destination we all share. No one has ever escaped it. And that is as it should be, because Death is very likely the single best invention of Life. It is Life&#8217;s change agent. It clears out the old to make way for the new. Right now the new is you, but someday not too long from now, you will gradually become the old and be cleared away. Sorry to be so dramatic, but it is quite true.</p>
<p>Your time is limited, so don&#8217;t waste it living someone else&#8217;s life. Don&#8217;t be trapped by dogma — which is living with the results of other people&#8217;s thinking. Don&#8217;t let the noise of others&#8217; opinions drown out your own inner voice. And most important, have the courage to follow your heart and intuition. They somehow already know what you truly want to become. Everything else is secondary.</p>
<p>When I was young, there was an amazing publication called <em>The Whole Earth Catalog</em>, which was one of the bibles of my generation. It was created by a fellow named Stewart Brand not far from here in Menlo Park, and he brought it to life with his poetic touch. This was in the late 1960&#8242;s, before personal computers and desktop publishing, so it was all made with typewriters, scissors, and polaroid cameras. It was sort of like Google in paperback form, 35 years before Google came along: it was idealistic, and overflowing with neat tools and great notions.</p>
<p>Stewart and his team put out several issues of <em>The Whole Earth Catalog</em>, and then when it had run its course, they put out a final issue. It was the mid-1970s, and I was your age. On the back cover of their final issue was a photograph of an early morning country road, the kind you might find yourself hitchhiking on if you were so adventurous. Beneath it were the words: &#8220;Stay Hungry. Stay Foolish.&#8221; It was their farewell message as they signed off. Stay Hungry. Stay Foolish. And I have always wished that for myself. And now, as you graduate to begin anew, I wish that for you.</p>
<p>Stay Hungry. Stay Foolish.</p>
<p>Thank you all very much.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://michael-george-hart.com/2010-11-27/2011/12/01/youve-got-to-find-what-you-love-jobs-says/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How do they figure the distance between celestial bodies?</title>
		<link>http://michael-george-hart.com/2010-11-27/2011/12/01/how-do-they-figure-the-distance-between-celestial-bodies/</link>
		<comments>http://michael-george-hart.com/2010-11-27/2011/12/01/how-do-they-figure-the-distance-between-celestial-bodies/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 18:37:17 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Physics]]></category>

		<guid isPermaLink="false">http://michael-george-hart.com/2010-11-27/?p=452</guid>
		<description><![CDATA[How do they figure the distance between celestial bodies? November 7, 2000 Dear Straight Dope: I&#8217;ve been wondering&#8211;what is the process that we use to measure the distance of objects in space? How do we really know that a planet &#8230; <a href="http://michael-george-hart.com/2010-11-27/2011/12/01/how-do-they-figure-the-distance-between-celestial-bodies/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h1>How do they figure the distance between celestial bodies?</h1>
<div>November 7, 2000</div>
<p>Dear Straight Dope:</p>
<p>I&#8217;ve been wondering&#8211;what is the process that we use to measure the distance of objects in space? How do we really know that a planet is 1,200 light years away?</p>
<p>— Mike, Rochester, NY</p>
<p>You probably think there&#8217;s a simple answer to this question, Mike. What&#8217;s frightening is that this is it. But we figure you&#8217;re old enough to take it.</p>
<p>There are a number of steps in the process, with the results of each step used to calibrate the next. To start with, we need to know the distances of things in the solar system. For this, we use something called Kepler&#8217;s Third Law. This states that for any object in the solar system, the orbital period <em>P </em>(in years) is related to the average radius of the orbit <em>A</em> by the formula <em>P2 = A3</em>. The period can be determined easily by going out at night and watching the planet or whatever move. Plugging in the <em>P</em> gives us the radius <em>A</em> in astronomical units, or AUs. An AU is the average distance from the earth to the sun. To figure the length of an AU, we need to measure at least one distance. Usually, this is done by sending a radar pulse to either Mars or Venus, when it&#8217;s at closest approach to the Earth. Since we now know the difference <em>|A</em>Mars or Venus &#8211; <em>A</em>Earth|, and we already knew the ratio <em>P</em>Mars or Venus/<em>P</em>Earth, the rest is child&#8217;s play.</p>
<p>OK, so now we&#8217;ve got the solar system licked. What about other stars? They&#8217;re too far away for radar to be any use. What we use here is a method called parallax (sometimes called trigonometric parallax). To see parallax on a small scale, hold one finger up at arm&#8217;s length in front of you, and look at it first with your left eye, and then with your right eye. Your finger will appear to change position relative to the background. Exactly how much depends on the distance <em>b</em> between your eyes (referred to as the baseline), and the distance <em>D</em> of your finger from your eyes. Specifically, for large distances, the formula is <em>D = 2b/theta</em>, where <em>theta</em> is the angle by which your finger shifts relative to the background, measured in radians (to get from degrees to radians, divide by 57.296). To use this method on the stars, we want the longest baseline we can easily get, which is the diameter of the Earth&#8217;s orbit. If you take a picture of an area of the sky one night, and then take another picture of the same area six months later, the nearby stars in that area of the sky will shift their positions slightly relative to the other stars. Parallaxes can be measured in this way for stars nearer than a few hundred lightyears; after that, the shift is too small to detect.</p>
<p>To get the distance of anything farther away than that, we usually use some sort of &#8220;standard candle&#8221; method. The apparent brightness of an object depends both on how bright it actually is, and on how far away it is. For example, if a hundred watt light bulb is 10 meters away, it&#8217;ll look exactly as bright as a 25-watt light bulb 5 meters away. A &#8220;standard candle&#8221; is an object of known brightness. If we then measure its apparent brightness, we can determine how far away it is. This can be used to determine any distance, as long as you can still see the object you&#8217;re using. For instance, we can use the distances from parallax to determine the average brightness of various colors of normal or &#8220;main sequence&#8221; stars, as they&#8217;re called. This gives us a standard candle good out to the various star clusters in our galaxy, a hundred thousand lightyears or so away.</p>
<p>Then, in some clusters, we see stars called Cepheid variables, whose brightness changes in a certain way with time. Their average brightness depends on their period, and if we see one in a cluster a known distance away, we can determine its brightness and thus determine exactly how the brightness depends on period, so we&#8217;ve got another standard candle. Since Cepheids are brighter than main sequence stars, we can use them at greater distances, allowing us to determine the distances of Cepheids in nearby galaxies, and thus the distances to those galaxies. This in turn allows us to determine the brightness of yet brighter standard candles, and so on. Currently, the largest distances are obtained from a certain type of exploding star called a supernova 1a. These are nearly ten billion times as bright as our sun, and can be seen nearly as far away as the edge of the visible universe. Oughta hold us for now.</p>
<p>— Chronos</p>
]]></content:encoded>
			<wfw:commentRss>http://michael-george-hart.com/2010-11-27/2011/12/01/how-do-they-figure-the-distance-between-celestial-bodies/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NCR NEAT 399 or simply NEAT 3</title>
		<link>http://michael-george-hart.com/2010-11-27/2011/11/22/ncr-neat-399-or-simply-neat-3/</link>
		<comments>http://michael-george-hart.com/2010-11-27/2011/11/22/ncr-neat-399-or-simply-neat-3/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 17:27:35 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://michael-george-hart.com/2010-11-27/?p=447</guid>
		<description><![CDATA[The NCR 499 Although not the first programming language, and by far not my favorite, that I taugh myself, NEAT 3 on a NCR 499 computer was my first professional consulting contract about the spring, summer period of 1979. The Bergen News, as &#8230; <a href="http://michael-george-hart.com/2010-11-27/2011/11/22/ncr-neat-399-or-simply-neat-3/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The <a title="NCR 499" href="http://www.thecorememory.com/TUPopUp.html?1=./assets/images/NCR-499-1.jpg&amp;2=585&amp;3=900&amp;4=NCR%20499&amp;5=1&amp;6=0" target="_blank">NCR 499</a></p>
<p>Although not the first programming language, and by far not my favorite, that I taugh myself, NEAT 3 on a NCR 499 computer was my first professional consulting contract about the spring, summer period of 1979.</p>
<p>The Bergen News, as it was called back then, had placed an ad in their paper for a computer programmer.</p>
<p>In those days people were more openminded and likely to give you a chance, if you were bold enough. You could literal walk into the business, without any experience, meet with the owner asking them to give you a job if you could prove that you could do the job; in this case learn how to develope software for the NCR 499 system using NEAT 3, within a two week period.</p>
<p>He was willing to take the bet on me since I was willing to charge a relatively small sum compare to the NCR 499 consultants he was finding. So he gave me all the manauals for NEAT 3 and the NCR 499 system which I took home and within a week was ready to show I knew what I was talking about.</p>
<p>At the time NCR sales people were not happy to be told by the then owner of the Bergen News thier services were not longer needed and the work was being done by an upstart at rockbottom prices (a story later relayed to several years later by the owner, as the owner started to upgrad to IBM PC&#8217;s). I didn&#8217;t think I was charging a rockbottom price for my skills. I was just happy someone had given me a chance to professionally prove myself.</p>
<p><a title="NCR 499" href="http://www.thecorememory.com/TUPopUp.html?1=./assets/images/NCR-499-1.jpg&amp;2=585&amp;3=900&amp;4=NCR%20499&amp;5=1&amp;6=0" target="_blank">This photographs </a>brings back grand old memories of the days developing my first set of professional software systems.</p>
<p>NEAT 3 as ripped from <a title="NCR 399 Programming Language" href="http://www.thecorememory.com/html/ncr_neat_399.html" target="_blank">CORE MEMORY pages</a></p>
<p><img id="Picture50" title="NCR NEAT 399" src="http://www.thecorememory.com/assets/images/autogen/a_printball_59002_2.gif" border="0" alt="NCR NEAT 399" hspace="0" width="590" height="39" align="top" /></p>
<p>NCR 399 Programming Language</p>
<p>Internal operations and certain external functions of the NCR 399 system are programmed in the <a href="http://www.thecorememory.com/NEAT_399.pdf" target="NewWindow">399 mnemonic language</a>, using near-English macro instructions designed specifically for accounting applications. The programmer must supply two types of information to the application program — data descriptions and procedural instructions. Data layout and coding worksheets are provided for the completion of this information.</p>
<p>The data layout worksheet is used to define the format of <a href="javascript:void(0);" target="_self"><img id="ThumbsUp5034" title="Data Layout Worksheet" src="http://www.thecorememory.com/assets/images/399-DLW-sm.jpg" border="0" alt="Data Layout Worksheet" hspace="7" vspace="7" width="164" height="128" align="right" /></a>the variables on which all arithmetic and data handling operations are to be performed. This data is stored in memory in the form of numeric or alphanumeric values provided as a part of the application program or as a result of previous operations. Each data field defined by the programmer will have a header associated with it in memory. This header contains information reflecting the format of the data field as specified by the programmer on the data layout worksheet. In addition to field length, data type, decimal position, and sign, such information as print position and paper advance code can be defined to achieve automatic print control.</p>
<p>If the data being defined is to be printed on the serial or line printer, the programmer can specify the column number where printing is to start and the number of lines to advance the paper after printing that data lield Then, when the data field is output to the printer, it will be printed automatically in the specified column and the paper advanced if necessary. This feature is especially advantageous when formatting and printing reports; it saves memory by eliminating unnecessary coding within the program.</p>
<p>The NCR 399 programmer need never be concerned with keeping track of actual data addresses in memory. Meaningful symbolic names are assigned to data fields in the program. Once the programmer assigns these names, he thereafter refers to data by name only; software automatically handles the hardware addressing.</p>
<p>Procedural instructions are entered on the 399 coding worksheet.<a href="javascript:void(0);" target="_self"><img id="ThumbsUp5033" title="Coding Worksheet" src="http://www.thecorememory.com/assets/images/399-CW-sm.jpg" border="0" alt="Coding Worksheet" hspace="7" vspace="7" width="164" height="129" align="right" /></a> These instructions: (1) define the functions that must be performed to achieve the end results of the application, and (2) specify the application data that is to be operated on by the interpreter. Instructions, which are variable in length, may contain up 10 three operand addresses.</p>
<p>The 399 language is made up of a comprehensive set of macro-instructions that control forms movement and printing, manipulate data, perform arithmetic functions, process tables, and transfer information to and from the I/O devices. Each macro is a software instruction that, when executed by the interpreter, initiates a series of hardware functions necessary to accomplish the specified task. For instance, when the programmer codes a PUT Serial Printer instruction, the interpreter initiates execution of all those internal functions required to print on a document inserted in the forms handler.</p>
<p>Functions that previously had to be performed manually by the operator now are accomplished under program control, resulting in faster, more efficient operation of the system with less chance of human error. These functions include such operations as positioning the serial printer for typing, rewinding the cassette tape, positioning forms to a specified printline, opening and closing the platen, and ejecting documents.</p>
<p>Simple Input/Output (I/O) instructions handle the normally complex operation of transferring data to and from peripheral units. For instance, to input data from an I/O device such as the card reader, the programmer need only code a GET Card Reader instruction. Issuance of the instruction causes data to be transferred from the card reader to an area in memory defined by the programmer. The instruction performs all necessary translation (from Hollerith card code to ASCII characters) and data formatting. Likewise, to punch a card, the programmer issues a PUT Card Punch instruction, which transfers data from memory to the card punch peripheral. Certain peripherals, such as the line printer, also provide control instructions that perform such functions as paper advance and print positioning.</p>
<p>Because each macro can initiate the performance of many functions, program length and complexity, and programming effort are reduced significantly. The 3-address structure of the language is another powerful feature that minimizes program length. For example, with just one instruction, a programmer can direct the 399 to add the contents of one address to the contents of another address and store the result in a third address.</p>
<p>Variations of the add instruction allow the programmer to:</p>
<p>(1) Add one series of individual consecutive fields to a second series of individual consecutive fields.</p>
<p><em>Add: A1 to B1 A2 to B2 A3 to B3 </em></p>
<p>(2) Add a series of individual consecutive numeric fields to a single field.</p>
<p><em>Add: A1 to B A2 to B A3 to B </em></p>
<p>(3) Add a single numeric field to a series of consecutive fields.</p>
<p><em>Add: A to B1 A to B2 A to B3 </em></p>
<p>Up to 31 consecutive fields can be affected by one add instruction. The subtract, multiply, divide, and move instructions operate in much the same manner.</p>
<p>The NCR 399 processor controlled both internal operations such as arithmetic, decision making, and data manipulation, and external functions su<a href="javascript:void(0);" target="_self"><img id="ThumbsUp5046" title="ASCII Code" src="http://www.thecorememory.com/assets/images/autogen/a_ASCIIcode.gif" border="0" alt="ASCII Code" hspace="7" vspace="7" width="217" height="150" align="right" /></a>ch as typing and forms alignment and movement. Normally, a processor such as that used in the 399 must be programmed at the hardware level, which means that the user either must write lengthy, complex programs or sacrifice a certain degree of flexibility by relying entirely on packaged software provided by the manufacturer. Recognizing the need to ease the user’s programming burden while still providing him with the ability to tailor the system to his own requirements, NCR decided to take an interpretive approach to programming. This approach permits the user to interface with the hardware through the medium of a simple, problem-solving programming language, enabling him to concentrate on the requirements of his system rather than on the intricacies of the equipment.</p>
<p>NCR 399 software was designed specifically to solve accounting problems. It simplifies the programming of even the most difficult applications — payroll, accounts receivable/accounts payable, inventory, financial reporting, utility billing, and so on. The 399 programming language provides clear, concise, near-English macro instructions that describe the steps necessary to accomplish a specified task. These instructions are entered on special 399 programming worksheets and become the application program. As the 399 processor does not recognize near-English instructions, they must be translated into a format that can be interpreted for execution by the processor. This format consists of series of bits; translation to that format is performed by an assembler program.</p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td align="center"><img id="Picture37" title="Program assembly" src="http://www.thecorememory.com/assets/images/399-software-106.jpg" border="0" alt="Program assembly" width="520" height="206" /></td>
</tr>
</tbody>
</table>
<p>When an error-free program has been assembled or reassembled on cassette, it is read into memory, and an interpreter is tailored to that particular application by a link loading process. All communication between the user program and the 399 processor is then controlled by the interpreter.</p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td align="center"><img id="Picture38" title="Program execution" src="http://www.thecorememory.com/assets/images/399-software-202.jpg" border="0" alt="Program execution" width="523" height="206" /></td>
</tr>
</tbody>
</table>
<p>             </p>
<p>Assembling 399 Programs</p>
<p>Each line coded on the programming worksheets is a source line; all the source lines for a given application constitute the source program. However, the source program is not executable by the processor in this form. It must be converted to a form compatible with the interpreter for execution by the 399 processor. This conversion is performed by the 399 assembler program, which is contained on the Master Software Cassette supplied with every 399 system.</p>
<p>NCR 399 application programs can be assembled directly on the<a href="javascript:void(0);" target="_self"><img id="ThumbsUp5035" title="Assembly Specifications for NCR 399" src="http://www.thecorememory.com/assets/images/399_ASW_sm.jpg" border="0" alt="Assembly Specifications for NCR 399" hspace="7" vspace="7" width="160" height="207" align="right" /></a> 399 unit or, optionally, on an NCR Century system. The assembly process is controlled through entries on the appropriate assembler specification worksheet.</p>
<p>These parameter sheets are used to supply the assembler with information about the application program and the 399 system on which it will be run, and to request that certain optional functions be performed during the assembly process itself. The worksheets become a part of the source program for input to the assembler. The source program may be punched into cards or it may be input to the assembler through the 399 alphanumeric keyboard directly from the worksheets. The operator is guided through the assembly process by the lights on the status indicator panel, which are used to request and verify his responses, request cassette changes, and indicate errors.</p>
<p>The 399 assembler operates in two phases. The first is a preassembly phase, which validates certain portions of the source input and writes it to cassette in preparation for the next phase. The resultant program<a href="javascript:void(0);" target="_self"><img id="ThumbsUp5036" title="Assembly Specifications for NCR Century" src="http://www.thecorememory.com/assets/images/399_ASW_Cen_sm.jpg" border="0" alt="Assembly Specifications for NCR Century" hspace="7" vspace="7" width="160" height="206" align="right" /></a> on cassette is called the reassembly master. Additionally, this phase calculates memory addresses for use with the associated symbolic reference names assigned by the programmer and builds a table that specifies which interpretive subroutines are to be included in the program.</p>
<p>The second phase reads one source line (one 80-character record) at a time, condenses it into a series of bits that indicate to the interpreter which routines to execute and on what data fields to operate, and records the assembled program on a cassette. A source program listing is printed on the serial printer as each statement is processed. Any errors encountered during assembly are printed as a notation preceding the erroneous source line.</p>
<p>Reassembly permits corrections, additions, or deletions to a previously assembled program. For instance, a program can be reassembled to correct errors detected during an initial assembly or to include additional logic when peripherals or memory are added to a system. Input to the assembler during the reassembly process includes the reassembly master (the cassette tape output during the first phase of assembly) and only those source lines affected by changes, eliminating the need to enter the entire program a second time. The program is modified by matching source lines, inserting new ones, and deleting old ones where necessary.</p>
<p>Programs can be assembled directly on a 399 system that includes two cassette handlers. If a system has only one cassette handler, NCR will provide, on a temporary basis, a second, plug-in cassette handler to permit program assembly. An NCR Century assembler is also available for assembling 399 programs.</p>
<p>Program Execution</p>
<p>The purpose of the assembly process is to convert an application<a href="javascript:void(0);" target="_self"><img id="ThumbsUp501" title="Application Program" src="http://www.thecorememory.com/assets/images/pic-399tech-24-1_sm.jpg" border="0" alt="Application Program" hspace="7" vspace="7" width="150" height="146" align="right" /></a> program into a format that can be used by the 399 interpreter for execution of the program. The assembled program contained on cassette is referred to as an unexecutable object program because it does not yet include the interpreter. To create an executable program, an interpreter must be tailored to that particular application. This is accomplished through a series of software programs called Linking Loader, which were written to the object program cassette during assembly. First, Linking Loader calls into memory the unexecutable object program from its cassette. Next, from the Master Software Cassette it calls into memory the basic interpreter and only those optional interpretives required by the program. The result is a memory-resident executable program.</p>
<p>The actual amount of memory allocated to the interpreter, user program, and data areas depends on application requirements. Once an executable program is built in memory, it can be processed and/or copied to cassette.</p>
<p>The interpreter is the software interface between the 399 language and the minicomputer and its peripherals. It controls all I/O devices and the sequence of program operations, ensuring that the proper routines are executed as necessary. The interpreter can be divided logically into three areas, or subsystems — executive control, internal operations, and I/O operations.</p>
<p>Automatic sequencing of operations within the 399 is performed by executive control, which uses instructions from the application program to perform the setup operations required by internal and I/O related subsystems, to control program sequencing, and to request operator input as required. In addition, the executive provides common routines that may be used by the operating subsystems, determines which operations program is to perform the application instruction, and transfers control accordingly.</p>
<p>The internal operations subsystem includes all those routines associated with arithmetics, data handling, and data formatting, as well as other standard routines designed to minimize the memory requirements of the interpreter.</p>
<p>The I/O operations subsystem performs all operations directly associated with peripheral devices and is responsible for hardware-related error detection and correction.</p>
<p>The interpreter’s normal sequence of operations begins with the executive, which reads and decodes an application instruction. Using the assembled instruction (the series of bits), it searches a table for the address of the designated macro routine. When the instruction is set up, control is transferred to the appropriate routine in the internal operations subsystem. I/O related routines are accessed by the internal operations subsystem as they are needed. Upon completion of all necessary operations, control is returned to the executive, which then reads and decodes the next program instruction.</p>
]]></content:encoded>
			<wfw:commentRss>http://michael-george-hart.com/2010-11-27/2011/11/22/ncr-neat-399-or-simply-neat-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Top 10 Reasons Leaders Fail</title>
		<link>http://michael-george-hart.com/2010-11-27/2011/11/17/441/</link>
		<comments>http://michael-george-hart.com/2010-11-27/2011/11/17/441/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 15:19:56 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Education]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://michael-george-hart.com/2010-11-27/?p=441</guid>
		<description><![CDATA[Ripped from the pages of CNBC.COM is something worth thinking about; Where does a person honestly rank themselves. The Moral Failure of Leaders: Business, Sports and Politics by Jack Stark, PhD, author of &#8220;The Championship Formula: How to Transform Your &#8230; <a href="http://michael-george-hart.com/2010-11-27/2011/11/17/441/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a title="The Top 10 Reasons Leaders Fail" href="http://www.cnbc.com/id/45292120/" target="_blank">Ripped from the pages of CNBC.COM</a> is something worth thinking about; Where does a person honestly rank themselves.</p>
<p>The Moral Failure of Leaders: Business, Sports and Politics by Jack Stark, PhD, author of <strong><strong><strong><span style="color: #0000ff;">&#8220;The Championship Formula: How to Transform Your Team Into a Dynasty.&#8221;</span></strong></strong></strong></p>
<p>Everyone has flaws. They key to success and to being a great leader is to not have too many flaws and especially to not have a fatal flaw.</p>
<p>What is a fatal flaw?</p>
<p>Think Madoff, Enron, Dominique Strauss-Kahn, John Edwards, those caught up in the Penn State sex scandal and many others.</p>
<p><strong><strong>The Cause </strong></strong></p>
<p>The cause of the “fatal flaws” is twofold – one moral and the other psychological.</p>
<p>I have always had a hard time figuring out why these seemingly bright, talented, well-educated leaders could fail so spectacularly and often so abruptly.</p>
<p>Then I remembered my training on moral development.</p>
<p>Leaders often fail when they don’t pass through the six stages of moral development during their formative childhood years. People can be “stuck” in the highest stage they attain and that stage will govern their moral behavior unless there is a significant intervention and treatment process.</p>
<p><strong><strong>Stages of Moral Development </strong></strong></p>
<ul>
<li><strong><strong>Stage 1 Avoiding punishment</strong></strong> (the most basic stage of moral development often found in young children).</li>
<li><strong><strong>Stage 2 Serving self-interest</strong></strong> (a dangerous stage to be stuck in morally, where the focus is “What’s in it for me?” and moral decisions are based on “What can I get out of it?”)</li>
<li><strong><strong>Stage 3 Seeking approval from others</strong></strong> (the stage usually occurring on one’s teens in which one behaves morally to live up to the expectations of others).</li>
<li><strong><strong>Stage 4 Following authority</strong></strong> (someone in this stage does as told and follows the rules).</li>
<li><strong><strong>Stage 5 Respect for social order</strong></strong> (in this stage of moral development, one’s behavior is driven by the desire to maintain social order and avoid chaos in society).</li>
<li><strong><strong>Stage 6 Universal ethical principles</strong></strong> (in this highest stage of moral development one is guided by conscience according to universal moral principles).
<ul><em></p>
<li><a href="http://en.wikipedia.org/wiki/Lawrence_Kohlberg's_stages_of_moral_development" target="_blank"><em><span style="color: #0000ff;">(See Kohlberg and Levine, 1983). </span></em></a></li>
<p> </p>
<p></em></ul>
</li>
</ul>
<p>The followers of leaders—be they employees, colleagues, fans, members of a religious group, or the rank and file of a military branch—want and need their leaders and heroes and to have character infused with the highest level of moral development. We want to follow and believe in someone whose personality traits we admire. It’s the glue that keeps us united.</p>
<div>
<div>
<div>
<div>&#8220;The cause of the “fatal flaws” is twofold – one moral and the other psychological.&#8221;</div>
<p><strong>Jack Stark, PhD<br />
</strong><em>Author, &#8220;The Championship Formula&#8221;</em></p>
</div>
</div>
</div>
<p> </p>
<p><strong><strong>The ability to handle high-pressure, challenging tasks can be addictive.</strong></strong> For some high-profile leaders, that level of pressure, in combination with opportunities to behave unethically, has led to their failure. We can learn from their unethical behavior.</p>
<p>My experience (thousands of interviews, interventions and therapy) allowed me to have insights into deceitful, unethical leaders and uncover the top 10 reasons why leaders fail—in my opinion based on my experience. The reasons are not in any priority ranking and often multiple reasons contribute to a leader’s demise.</p>
<p><strong><strong>Top 10 Reasons Leaders Fail </strong></strong></p>
<ol>
<li><strong><strong>Greed.</strong></strong> I’m going to get mine since everyone else is and besides, I deserve it. Look at what I have done.</li>
<li><strong><strong>Insecurity. </strong></strong>Poor self-esteem based on family experiences – shockingly high.</li>
<li><strong><strong>Power.</strong></strong> I am in control – I want and get the attention I need.</li>
<li><strong><strong>Arrogance.</strong></strong> Delusion belief: I am better than anyone else.</li>
<li><strong><strong>Narcissism.</strong></strong> Severe form of selfishness and often an inability to love others.</li>
<li><strong><strong>Paranoia.</strong></strong> Never trust anyone – no such thing as loyalty.</li>
<li><strong><strong>Manic Behavior</strong></strong>. Obsessively driven which often results in a big crash.</li>
<li><strong><strong>Addictions.</strong></strong> Drugs, alcohol, gambling and sexual compulsions.</li>
<li><strong><strong>Burnout and Depression</strong></strong>. Often hidden and at least subconsciously reasons for irrational behavior.</li>
<li><strong><strong>Moral Deficiencies</strong></strong>. Primitive moral development and rationalization and blaming.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://michael-george-hart.com/2010-11-27/2011/11/17/441/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unix/Linux Administration Logical Volume Management Guide</title>
		<link>http://michael-george-hart.com/2010-11-27/2011/09/26/unixlinux-administration-logical-volume-management-guide/</link>
		<comments>http://michael-george-hart.com/2010-11-27/2011/09/26/unixlinux-administration-logical-volume-management-guide/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 07:20:37 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Computer Science]]></category>

		<guid isPermaLink="false">http://michael-george-hart.com/2010-11-27/?p=433</guid>
		<description><![CDATA[Ripped from the pages http://content.hccfl.edu/pollock/AUnix1/LVM.htm &#160; Unix/Linux Administration Logical Volume Management Guide ©2005 Wayne Pollock, Tampa Florida USA. All Rights Reserved. Adapted from the LVM How-to page from The Linux Documentation Project website. &#160; LVM (Logical Volume Management) Overview: In &#8230; <a href="http://michael-george-hart.com/2010-11-27/2011/09/26/unixlinux-administration-logical-volume-management-guide/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ripped from the pages<a href="http://content.hccfl.edu/pollock/AUnix1/LVM.htm"> http://content.hccfl.edu/pollock/AUnix1/LVM.ht</a>m</p>
<div><a name="Top"></a>&nbsp;</p>
<h1>Unix/Linux Administration<br />
Logical Volume Management Guide</h1>
<h3>©2005 Wayne Pollock, Tampa Florida USA.<br />
All Rights Reserved.</h3>
<blockquote><p>Adapted from the  <a title="This link takes you to an external site" href="http://www.tldp.org/HOWTO/LVM-HOWTO/index.html"> LVM How-to<img src="http://content.hccfl.edu/pollock/images/extlink.gif" alt="[external link]" /></a> page<br />
from <a title="This link takes you to an external site" href="http://www.tldp.org/"> The Linux Documentation Project<img src="http://content.hccfl.edu/pollock/images/extlink.gif" alt="[external link]" /></a> website.</p></blockquote>
</div>
<div><a name="Overview"></a>&nbsp;</p>
<h2><acronym title="Logical Volume Management">LVM</acronym> (Logical Volume Management) Overview:</h2>
</div>
<div>
<p>In the olden days computer disks were small compared to the data set sizes that were needed.  A solution is to make several physical disks appear <em>virtually</em> (or <em>logically</em>) as a single much larger disk.  A large filesystem could then be created on that virtual disk.</p>
<p>Later hard disk sizes grew large enough that it made sense to do the opposite: make one physical disk appear as several <em>virtual</em> disks.  Each virtual disk holds a filesystem independently of the others.  Today such virtual disks are called disk &#8220;<em>partitions</em>&#8220;.</p>
<p>Now we have come full circle.  Large <em>data warehouse</em> applications require very large filesystems to hold the database data files.  To support this sort of application the old idea of combining several disks into one has been resurrected.  Novell Netware supported this feature since the 1990s.  The physical disk (or selected disk partitions) are formatted to be &#8220;<em>physical volume segments</em>&#8220;.  All added physical volume segments become part of a single large <em>virtual disk</em>.  The administrator can then create logical &#8220;<em>volumes</em>&#8220;, that is, a filesystem.  The exciting part is that if some volume is low on space, you can extend the virtual disk by adding another physical volume segment to it, and then increase the (logical) volume&#8217;s size.  This operation is fast and doesn&#8217;t disturb the existing data or other partitions (or volumes)!</p>
<p>The modern Unix (and Linux) version of this idea is called &#8220;<em>Logical Volume Management</em>&#8221; (or &#8220;LVM&#8221;).  LVM allows the administrator to</p>
<ul>
<li> use and allocate disk space more efficiently and flexibly</li>
<li> move logical volumes between different physical devices</li>
<li> have very large logical volumes span a number of physical devices</li>
<li> take <em>snapshots</em> of whole filesystems easily, allowing      on-line backup of those filesystems</li>
<li> replace on-line drives without interrupting services</li>
</ul>
<p>Linux also supports software <acronym title="Redundant Array of Inexpensive Disks">RAID</acronym>, which, like LVM, can be used to provide <em>disk striping</em>.  The two systems are independent of each other.  So you can use RAID to provide striping and use that RAID volume as a physical volume for LVM.  There is no reason to use both software RAID and LVM, although it can be done.  However it does make good sense to use hardware RAID and LVM together.</p>
<p>As a quick example of what can be done, suppose you need to grow some filesystem by 500 MB.  Without LVM, you must either have a spare 500 MB on the same physical disk or the entire filesystem must be moved to another (larger) disk.  Even if you have the space, all the other partitions (and their filesystems) must be moved, so the 500 MB is at the end of the partition you wish to grow.  Then all the data must be backed up, the partition changed, and the old data restored.  While today there are tools such as <code>parted</code> that can manage this for regular partitions (not LVs), using LVM you can quickly and safely grow a filesystem in this simple way:</p>
<pre>  root# <strong>umount /dev/vg1/lv1</strong>
  root# <strong>e2fsadm /dev/vg1/lv1 -L+500M</strong>
  root# <strong>mount /dev/vg1/lv1</strong></pre>
<p>The free space can be anywhere, even on another disk!</p>
<p>LVM for Linux has had two major versions (so far).  Both have many more features and controls than the older Novell scheme.  While the additional controls and features aren&#8217;t always needed, you still must understand them in order to setup and manage LVM.  LVM is also available in recent Solaris and other Unix systems, however different terms may be used for the same concepts.  The <em>Veritas Volume Manager</em>, (&#8220;VVM&#8221; or &#8220;VxVM&#8221;) is a proprietary but popular logical volume manager from Veritas (now part of Symantec).  It is available for Windows, AIX, Solaris, Linux, and HP-UX (where it is the system default LVM).  Also take a look at the <a href="http://sourceforge.net/projects/evms/"> Enterprise Volume Management System</a> (a sourceforge.net project).</p>
</div>
<div><a name="Concepts"></a>&nbsp;</p>
<h2>Basic Concepts and Terminology:</h2>
</div>
<div><img src="http://content.hccfl.edu/pollock/AUnix1/LVM-Fig1.gif" alt="[relationship of PVs, VGs, and LVs]" />&nbsp;</p>
<h3>Figure 1</h3>
</div>
<div>
<p>With LVM, physical volume segments are simply called &#8220;<dfn>physical volumes</dfn>&#8221; (or &#8220;<dfn><acronym title="Physical Volume">PV</acronym>s</dfn>&#8220;).  These PVs are usually entire disks but may be disk partitions.  The PVs in turn are combined to create one or more large virtual disks called &#8220;<dfn>volume groups</dfn>&#8221; (or &#8220;<dfn><acronym title="Volume Group">VG</acronym>s</dfn>&#8220;).  While you can create many VGs, one may be sufficient.  A VG can grow or shrink by adding or removing PVs from it.  VGs appear to be block devices, similar to other disks such as <code>/dev/hda</code>.  In fact each VG can be referred to by the name &#8220;<code>/dev/<em>VG_name</em></code>&#8220;.</p>
<p>Once you have one or more volume groups you can create one or more virtual partitions called &#8220;<dfn>logical volumes</dfn>&#8221; (or &#8220;<dfn><acronym title="Logical Volume">LV</acronym>s</dfn>&#8220;).  Note each LV must fit entirely within a single VG.  LVs appear to be block devices similar to disk partitions such as <code>/dev/hda1</code>, with entries named &#8220;<code>/dev/<em>VG_name</em>/<em>LV_name</em></code>&#8220;.  LVs have a number of parameters that can be set (and later most can be changed) that can affect disk I/O performance, including extent size, chunk size, stripe size and stripe set size, and read-ahead.  These are discussed below.</p>
</div>
<div>
<table border="1" cellpadding="8" rules="none" summary="Logical volume management common acronyms">
<thead>
<tr>
<th>Term</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<th>PE</th>
<td>Physical Extent</td>
</tr>
<tr>
<th>LE</th>
<td>Logical Extent</td>
</tr>
<tr>
<th>PV</th>
<td>Physical Volume</td>
</tr>
<tr>
<th>VG</th>
<td>Volume Group</td>
</tr>
<tr>
<th>LV</th>
<td>Logical Volume</td>
</tr>
</tbody>
</table>
<p>Table 1: LVM Acronyms</p>
</div>
<div>
<p>Finally, you can create any type of filesystem you wish on the logical volume, including as <code>swap</code> space.  Note that some filesystems are more useful with LVM than others.  For example not all filesystems support growing and shrinking.  <code>ext2</code>, <code>ext3</code>, <code>xfs</code>, and <code>reiserfs</code> do support such operations and would be good choices.  The relationship between PVs, VGs, and LVs is illustrated in figure 1.  Table 1 summarizes these acronyms.</p>
</div>
<div><a name="Extents"></a>&nbsp;</p>
<h3>Extents:</h3>
</div>
<div>
<p>When creating a volume group from one or more physical volumes, you must specify the size of the &#8220;<dfn>extents</dfn>&#8221; of each of the physical volumes that make up the VG.  Each extent is a single contiguous chunk of disk space, typically 4M in size, but can range from 8K to 16G in powers of 2 only.  (Extents are analogous to disk <em>blocks</em> or <em>clusters</em>.)  The significance of this is that the size of logical volumes are specified as a number of extents.  Logical volumes can thus grow and shrink in increments of the extent size.  A volume group&#8217;s extent size cannot be changed after it is set.</p>
<p>The system internally numbers the extents for both logical and physical volumes.  These are called <dfn>logical extents</dfn> (or <dfn><acronym title="Logical Extent">LE</acronym>s</dfn>) and <dfn>physical extents</dfn> (or <dfn><acronym title="Physical Extent">PE</acronym>s</dfn>), respectively.  When a logical volume is created a <em>mapping</em> is defined between logical extents (which are logically numbered sequentially starting at zero) and physical extents (which are also numbered sequentially).</p>
<p>To provide acceptable performance the extent size must be a multiple of the actual disk cluster size (i.e., the size of the smallest chunk of data that can be accessed in a single disk I/O operation).  In addition some applications (such as <em>Oracle</em> database) have performance that is very sensitive to the extent size.  So setting this correctly also depends on what the storage will be used for, and is considered part of the system administrator&#8217;s job of tuning the system.</p>
</div>
<div><a name="Booting"></a>&nbsp;</p>
<h3>Booting Consideration with LVM:</h3>
</div>
<div>
<p>LVM can be use with RAID.  LVM can be used to hold all filesystems.  However special considerations apply when using LVs for the boot and root filesystems.  This is because the <acronym title="Basic Input Output System">BIOS</acronym> code in the <acronym title="Read Only Memory">ROM</acronym> of the motherboard of your computer must be able to locate and load the kernel.  So if the boot partition was a LV, the BIOS would need to know about PVs, VGs, and LVs, and it probably doesn&#8217;t.  Unless you are using some custom BIOS you must not make the bootable partition an LV.</p>
<p>The <code>root</code> partition (if it isn&#8217;t also the boot partition) may be a logical volume.  However this means the kernel must access the <code>root</code> partition <em>before</em> it can load any (e.g., LVM) kernel modules.  Thus the modules for LVM must be compiled into the kernel.  This is rarely the case with standard distributions!  (There is a similar issue with <acronym title="Small Computer System Interface">SCSI</acronym> drivers, as most kernels only compile in the <acronym title="Integrated ">IDE</acronym> drivers.)  For this reason, as well as allowing a filesystem to be accessed by another operating system (yes there are <code>ext2</code> drivers available for Windows), some system administrators prefer to make the <code>root</code> filesystem on a regular partition rather than on a logical volume.  Note in this case you can make a single <code>root</code>+<code>boot</code> partition.</p>
<p>The solution to using a logical volume for your <code>root</code> filesystem (as it is with SCSI) is either to build a custom kernel with the correct drivers compiled in, or to make sure the system loads a <acronym title="Random Access Memory">RAM</acronym> disk initially, known as <code>initrd</code>, which contains all the correct modules.  This RAM disk then loads the system as normal, and goes away.  Creating a ramdisk on Linux is simple using the <code>mkinitrd</code> script.  Just run this command (as root).  You need to know the kernel version, and then you must update <code>grub.conf</code> to use the ramdisk:</p>
<pre>/root# <strong>KERNEL_VERSION=`uname -r`</strong>
/root# <strong>mkinitrd -v initrd.$KERNEL_VERSION $KERNEL_VERSION</strong>
/root# <strong>mv initrd.$KERNEL_VERSION /boot</strong>
/root# <strong>vi /boot/grub/grub.conf  # or /boot/grub/menu.lst</strong></pre>
<p>Before logical volumes can be mounted, the LVM driver must be loaded (or compiled in) to the kernel.  Next all physical volumes on all available drives must be found and examined, in order to determine all the volume groups.  Finally the volume groups must be <em>activated</em>, which causes the kernel to recognize the various block devices.  Only then can the filesystems within logical volumes be mounted. So most systems add code similar to the following to the boot up scripts (typically the <code>rc.sysinit</code> script):</p>
<pre># LVM2 initialization
if [ -x /sbin/lvm.static ]  # Check for LVM v2
then
   # make sure device mapper (LVM2) kernel module is loaded:
   if ! grep -q "device-mapper" /proc/devices 2&gt;/dev/null
   then
      modprobe dm-mod &gt;/dev/null 2&gt;&amp;1
   fi
   # Cleanup and then recreate device mapper control file:
   /bin/rm -f /dev/mapper/control
   echo "mkdmnod" | /sbin/nash --quiet &gt;/dev/null 2&gt;&amp;1
   if [ -c /dev/mapper/control ]  # if LVM2 is loaded:
   then  # Check for any physical volumes:
      if /sbin/lvm.static vgscan &gt; /dev/null 2&gt;&amp;1
      then
         echo "Setting up Logical Volume Management:"
         # Activate volume groups and re-create all /dev entries:
         /sbin/lvm.static vgchange -a y &amp;&amp; /sbin/lvm vgmknodes
      fi
   fi
fi</pre>
<p>You may want to edit the file <code>/etc/init.d/halt</code> to <em>deactivate</em> the volume groups at shutdown.  However this shouldn&#8217;t be necessary when using LVM version 2.  To deactivate volume groups, insert the following near the end of this file (just after the filesystems are mounted read-only and before the comment that says &#8220;<tt>Now halt or reboot</tt>&#8220;):</p>
<pre># Deactivate LVM:
if [ -x /sbin/lvm.static ]  # Check for LVM v2
then
   echo "Deactivating LVM volume groups:"
   /sbin/lvm.static vgchange -a n
fi</pre>
<p>Like all storage devices data may become corrupted over time.  LVM provides a command &#8220;<code>vgck</code>&#8221; you can use to periodically check the consistency of your volume groups.  It may pay to add this command to the bootup scripts.</p>
</div>
<div><a name="Mapping"></a>&nbsp;</p>
<h3>Linear and Striped Mapping:</h3>
</div>
<div>
<p>Let&#8217;s suppose we have a volume group called <code>VG1</code>, and this volume group has a physical extent size of 4M.  Suppose too this volume group is composed of one disk partition <code>/dev/hda1</code> and one whole disk <code>/dev/hdb</code>.  These will become physical volumes <code>PV1</code> and <code>PV2</code> (more meaningful names for a particular scenario can be given if desired).</p>
<p>The PVs are different sizes and we get 99 (4M) extents in <code>PV1</code> and 248 extents in <code>PV2</code>, for a total of 347 extents in <code>VG1</code>.  Now any number of LVs of any size can be created from the VG, as long as the total number of extents of all LVs sums to no more than 347.  To make the LVs appear the same as regular disk partitions to the filesystem software, the logical extents are numbered sequentially within the LV.  However some of these LEs may be stored in the PEs on <code>PV1</code> and others on <code>PV2</code>.  For instance LE[1] of some LV in <code>VG1</code> could map onto PE[51] of <code>PV1</code>, and thus data written to the first 4M of the LV is in fact written to the 51st extent of <code>PV1</code>.</p>
<p>When creating LVs an administrator can choose between two general strategies for mapping logical extents onto physical extents:</p>
<ol>
<li> <dfn>Linear mapping</dfn> will assign a range of      PE&#8217;s to an area of an      LV in order (e.g., LE 1–99 map to <code>PV1</code>&#8216;s PEs,     and LE 100–347 map onto <code>PV2</code>&#8216;s PEs).</li>
<li> <dfn>Striped mapping</dfn> will interleave the disk      blocks of the      logical extents across a number of physical volumes.       You can decide the number of PVs to stripe across (the <em>stripe      set size</em>), as well as the size of each stripe.</li>
</ol>
<p>When using striped mapping, all PVs in the same stripe set need to be the same size.  So in our example the LV can be no more than 198 (99 + 99) extents in size.  The remaining extents in PV2 can be used for some other LVs, using linear mapping.</p>
<p>The size of the stripes is independent of the extent size, but must be a power of 2 between 4K and 512K.  (This value <code><em>n</em></code> is specified as a power of 2 in this formula: <code>(2^<em>n</em>) × 1024 bytes</code>, where 2 ≤ <code><em>n</em></code> ≤ 9.)  The stripe size should also be a multiple of the disk sector size, and finally the extent size should be a multiple of this stripe size.  If you don&#8217;t do this, you will end up with fragmented extents (as the last bit of space in the extent will be unusable).</p>
<p>Tables 2 and 3 below illustrate the differences between linear and striped mapping.  Suppose you use a stripe size of 4K, an extent size of 12K, and a stripe set of 3 PVs (PVa, PVb, and PVc), each of which is 100 extents.  Then the mapping for an LV ( whose extents we&#8217;ll call LV1, LV2, &#8230;) to PVs (whose extents we&#8217;ll call PVa1, PVa2, &#8230;, PVb1, PVb2, &#8230;, PVc1, PVc2, &#8230;) might look something like the following.  (In this table the notation means <em>volume_name</em> <em>extent_number</em> . <em>stripe_number</em>):</p>
</div>
<div>
<table border="0" cellpadding="12" rules="cols" summary="layout table showing both linear and striped mappings">
<tbody>
<tr>
<td>
<table border="0" summary="Example of striped mapping of LVs to PVs">
<caption>Example of Linear Mapping</caption>
<thead>
<tr>
<th>Logical Extents</th>
<th></th>
<th>Physical Extents</th>
</tr>
</thead>
<tbody>
<tr>
<td>LV1</td>
<td>→</td>
<td>PVa1</td>
</tr>
<tr>
<td>LV2</td>
<td>→</td>
<td>PVa2</td>
</tr>
<tr>
<td>LV3</td>
<td>→</td>
<td>PVa3</td>
</tr>
<tr>
<td>LV4</td>
<td>→</td>
<td>PVa4</td>
</tr>
<tr>
<td>&#8230;</td>
<td>→</td>
<td>&#8230;</td>
</tr>
<tr>
<td>LV99</td>
<td>→</td>
<td>PVa99</td>
</tr>
<tr>
<td>LV100</td>
<td>→</td>
<td>PVb1</td>
</tr>
<tr>
<td>LV101</td>
<td>→</td>
<td>PVb2</td>
</tr>
<tr>
<td>&#8230;</td>
<td>→</td>
<td>&#8230;</td>
</tr>
<tr>
<td>LV199</td>
<td>→</td>
<td>PVb99</td>
</tr>
<tr>
<td>LV200</td>
<td>→</td>
<td>PVc1</td>
</tr>
<tr>
<td>LV201</td>
<td>→</td>
<td>PVc2</td>
</tr>
<tr>
<td>&#8230;</td>
<td>→</td>
<td>&#8230;</td>
</tr>
</tbody>
</table>
</td>
<td>
<table border="0" summary="Example of striped mapping of LVs to PVs">
<caption>Example of Striped Mapping</caption>
<thead>
<tr>
<th>Logical Extents</th>
<th></th>
<th>Physical Extents</th>
</tr>
</thead>
<tbody>
<tr>
<td>LV1.1</td>
<td>→</td>
<td>PVa1.1</td>
</tr>
<tr>
<td>LV1.2</td>
<td>→</td>
<td>PVb1.1</td>
</tr>
<tr>
<td>LV1.3</td>
<td>→</td>
<td>PVc1.1</td>
</tr>
<tr>
<td>LV2.1</td>
<td>→</td>
<td>PVa1.2</td>
</tr>
<tr>
<td>LV2.2</td>
<td>→</td>
<td>PVb1.2</td>
</tr>
<tr>
<td>LV2.3</td>
<td>→</td>
<td>PVc1.2</td>
</tr>
<tr>
<td>LV3.1</td>
<td>→</td>
<td>PVa1.3</td>
</tr>
<tr>
<td>LV3.2</td>
<td>→</td>
<td>PVa1.3</td>
</tr>
<tr>
<td>LV3.3</td>
<td>→</td>
<td>PVa1.3</td>
</tr>
<tr>
<td>LV4.1</td>
<td>→</td>
<td>PVa2.1</td>
</tr>
<tr>
<td>LV4.2</td>
<td>→</td>
<td>PVb2.1</td>
</tr>
<tr>
<td>LV4.3</td>
<td>→</td>
<td>PVc2.1</td>
</tr>
<tr>
<td>&#8230;</td>
<td>→</td>
<td>&#8230;</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>Tables 2 and 3: Linear versus Striped Mapping</p>
</div>
<div>
<p>In certain situations striping can improve the performance of the logical volume but it can be complex to manage.  However note that striped mapping is useless and will in fact hurt performance, unless the PVs used in the stripe set are from different disks, preferably using different controllers.</p>
<p>(In version 1 of LVM LVs created using striping cannot be extended past the PVs on which they were originally created.  In the current version (LVM 2) striped LVs can be extended by concatenating another set of devices onto the end of the first set.  However this could lead to a situation where (for example) a single LV ends up as a 2 stripe set, concatenated with a linear (non-striped) set, and further concatenated with a 4 stripe set!</p>
</div>
<div><a name="Snapshots"></a>&nbsp;</p>
<h3>Snapshots:</h3>
</div>
<div>
<p>A wonderful facility provided by LVM is a <dfn>snapshot</dfn>.  This allows an administrator to create a new logical volume which is an exact copy of an existing logical volume (called the <dfn>original</dfn>), frozen at some point in time.  This copy is read-only.  Typically this would be used when (for instance) a backup needs to be performed on the logical volume but you don&#8217;t want to halt a live system that is changing the data.  When done with the snapshot the system administrator can just unmount it and then remove it.  This facility does require that the snapshot be made at a time when the data on the logical volume is in a consistent state, but the time the original LV must be off-line is <em>much</em> less than a normal backup would take to complete.</p>
<p>In addition the copy typically only needs about 20% or less of the disk space of the original.  Essentially, when the snapshot is made nothing is copied.  However as the original changes, the updated disk blocks are first copied to the snapshot disk area before being written with the changes.  The more changes are made to the original, the more disk space the snapshot will need.</p>
<p>When creating logical volumes to be used for snapshots, you must specify the <dfn>chunk size</dfn>.  This is the size of the data block copied from the original to the snapshot volume.  For good performance this should be set to the size of the data blocks written by the applications using the original volume.  While this chunk size is independent of both the extent size and the stripe size (if striping is used), it is likely that the disk block (or cluster or page) size, the stripe size, and the chunk size should all be the same.  Note the chunk size must be a power of 2 (like the stripe size), between 4K and 1M.  (The extent size should be a multiple of this size.)</p>
<p>You should remove snapshot volumes as soon as you are finished with them, because they take a copy of all data written to the original volume and this can hurt performance.  In addition, if the snapshot volume fills up errors will occur.</p>
</div>
<div><a name="Admin"></a>&nbsp;</p>
<h2>LVM Administration — Commands and Procedures:</h2>
</div>
<div>
<p>The <code>lvm</code> command permits the administrator to perform all LVM operations using this one interactive command, which includes built-in help and will remember command line arguments used from previous commands for the current command.  However each LVM command is also available as a stand-alone command (that can be scripted).  These are discussed briefly below, organized by task.  See the man page for the commands (or use the built-in help of <code>lvm</code>) for complete details.</p>
</div>
<div><a name="Plan"></a>&nbsp;</p>
<h3>Plan the Disk Layout:</h3>
</div>
<div>
<p>Disk I/O is often the determining factor in overall system performance.  If your system has multiple disks and controllers, the correct strategy is to have them all used in parallel (that is, simultaneously) as much of the time as possible.  In addition you should aim to place files in such a way as to minimize disk head movement (and thus minimize <em>seek time</em>).</p>
<p>While the performance improvements are real they often aren&#8217;t significant.  Whether or not to worry about these issues depends upon the current performance, file size, type, and access patterns, and which applications are running.  Some ways to maximize performance are:</p>
<ul>
<li> To support a large number of users, say on a development      system, you can use linear mapping of your logical volumes      to a large number of physical volumes on different disks,      hopefully using different controllers as well.</li>
<li> On a production system running several different services, the      files for each service should be placed on different physical      disks (so for example the web server I/O won&#8217;t interfere with      the FTP server I/O).</li>
<li> On a database server the files for the following should be placed      on different disks: tables, their indexes, log files, and frequently      used tables (that don&#8217;t get cached in RAM).</li>
<li> If possible it pays to keep the operating system files (i.e.,      <code>boot</code>, <code>root</code>, <code>/var/log</code>, swap)      on one disk and the rest of the system on another, so the system&#8217;s      disk I/O doesn&#8217;t interfere with the service&#8217;s I/O.</li>
<li> Large files are often accessed <em>sequentially</em>.       Such access is most efficient when the data blocks of the file are      contiguous, at the outer edge of the disk (cylinder zero).       In addition striping across different disks is very helpful in      minimizing disk head movement and allowing parallel read/write      operations.</li>
<li> Large sequentially accessed files, such as those on a web or      <acronym title="File Transfer Protocol">FTP</acronym> server      can also benefit from a LVM feature called <em>read ahead</em>.       This allows the next block to be read from disk to RAM at the same      time as the current block, useful when the data is contiguous.       (Non-LVM disk read-ahead is also settable in Linux, by changing      some parameters in <code>/proc/sys/vm</code>.)</li>
<li> On the other hand, randomly accessed files benefit from a more      central placement on a disk, as this will tend to minimize disk      <em>seek time</em>.</li>
<li> Using striped mapping can speed up access to large, sequentially      accessed files, as more disks (and controllers) are used      simultaneously.       Smaller, randomly accessed files don&#8217;t benefit much from      striping.</li>
<li> To avoid striping performance problems you should format one PV      per whole disk.       LVM can&#8217;t tell if two PVs are on the same physical disk or not,      so if you create a multiple PVs per disk and then create      striped LVs, the stripes could be on different partitions      on the same disk.       This would result in a decrease in performance rather      than an increase.       If you do format a disk with multiple PVs, make sure no two of them      are added to the same volume group if striped mapping will be used!</li>
<li> For a production system it is recommended that you create      one PV per whole disk, for Administrative convenience.       It&#8217;s easier to keep track of      the hardware in a system if each real disk only appears once.       This becomes particularly true if a disk fails.</li>
</ul>
<p>Other factors affect the disk I/O performance.  Often these other factors overshadow any performance gains from careful disk layout.  One example is the disk scheduler in the kernel.  The 2.6 version of the Linux kernel comes with two different schedulers you can select between.  In addition the kernel supports features such as <em>read-ahead</em> independently of any LVM settings.</p>
<p>Another issue is the disk controller settings.  Sometimes the disk schedules disk I/O regardless of the kernel.  Disks also have configurable settings, including DMA, buffering, etc.  These can be changed with &#8220;<code>hdparam</code>&#8221; and other utilities.</p>
<p>Other factors that affect performance include bus type and speed, and what other devices are attached to that bus.</p>
</div>
<div><a name="FormatPV"></a>&nbsp;</p>
<h3>Format Physical Volumes (PVs)</h3>
</div>
<div>
<p>To initialize a disk or disk partition as a physical volume you just run the  &#8220;<code>pvcreate</code>&#8221; command on the whole disk.  For example:</p>
<pre>  pvcreate /dev/hdb</pre>
<p>This creates a <em>volume group descriptor</em> at the start of the second IDE disk.  You can initialize several disks and/or partitions at once.  Just list all the disks and partitions on the command line you wish to format as PVs.</p>
<p>Sometimes this procedure may not work correctly, depending on how the disk (or partition) was previously formatted.  If you get an error that LVM can&#8217;t initialize a disk with a partition table on it, first make sure that the disk you are operating on is the correct one!  Once you have confirmed that <code> /dev/hdb</code> is the disk you really want to reformat, run the following <code>dd</code> command to erase the old partition table:</p>
<pre># Warning DANGEROUS!
# The following commands will destroy the partition table on the
# disk being operated on.  Be very sure it is the correct disk!
dd if=/dev/zero of=/dev/hdb bs=1k count=1 blockdev \
    --rereadpt /dev/hdb</pre>
<p>For partitions run &#8220;<code>pvcreate</code>&#8221; on the partition:</p>
<pre>    pvcreate /dev/hdb1</pre>
<p>This creates a <em>volume group descriptor</em> at the start of the <code>/dev/hdb1</code> partition.  (Note that if using LVM version 1 on PCs with DOS partitions, you must first set the partition type to &#8220;<code>0x8e</code>&#8221; using <code>fdisk</code> or some other similar program.)</p>
</div>
<div><a name="CreateVG"></a>&nbsp;</p>
<h3>Create Volume Groups (VGs)</h3>
</div>
<div>
<p>Use the &#8220;<code>vgcreate</code>&#8221; program to group selected PVs into VGs, and to optionally set the extent size (the default is 4MB).  The following command creates a volume group named &#8220;<code>VG1</code>&#8221; from two disk partitions from different disks:</p>
<pre>    vgcreate VG1 /dev/hda1 /dev/hdb1</pre>
<p>Modern systems may use &#8220;<code>devfs</code>&#8221; or some similar system, which creates symlinks in <code>/dev</code> for detected disks.  With such systems names like &#8220;<code>/dev/hda1</code>&#8221; are actually the symlinks to the real names.  You can use either the symlink or the real name in the LVM commands, however the older version of LVM demanded you use the real device names, such as <code>/dev/ide/host0/bus0/target0/lun0/part1</code> and <code>/dev/ide/host0/bus0/target1/lun0/part1</code>.</p>
<p>You can also specify the extent size with this command using the &#8220;<code>-s <em>size</em></code>&#8221; option, if the 4Mb default not what you want.  The <code><em>size</em></code> is a value followed by one of k (for kilobytes), m (megabytes), g (gigabytes), or t (tetrabytes).  In addition you can put some limits on the number of physical or logical volumes the volume can have.  You may want to change the extent size for performance, administrative convenience, or to support very large logical volumes.  (Note there may be kernel limits and/or application limits on the size of LVs and files on your system.  For example Linux 2.4 kernel has a max size of 2TB.)</p>
<p>The &#8220;<code>vgcreate</code>&#8221; command adds some information to the headers of the included PVs.  However the kernel modules needed to use the VGs as disks aren&#8217;t loaded yet, and thus the kernel doesn&#8217;t &#8220;see&#8221; the VGs you created.  To make the VGs visible you must <em>activate</em> them.  Only active volume groups are subject to changes and allow access to their logical  volumes.</p>
<p>To activate a single volume group <code>VG1</code>, use the command:</p>
<pre>    vgchange -a y /dev/VG1</pre>
<p>(&#8220;<code>-a</code>&#8221; is the same as &#8220;<code>--available</code>&#8220;.)   To active all volume groups on the system use:</p>
<pre>    vgchange -a y</pre>
</div>
<div><a name="CreateLV"></a>&nbsp;</p>
<h3>Create Logical Volumes (LVs)</h3>
</div>
<div>
<p>Creating a logical volume in some VG is the most complex part of LVM setup, due to the many options available.  The basic command syntax is:</p>
<pre>    lvcreate <em>options</em> <em>size</em> <em>VG_name</em></pre>
<p><a name="size"></a> Where <code><em>size</em></code> is either &#8220;<code>-l <em>num_extents</em></code>&#8221; or &#8220;<code>-L <em>num_bytes</em></code>&#8220;, where <em>num_bytes</em> is a number followed by one of k, m, g, or t.  If this second form is used you may not get an LV of that exact size, as LVs are always a whole number of extents.  You can also use &#8220;<code>--extents</code>&#8221; for &#8220;<code>-l</code>&#8221; or &#8220;<code>--size</code>&#8221; for &#8220;<code>-L</code>&#8220;.</p>
<p>One of the most common options is &#8220;<code>-n <em>name</em></code>&#8221; (you can use &#8220;<code>--name</code>&#8221; for &#8220;<code>-n</code>&#8220;) to specify a name for the logical volume.  If you don&#8217;t use this option than the LVs are named automatically &#8220;<code>lvol1</code>&#8220;, &#8220;<code>lvol2</code>&#8220;, &#8220;<code>lvol3</code>&#8220;, etc.</p>
<p>Other options include &#8220;<code>-C y</code>&#8221; (or &#8220;<code>--contiguous y</code>&#8220;) to create an LV with contiguous allocation, &#8220;<code>-i <em>num_stripes</em> -I <em>stripe_size</em></code>&#8221; to create an LV with striped mapping (<em>stripe_size</em> is a number between 2 and 9, as described above), and &#8220;<code>-r <em>num_sectors</em></code>&#8221; (or &#8220;<code>--readahead <em>num_sectors</em></code>&#8220;) to set the amount of read ahead to a value between 2 and 120.</p>
<p>Another form of this command is used to create snapshot volumes.  This will be discussed below.</p>
<p>Some examples of creating logical volumes <code>LV1</code> and <code>LV2</code> from the volume group <code>VG1</code>:</p>
<pre># To create a 20GB linear LV named "LV1" for some VG named
# "VG1" and its block device special file "/dev/VG1/LV1":
lvcreate -L 20g -n LV1 VG1

# To create a LV of 100 extents with 2 stripes and stripe size 4 KB:
lvcreate -i 2 -I 4 -l 100 -n LV2 VG1</pre>
<p>If you want to create an LV that uses the entire VG, use the &#8220;<code>vgdisplay</code>&#8221; command to find the &#8220;Total PE&#8221; size, then use that when running <code>lvcreate</code>.</p>
<p>Once the LVs have been created you can format them with filesystems (or as <em>swap space</em>) using standard tools such as &#8220;<code>mkfs</code>&#8220;.  If the new filesystem can be successfully mounted, a final step is to edit the <code>/etc/fstab</code> file and possibly the <code>rc.sysinit</code> file, so that the volumes are mounted automatically at boot time.  It may also be necessary to setup an initial ramdisk for booting (if the &#8220;root&#8221; filesystem is built on a logical volume).</p>
</div>
<div><a name="UseSnap"></a>&nbsp;</p>
<h3>Create and Use a Snapshot</h3>
</div>
<div>
<p>To create a snapshot of some existing LV, a form of the <code>lvcreate</code> command is used:</p>
<pre>root# <strong>lvcreate <em>size</em> <em>option</em> -s -n <em>name</em> <em>existing_LV</em></strong></pre>
<p>where <em>size</em> is as discussed <a href="http://content.hccfl.edu/pollock/AUnix1/LVM.htm#size">previously</a>, &#8220;<code>-s</code>&#8221; (or &#8220;<code>--snapshot</code>&#8220;) indicates a snapshot LV, &#8220;<code>-n <em>name</em></code>&#8221; (or &#8220;<code>--name <em>name</em></code>&#8220;) says to call the snapshot LV <em>name</em>.  The only option allowed is &#8220;<code>-c <em>chunk_size</em></code>&#8221; (or &#8220;<code>--chunksize <em>chunk_size</em></code>&#8220;), where <em>chunk_size</em> is specified as a power of 2 in this formula: <code>(2^<em>chunk_size</em>) × 1024 bytes</code>, where 2 ≤ <code><em>chunk_size</em></code> ≤ 10.)</p>
<p>Suppose you have a volume group VG1 with a logical volume LV1 you wish to backup using a snapshot.  you can estimate the time the backup will take, and the amount of disk writes that will take place during that time (plus a generous fudge factor), say 300MB.  Then you would run the command:</p>
<pre>root# <strong>lvcreate -l 300m -s -n backup LV1</strong></pre>
<p>to create a snapshot logical volume named <code>/dev/VG1/backup</code> which has read-only access to the contents of the original logical volume named <code>/dev/VG1/LV1</code> at point in time the snapshot was created.  Assuming the original logical volume contains a file system you now <code>mount</code> the snapshot logical volume on some (empty) directory, then backup the mounted snapshot while the original filesystem continues to get updated.  When finished, unmount the snapshot and delete it (or it will continue to grow as LV1 changes, and eventually run out of space).</p>
<p>Note:  If the snapshot is of an XFS filesystem, the <code>xfs_freeze</code> command should be used to quiesce the filesystem before creating the snapshot (if the filesystem is mounted):</p>
<pre>/root# <strong>xfs_freeze -f /mnt/point;</strong>
/root# <strong>lvcreate -L 300M -s -n backup /dev/VG1/LV1</strong>
/root# <strong>xfs_freeze -u /mnt/point</strong>
Warning	Full snapshot are automatically disabled</pre>
<p>Now create a mount-point (an empty directory) and mount the volume:</p>
<pre>/root# <strong>mkdir /mnt/dbbackup</strong>
/root# <strong>mount /dev/VG1/backup /mnt/dbbackup</strong>
mount: block device /dev/ops/dbbackup is write-protected, mounting read-only</pre>
<p>If you are using XFS as the filesystem you will need to add the &#8220;nouuid&#8221; option to the mount command as follows:</p>
<pre>/root# <strong>mount /dev/VG1/backup /mnt/dbbackup -o nouuid,ro</strong></pre>
<p>Do the backup, say by using <code>tar</code> to some &#8220;DDS4&#8243; or &#8220;DAT&#8221; tape backup device:</p>
<pre>/root# <strong>tar -cf /dev/rmt0 /mnt/dbbackup</strong>
tar: Removing leading `/' from member names</pre>
<p>When the backup has finished you unmount the volume and remove it from the system:</p>
<pre>root# <strong>umount /mnt/dbbackup</strong>
root# <strong>lvremove /dev/VG1/backup</strong>
lvremove -- do you really want to remove "/dev/VG1/backup"? [y/n]: <strong>y</strong>
lvremove -- doing automatic backup of volume group "VG1"
lvremove -- logical volume "/dev/VG1/backup" successfully removed</pre>
</div>
<div><a name="Info"></a>&nbsp;</p>
<h3>Examining LVM Information</h3>
</div>
<div>
<p>To see information about some VG use:</p>
<pre>vgdisplay <em>some_volume_group</em>
vgs <em>some_volume_group</em></pre>
<p>To see information about some PV use the command:</p>
<pre>pvdisplay <em>some_disk_or_partition</em> # e.g., /dev/hda1
pvs <em>some_disk_or_partition</em></pre>
<p>To see information about some LV use:</p>
<pre>lvdisplay <em>some-logical-volume</em>
lvs <em>some-logical-volume</em></pre>
<p>The man pages for these commands provides further details.</p>
</div>
<div><a name="Grow"></a>&nbsp;</p>
<h3>Grow VGs, LVs, and Filesystems</h3>
</div>
<div>
<p>To grow a filesystem, you must install a new hard disk (unless you have free space available), format it as a PV,add that PV to your VG, then add the space to your LV, and finally use the filesystem tools to grow it.  (Not all filesystem allow or come with tools to grow and shrink them!)</p>
<p>VGs are resizable (spelled in Linux as &#8220;resizeable&#8221;) by adding or removing PVs from them.  However by default they are created as fixed in size.  To mark a VG as resizable use the command:</p>
<pre>root# <strong>vgchange -x y  #or --resizeable y</strong></pre>
<p>Once this is done add a PV (say &#8220;hdb2&#8243;) to some VG (say &#8220;VG1&#8243;) with the command:</p>
<pre>root# <strong>vgextend VG1 /dev/hdb2</strong></pre>
<p>Next, extend an LV with the &#8220;<code>lvextend</code>&#8221; command.  This command works almost the same as the &#8220;<code>lvcreate</code>&#8221; command, but with a few different options.  When specifying how much to increase the size of the LV, you can either specify how much to grow the LV with &#8220;+<em>size</em>&#8221; or you can specify the new (absolute) size (by omitting the plus sign).  So to extend the LV &#8220;LV1&#8243; on VG &#8220;VG1&#8243; by 2GB, use:</p>
<pre>root# <strong>lvextend -L +2G /dev/VG1/LV1</strong></pre>
<p>You could also use:</p>
<pre>root# <strong>lvresize -L +2G /dev/VG1/LV1</strong></pre>
<p>It would be a good idea to use the same <a href="http://content.hccfl.edu/pollock/AUnix1/LVM.htm#Mapping">mapping</a> as the original LV, or you will have strange performance issues!  Also note this command can be used to extend a snapshot volume if necessary.</p>
<p>After you have extended the logical volume the last step is to increase the file system size.  How you do this depends on the file system you are using.  Most filesystem types come with their own utilities to grow/shrink filesystems, if they allow that.  These utilities usually grow to fill the entire partition or LV, so there is no need to specify the filesystem size.</p>
<p>Some common filesystem utilities are (assume we are expanding the <code>/home</code> filesystem in LV1 on VG1):</p>
<ul>
<li> EXT2 and EXT3:<br />
EXT2/3 filesystems must be unmounted before they can be resized.       The commands to use are:&nbsp;</p>
<pre>root# <strong>umount /home</strong> # /home is the mount point for /dev/VG1/LV1
root# <strong>fsck -f /home</strong> # required!
root# <strong>resize2fs /dev/VG1/LV1</strong> # grow FS to fill LV1.
root# <strong>mount /home</strong></pre>
</li>
<li> Reiserfs:<br />
The Reiserfs file system can be safely resized while mounted.       If unmounted resizing is preferred, first <code>umount</code> and afterward <code>mount</code> the filesystem.       For online resizing just use:&nbsp;</p>
<pre>root# <strong>resize_reiserfs -f /dev/VG1/LV1</strong></pre>
</li>
<li> XFS:<br />
The XFS file systems must be mounted to be resized,      and the mount-point is specified rather than the device name:&nbsp;</p>
<pre>root# <strong>xfs_growfs /home</strong></pre>
</li>
<li> JFS:<br />
Like XFS, the JFS file system must be mounted to be resized      and the mount-point is specified rather than the device name.       JFS doesn&#8217;t have a special utility for resizing, but the      <code>mount</code> command has an option that can be used:&nbsp;</p>
<pre>root# <strong>mount -o remount,resize /home</strong></pre>
<p>In some cases the exact number of blocks must be specified.  (A kernel bug in some older Linux versions prevents the LV size from being determined automatically.)  For example to resize a JFS file system that has a 4KB block size (the default) to 4GB, you must use 1M 4KB-blocks.  Now &#8220;1M&#8221; is 2 raised to the power of 20 (=1048576), so use:</p>
<pre>root# <strong>mount -o remount,resize=1048576 /home</strong></pre>
</li>
</ul>
</div>
<div><a name="Shrink"></a>&nbsp;</p>
<h3>Shrink VGs, LVs, and Filesystems</h3>
</div>
<div>
<p>To shrink a filesystem, you perform the same steps for growing one but in reverse order.  You first shrink the filesystem, then remove the space from the LV (and put it back into the VG).  Other LVs in the same VG can now use that space.  To use it in another VG, you must remove the corresponding PV from the one VG and add it to the other VG.</p>
<p>To shrink a LV you must first shrink the filesystem in that LV.  This can be done with the <code>resize2fs</code> for EXT2/3, or <code>resize_reiserfs</code> for ReiserFS (doing this off-line is safer but not required).  There are similar tools for other filesystem types.  Here&#8217;s an example of shrinking <code>/home</code> by 1 GB:</p>
<pre># <strong>df</strong>
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1             145M   16M  122M  12% /boot
/dev/mapper/vg01-lv01  49G  3.7G   42G   9% /home
...
# <strong>umount /home</strong>
# <strong>fsck -f /home</strong> # required!
fsck 1.38 (30-Jun-2005)
e2fsck 1.38 (30-Jun-2005)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/home: 32503/6406144 files (0.3% non-contiguous), 1160448/12845056 blocks
# <strong>resize2fs -p /dev/vg01/lv01 48G</strong>
resize2fs 1.38 (30-Jun-2005)
Resizing the filesystem on /dev/vg01/lv01 to 12799788 (4k) blocks.
Begin pass 3 (max = 9)
Scanning inode table          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/vg01/lv01 is now 12799788 blocks long.</pre>
<p>Currently XFS and JFS filesystem types do not support shrinking.  If a newer version of these filesystems will support this, <code>mount</code> may have been updated to support these filesystem types.  (And if not a new tool may be released.)  For such filesystems you can resize them the hard way: Backup the data using some archive tool (e.g., <code>cpio</code>, <code>tar</code>, <code>star</code>, or you can copy the data to some other disk).  Then delete the filesystem in the LV, then shrink the LV, then recreate the new (smaller) filesystem, and finally restore the data.</p>
<p>Once the filesystem has been shrunk it is time to shrink the logical volume.  You can use either the <code>lvreduce</code> command or the <code>lvresize</code> command.  Continuing from the example above:</p>
<pre># <strong>lvresize -L -1G /dev/vg01/lv01</strong>
  Rounding up size to full physical extent 96.00 MB
  WARNING: Reducing active logical volume to 48 GB
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce lv01? [y/n]: <strong>y</strong>
  Reducing logical volume lv01 to 48 GB
  Logical volume lv01 successfully resized
# <strong>mount /home</strong></pre>
<p>To shrink a VG (say &#8220;<code>VG1</code>&#8220;), a PV (say &#8220;<code>hdc</code>&#8220;) can be removed from it if none of that PV&#8217;s extents (the PEs) are in use by any LV.  Run the command:</p>
<pre>root# <strong>vgreduce VG1 /dev/hdc</strong></pre>
<p>You might want to do this to upgrade or replace a worn-out disk.  If the PV is in use by some LV, you must first migrate the data to another available PV within the same VG.  To move all the data from a PV (say &#8220;<code>hdb2</code>&#8220;) to any unused, large enough PV within that VG, use the command:</p>
<pre>root# <strong>pvmove /dev/hdb2</strong></pre>
</div>
<div><a name="Delete"></a>&nbsp;</p>
<h3>Delete LVs and VGs</h3>
</div>
<div>
<p>A logical volume (say &#8220;<code>LV3</code>&#8221; on the volume group &#8220;<code>VG2</code>&#8220;) must be unmounted before it can be removed.  The steps for this are simple:</p>
<pre>root# <strong>umount /dev/VG2/LV3</strong>
root# <strong>lvremove /dev/VG2/LV3</strong></pre>
<p>Before a volume group (say &#8220;<code>VG2</code>&#8220;) is removed you must first <em>deactivate</em> it.  This is done with the command:</p>
<pre>root# <strong>vgchange -a n VG2</strong></pre>
<p>Now the VG can be removed.  This of course will destroy all LVs within it.  The various PVs that made up that VG can then be re-assigned to some other VGs.  Remove (a non-active) volume group with:</p>
<pre>root# <strong>vgremove VG2</strong></pre>
</div>
<div><a name="Summary"></a>&nbsp;</p>
<h2>Summary and Examples</h2>
</div>
<div>
<p>In the following examples assume that LVM2 is installed and up to date, and the boot scripts have been modified already if needed.  The first example includes some commentary and some command output; the second is much shorter but uses the long option names just for fun.</p>
<h3>Home directory Example</h3>
<p>In this example we will create a logical volume to hold the &#8220;<code>/home</code>&#8221; partition for a multi-media development system.  The system will use a standard EXT3 filesystem of 60 GB, built using 3 25GB SCSI disks (and no hardware RAID).  Since multi-media uses large files it makes sense to use stripe mapping and read-ahead.  We will call the volume group &#8220;<code>vg1</code>&#8221; and the logical volume &#8220;<code>home</code>&#8220;:</p>
<ol>
<li> Initialize the disks as PVs:<br />
/root# <strong>pvcreate /dev/sda /dev/sdb /dev/sdc</strong></li>
<li> Create a Volume Group, then check it&#8217;s size:
<pre>/root# <strong>vgcreate vg1 /dev/sda /dev/sdb /dev/sdc</strong>
/root# <strong>vgdisplay</strong>
vgdisplay
--- Volume Group ---
VG Name	          vg1
VG Access             read/write
VG Status             available/resizable
VG #                  1
MAX LV                256
Cur LV                0
Open LV               0
MAX LV Size           255.99 GB
Max PV                256
Cur PV                3
Act PV                3
VG Size               73.45 GB
PE Size               4 MB
Total PE              18803
Alloc PE / Size       0 / 0
Free  PE / Size       18803/ 73.45 GB
VG UUID               nP2PY5-5TOS-hLx0-FDu0-2a6N-f37x-0BME0Y</pre>
</li>
<li> Create a 60 GB logical volume, with stripe set of 3 PVs      and stripe size of 4 (which shows 2^4 KB = 16KB):
<pre>/root# <strong>lvcreate -i 3 -I 4 -L 60G -n home vg1</strong>
lvcreate -- rounding 62614560 KB to stripe boundary size 62614560 KB / 18803 PE
lvcreate -- doing automatic backup of "vg1"
lvcreate -- logical volume "/dev/vg1/home" successfully created</pre>
</li>
<li> Create an EXT3 filesystem in the new LV:
<pre>/root# <strong>mkfs -t ext3 /dev/vg1/home</strong></pre>
</li>
<li> Test the new FS:
<pre>/root# <strong>mount /dev/vg1/home /mnt</strong>
/root# <strong>df | grep /mnt</strong>
/root# <strong>umount /dev/vg1/home</strong></pre>
</li>
<li> Update <code>/etc/fstab</code> with the revised entry for      <code>/home</code>.</li>
<li> Finally, don&#8217;t forget to update the system journal.</li>
</ol>
<h3>Oracle Database Example</h3>
<p>In this example we will create 2 LVs for an Oracle database.  Oracle manages its own striping and read-head/caching, so we won&#8217;t use these LVM features.  However using hardware RAID <em>is</em> useful, so we will use two RAID 10 disks, <code>hdb</code> and <code>hdc</code>.  The tables will use one logical volume called &#8220;<code>tables</code>&#8221; on one disk and the indexes and control files will be on a second LV called &#8220;<code>indexes</code>&#8221; on the other disk.  Both LVs will exist in the VG called &#8220;<code>db</code>&#8220;.  Both filesystems will be XFS, for good performance for large database files:</p>
<pre>/root# <strong>pvcreate /dev/hdb /dev/hdc</strong>
/root# <strong>vgcreate db /dev/hdb /dev/hdc</strong>
/root# <strong>lvcreate --size 200G --name tables db</strong>
/root# <strong>lvcreate --size 200G --name indexes db</strong>
/root# <strong>mkfs -t xfs /dev/db/tables</strong>
/root# <strong>mkfs -t xfs /dev/db/indexes</strong>
/root# <strong>vi /etc/fstab</strong>
/root# <strong>vi ~/system-journal</strong></pre>
</div>
<div>
<p>&nbsp;</p>
<hr />
<table border="0" cellspacing="0" cellpadding="0" width="100%" summary="Page Footer with contact info and approval icons">
<caption> </caption>
<tbody>
<tr>
<td>Send comments and questions to <a href="mailto:pollock@acm.org?subject=Unix/Linux%20Admin%20Question%3A%20LVM">pollock@acm.org</a><br />
<em> Last updated by Wayne Pollock on 09/26/2011 03:08:38.</em></td>
<td align="right"><a title="Check the validity of this site’s HTML (AccessKey: H)" accesskey="h" href="http://validator.w3.org/check/referer?verbose=1"> <img id="htmlLogo" src="http://content.hccfl.edu/pollock/images/valid-html401.gif" alt="Valid HTML 4.01!" /></a> <a title="Check the validity of this site’s CSS (AccessKey: C)" accesskey="c" href="http://jigsaw.w3.org/css-validator/check/referer?profile=css3&amp;usermedium=all&amp;warning=1&amp;lang=en"> <img id="cssLogo" src="http://content.hccfl.edu/pollock/images/vcss.gif" alt="Valid CSS!" /></a> <a title="WAI Content Accessibility Guidelines 1 tested with CynthiaSays.com (AccessKey: A)" tabindex="0" accesskey="a" href="http://www.cynthiasays.com/mynewtester/cynthia.exe?Url1=http://content.hccfl.edu/pollock/AUnix1/LVM.htm&amp;rptmode=2"> <img id="aaaLogo" src="http://content.hccfl.edu/pollock/images/wcag1AAA.gif" alt="Website accessibility rating WCAG 1.0 AAA Approved by Cynthia Says" /></a> <a title="U.S. Section 508 accessibility Guidelines tested with CynthiaSays.com (AccessKey: 5)" tabindex="0" accesskey="5" href="http://www.cynthiasays.com/mynewtester/cynthia.exe?Url1=http://content.hccfl.edu/pollock/AUnix1/LVM.htm&amp;rptmode=-1"> <img id="sec508Logo" src="http://content.hccfl.edu/pollock/images/508-button.jpg" alt="Website accessibility rating Section 508 approved by Cynthia Says" /></a></td>
</tr>
</tbody>
</table>
</div>
]]></content:encoded>
			<wfw:commentRss>http://michael-george-hart.com/2010-11-27/2011/09/26/unixlinux-administration-logical-volume-management-guide/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bonds</title>
		<link>http://michael-george-hart.com/2010-11-27/2011/09/19/bonds/</link>
		<comments>http://michael-george-hart.com/2010-11-27/2011/09/19/bonds/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 14:16:09 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Language of Business]]></category>

		<guid isPermaLink="false">http://michael-george-hart.com/2010-11-27/?p=427</guid>
		<description><![CDATA[Bonds are loans that investors make to corporation and goverments. The borrowers get the cash they need while the lender earn interest. Has fixed maturity date when the bond expires and the loan must be paid back in full at &#8230; <a href="http://michael-george-hart.com/2010-11-27/2011/09/19/bonds/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Bonds are loans that investors make to corporation and goverments. The borrowers get the cash they need while the lender earn interest.</p>
<p>Has fixed maturity date when the bond expires and the loan must be paid back in full at par value.</p>
<p>The interest a bond pays is also set when the bond is issued.</p>
<p>Investors can buy bonds issued by U.S. companies, by the U.S. Treasury, by various cities and states and various federal, state and local goverment agencies.  Many overseas companies and goverments also sell bonds to U.S. inverstors. When those bonds are sold in dollars rather than the currency of the issuing country, they&#8217;re sometimes know as yankee bonds.</p>
<p>The life, or term, of any bond is fixed at the time of issue. It can range from short-term (usually a year of less), to intermediate-term(two to ten years), to long-term(30 years or more)</p>
<p>The relationship between the interest rates paid on short-term and long-term bonds is called the yield curve</p>
<p>People try to make money on bonds by trading them because of interest rate fluctuation</p>
<p>The value of a bond is determined by the interest it pays and what&#8217;t happening in the economy.</p>
<p>If the bond inversto buys at par, and holds the bond to maturity, inflation (or the shrinking value of the dollar) is the worst enemy. The longer the maturity of the bond, the greater this risk that at some point inflation will rise dramatically and reduce the value of the dolllars that the invertor is repaid.</p>
<p>The bond prices fluctuate according to the interest rate the bond pays, the degree of certainty of repayment and the overall economic conditions  &#8211;especially the rate of inflation&#8211; which influence interest rates.</p>
<p>Generally, when inflation is up, interest rates go up. And conversely, when inflation is low, so are interest rates.</p>
<p>The Yield of a bond is what you actually earn. Most charts express current yield as a percentage; that is if you have a bond that pays n%, it means your interest payments will be n% of the what you pay for the bond.</p>
<p>The formula for yield is (annual interest)/(price paid)</p>
]]></content:encoded>
			<wfw:commentRss>http://michael-george-hart.com/2010-11-27/2011/09/19/bonds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenMP fast track</title>
		<link>http://michael-george-hart.com/2010-11-27/2011/08/11/openmp-fast-track/</link>
		<comments>http://michael-george-hart.com/2010-11-27/2011/08/11/openmp-fast-track/#comments</comments>
		<pubDate>Thu, 11 Aug 2011 18:59:24 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[openMP]]></category>

		<guid isPermaLink="false">http://michael-george-hart.com/2010-11-27/?p=420</guid>
		<description><![CDATA[Ripped from the page &#8221;Guide into OpenMP: Easy multithreading programming for C++&#8221; By Joel Yliluoma, September 2007; last update in December 2008 Abstract This document attempts to give a quick introduction to OpenMP (as of version 3.0), a simple C/C++/Fortran compiler &#8230; <a href="http://michael-george-hart.com/2010-11-27/2011/08/11/openmp-fast-track/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ripped from the page &#8221;<a href="http://bisqwit.iki.fi/story/howto/openmp/" target="_blank">Guide into OpenMP: Easy multithreading programming for C++</a>&#8221;</p>
<p><small>By <a id="i1EE48DDA" href="http://iki.fi/bisqwit/">Joel Yliluoma</a>, September 2007; last update in December 2008</small></p>
<h2><a name="Abstract"></a>Abstract</h2>
<div>This document attempts to give a quick introduction to <a id="i43463F8" href="http://www.openmp.org/">OpenMP</a> (as of version 3.0), a simple C/C++/Fortran compiler extension that allows to add parallelism into existing source code without significantly having to rewrite it.In this document, we concentrate on the GCC compiler and the C++ language in particular. However, other compilers and languages supporting OpenMP also exist.This document covers OpenMP 3.0, but because version 2.5 is more commonly supported than 3.0, we also place emphasis on version 2.5.</div>
<div>Table of contents [expand all] [collapse all]</div>
<ul id="wikitoc1">
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Abstract">Abstract </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#PrefaceImportanceOfMultithreading">Preface: Importance of multithreading </a>
<ul>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#SupportInDifferentCompilers">Support in different compilers </a></li>
</ul>
</li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#IntroductionToOpenmpInC">Introduction to OpenMP in C++ </a>
<ul>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#ExampleInitializingATableInParallel">Example: Initializing a table in parallel </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#ExampleCalculatingTheMandelbrotFractalInParallel">Example: Calculating the Mandelbrot fractal in parallel </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Discussion">Discussion </a></li>
</ul>
</li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Syntax">The syntax </a>
<ul>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#ParallelPragma">The <tt>parallel</tt> pragma </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#LoopDirectiveFor">Loop directive: <tt>for</tt> </a>
<ul>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#WhatAreParallelForAndATeam">What are: <tt>parallel</tt>, <tt>for</tt> and a team </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Scheduling">Scheduling </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Ordering">Ordering </a></li>
</ul>
</li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Sections">Sections </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#TaskDirectiveOpenmp 3 0Only">The <tt>task</tt> directive (OpenMP 3.0 only) </a></li>
</ul>
</li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#ThreadSafetyIEMutualExclusion">Thread-safety (i.e. mutual exclusion) </a>
<ul>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Atomicity">Atomicity </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#CriticalDirective">The <tt>critical</tt> directive </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Locks">Locks </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#FlushDirective">The <tt>flush</tt> directive </a></li>
</ul>
</li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#ControllingWhichDataToShareBetweenThreads">Controlling which data to share between threads </a>
<ul>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#PrivateFirstprivateAndSharedClauses">The <tt>private</tt>, <tt>firstprivate</tt> and <tt>shared</tt> clauses </a>
<ul>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#DifferenceBetweenPrivateAndFirstprivate">The difference between <tt>private</tt> and <tt>firstprivate</tt> </a></li>
</ul>
</li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#LastprivateClause">The <tt>lastprivate</tt> clause </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#DefaultClause">The <tt>default</tt> clause </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#ReductionClause">The <tt>reduction</tt> clause </a></li>
</ul>
</li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#ExecutionSynchronization">Execution synchronization </a>
<ul>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#BarrierDirectiveAndTheNowaitClause">The <tt>barrier</tt> directive and the <tt>nowait</tt> clause </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#SingleAndMasterDirectives">The <tt>single</tt> and <tt>master</tt> directives </a></li>
</ul>
</li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#LoopNesting">Loop nesting </a>
<ul>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Problem">The problem </a>
<ul>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#SolutionInOpenmp 3 0">Solution in OpenMP 3.0 </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#WorkaroundsInOpenmp 2 5">Workarounds in OpenMP 2.5 </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Performance">Performance </a></li>
</ul>
</li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Restrictions">Restrictions </a></li>
</ul>
</li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Shortcomings">Shortcomings </a>
<ul>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#OpenmpAndFork">OpenMP and fork() </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#CancellingOfThreadsAndBreakingOutOfLoops">Cancelling of threads (and breaking out of loops) </a></li>
</ul>
</li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#SomeSpecificGotchas">Some specific gotchas </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#Other">Other </a></li>
<li> <a href="http://bisqwit.iki.fi/story/howto/openmp/#FurtherReading">Further reading </a></li>
</ul>
<h2><a name="PrefaceImportanceOfMultithreading"></a>Preface: Importance of multithreading</h2>
<div>As CPU speeds no longer improve as significantly as they did before, multicore systems are becoming more popular.To harness that power, it is becoming important for programmers to be knowledgeable in parallel programming — making a program execute multiple things simultaneously.This document attempts to give a quick introduction to <a id="i43463F8" href="http://www.openmp.org/">OpenMP</a>, a simple C/C++/Fortran compiler extension that allows to add parallelism into existing source code without significantly having to entirely rewrite it.In this document, we concentrate on the GCC compiler and the C++ language in particular. However, other compilers and languages supporting OpenMP also exist.</div>
<h3><a name="SupportInDifferentCompilers"></a>Support in different compilers</h3>
<div>
<ul>
<li>OpenMP 2.5 is supported by the GNU Compiler Collection (GCC) since version 4.2. Add the commandline option <tt>-fopenmp</tt> to enable it.</li>
<li>OpenMP 3.0 is supported by the GNU Compiler Collection (GCC) since version 4.4. Add the commandline option <tt>-fopenmp</tt> to enable it.</li>
<li>OpenMP 2.5 is supported by Microsoft Visual C++ 2005 (cl). Add the commandline option <tt>/openmp</tt> to enable it.</li>
<li>OpenMP 2.5 is supported by Intel C Compiler (icc) since version 10.1. Add the commandline option <tt>-openmp</tt> to enable it. Add the <tt>-openmp-stubs</tt> option instead to enable the library without actual parallel execution.</li>
<li>OpenMP 3.0 is supported by Intel C Compiler (icc) since version 11.0. Add the commandline option <tt>-openmp</tt> to enable it. Add the <tt>-openmp-stubs</tt> option instead to enable the library without actual parallel execution.</li>
</ul>
<p>Note: If your GCC complains that &#8220;-fopenmp&#8221; is valid for D but not for C++ when you try to use it, or does not recognize the option at all, your GCC version is too old. If your linker complains about missing GOMP functions, you forgot to specify &#8220;-fopenmp&#8221; in the linking.More information: <a id="iA546AB2C" href="http://openmp.org/wp/openmp-compilers/">http://openmp.org/wp/openmp-compilers/</a></p>
</div>
<h2><a name="IntroductionToOpenmpInC"></a>Introduction to OpenMP in C++</h2>
<div>OpenMP consists of a set of compiler <tt>#pragma</tt>s that control how the program works. The pragmas are designed so that even if the compiler does not support them, the program will still yield correct behavior, but without any parallelism.Here are two simple example programs demonstrating OpenMP.You can compile them like this:</div>
<pre>  g++ tmp.cpp -fopenmp</pre>
<h3><a name="ExampleInitializingATableInParallel"></a>Example: Initializing a table in parallel</h3>
<div>
<pre>  #include &lt;cmath&gt;
  int main()
  {
    const int size = 256;
    double sinTable[size];

    #pragma omp parallel for
    for(int n=0; n&lt;size; ++n)
      sinTable[n] = std::sin(2 * M_PI * n / size);

    // the table is now initialized
  }</pre>
</div>
<h3><a name="ExampleCalculatingTheMandelbrotFractalInParallel"></a>Example: Calculating the Mandelbrot fractal in parallel</h3>
<div>This program calculates the classic <a id="i16BA8AAA" href="http://en.wikipedia.org/wiki/Mandelbrot_fractal">Mandelbrot fractal</a> at a low resolution and renders it with ASCII characters, calculating multiple pixels in parallel.</div>
<pre> #include &lt;complex&gt;
 #include &lt;cstdio&gt;

 typedef std::complex&lt;double&gt; complex;

 int MandelbrotCalculate(complex c, int maxiter)
 {
     // iterates z = z² + c until |z| &gt;= 2 or maxiter is reached,
     // returns the number of iterations.
     complex z = c;
     int n=0;
     for(; n&lt;maxiter; ++n)
     {
         if( std::abs(z) &gt;= 2.0) break;
         z = z*z + c;
     }
     return n;
 }
 int main()
 {
     const int width = 78, height = 44, num_pixels = width*height;

     const complex center(-.7, 0), span(2.7, -(4/3.0)*2.7*height/width);
     const complex begin = center-span/2.0, end = center+span/2.0;
     const int maxiter = 100000;

   #pragma omp parallel for ordered schedule(dynamic)
     for(int pix=0; pix&lt;num_pixels; ++pix)
     {
         const int x = pix%width, y = pix/width;

         complex c = begin + complex(x * span.real() / (width +1.0),
                                     y * span.imag() / (height+1.0));

         int n = MandelbrotCalculate(c, maxiter);
         if(n == maxiter) n = 0;

       #pragma omp ordered
         {
           char c = ' ';
           if(n &gt; 0)
           {
               static const char charset[] = ".,c8M@jawrpogOQEPGJ";
               c = charset[n % (sizeof(charset)-1)];
           }
           std::putchar(c);
           if(x+1 == width) std::puts("|");
         }
     }
 }</pre>
<p>(There are a multitude of ways this program can be improved but that is beside the point.)</p>
<h3><a name="Discussion"></a>Discussion</h3>
<div>As you can see, there is very little in the program that indicates that it runs in parallel. If you remove the <tt>#pragma</tt> lines, the result is still a valid C++ program that runs and does the expected thing.Only when the compiler interprets those <tt>#pragma</tt> lines, it becomes a parallel program. It really does calculate N values simultaneously where N is the number of threads. In GCC, libgomp determines that from the number of processors.By C and C++ standards, if the compiler encounters a <tt>#pragma</tt> that it does not support, it will ignore it. So adding the OMP statements can be done safely<a name="r1"></a><sup>[<a href="http://bisqwit.iki.fi/story/howto/openmp/#1">1</a>]</sup> without breaking compatibility with legacy compilers.There is also a runtime library that can be accessed through <tt>omp.h</tt>, but it is less often needed. If you need it, you can check the #define <tt>_OPENMP</tt> for conditional compilation in case of compilers that don&#8217;t support OpenMP.[<a name="1"></a><a href="http://bisqwit.iki.fi/story/howto/openmp/#r1">1</a>]: Within the usual parallel programming issues (concurrency, mutual exclusion) of course.</div>
<h2><a name="Syntax"></a>The syntax</h2>
<div>All OpenMP directives in C and C++ are indicated with a <tt>#pragma omp</tt> followed by parameters, ending in a newline. The pragma usually applies only into the statement immediately following it, except for the <tt>barrier</tt> and <tt>flush</tt> commands, which do not have associated statements.</div>
<h3><a name="ParallelPragma"></a>The <tt>parallel</tt> pragma</h3>
<div>The parallel pragma starts a parallel block. It creates a <em>team</em> of N threads (where N is determined at runtime, usually from the number of CPU cores, but may be affected by a few things), all of which execute the next statement (or the next block, if the statement is a {…} -enclosure). After the statement, the threads join back into one.</div>
<pre>  #pragma omp parallel
  {
    // Code inside this region runs in parallel.
    printf("Hello!\n");
  }</pre>
<p>This example prints the text &#8220;Hello!&#8221; followed by a newline as many times as there are threads in the team created. For a dual-core system, it will output the text twice. (Note: It may also output something like &#8220;HeHlellolo&#8221;, depending on system, because the printing happens in parallel.)Internally, GCC implements this by creating a magic function and moving the associated code into that function, so that all the variables declared within that block become local variables of that function (and thus, locals to each thread).<br />
ICC, on the other hand, uses a mechanism resembling <tt>fork()</tt>, and does not create a magic function. Both implementations are, of course, valid, and semantically identical.Variables shared from the context are handled transparently, sometimes by passing a reference and sometimes by using register variables which are flushed at the end of the parallel block (or whenever a <tt>flush</tt> is executed).The parallelism can be made <em>conditional</em> by including a <tt>if</tt> clause in the parallel command, such as:</p>
<pre>  extern int parallelism_enabled;
  #pragma omp parallel for if(parallelism_enabled)
  for(int c=0; c&lt;n; ++c)
    handle(c);</pre>
<p>In this case, if <tt>parallelism_enabled</tt> evaluates to a zero value, the number of threads in the team that processes the <tt>for</tt> loop will always be exactly one.</p>
<h3><a name="LoopDirectiveFor"></a>Loop directive: <tt>for</tt></h3>
<div>The <tt>for</tt> directive splits the for-loop so that each thread in the current team handles a different portion of the loop.</div>
<pre> #pragma omp for
 for(int n=0; n&lt;10; ++n)
 {
   printf(" %d", n);
 }
 printf(".\n");</pre>
<p>This loop will output each number from 0…9 once. However, it does not do so necessarily in order. It may output, for example:</p>
<pre>  0 5 6 7 1 8 2 3 4 9.</pre>
<p>Internally, the above loop becomes into code equivalent to this:</p>
<pre>  int this_thread = omp_get_thread_num(), num_threads = omp_get_num_threads();
  int my_start = (this_thread  ) * 10 / num_threads;
  int my_end   = (this_thread+1) * 10 / num_threads;
  for(int n=my_start; n&lt;my_end; ++n)
    printf(" %d", n);</pre>
<p>So each thread gets a different section of the loop, and they execute their own sections in parallel.Note: <tt>#pragma omp for</tt> only delegates portions of the loop for different threads in the <em>current team</em>. A <em>team</em> is the group of threads executing the program. At program start, the team consists only of a single member: the master thread that runs the program.To create a new team of threads, you need to specify the <tt>parallel</tt> keyword. It can be specified in the surrounding context:</p>
<pre> #pragma omp parallel
 {
  #pragma omp for
  for(int n=0; n&lt;10; ++n) printf(" %d", n);
 }
 printf(".\n");</pre>
<p>Equivalent shorthand is to specify it in the pragma itself, as <tt>#pragma omp parallel for</tt>:</p>
<pre> #pragma omp parallel for
 for(int n=0; n&lt;10; ++n) printf(" %d", n);
 printf(".\n");</pre>
<p>You can explicitly specify the number of threads to be created in the team, using the <tt>num_threads</tt> attribute:</p>
<pre> #pragma omp parallel num_threads(3)
 {
   // This code will be executed by three threads.

   // Chunks of this loop will be divided amongst
   // the (three) threads of the current team.
   #pragma omp for
   for(int n=0; n&lt;10; ++n) printf(" %d", n);
 }</pre>
<p>Note that OpenMP also works for C. However, in C, you need to set explicitly the loop variable as <tt>private</tt>, because C does not allow declaring it in the loop body:</p>
<pre> int n;
 #pragma omp for private(n)
 for(n=0; n&lt;10; ++n) printf(" %d", n);
 printf(".\n");</pre>
<p>See the &#8220;private and shared clauses&#8221; section for details.In OpenMP 2.5, the iteration variable in <tt>for</tt> must be a signed integer variable type. In OpenMP 3.0, it may also be an unsigned integer variable type, a pointer type or a constant-time random access iterator type. In the latter case, <tt>std::distance()</tt> will be used to determine the number of loop iterations.</p>
<h4><a name="WhatAreParallelForAndATeam"></a>What are: <tt>parallel</tt>, <tt>for</tt> and a team</h4>
<div>The difference between <tt>parallel</tt>, <tt>parallel for</tt> and <tt>for</tt> is as follows:</div>
<ul>
<li>A team is the group of threads that execute currently.
<ul>
<li>At the program beginning, the team consists of a single thread.</li>
<li>A <tt>parallel</tt> directive splits the current thread into <em>a new team</em> of threads for the duration of the next block/statement, after which the team merges back into one.</li>
</ul>
</li>
<li><tt>for</tt> divides the work of the for-loop among the threads of the <em>current team</em>. It does not create threads, it only divides the work amongst the threads of the currently executing team.</li>
<li><tt>parallel for</tt> is a shorthand for two commands at once: <tt>parallel</tt> and <tt>for</tt>. Parallel creates a new team, and <tt>for</tt> splits that team to handle different portions of the loop.</li>
</ul>
<p>If your program never contains a <tt>parallel</tt> directive, there is never more than one thread; the master thread that starts the program and runs it, as in non-threading programs.</p>
<h4><a name="Scheduling"></a>Scheduling</h4>
<div>The scheduling algorithm for the for-loop can explicitly controlled.</div>
<pre> #pragma omp for schedule(static)
 for(int n=0; n&lt;10; ++n) printf(" %d", n);
 printf(".\n");</pre>
<p><tt>static</tt> is the default schedule as shown above. Upon entering the loop, each thread independently decides which chunk of the loop they will process.There is also the <tt>dynamic</tt> schedule:</p>
<pre> #pragma omp for schedule(dynamic)
 for(int n=0; n&lt;10; ++n) printf(" %d", n);
 printf(".\n");</pre>
<p>In the dynamic schedule, there is no predictable order in which the loop items are assigned to different threads. Each thread asks the OpenMP runtime library for an iteration number, then handles it, then asks for next, and so on. This is most useful when used in conjunction with the <tt>ordered</tt> clause, or when the different iterations in the loop may take different time to execute.The chunk size can also be specified to lessen the number of calls to the runtime library:</p>
<pre> #pragma omp for schedule(dynamic, 3)
 for(int n=0; n&lt;10; ++n) printf(" %d", n);
 printf(".\n");</pre>
<p>In this example, each thread asks for an iteration number, executes 3 iterations of the loop, then asks for another, and so on. The last chunk may be smaller than 3, though.Internally, the loop above becomes into code equivalent to this (illustration only, do not write code like this):</p>
<pre>  int a,b;
  if(GOMP_loop_dynamic_start(0,10,1, 3, &amp;a,&amp;b))
  {
    do {
      for(int n=a; n&lt;b; ++n) printf(" %d", n);
    } while(GOMP_loop_dynamic_next(&amp;a,&amp;b));
  }</pre>
<p>The <tt>guided</tt> schedule appears to have behavior of <tt>static</tt> with the shortcomings of <tt>static</tt> fixed with <tt>dynamic</tt>-like traits. It is difficult to explain — <a id="i127A9E53" href="http://bisqwit.iki.fi/jutut/kuvat/openmphowto/mandelbrot-demo.zip">this example program</a> maybe explains it better than words. (Requires libSDL to compile.)</p>
<h4><a name="Ordering"></a>Ordering</h4>
<div>The order in which the loop iterations are executed is unspecified, and depends on runtime conditions.However, it is possible to force that certain events within the loop happen in a predicted order, using the <tt>ordered</tt> clause.</div>
<pre> #pragma omp for ordered schedule(dynamic)
 for(int n=0; n&lt;100; ++n)
 {
   files[n].compress();

   #pragma omp ordered
   send(files[n]);
 }</pre>
<p>This loop &#8220;compresses&#8221; 100 files with some files being compressed in parallel, but ensures that the files are &#8220;sent&#8221; in a sequential order.If the thread assigned to compress file 7 is done but the file 6 has not yet been sent, the thread will wait before sending, and before starting to compress another file. The <tt>ordered</tt> clause in the loop guarantees that there always exists one thread that is handling the lowest-numbered unhandled task.Each file is compressed and sent exactly once, but the compression may happen in parallel.There may only be one <tt>ordered</tt> block per an ordered loop, no less and no more. In addition, the enclosing <tt>for</tt> directive must contain the <tt>ordered</tt> clause.</p>
<h3><a name="Sections"></a>Sections</h3>
<div>Sometimes it is handy to indicate that &#8220;this and this can run in parallel&#8221;. The <tt>sections</tt> setting is just for that.</div>
<pre> #pragma omp sections
 {
   { Work1(); }
   #pragma omp section
   { Work2();
     Work3(); }
   #pragma omp section
   { Work4(); }
 }</pre>
<p>This code indicates that any of the tasks <tt>Work1</tt>, <tt>Work2 + Work3</tt> and <tt>Work4</tt> may run in parallel, but that <tt>Work2</tt> and <tt>Work3</tt> must be run in sequence. Each work is done exactly once.As usual, if the compiler ignores the pragmas, the result is still a correctly running program.Internally, GCC implements this as a combination of the parallel <tt>for</tt> and a switch-case construct. Other compilers may implement it differently.Note: <tt>#pragma omp sections</tt> only delegates the sections for different threads in the current team. To create a team, you need to specify the <tt>parallel</tt> keyword either in the surrounding context or in the pragma, as <tt>#pragma omp parallel sections</tt>.<br />
Example:</p>
<pre> #pragma omp parallel sections // starts a new team
 {
   { Work1(); }
   #pragma omp section
   { Work2();
     Work3(); }
   #pragma omp section
   { Work4(); }
 }</pre>
<p>or</p>
<pre> #pragma omp parallel // starts a new team
 {
   //Work0(); // this function would be run by all threads.

   #pragma omp sections // divides the team into sections
   {
     // everything herein is run only once.
     { Work1(); }
     #pragma omp section
     { Work2();
       Work3(); }
     #pragma omp section
     { Work4(); }
   }

   //Work5(); // this function would be run by all threads.
 }</pre>
<h3><a name="TaskDirectiveOpenmp 3 0Only"></a>The <tt>task</tt> directive (OpenMP 3.0 only)</h3>
<div>When <tt>for</tt> and <tt>sections</tt> are too cumbersome, the <tt>task</tt> directive can be used. This is only supported in OpenMP 3.0.These examples are from the OpenMP 3.0 manual:</div>
<pre>struct node { node *left, *right; };
extern void process(node* );
void traverse(node* p)
{
    if (p-&gt;left)
        #pragma omp task // p is firstprivate by default
        traverse(p-&gt;left);
    if (p-&gt;right)
        #pragma omp task // p is firstprivate by default
        traverse(p-&gt;right);
    process(p);
}</pre>
<p>In the next example, we force a postorder traversal of the tree by adding a taskwait directive. Now, we can safely assume that the left and right sons have been executed before we process the current node.</p>
<pre>struct node { node *left, *right; };
extern void process(node* );
void postorder_traverse(node* p)
{
    if (p-&gt;left)
        #pragma omp task // p is firstprivate by default
        postorder_traverse(p-&gt;left);
    if (p-&gt;right)
        #pragma omp task // p is firstprivate by default
        postorder_traverse(p-&gt;right);
    #pragma omp taskwait
    process(p);
}</pre>
<p>The following example demonstrates how to use the task construct to process elements of a linked list in parallel. The pointer p is firstprivate by default on the task construct so it is not necessary to specify it in a firstprivate clause.</p>
<pre>struct node { int data; node* next; };
extern void process(node* );
void increment_list_items(node* head)
{
    #pragma omp parallel
    {
        #pragma omp single
        {
            for(node* p = head; p; p = p-&gt;next)
            {
            	#pragma omp task
            	process(p); // p is firstprivate by default
            }
        }
    }
}</pre>
<h2><a name="ThreadSafetyIEMutualExclusion"></a>Thread-safety (i.e. mutual exclusion)</h2>
<div>There are a wide array of concurrency and mutual exclusion problems related to multithreading programs. I won&#8217;t explain them here in detail; there are many good books dealing with the issue. (For example, <em>Multithreaded, Parallel, and Distributed Programming</em> by Gregory R. Andrews.)Instead, I will explain the tools that OpenMP provides to handle mutual exclusion correctly.</div>
<h3><a name="Atomicity"></a>Atomicity</h3>
<div>Atomicity means that something is inseparable; an event either happens completely or it does not happen at all, and another thread cannot intervene during the execution of the event.</div>
<pre> #pragma omp atomic
 counter += value;</pre>
<p>The <tt>atomic</tt> keyword in OpenMP specifies that the denoted action happens atomically. It is commonly used to update counters and other simple variables that are accessed by multiple threads simultaneously.Unfortunately, the atomicity setting can only be specified to simple expressions that usually can be compiled into a single processor opcode, such as increments, decrements, xors and the such. For example, it cannot include function calls, array indexing, overloaded operators, non-POD types, or multiple statements. Furthermore, it only specifies atomicity for the action relating to the lefthand side of the operation; it does not guarantee that the expression on the right side of the operator is evaluated atomically. If you need to atomicise more complex constructs, use either the <tt>critical</tt> directive or the locks, as explained below.See also <tt>reduction</tt>.</p>
<h3><a name="CriticalDirective"></a>The <tt>critical</tt> directive</h3>
<div>The <tt>critical</tt> directive restricts the execution of the associated statement / block to a single thread at time.The <tt>critical</tt> directive may optionally contain a global name that identifies the type of the <tt>critical</tt> directive. No two threads can execute a <tt>critical</tt> directive of the same name at the same time.If the name is omitted, a default name is assumed.</div>
<pre> #pragma omp critical(dataupdate)
 {
   datastructure.reorganize();
 }
 ...
 #pragma omp critical(dataupdate)
 {
   datastructure.reorganize_again();
 }</pre>
<p>In this example, only one of the critical sections named &#8220;dataupdate&#8221; may be executed at any given time, and only one thread may be executing it at that time. I.e. the functions &#8220;reorganize&#8221; and &#8220;reorganize_again&#8221; cannot be invoked at the same time, and two calls to the function cannot be active at the same time. (Except if other calls exist elsewhere, unprotected by the <tt>critical</tt> directive.)Note: The critical section names are global to the entire program (regardless of module boundaries). So if you have a critical section by the same name in multiple modules, not two of them can be executed at the same time.If you need something like a local mutex, see below.</p>
<h3><a name="Locks"></a>Locks</h3>
<div>The OpenMP runtime library provides a lock type, <tt>omp_lock_t</tt> in its include file, <tt>omp.h</tt>.The lock type has five manipulator functions:</div>
<ul>
<li><tt>omp_init_lock</tt> initializes the lock. After the call, the lock is unset.</li>
<li><tt>omp_destroy_lock</tt> destroys the lock. The lock must be unset before this call.</li>
<li><tt>omp_set_lock</tt> attempts to set the lock. If the lock is already set by another thread, it will wait until the lock is no longer set, and then sets it.</li>
<li><tt>omp_unset_lock</tt> unsets the lock. It should only be called by the same thread that set the lock; the consequences of doing otherwise are undefined.</li>
<li><tt>omp_test_lock</tt> attempts to set the lock. If the lock is already set by another thread, it returns 0; if it managed to set the lock, it returns 1.</li>
</ul>
<p>Here is an example of a wrapper around <tt>std::set&lt;&gt;</tt> that provides per-instance mutual exclusion while still working even if the compiler does not support OpenMP.You can maintain backward compability with non-OpenMP-supporting compilers by enclosing the library references in <tt>#ifdef _OPENMP</tt>…<tt>#endif</tt> blocks.</p>
<pre> #ifdef _OPENMP
 # include &lt;omp.h&gt;
 #endif
 #include &lt;set&gt;

 class data
 {
 private:
   std::set&lt;int&gt; flags;
 #ifdef _OPENMP
   omp_lock_t lock;
 #endif
 public:
   data() : flags()
   {
 #ifdef _OPENMP
     omp_init_lock(&amp;lock);
 #endif
   }
   ~data()
   {
 #ifdef _OPENMP
     omp_destroy_lock(&amp;lock);
 #endif
   }

   bool set_get(int c)
   {
   #ifdef _OPENMP
     omp_set_lock(&amp;lock);
   #endif
     bool found = flags.find(c) != flags.end();
     if(!found) flags.insert(c);
   #ifdef _OPENMP
     omp_unset_lock(&amp;lock);
   #endif
     return found;
   }
 };</pre>
<p>Of course, you would really rather wrap the lock into a custom container to avoid littering the code with <tt>#ifdef</tt>s and also for providing exception-safety:</p>
<pre> #ifdef _OPENMP
 # include &lt;omp.h&gt;
 struct MutexType
 {
   MutexType() { omp_init_lock(&amp;lock); }
   ~MutexType() { omp_destroy_lock(&amp;lock); }
   void Lock() { omp_set_lock(&amp;lock); }
   void Unlock() { omp_unset_lock(&amp;lock); }

   MutexType(const MutexType&amp; ) { omp_init_lock(&amp;lock); }
   MutexType&amp; operator= (const MutexType&amp; ) { return *this; }
 public:
   omp_lock_t lock;
 };
 #else
 /* A dummy mutex that doesn't actually exclude anything,
  * but as there is no parallelism either, no worries. */
 struct MutexType
 {
   void Lock() {}
   void Unlock() {}
 };
 #endif

 /* An exception-safe scoped lock-keeper. */
 struct ScopedLock
 {
   explicit ScopedLock(MutexType&amp; m) : mut(m), locked(true) { mut.Lock(); }
   ~ScopedLock() { Unlock(); }
   void Unlock() { if(!locked) return; locked=false; mut.Unlock(); }
   void LockAgain() { if(locked) return; mut.Lock(); locked=true; }
 private:
   MutexType&amp; mut;
   bool locked;
 private: // prevent copying the scoped lock.
   void operator=(const ScopedLock&amp;);
   ScopedLock(const ScopedLock&amp;);
 };</pre>
<p>This way, the example above becomes a lot simpler:</p>
<pre> #include &lt;set&gt;

 class data
 {
 private:
   std::set&lt;int&gt; flags;
   MutexType lock;
 public:
   bool set_get(int c)
   {
     ScopedLock lck(lock); // locks the mutex

     if(flags.find(c) != flags.end()) return true; // was found
     flags.insert(c);
     return false; // was not found
   } // automatically releases the lock when lck goes out of scope.
 };</pre>
<p>There is also a lock type that supports nesting, <tt>omp_nest_lock_t</tt>. I won&#8217;t cover it here.</p>
<h3><a name="FlushDirective"></a>The <tt>flush</tt> directive</h3>
<div>Even when variables used by threads are supposed to be shared, the compiler may take liberties and optimize them as register variables. This can skew concurrent observations of the variable. The <tt>flush</tt> directive can be used to ensure that the value observed in one thread is also the value observed by other threads.This example comes from the OpenMP specification.</div>
<pre>          /* presumption: int a = 0, b = 0; */

    /* First thread */                /* Second thread */
    b = 1;                            a = 1;
    #pragma omp flush(a,b)            #pragma omp flush(a,b)
    if(a == 0)                        if(b == 0)
    {                                 {
      /* Critical section */            /* Critical section */
    }                                 }</pre>
<p>In this example, it is enforced that at the time either of <tt>a</tt> or <tt>b</tt> is accessed, the other is also up-to-date, practically ensuring that not both of the two threads enter the critical section. (Note: It is still possible that neither of them can enter it.)You need the <tt>flush</tt> directive when you have writes to and reads from the same data in different threads.<strong>If the program appears to work correctly without the <tt>flush</tt> directive, it does not mean that the <tt>flush</tt> directive is not required.</strong> It just may be that your compiler is not utilizing all the freedoms the standard allows it to do. You <em>need</em> the <tt>flush</tt> directive whenever you access shared data in multiple threads: After a write, before a read.However, I do not know these:</p>
<ul>
<li>Is <tt>flush</tt> needed if the shared variable is declared <tt>volatile</tt>?</li>
<li>Is <tt>flush</tt> needed if all access to the shared variable is <tt>atomic</tt> or restricted by <tt>critical</tt> sections?</li>
</ul>
<h2><a name="ControllingWhichDataToShareBetweenThreads"></a>Controlling which data to share between threads</h2>
<div>In the parallel section, it is possible to specify which variables are shared between the different threads and which are not. By default, all variables are shared except those declared within the parallel block.</div>
<h3><a name="PrivateFirstprivateAndSharedClauses"></a>The <tt>private</tt>, <tt>firstprivate</tt> and <tt>shared</tt> clauses</h3>
<div>
<pre> int a, b=0;
 #pragma omp parallel for private(a) shared(b)
 for(a=0; a&lt;50; ++a)
 {
   #pragma omp atomic
   b += a;
 }</pre>
<p>This example explicitly specifies that <tt>a</tt> is private (each thread has their own copy of it) and that <tt>b</tt> is shared (each thread accesses the same variable).</p>
<h4><a name="DifferenceBetweenPrivateAndFirstprivate"></a>The difference between <tt>private</tt> and <tt>firstprivate</tt></h4>
<div>Note that a private copy is an uninitialized variable by the same name and same type as the original variable; it does <em>not</em> copy the value of the variable that was in the surrounding context.Example:</div>
<pre> #include &lt;string&gt;
 #include &lt;iostream&gt;

 int main()
 {
     std::string a = "x", b = "y";
     int c = 3;

     #pragma omp parallel private(a,c) shared(b) num_threads(2)
     {
         a += "k";
         c += 7;
         std::cout &lt;&lt; "A becomes (" &lt;&lt; a &lt;&lt; "), b is (" &lt;&lt; b &lt;&lt; ")\n";
     }
 }</pre>
<p>This will output the string &#8220;k&#8221;, not &#8220;xk&#8221;. At the entrance of the block, <tt>a</tt> becomes a new instance of <tt>std::string</tt>, that is initialized with the default constructor; it is not initialized with the copy constructor.Internally, the program becomes like this:</p>
<pre> int main()
 {
     std::string a = "x", b = "y";
     int c = 3;

     OpenMP_thread_fork(2);
     {                  // Start new scope
         std::string a; // Note: It is a new local variable.
         int c;         // This too.
         a += "k";
         c += 7;
         std::cout &lt;&lt; "A becomes (" &lt;&lt; a &lt;&lt; "), b is (" &lt;&lt; b &lt;&lt; ")\n";
     }                  // End of scope for the local variables
     OpenMP_join();
 }</pre>
<p>In the case of primitive (POD) datatypes (<tt>int</tt>, <tt>float</tt>, <tt>char*</tt> etc.), the private variable is uninitialized, just like any declared but not initialized local variable. It does not contain the value of the variable from the surrounding context. Therefore, the increment of <tt>c</tt> is moot here; the value of the variable is still undefined. (Unfortunately GCC, as of version 4.2.1, does not yet warn about uninitialized values in situations like this.)If you actually need a <em>copy</em> of the original value, use the <tt>firstprivate</tt> clause instead.</p>
<pre> #include &lt;string&gt;
 #include &lt;iostream&gt;

 int main()
 {
     std::string a = "x", b = "y";
     int c = 3;

     #pragma omp parallel firstprivate(a,c) shared(b) num_threads(2)
     {
         a += "k";
         c += 7;
         std::cout &lt;&lt; "A becomes (" &lt;&lt; a &lt;&lt; "), b is (" &lt;&lt; b &lt;&lt; ")\n";
     }
 }</pre>
<p>Now the output becomes &#8220;A becomes (xk), b is (y)&#8221;.</p>
<h3><a name="LastprivateClause"></a>The <tt>lastprivate</tt> clause</h3>
<div>The <tt>lastprivate</tt> clause defines a variable private as in <tt>firstprivate</tt> or <tt>private</tt>, but causes the value from the last task to be copied back to the original value after the end of the loop/sections construct.</div>
<ul>
<li>In a loop construct (<tt>for</tt> directive), the last value is the value assigned by the thread that handles the last iteration of the loop. Values assigned during other iterations are ignored.</li>
<li>In a sections construct (<tt>sections</tt> directive), the last value is the value assigned in the last section denoted by the <tt>section</tt> directive. Values assigned in other sections are ignored.</li>
</ul>
<p>Example:</p>
<pre> #include &lt;stdio.h&gt;
 int main()
 {
    int done = 4, done2 = 5;

     #pragma omp parallel for lastprivate(done, done2) num_threads(2) schedule(static)
     for(int a=0; a&lt;8; ++a)
     {
       if(a==2) done=done2=0;
       if(a==3) done=done2=1;
     }
     printf("%d,%d\n", done,done2);
 }</pre>
<p>This program outputs &#8220;4196224,-348582208&#8243;, because internally, this program became like this:</p>
<pre> #include &lt;stdio.h&gt;
 int main()
 {
    int done = 4, done2 = 5;
    OpenMP_thread_fork(2);
    {
        int this_thread = omp_get_thread_num(), num_threads = 2;
        int my_start = (this_thread  ) * 8 / num_threads;
        int my_end   = (this_thread+1) * 8 / num_threads;

        int priv_done, priv_done2; // not initialized, because firstprivate was not used

        for(int a=my_start; a&lt;my_end; ++a)
        {
            if(a==2) priv_done=priv_done2=0;
            if(a==3) priv_done=priv_done2=1;
        }
        if(my_end == <img src='http://michael-george-hart.com/2010-11-27/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' />
        {
           // assign the values back, because this was the last iteration
           done  = priv_done;
           done2 = priv_done2;
        }
    }
    OpenMP_join();
 }</pre>
<p>As one can observe, the values of priv_done and priv_done2 are not assigned even once during the course of the loop that iterates through 4&#8230;7. As such, the values that are assigned back are completely bogus.Therefore, <tt>lastprivate</tt> cannot be used to e.g. fetch the value of a flag assigned randomly during a loop. Use <tt>reduction</tt> for that, instead.Where this behavior <em>can</em> be utilized though, is in situations like this (from OpenMP manual):</p>
<pre> void loop()
 {
   int i;
   #pragma omp for lastprivate(i)
   for(i=0; i&lt;get_loop_count(); ++i) // note: get_loop_count() must be a pure function.
       { ... }

   printf("%d\n", i); // this shows the number of loop iterations done.
 }</pre>
<h3><a name="DefaultClause"></a>The <tt>default</tt> clause</h3>
<div>The most useful purpose on the <tt>default</tt> clause is to check whether you have remembered to consider all variables for the private/shared question, using the <tt>default(none)</tt> setting.</div>
<pre> int a, b=0;
 // This code won't compile: It will require that
 // it will be explicitly specified whether a is shared or private.
 #pragma omp parallel default(none) shared(b)
 {
   b += a;
 }</pre>
<p>The <tt>default</tt> clause can also be used to set that all variables are <tt>shared</tt> by default (<tt>default(shared)</tt>).</p>
<blockquote><p>Note: Because different compilers have different ideas about which variables are <em>implicitly</em> private or shared, and for which it is an <em>error</em> to explicitly state the private/shared status, it is recommended to use the <tt>default(none)</tt> setting only during development, and drop it in production/distribution code.</p></blockquote>
<h3><a name="ReductionClause"></a>The <tt>reduction</tt> clause</h3>
<div>The <tt>reduction</tt> clause is a mix between the <tt>private</tt>, <tt>shared</tt>, and <tt>atomic</tt> clauses.<br />
It allows to accumulate a shared variable without the <tt>atomic</tt> clause, but the type of accumulation must be specified. It will often produce faster executing code than by using the <tt>atomic</tt> clause.This example calculates <a id="iFB1BB060" href="http://en.wikipedia.org/wiki/factorial">factorial</a> using threads:</div>
<pre> int factorial(int number)
 {
   int fac = 1;
   #pragma omp parallel for reduction(*:fac)
   for(int n=2; n&lt;=number; ++n)
     fac *= n;
   return fac;
 }</pre>
<ul>
<li>At the beginning of the parallel block, a private copy is made of the variable and preinitialized to a certain value .</li>
<li>At the end of the parallel block, the private copy is atomically merged into the shared variable using the defined operator.</li>
</ul>
<p>(The private copy is actually just a new local variable by the same name and type; the original variable is not accessed to create the copy.)The syntax of the clause is:</p>
<pre>  reduction(<em>operator</em>:<em>list</em>)</pre>
<p>where <em>list</em> is the list of variables where the operator will be applied to, and <em>operator</em> is one of these:</p>
<table border="1">
<tbody>
<tr>
<th>Operator</th>
<th>Initialization value</th>
</tr>
<tr>
<td><tt>+</tt>, <tt>-</tt>, <tt>|</tt>, <tt>^</tt>, <tt>||</tt></td>
<td><tt>0</tt></td>
</tr>
<tr>
<td><tt>*</tt>, <tt>&amp;&amp;</tt></td>
<td><tt>1</tt></td>
</tr>
<tr>
<td><tt>&amp;</tt></td>
<td><tt>~0</tt></td>
</tr>
</tbody>
</table>
<p>To write the factorial function (shown above) without <tt>reduction</tt>, it probably would look like this:</p>
<pre> int factorial(int number)
 {
   int fac = 1;
   #pragma omp parallel for
   for(int n=2; n&lt;=number; ++n)
   {
     #pragma omp atomic
     fac *= n;
   }
   return fac;
 }</pre>
<p>However, this code would be less optimal than the one with <tt>reduction</tt>: it misses the opportunity to use a local (possible register) variable for the cumulation, and needlessly places load/synchronization demands on the shared memory variable. In fact, due to the bottleneck of that atomic variable (only one thread may access it simultaneously), it would completely nullify the gains of parallelism in that loop.The version with <tt>reduction</tt> is equivalent to this code (illustration only):</p>
<pre> int factorial(int number)
 {
   int fac = 1;
   #pragma omp parallel
   {
     int fac_private = 1; /* This value comes from the table shown above */
     #pragma omp for nowait
     for(int n=2; n&lt;=number; ++n)
       fac_private *= n;
     #pragma omp atomic
     fac *= fac_private;
   }
   return fac;
 }</pre>
<p>Note how it moves the atomic operation out from the loop.The restrictions in <tt>reduction</tt> and <tt>atomic</tt> are very similar: both can only be done on POD types; neither allows overloaded operators, and both have the same set of supported operators.As an example of how the <tt>reduction</tt> clause can be used to produce semantically different code when OpenMP is enabled and when it is disabled, this example prints the number of threads that executed the parallel block:</p>
<pre> int a = 0;
 #pragma omp parallel reduction (+:a)
 {
   a = 1; // Assigns a value to the private copy.
   // Each thread increments the value by 1.
 }
 printf("%d\n", a);</pre>
<p>If you preinitialized &#8220;a&#8221; to 4, it would print a number &gt;= 5 if OpenMP was enabled, and 1 if OpenMP was disabled.<br />
<em>Note: If you really need to detect whether OpenMP is enabled, use the <tt>_OPENMP</tt> #define instead. To get the number of threads, use <tt>omp_get_num_threads()</tt> instead.</em></p>
<h2>Execution synchronization</h2>
<div>
<h3>The <tt>barrier</tt> directive and the <tt>nowait</tt> clause</h3>
<div>The <tt>barrier</tt> directive causes threads encountering the barrier to wait until all the other threads in the same team have encountered the barrier.</div>
<pre> #pragma omp parallel
 {
   /* All threads execute this. */
   SomeCode();

   #pragma omp barrier

   /* All threads execute this, but not before
    * all threads have finished executing SomeCode().
    */
   SomeMoreCode();
 }</pre>
<p>Note: There is an implicit barrier at the end of each parallel block, and at the end of each <tt>sections</tt>, <tt>for</tt> and <tt>single</tt> statement, unless the <tt>nowait</tt> directive is used.Example:</p>
<pre> #pragma omp parallel
 {
   #pragma omp for
   for(int n=0; n&lt;10; ++n) Work();

   // This line is not reached before the for-loop is completely finished
   SomeMoreCode();
 }

 // This line is reached only after all threads from
 // the previous parallel block are finished.
 CodeContinues();

 #pragma omp parallel
 {
   #pragma omp for nowait
   for(int n=0; n&lt;10; ++n) Work();

   // This line may be reached while some threads are still executing the for-loop.
   SomeMoreCode();
 }

 // This line is reached only after all threads from
 // the previous parallel block are finished.
 CodeContinues();</pre>
<p>The <tt>nowait</tt> directive can only be attached to <tt>sections</tt>, <tt>for</tt> and <tt>single</tt>. It cannot be attached to the within-loop <tt>ordered</tt> clause, for example.</p>
<h3>The <tt>single</tt> and <tt>master</tt> directives</h3>
<div>The <tt>single</tt> directive specifies that the given statement/block is executed by only one thread. It is unspecified which thread. Other threads skip the statement/block and wait at an implicit barrier at the end of the construct.</div>
<pre> #pragma omp parallel
 {
   Work1();
   #pragma omp single
   {
     Work2();
   }
   Work3();
 }</pre>
<p>In a 2-cpu system, this will run Work1() twice, Work2() once and Work3() twice. There is an implied barrier at the end of the <tt>single</tt> directive, but not at the beginning of it.Note: Do not assume that the <tt>single</tt> block is executed by whichever thread gets there first. According to the standard, the decision of which thread executes the block is implementation-defined, and therefore making assumptions on it is non-conforming. In GCC, the decision is hidden inside the mechanics of libgomp.The <tt>master</tt> directive is similar, except that the statement/block is run by the <em>master</em> thread, and there is no implied barrier; other threads skip the construct without waiting.</p>
<pre> #pragma omp parallel
 {
   Work1();

   // This...
   #pragma omp master
   {
     Work2();
   }

   // ...is practically identical to this:
   if(omp_get_thread_num() == 0)
   {
     Work2();
   }

   Work3();
 }</pre>
<p>Unless you use the <tt>threadprivate</tt> clause, the only important difference between <tt>single nowait</tt> and <tt>master</tt> is that if you have multiple <tt>master</tt> blocks in a <tt>parallel</tt> section, you are guaranteed that they are executed by the same thread every time, and hence, the values of <tt>private</tt> (thread-local) variables are the same.</p>
<h2>Loop nesting</h2>
<div>
<h3>The problem</h3>
<div>A beginner at OpenMP will quickly find out that this code will not do the expected thing:</div>
<pre> #pragma omp parallel for
 for(int y=0; y&lt;25; ++y)
 {
   #pragma omp parallel for
   for(int x=0; x&lt;80; ++x)
   {
     tick(x,y);
   }
 }</pre>
<p>The beginner expects there to be N tick() calls active at the same time (where N = number of processors). Although that is true, the inner loop is not actually parallelised. Only the outer loop is. The inner loop runs in a pure sequence, as if the whole inner <tt>#pragma</tt> was omitted.At the entrance of the inner <tt>parallel</tt> directive, the OpenMP runtime library (libgomp in case of GCC) detects that there already exists a team, and instead of a new team of N threads, it will create a team consisting of only the calling thread.Rewriting the code like this won&#8217;t work:</p>
<pre> #pragma omp parallel for
 for(int y=0; y&lt;25; ++y)
 {
   #pragma omp for // ERROR, nesting like this is not allowed.
   for(int x=0; x&lt;80; ++x)
   {
     tick(x,y);
   }
 }</pre>
<p>This code is erroneous and will cause the program to malfunction. See the restrictions chapter below for details.</p>
<h4>Solution in OpenMP 3.0</h4>
<div>In OpenMP 3.0, the loop nesting problem can be solved by using the <tt>collapse</tt> clause in the <tt>for</tt> directive.Example:</div>
<pre> #pragma omp parallel for collapse(2)
 for(int y=0; y&lt;25; ++y)
   for(int x=0; x&lt;80; ++x)
   {
     tick(x,y);
   }</pre>
<p>The number specified in the <tt>collapse</tt> clauses is the number of nested loops that are subject to the work-sharing semantics of the OpenMP <tt>for</tt> directive.</p>
<h4>Workarounds in OpenMP 2.5</h4>
<div>Unfortunately, as of release 4.3, GCC does not yet support OpenMP 3.0. Workarounds exist for OpenMP 2.5.As was shown in the Mandelbrot example near the beginning of this document, the problem can be worked around by turning the nested loop into a non-nested loop:</div>
<pre> #pragma omp parallel for
 for(int pos=0; pos&lt;(25*80); ++pos)
 {
   int x = pos%80;
   int y = pos/80;
   tick(x,y);
 }</pre>
<p>However, rewriting code like this can be a nuisance.An alternative is to enable nested threading:</p>
<pre> omp_set_nested(1);
 #pragma omp parallel for
 for(int y=0; y&lt;25; ++y)
 {
   #pragma omp parallel for
   for(int x=0; x&lt;80; ++x)
   {
     tick(x,y);
   }
 }</pre>
<p>In this example, the inner loop is also parallelised. However, instead of N threads, the user will find N*N threads running, because the nested <tt>parallel</tt> directive now starts a new team of N threads instead of starting a single-thread team. This might be highly undesirable, hence why the nesting flag is disabled by default.So it might be wisest to write the code like this:</p>
<pre> for(int y=0; y&lt;25; ++y)
 {
   #pragma omp parallel for
   for(int x=0; x&lt;80; ++x)
   {
     tick(x,y);
   }
 }</pre>
<p>Now only the inner loop is run in parallel. In most cases, it is only slightly less optimal than the code that was rewritten to use only one loop.</p>
<h4>Performance</h4>
<div>One may be worried about the creation of new threads within the inner loop. Worry not, the libgomp in GCC is smart enough to actually only creates the threads once. Once the team has done its work, the threads are returned into a &#8220;dock&#8221;, waiting for new work to do.In other words, the number of times the <tt>clone</tt> system call is executed is exactly equal to the maximum number of concurrent threads. The <tt>parallel</tt> directive is not the same as a combination of <tt>pthread_create</tt> and <tt>pthread_join</tt>.There will be lots of locking/unlocking due to the implied barriers, though. I don&#8217;t know if that can be reasonably avoided or whether it even should.</div>
</div>
<h3>Restrictions</h3>
<div>There are restrictions for which clauses can be nested under which directives. The restrictions are listed in the OpenMP official specification.</div>
<h2>Shortcomings</h2>
<div>
<h3>OpenMP and fork()</h3>
<div>It is worth mentioning that using OpenMP in a program that calls <tt>fork()</tt> requires special consideration.This problem only affects GCC; ICC is not affected.If your program intends to become a background process using <tt>daemonize()</tt> or other similar means, you must not use the OpenMP features <em>before</em> the fork. After OpenMP features are utilized, a fork is only allowed if the child process does not use OpenMP features, or it does so as a completely new process (such as after <tt>exec()</tt>).This is an example of an erroneous program:</div>
<pre>  #include &lt;stdio.h&gt;
  #include &lt;sys/wait.h&gt;
  #include &lt;unistd.h&gt;

  void a()
  {
    #pragma omp parallel num_threads(2)
    {
      puts("para_a"); // output twice
    }
    puts("a ended"); // output once
  }
  void b()
  {
    #pragma omp parallel num_threads(2)
    {
      puts("para_b");
    }
    puts("b ended");
  }

  int main() {
   a();   // Invokes OpenMP features (parent process)
   int p = fork();
   if(!p)
   {
     b(); // ERROR: Uses OpenMP again, but in child process
     _exit(0);
   }
   wait(NULL);
   return 0;
  }</pre>
<p>When run, this program hangs, never reaching the line that outputs &#8220;b ended&#8221;.There is currently no workaround; the libgomp API does not specify functions that can be used to prepare for a call to <tt>fork()</tt>.</p>
<h3>Cancelling of threads (and breaking out of loops)</h3>
<div>Suppose that we want to optimize this function with parallel processing:</div>
<pre> /* Returns any position from the haystack where the needle can
  * be found, or NULL if no such position exists. It is not guaranteed
  * to find the first matching position; it only guarantees to find
  * _a_ matching position if one exists.
  */
 const char* FindAnyNeedle(const char* haystack, size_t size, char needle)
 {
   for(size_t p = 0; p &lt; size; ++p)
     if(haystack[p] == needle)
     {
       /* This breaks out of the loop. */
       return haystack+p;
     }
   return NULL;
 }</pre>
<p>Our first attempt might be to simply tack a <tt>#pragma parallel for</tt> before the <tt>for</tt> loop, but that doesn&#8217;t work: OpenMP requires that a loop construct processes each iteration. Breaking out of the loop (using <tt>return</tt>, <tt>goto</tt>, <tt>break</tt>, <tt>throw</tt> or other means) is not allowed.To solve finder problems where N threads search for a solution and once a solution is found by any thread, all threads end their search, you will need to seek other resolutions:</p>
<ul>
<li>Use pthreads and <tt>pthread_cancel()</tt> instead of OpenMP.</li>
<li>Poll an interrupt flag.</li>
</ul>
<p>Example of polling an interrupt flag (&#8220;done&#8221;).</p>
<pre> const char* FindAnyNeedle(const char* haystack, size_t size, char needle)
 {
   const char* result = NULL;
   bool done = false;
   #pragma omp parallel for
   for(size_t p = 0; p &lt; size; ++p)
   {
     #pragma omp flush(done)
     if(!done)
     {
       /* Do work only if no thread has found the needle yet. */
       if(haystack[p] == needle)
       {
         /* Inform the other threads that we found the needle. */
         done = true;
         #pragma omp flush(done)
         result = haystack+p;
       }
     }
   }
   return result;
 }</pre>
<p>However, the above version has a performance shortcoming: if a thread detects that the search is over (&#8220;done&#8221; is true), they will still iterate through their respective chunks of the <tt>for</tt> loop. You could just as well ignore the whole &#8220;done&#8221; flag:</p>
<pre> const char* FindAnyNeedle(const char* haystack, size_t size, char needle)
 {
   const char* result = NULL;
   #pragma omp parallel for
   for(size_t p = 0; p &lt; size; ++p)
     if(haystack[p] == needle)
       result = haystack+p;
   return result;
 }</pre>
<p>This does not incur any savings in memory access; each position in &#8220;haystack&#8221; is still searched. Furthermore, the value of &#8220;result&#8221; may be set multiple times, once for each match. If matches are abundant, it may be a lot slower than the non-parallel version was.The only possibility to avoid the extra loops is to avoid the OpenMP <tt>for</tt> directive alltogether and write it manually:</p>
<pre> const char* FindAnyNeedle(const char* haystack, size_t size, char needle)
 {
   const char* result = NULL;
   bool done = false;
   #pragma omp parallel
   {
     int this_thread = omp_get_thread_num(), num_threads = omp_get_num_threads();
     size_t beginpos = (this_thread+0) * size / num_threads;
     size_t endpos   = (this_thread+1) * size / num_threads;
     // watch out for overflow in that multiplication.

     for(size_t p = beginpos; p &lt; endpos; ++p)
     {
       /* End loop if another thread already found the needle. */
       #pragma omp flush(done)
       if(done) break;

       if(haystack[p] == needle)
       {
         /* Inform the other threads that we found the needle. */
         done = true;
         #pragma omp flush(done)
         result = haystack+p;
         break;
       }
     }
   }
   return result;
 }</pre>
<p>In this version, no extra iterations are done, but there is the fact that the &#8220;done&#8221; variable is polled at each loop. If that bothers you, you can seek a middle ground by dividing the loop into shorter sections where you don&#8217;t poll the interrupt flag, and only checking it in the between of them:</p>
<pre> const char* FindAnyNeedle(const char* haystack, size_t size, char needle)
 {
   const char* result = NULL;
   bool done = false;
   size_t beginpos = 0, n_per_loop = 4096 * omp_get_max_threads();
   while(beginpos &lt; size &amp;&amp; !done)
   {
     size_t endpos = std::min(size, beginpos + n_per_loop);
     #pragma omp parallel for reduction(|:done)
     for(size_t p = beginpos; p &lt; endpos; ++p)
       if(haystack[p] == needle)
       {
         /* Found it. */
         done = true;
         result = haystack+p;
       }
     beginpos = endpos;
   }
   return result;
 }</pre>
<p>This however again does not guarantee that no extra comparisons are done; the value of &#8220;result&#8221; may be set multiple times in this function.If this is also unacceptable, then OpenMP has no more solutions remaining. You can use pthreads and try <tt>pthread_create</tt> to create the team and <tt>pthread_cancel</tt> to topple the sibling threads. Such a solution is not portable and is out of the scope of this article. (It can however be downloaded <a id="i5F5840D2" href="http://bisqwit.iki.fi/jutut/kuvat/openmphowto/pthread_cancel_demo.cpp">here</a>.)</p>
<h2>Some specific gotchas</h2>
<div><strong>C++</strong></div>
<ul>
<li>STL is not thread-safe. If you use STL containers in a parallel context, you <em>must</em> exclude concurrent access using locks or other mechanisms. Const-access is usually fine, as long as non-const access does not occur at the same time.</li>
<li>Exceptions may not be thrown and caught across omp directives. That is, if a code inside an <tt>omp for</tt> throws an exception, the exception must be caught before the end of the loop iteration; and an exception thrown inside a <tt>parallel</tt> section must be caught by the same thread before the end of the <tt>parallel</tt> section.</li>
</ul>
<p><strong>C</strong></p>
<ul>
<li>C does not allow variables to be declared in the <tt>for</tt> syntax, which means that by default, variables used for <tt>for</tt> iteration become shared. You must use the <tt>private</tt> clause explictly for loop variables.</li>
</ul>
<p><strong>GCC</strong></p>
<ul>
<li><tt>fork()</tt> is troublematic when used together with OpenMP. See the chapter &#8220;OpenMP and fork()&#8221; above for details.</li>
</ul>
<h2>Other</h2>
<div>For the data copying clauses such as <tt>threadprivate</tt>, <tt>copyprivate</tt> and <tt>copyin</tt>, see the official specification.</div>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://michael-george-hart.com/2010-11-27/2011/08/11/openmp-fast-track/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Marginal distribution</title>
		<link>http://michael-george-hart.com/2010-11-27/2011/08/05/marginal-distribution/</link>
		<comments>http://michael-george-hart.com/2010-11-27/2011/08/05/marginal-distribution/#comments</comments>
		<pubDate>Fri, 05 Aug 2011 14:46:53 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Language of Business]]></category>

		<guid isPermaLink="false">http://michael-george-hart.com/2010-11-27/?p=418</guid>
		<description><![CDATA[In probability theory and statistics, the marginal distribution of a subset of a collection of random variables is the probability distribution of the variables contained in the subset. The term marginal variable is used to refer to those variables in &#8230; <a href="http://michael-george-hart.com/2010-11-27/2011/08/05/marginal-distribution/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><!-- bodytext -->In <a title="Probability theory" href="http://en.wikipedia.org/wiki/Probability_theory">probability theory</a> and <a title="Statistics" href="http://en.wikipedia.org/wiki/Statistics">statistics</a>, the <strong>marginal distribution</strong> of a subset of a collection of random variables is the probability distribution of the variables contained in the subset. The term <strong>marginal variable</strong> is used to refer to those variables in the subset of variables being retained. These terms are dubbed &#8220;marginal&#8221; because they used to be found by summing values in a table along rows or columns, and writing the sum in the margins of the table.<sup id="cite_ref-0"><a href="http://en.wikipedia.org/wiki/Marginal_distribution#cite_note-0">[1]</a></sup> The distribution of the marginal variables (the marginal distribution) is obtained by <strong>marginalizing</strong> over the distribution of the variables being discarded, and the discarded variables are said to have been <strong>marginalized out</strong>.</p>
<p>The context here is that the theoretical studies being undertaken, or the <a title="Data analysis" href="http://en.wikipedia.org/wiki/Data_analysis">data analysis</a> being done, involves a wider set of random variables but that attention is being limited to a reduced number of those variables. In many applications an analysis may start with a given collection of random variables, then first extend the set by defining new ones (such as the sum of the original random variables) and finally reduce the number by placing interest in the marginal distribution of a subset (such as the sum). Several different analyses may be done, each treating a different subset of variables as the marginal variables.</p>
<table id="toc">
<tbody>
<tr>
<td>
<div id="toctitle">
<h2>Contents</h2>
<p> </p>
</div>
<ul>
<li>1 Two-variable case</li>
<li>2 Real-world example</li>
<li>3 General cases</li>
<li>4 See also</li>
<li>5 References</li>
<li>6 Bibliography</li>
</ul>
</td>
</tr>
</tbody>
</table>
<h2>Two-variable case</h2>
<div>
<div>
<p><a href="http://en.wikipedia.org/wiki/File:Jointdist_twodepvars.PNG"><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Jointdist_twodepvars.PNG/200px-Jointdist_twodepvars.PNG" alt="" width="200" height="223" /></a></p>
<div>
<div><a title="Enlarge" href="http://en.wikipedia.org/wiki/File:Jointdist_twodepvars.PNG"><img src="http://bits.wikimedia.org/skins-1.17/common/images/magnify-clip.png" alt="" width="15" height="11" /></a></div>
<p>Joint and marginal distributions of a pair of discrete, random variables X,Y having nonzero mutual information I(X; Y).</p>
</div>
</div>
</div>
<p>Given two <a title="Random variable" href="http://en.wikipedia.org/wiki/Random_variable">random variables</a> <em>X</em> and <em>Y</em> whose joint distribution is known, the marginal distribution of <em>X</em> is simply the <a title="Probability distribution" href="http://en.wikipedia.org/wiki/Probability_distribution">probability distribution</a> of <em>X</em> averaging over information about <em>Y</em>. This is typically calculated by summing or integrating the joint probability distribution over <em>Y</em>.</p>
<p>For discrete random variables, the marginal <a title="Probability mass function" href="http://en.wikipedia.org/wiki/Probability_mass_function">probability mass function</a> can be written as Pr(<em>X</em> = <em>x</em>). This is</p>
<dl>
<dd><img src="http://upload.wikimedia.org/math/2/6/e/26e6dc2f80497713ec487693ff635f9d.png" alt="\Pr(X=x) = \sum_{y} \Pr(X=x,Y=y) = \sum_{y} \Pr(X=x|Y=y) \Pr(Y=y)," /> </dd>
</dl>
<p>where Pr(<em>X</em> = <em>x</em>,<em>Y</em> = <em>y</em>) is the joint distribution of <em>X</em> and <em>Y</em>, while Pr(<em>X</em> = <em>x</em>|<em>Y</em> = <em>y</em>) is the conditional distribution of <em>X</em> given <em>Y</em>. In this case, the variable <em>Y</em> has been marginalized out.</p>
<p>Bivariate marginal and joint probabilities for discrete random variables are often displayed as <a title="Frequency distribution" href="http://en.wikipedia.org/wiki/Frequency_distribution#Joint_frequency_distributions">two-way tables</a>.</p>
<p>Similarly for continuous random variables, the marginal <a title="Probability density function" href="http://en.wikipedia.org/wiki/Probability_density_function">probability density function</a> can be written as <em>p</em><sub><em>X</em></sub>(<em>x</em>). This is</p>
<dl>
<dd><img src="http://upload.wikimedia.org/math/7/b/8/7b8c825a622dd0a5bfe7168756873465.png" alt="p_{X}(x) = \int_y p_{X,Y}(x,y) \, dy = \int_y p_{X|Y}(x|y) \, p_Y(y) \, dy ," /> </dd>
</dl>
<p>where <em>p</em><sub><em>X</em>,<em>Y</em></sub>(<em>x</em>,<em>y</em>) gives the joint distribution of <em>X</em> and <em>Y</em>, while <em>p</em><sub><em>X</em>|<em>Y</em></sub>(<em>x</em>|<em>y</em>) gives the conditional distribution for <em>X</em> given <em>Y</em>. Again, the variable <em>Y</em> has been marginalized out.</p>
<h2>Real-world example</h2>
<p>Imagine for example you want to compute the probability that a pedestrian will be hit by a car while crossing the road at a pedestrian crossing. Let H be a discrete random variable describing the probability of being hit by a car while walking over the crossing, taking one value from { hit, not hit }. Let L be a discrete random variable describing the probability of the cross traffic&#8217;s traffic light state at a given moment, taking one from { red, yellow, green }.</p>
<p>Realistically, H will be dependent on L. That is, P(H = hit) and P(H = not hit) will take different values depending on whether L is red, yellow or green. You are, for example, far more likely to be hit by a car if you try to cross while the lights for cross traffic are green than if they are red. In other words, for any given possible pair of values for H and L, you must feed them into the <a title="Joint probability distribution" href="http://en.wikipedia.org/wiki/Joint_probability_distribution">joint probability distribution</a> of H and L to find the probability of that pair of events occurring together.</p>
<p>However, in trying to calculate the <strong>marginal probability</strong> P(H=hit), what we are asking for is the probability that H=hit, where we don&#8217;t actually know the particular value of L. In general you can be hit if the lights are red OR if the lights are yellow OR if the lights are green. So in this case the answer for the marginal probability can be found by summing P(H,L) = P(hit,L) for all possible values of L.</p>
<p>Here is a table showing the conditional probabilities of being hit, depending on the state of the lights. (Note that due to the dependence, only the columns in this table must add up to 1).</p>
<table>
<tbody>
<tr>
<th colspan="4" align="center">Conditional distribution: P(H|L)</th>
</tr>
<tr>
<th> </th>
<th width="60">L=Red</th>
<th width="60">L=Yellow</th>
<th width="60">L=Green</th>
</tr>
<tr>
<td>H=Not Hit</td>
<td align="center">0.99</td>
<td align="center">0.9</td>
<td align="center">0.2</td>
</tr>
<tr>
<td>H=Hit</td>
<td align="center">0.01</td>
<td align="center">0.1</td>
<td align="center">0.8</td>
</tr>
</tbody>
</table>
<p>To find the joint probability distribution, we need more data. Let&#8217;s say that P(L=red) = 0.7, P(L=yellow) = 0.1, P(L=green) = 0.2. Multiplying the columns in the conditional distribution by the appropriate values, we find the joint probability distribution of H and L. (Note that the cells in this table, excluding the marginal probabilities, now add up to 1).</p>
<table>
<tbody>
<tr>
<th colspan="4" align="center">Joint distribution: P(H,L)</th>
</tr>
<tr>
<th> </th>
<th width="60">L=Red</th>
<th width="60">L=Yellow</th>
<th width="60">L=Green</th>
<th width="60">Marginal probability</th>
</tr>
<tr>
<th>H=Not Hit</th>
<td align="center">0.693</td>
<td align="center">0.09</td>
<td align="center">0.04</td>
<th align="center">0.823</th>
</tr>
<tr>
<th>H=Hit</th>
<td align="center">0.007</td>
<td align="center">0.01</td>
<td align="center">0.16</td>
<th align="center">0.177</th>
</tr>
<tr>
<th>Total</th>
<th align="center">0.7</th>
<th align="center">0.1</th>
<th align="center">0.2</th>
<th align="center">1</th>
</tr>
</tbody>
</table>
<p>The marginal probability P(H=Hit) is the sum of the bottom row (above the totals row), as this is the probability of being hit when the lights are red OR yellow OR green. Similarly, the marginal probability that P(H=Not Hit) is the sum of the top row. It is important to interpret this result correctly. The chance of being hit by a car when you cross the road is obviously a lot less than 17.7%. However, what this figure is actually saying is that if you were to ignore the state of the traffic lights and cross the road no matter their color, you would have a 17.7% risk of being hit by a car. This seems more reasonable.</p>
<h2>General cases</h2>
<p>For multivariate distributions, formulae similar to those above apply with the symbols <em>X</em> and/or <em>Y</em> being interpreted as vectors. In particular, each summation or integration would be over all variables except those contained in <em>X</em>.</p>
<h2>See also</h2>
<ul>
<li><a title="Joint probability distribution" href="http://en.wikipedia.org/wiki/Joint_probability_distribution">Joint probability distribution</a></li>
<li><a title="Wasserstein metric" href="http://en.wikipedia.org/wiki/Wasserstein_metric">Wasserstein metric</a></li>
</ul>
<h2>References</h2>
<div>
<ol>
<li id="cite_note-0"><strong><a href="http://en.wikipedia.org/wiki/Marginal_distribution#cite_ref-0">^</a></strong> Trumpler and Weaver (1962), pp. 32–33.</li>
</ol>
</div>
<h2>Bibliography</h2>
<ul>
<li>Everitt, B. S. (2002). <em>The Cambridge Dictionary of Statistics</em>. Cambridge University Press. <a title="International Standard Book Number" href="http://en.wikipedia.org/wiki/International_Standard_Book_Number">ISBN</a> <a title="Special:BookSources/0-521-81099-x" href="http://en.wikipedia.org/wiki/Special:BookSources/0-521-81099-x">0-521-81099-x</a>. </li>
<li>Trumpler, Robert J. and Harold F. Weaver (1962). <em>Statistical </em></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://michael-george-hart.com/2010-11-27/2011/08/05/marginal-distribution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Joint probability distribution</title>
		<link>http://michael-george-hart.com/2010-11-27/2011/08/05/joint-probability-distribution/</link>
		<comments>http://michael-george-hart.com/2010-11-27/2011/08/05/joint-probability-distribution/#comments</comments>
		<pubDate>Fri, 05 Aug 2011 14:42:17 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Language of Business]]></category>

		<guid isPermaLink="false">http://michael-george-hart.com/2010-11-27/?p=414</guid>
		<description><![CDATA[In the study of probability, given two random variables X and Y that are defined on the same probability space, the joint distribution for X and Y defines the probability of events defined in terms of both X and Y. &#8230; <a href="http://michael-george-hart.com/2010-11-27/2011/08/05/joint-probability-distribution/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In the study of <a title="Probability" href="http://en.wikipedia.org/wiki/Probability"><span style="color: #0645ad;">probability</span></a>, given two <a title="Random variable" href="http://en.wikipedia.org/wiki/Random_variable"><span style="color: #0645ad;">random variables</span></a> <em>X</em> and <em>Y</em> that are defined on the same <a title="Probability space" href="http://en.wikipedia.org/wiki/Probability_space"><span style="color: #0645ad;">probability space</span></a>, the <strong>joint distribution</strong> for <em>X</em> and <em>Y</em> defines the probability of events defined in terms of both <em>X</em> and <em>Y</em>. In the case of only two random variables, this is called a <strong>bivariate distribution</strong>, but the concept generalizes to any number of random variables, giving a <strong>multivariate distribution</strong>.</p>
<table id="toc" class="toc">
<tbody>
<tr>
<td>
<div id="toctitle">
<h2><strong>Contents</strong></h2>
<p><span class="toctoggle"><span style="font-size: x-small;"> </span></span></p>
</div>
<ul>
<li class="toclevel-1 tocsection-1"><span class="tocnumber"><span style="color: #0645ad;">1</span></span><span style="color: #0645ad;"> </span><span class="toctext"><span style="color: #0645ad;">Cumulative distribution</span></span></li>
<li class="toclevel-1 tocsection-2"><span class="tocnumber"><span style="color: #0645ad;">2</span></span><span style="color: #0645ad;"> </span><span class="toctext"><span style="color: #0645ad;">Discrete case</span></span></li>
<li class="toclevel-1 tocsection-3"><span class="tocnumber"><span style="color: #0645ad;">3</span></span><span style="color: #0645ad;"> </span><span class="toctext"><span style="color: #0645ad;">Continuous case</span></span></li>
<li class="toclevel-1 tocsection-4"><span class="tocnumber"><span style="color: #0645ad;">4</span></span><span style="color: #0645ad;"> </span><span class="toctext"><span style="color: #0645ad;">Mixed case</span></span></li>
<li class="toclevel-1 tocsection-5"><span class="tocnumber"><span style="color: #0645ad;">5</span></span><span style="color: #0645ad;"> </span><span class="toctext"><span style="color: #0645ad;">General multidimensional distributions</span></span></li>
<li class="toclevel-1 tocsection-6"><span class="tocnumber"><span style="color: #0645ad;">6</span></span><span style="color: #0645ad;"> </span><span class="toctext"><span style="color: #0645ad;">Joint distribution for independent variables</span></span></li>
<li class="toclevel-1 tocsection-7"><span class="tocnumber"><span style="color: #0645ad;">7</span></span><span style="color: #0645ad;"> </span><span class="toctext"><span style="color: #0645ad;">See also</span></span></li>
<li class="toclevel-1 tocsection-8"><span class="tocnumber"><span style="color: #0645ad;">8</span></span><span style="color: #0645ad;"> </span><span class="toctext"><span style="color: #0645ad;">External links</span></span></li>
</ul>
</td>
</tr>
</tbody>
</table>
<h2><span id="Cumulative_distribution" class="mw-headline"><span style="color: #000000;">Cumulative distribution</span></span></h2>
<p>The <a title="Cumulative distribution function" href="http://en.wikipedia.org/wiki/Cumulative_distribution_function"><span style="color: #0645ad;">cumulative distribution function</span></a> for a pair of random variables is defined in terms of their joint probability distribution;</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/c/9/8/c984b133818137f89a05cd2069fb4776.png" alt="F(x,y)=P(X \le x, Y \le y) ." /> </dd>
</dl>
<h2><span id="Discrete_case" class="mw-headline"><span style="color: #000000;">Discrete case</span></span></h2>
<p>For <a class="mw-redirect" title="Discrete random variable" href="http://en.wikipedia.org/wiki/Discrete_random_variable"><span style="color: #0645ad;">discrete random variables</span></a>, the joint <a title="Probability mass function" href="http://en.wikipedia.org/wiki/Probability_mass_function"><span style="color: #0645ad;">probability mass function</span></a> is</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/2/f/4/2f461043224c19ea8f29ce4d79076f38.png" alt=" \begin{align} \mathrm{P}(X=x\ \mathrm{and}\ Y=y) &amp; {} = \mathrm{P}(Y=y \mid X=x) \cdot \mathrm{P}(X=x) \\ &amp; {} = \mathrm{P}(X=x \mid Y=y) \cdot \mathrm{P}(Y=y). \end{align} " /> </dd>
</dl>
<p>Since these are probabilities, we have</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/6/d/9/6d9a5ea9ce8eb788004f1e3d70336619.png" alt="\sum_x \sum_y \mathrm{P}(X=x\ \mathrm{and}\ Y=y) = 1.\;" /> </dd>
</dl>
<h2><span id="Continuous_case" class="mw-headline"><span style="color: #000000;">Continuous case</span></span></h2>
<p>Similarly for <a class="mw-redirect" title="Continuous random variable" href="http://en.wikipedia.org/wiki/Continuous_random_variable"><span style="color: #0645ad;">continuous random variables</span></a>, the <strong>joint <a title="Probability density function" href="http://en.wikipedia.org/wiki/Probability_density_function"><span style="color: #0645ad;">probability density function</span></a></strong> can be written as <em>f</em><sub><em>X</em>,<em>Y</em></sub>(<em>x</em>, <em>y</em>) and this is</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/e/0/a/e0a642fc742fbb35fc64ccfce32c1f90.png" alt="f_{X,Y}(x,y) = f_{Y|X}(y|x)f_X(x) = f_{X|Y}(x|y)f_Y(y)\;" /> </dd>
</dl>
<p>where <em>f</em><sub><em>Y</em>|<em>X</em></sub>(<em>y</em>|<em>x</em>) and <em>f</em><sub><em>X</em>|<em>Y</em></sub>(<em>x</em>|<em>y</em>) give the <a class="mw-redirect" title="Conditional distribution" href="http://en.wikipedia.org/wiki/Conditional_distribution"><span style="color: #0645ad;">conditional distributions</span></a> of <em>Y</em> given <em>X</em> = <em>x</em> and of <em>X</em> given <em>Y</em> = <em>y</em> respectively, and <em>f</em><sub><em>X</em></sub>(<em>x</em>) and <em>f</em><sub><em>Y</em></sub>(<em>y</em>) give the <a title="Marginal distribution" href="http://en.wikipedia.org/wiki/Marginal_distribution"><span style="color: #0645ad;">marginal distributions</span></a> for <em>X</em> and <em>Y</em> respectively.</p>
<p>Again, since these are probability distributions, one has</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/9/2/8/92842679851865ae86da1a2cf29d9b98.png" alt="\int_x \int_y f_{X,Y}(x,y) \; dy \; dx= 1." /> </dd>
</dl>
<h2><span id="Mixed_case" class="mw-headline"><span style="color: #000000;">Mixed case</span></span></h2>
<p>In some situations <em>X</em> is continuous but <em>Y</em> is discrete. For example, in a <a title="Logistic regression" href="http://en.wikipedia.org/wiki/Logistic_regression"><span style="color: #0645ad;">logistic regression</span></a>, one may wish to predict the probability of a binary outcome <em>Y</em> conditional on the value of a continuously-distributed <em>X</em>. In this case, (<em>X</em>, <em>Y</em>) has neither a probability density function nor a probability mass function in the sense of the terms given above. On the other hand, a &#8220;mixed joint density&#8221; can be defined in either of two ways:</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/3/3/f/33fa2346d24b2191ea9eb4e502a7530f.png" alt=" \begin{align} f_{X,Y}(x,y) &amp;= f_{X|Y}(x|y)\mathrm{P}(Y=y)\\              &amp;= \mathrm{P}(Y=y \mid X=x) f_X(x) \end{align} " /> </dd>
</dl>
<p>Formally, <em>f</em><sub><em>X</em>,<em>Y</em></sub>(<em>x</em>, <em>y</em>) is the probability density function of (<em>X</em>, <em>Y</em>) with respect to the <a title="Product measure" href="http://en.wikipedia.org/wiki/Product_measure"><span style="color: #0645ad;">product measure</span></a> on the respective <a title="Support (measure theory)" href="http://en.wikipedia.org/wiki/Support_(measure_theory)"><span style="color: #0645ad;">supports</span></a> of <em>X</em> and <em>Y</em>. Either of these two decompositions can then be used to recover the joint cumulative distribution function:</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/a/9/e/a9e03022f764b8568d7f0ec73fea11ad.png" alt=" \begin{align} F_{X,Y}(x,y)&amp;=\sum\limits_{t\le y}\int_{s=-\infty}^x f_{X,Y}(s,t)\;ds \end{align} " /> </dd>
</dl>
<p>The definition generalizes to a mixture of arbitrary numbers of discrete and continuous random variables.</p>
<h2><span id="General_multidimensional_distributions" class="mw-headline"><span style="color: #000000;">General multidimensional distributions</span></span></h2>
<p>The <a title="Cumulative distribution function" href="http://en.wikipedia.org/wiki/Cumulative_distribution_function"><span style="color: #0645ad;">cumulative distribution function</span></a> for a vector of random variables is defined in terms of their joint probability distribution;</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/8/d/a/8dae03ca4472174009120c32233448f3.png" alt="F(x_1,\dots,x_n)=P(X_1 \le x_1,\dots, X_n \le x_n) ." /> </dd>
</dl>
<p>The joint distribution for two random variables can be extended to many random variables <em>X</em><sub>1</sub>, &#8230; <em>X</em><sub><em>n</em></sub> by adding them sequentially with the identity</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/2/d/e/2de5bb24b1998e5722dddc7980944e7c.png" alt="\begin{align} f_{X_1, \ldots X_n}(x_1, \ldots x_n) =&amp; f_{X_n | X_1, \ldots X_{n-1}}( x_n | x_1, \ldots x_{n-1}) f_{X_1, \ldots X_{n-1}}( x_1, \ldots x_{n-1} )\\ =&amp; f_{X_1} (x_1) \\  &amp; \cdot f_{X_2|X_1} (x_2|x_1)\\  &amp; \cdot \dots \\  &amp; \cdot f_{X_{n-1}| X_1 \ldots X_{n-2}}(x_{n-1}| x_1, \ldots x_{n-2} ) \\  &amp; \cdot f_{X_n | X_1, \ldots X_{n-1}}( x_n | x_1, \ldots x_{n-1}),\end{align}" /> </dd>
</dl>
<p>where</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/3/2/5/325a979790aba34da760204e5682d7cc.png" alt="\begin{align} f_{X_i| X_1, \ldots X_{i-1}}(x_i | x_1, \ldots x_{i-1})=   &amp;\frac{f_{X_1, \dots X_i}(x_1,\dots x_i)}{\int f_{X_1, \dots X_i}(x_1,\dots x_{i-1},u_i) \mathrm{d} u_i}\\ = &amp;\frac{\int \dots \int f_{X_1, \dots X_n}(x_1,\dots x_i,u_{i+1}, \dots u_n) \mathrm{d} u_{i+1}\dots \mathrm{d}u_n}{\int \dots \int \int f_{X_1, \dots X_n}(x_1,\dots x_{i-1},u_i, \dots u_n) \mathrm{d} u_i \,\mathrm{d} u_{i+1}\dots \mathrm{d}u_n} \end{align}" /> </dd>
</dl>
<p>and</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/a/c/1/ac180da3d2ab5beb7408bb9592c8f020.png" alt="f_{X_1,\dots X_i}(x_1,\dots x_i) = \int \dots \int f_{X_1,\dots X_n}(x_1,\dots x_i,x_{i+1},\dots x_n) \mathrm{d} x_{i+1} \dots \mathrm{d} x_n" /> </dd>
</dl>
<p>(notice, that these latter identities can be useful to generate a random variable <img class="tex" src="http://upload.wikimedia.org/math/6/3/2/632d186ef0daf40998775f191a085464.png" alt="(X_1, \dots X_n)" /> with given distribution function <img class="tex" src="http://upload.wikimedia.org/math/9/d/a/9da1d1c959bb7f118fa99cb08ec34ece.png" alt="f(x_1,\dots x_n)" />); the density of the <a title="Marginal distribution" href="http://en.wikipedia.org/wiki/Marginal_distribution"><span style="color: #0645ad;">marginal distribution</span></a> is</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/e/f/d/efd64951171fd25d87d4d2fddbf6a18b.png" alt="f_{X_i}(x_i) = \int \dots \int \int \dots \int f_{X_1,\dots X_n}(x_1,\dots x_{i-1},x_i,x_{i+1},\dots x_n) \mathrm{d} x_1\dots \mathrm{d}x_{i-1} \, \mathrm{d}x_{i+1} \dots \mathrm{d}x_n." /> </dd>
</dl>
<p>The joint cumulative distribution function is</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/e/c/1/ec100511fbbc0350228aa65f0a00dae0.png" alt="F_{X_1,\dots X_n}\left( x_1, \dots x_n\right)= \int_{-\infty}^{x_1} \dots \int_{-\infty}^{x_n} f_{X_1,\dots X_n}\left(u_1,\dots u_n\right) \mathrm{d} u_1 \dots \mathrm{d}u_n," /> </dd>
</dl>
<p>and the conditional distribution function is accordingly</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/1/4/1/141d7dff2f2882c10e4ff4d2c88f7fd6.png" alt="\begin{align} F_{X_i| X_1, \ldots X_{i-1}}(x_i| x_1, \ldots x_{i-1})=   &amp;\frac{\int_{-\infty}^{x_i}f_{X_1, \dots X_i}(x_1,\dots x_{i-1},u_i)\mathrm{d}u_i}{\int_{-\infty}^\infty f_{X_1, \dots X_i}(x_1,\dots x_{i-1},u_i) \mathrm{d} u_i}\\ = &amp;\frac{\int_{-\infty}^\infty \dots \int_{-\infty}^\infty \int_{-\infty}^{x_i} f_{X_1, \dots X_n}(x_1,\dots x_{i-1},u_i, \dots u_n) \mathrm{d} u_i\dots \mathrm{d}u_n}{\int_{-\infty}^\infty \dots \int_{-\infty}^\infty \int_{-\infty}^\infty f_{X_1, \dots X_n}(x_1,\dots x_{i-1},u_i,\dots u_n) \mathrm{d} u_i \dots \mathrm{d} u_n}. \end{align}" /> </dd>
</dl>
<p>Expectation reads</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/2/9/1/291ca6caee24806f2e7905082f14dec4.png" alt="\mathbb{E}\left[h(X_1,\dots X_n) \right]=\int_{-\infty}^\infty \dots \int_{-\infty}^\infty h(x_1,\dots x_n) f_{X_1,\dots X_n}(x_1,\dots x_n) \mathrm{d} x_1 \dots \mathrm{d} x_n;" /> </dd>
</dl>
<p>suppose that <em>h</em> is smooth enough and <img class="tex" src="http://upload.wikimedia.org/math/c/7/e/c7e1d91e2e5d59b3e958605e257c1a50.png" alt="h(u_1,\dots u_n)=h(x_1,\dots x_n)" /> for <img class="tex" src="http://upload.wikimedia.org/math/8/1/7/817c067f4ed893e608127686c18f2617.png" alt="u_1 \ge x_1, \dots u_n\ge x_n" />, then, by iterated <a title="Integration by parts" href="http://en.wikipedia.org/wiki/Integration_by_parts"><span style="color: #0645ad;">integration by parts</span></a>,</p>
<dl>
<dd><img class="tex" src="http://upload.wikimedia.org/math/3/a/2/3a24fab2c5766d7b38db2b99ecec2e4c.png" alt="\begin{align}\mathbb{E}\left[h(X_1,\dots X_n) \right]=&amp; h(x_1,\dots x_n)+ \\ &amp; (-1)^n \int_{-\infty}^{x_1} \dots \int_{-\infty}^{x_n} F_{X_1,\dots X_n}(u_1,\dots u_n) \frac{\partial^n}{\partial x_1 \dots \partial x_n} h(u_1,\dots u_n) \mathrm{d} u_1 \dots \mathrm{d} u_n.\end{align}" /> </dd>
</dl>
<h2><span id="Joint_distribution_for_independent_variables" class="mw-headline"><span style="color: #000000;">Joint distribution for independent variables</span></span></h2>
<p>If for discrete random variables <img class="tex" src="http://upload.wikimedia.org/math/d/d/d/ddd06bc72619b6c4bd2781d07398d2ce.png" alt="\ P(X = x \ \mbox{and} \ Y = y ) = P( X = x) \cdot P( Y = y) " /> for all <em>x</em> and <em>y</em>, or for absolutely continuous random variables <img class="tex" src="http://upload.wikimedia.org/math/f/4/b/f4bcd43407296ef7ff52b947f0b3c543.png" alt="\ f_{X,Y}(x,y) = f_X(x) \cdot f_Y(y) " /> for all <em>x</em> and <em>y</em>, then <em>X</em> and <em>Y</em> are said to be <a class="mw-redirect" title="Statistical independence" href="http://en.wikipedia.org/wiki/Statistical_independence"><span style="color: #0645ad;">independent</span></a>.</p>
<h2><span id="See_also" class="mw-headline"><span style="color: #000000;">See also</span></span></h2>
<ul>
<li><a title="Chow-Liu tree" href="http://en.wikipedia.org/wiki/Chow-Liu_tree"><span style="color: #0645ad;">Chow-Liu tree</span></a></li>
<li><a title="Conditional probability" href="http://en.wikipedia.org/wiki/Conditional_probability"><span style="color: #0645ad;">Conditional probability</span></a></li>
<li><a title="Copula (statistics)" href="http://en.wikipedia.org/wiki/Copula_(statistics)"><span style="color: #0645ad;">Copula (statistics)</span></a></li>
<li><a class="mw-redirect" title="Bayesian networks" href="http://en.wikipedia.org/wiki/Bayesian_networks"><span style="color: #0645ad;">Bayesian networks</span></a></li>
<li><a title="Disintegration theorem" href="http://en.wikipedia.org/wiki/Disintegration_theorem"><span style="color: #0645ad;">Disintegration theorem</span></a></li>
<li><a title="Multivariate statistics" href="http://en.wikipedia.org/wiki/Multivariate_statistics"><span style="color: #0645ad;">Multivariate statistics</span></a></li>
<li><a title="Multivariate normal distribution" href="http://en.wikipedia.org/wiki/Multivariate_normal_distribution"><span style="color: #0645ad;">Multivariate normal distribution</span></a></li>
<li><a title="Multivariate stable distribution" href="http://en.wikipedia.org/wiki/Multivariate_stable_distribution"><span style="color: #0645ad;">Multivariate stable distribution</span></a></li>
<li><a title="Negative multinomial distribution" href="http://en.wikipedia.org/wiki/Negative_multinomial_distribution"><span style="color: #0645ad;">Negative multinomial distribution</span></a></li>
<li><a title="Statistical interference" href="http://en.wikipedia.org/wiki/Statistical_interference"><span style="color: #0645ad;">Statistical interference</span></a></li>
</ul>
<h2><span id="External_links" class="mw-headline"><span style="color: #000000;">External links</span></span></h2>
<ul>
<li><a class="external text" rel="nofollow" href="http://planetmath.org/?op=getobj&amp;from=objects&amp;id=576"><span style="color: #3366bb;">Joint continuous density function</span></a> on <a title="PlanetMath" href="http://en.wikipedia.org/wiki/PlanetMath"><span style="color: #0645ad;">PlanetMath</span></a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://michael-george-hart.com/2010-11-27/2011/08/05/joint-probability-distribution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.845 seconds -->

