{"id":8391,"date":"2017-02-10T09:00:27","date_gmt":"2017-02-10T14:00:27","guid":{"rendered":"https:\/\/blogs.mathworks.com\/pick\/?p=8391"},"modified":"2017-02-10T09:52:52","modified_gmt":"2017-02-10T14:52:52","slug":"semaphore-posix-and%e2%80%8b-windows","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/pick\/2017\/02\/10\/semaphore-posix-and%e2%80%8b-windows\/","title":{"rendered":"Semaphore POSIX and\u200b Windows"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\n   <introduction><\/p>\n<p><a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/3208495\">Sean<\/a>&#8216;s pick this week is <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/45504-semaphore-posix-and-windows\">Semaphore POSIX and Windows<\/a> by <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/4033217\">Andrew Smart<\/a>.\n      <\/p>\n<p>   <\/introduction><\/p>\n<h3>Background<a name=\"1\"><\/a><\/h3>\n<p>I&#8217;ve been working with someone to help them parallelize multiple simulations of an external program.  The external program can be driven by its COM API on Windows using <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/actxserver.html\"><tt>actxserver<\/tt><\/a>. This is an ideal candidate for parallel computing because the simulation takes minutes to hours to run and needs to be run for different configurations where there are no dependencies between runs.\n   <\/p>\n<p>My first attempt at this was to use a <a href=\"https:\/\/www.mathworks.com\/help\/distcomp\/parfor.html\"><tt>parfor<\/tt><\/a> loop, looping over configurations in parallel.  It worked the first time(!), but broke the second time and continued to be unreliable.  The problem was that I cannot open the <tt>actxserver<\/tt> at the same time from multiple parallel workers because a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Race_condition\">race condition<\/a> is encountered.\n   <\/p>\n<p>So the challenge: How to enforce that each parallel worker opens the <tt>actxserver<\/tt> at a different time than the others, ideally immediately after the other has finished.\n   <\/p>\n<p>The way to do this is with a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Semaphore_%28programming%29\">semaphore<\/a>, which MATLAB does not have built in.  A semaphore is used to control access to a shared resource.  I vaguely remembered having seen this on the File Exchange before and checked my Pick of the Week candidates list and sure enough, there it was, waiting for a use-case!\n   <\/p>\n<h3>Using The Semaphore<a name=\"2\"><\/a><\/h3>\n<p><b>NOTE<\/b> To use the semaphore, you need to compile using the following command:<\/p>\n<pre class=\"language-matlab\">mex <span class=\"string\">-O<\/span> <span class=\"string\">-v<\/span> <span class=\"string\">semaphore.c<\/span><\/pre>\n<\/p>\n<p>I will first create the semaphore from the client MATLAB.  The parallel workers will grab it before opening the <tt>actxserver<\/tt> and release it after.  The first worker to execute will grab the semaphore, making the other workers enter a First-In-First-Out queue to repeat the process.  After a few seconds of initialization time, all of the workers will be running the lengthy simulation in parallel.\n   <\/p>\n<p>Open parallel computing pool.  This pool has two workers because I have a dual core laptop.<\/p>\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">gcp<\/pre>\n<pre style=\"font-style:oblique\">ans = \r\n Pool with properties: \r\n\r\n            Connected: true\r\n           NumWorkers: 2\r\n              Cluster: local\r\n        AttachedFiles: {}\r\n          IdleTimeout: 90 minute(s) (85 minutes remaining)\r\n          SpmdEnabled: true\r\n<\/pre>\n<p>Create semaphore with key 1 and value 1.  The value here matters, use 1.<\/p>\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">semkey = 1;\r\nsemaphore(<span style=\"color: #A020F0\">'create'<\/span>,semkey,1)<\/pre>\n<p>Run the <tt>parfor<\/tt>-loop\n   <\/p>\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\"><span style=\"color: #0000FF\">parfor<\/span> ii = 1:4\r\n    <span style=\"color: #0000FF\">try<\/span>\r\n        semaphore(<span style=\"color: #A020F0\">'wait'<\/span>,semkey)\r\n        disp(string(<span style=\"color: #A020F0\">'Iteration '<\/span>) + ii + <span style=\"color: #A020F0\">' Started: '<\/span> + string(datetime(<span style=\"color: #A020F0\">'now'<\/span>)))\r\n        pause(2) <span style=\"color: #228B22\">% Proxy for actxserver()<\/span>\r\n        semaphore(<span style=\"color: #A020F0\">'post'<\/span>,semkey)\r\n        disp(string(<span style=\"color: #A020F0\">'Iteration '<\/span>) + ii + <span style=\"color: #A020F0\">' Finished: '<\/span> + string(datetime(<span style=\"color: #A020F0\">'now'<\/span>)))\r\n        <span style=\"color: #228B22\">% Run the simulation here<\/span>\r\n\r\n    <span style=\"color: #0000FF\">catch<\/span>\r\n        <span style=\"color: #228B22\">% In case something goes wrong, release the semaphore<\/span>\r\n        semaphore(<span style=\"color: #A020F0\">'post'<\/span>,semkey)\r\n\r\n    <span style=\"color: #0000FF\">end<\/span>\r\n<span style=\"color: #0000FF\">end<\/span><\/pre>\n<pre style=\"font-style:oblique\">Iteration 3 Started: 08-Feb-2017 11:09:34\r\nIteration 2 Started: 08-Feb-2017 11:09:32\r\nIteration 2 Finished: 08-Feb-2017 11:09:34\r\nIteration 1 Started: 08-Feb-2017 11:09:37\r\nIteration 3 Finished: 08-Feb-2017 11:09:37\r\nIteration 1 Finished: 08-Feb-2017 11:09:39\r\nIteration 4 Started: 08-Feb-2017 11:09:39\r\nIteration 4 Finished: 08-Feb-2017 11:09:41\r\n<\/pre>\n<p>If you look at the times, you will see that iteration 2 started at 32 seconds, and finished two seconds later (<tt>parfor<\/tt> iterations do not run in sorted order).  Iteration 3 starts immediately after 2 and when it finishes iteration 1 begins.  Iteration 4 starts after iteration 1 completes.\n   <\/p>\n<p>Here&#8217;s an annotated image:<\/p>\n<p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/parfortiming.png\"> <\/p>\n<p>Clean up after.<\/p>\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">semaphore(<span style=\"color: #A020F0\">'destroy'<\/span>,semkey)<\/pre>\n<p>I was able to get this working in just a few minutes but did learn a couple lessons the hard way.  A few things to note:<\/p>\n<div>\n<ul>\n<li>Use <tt>try\/catch<\/tt> around the operations you&#8217;re doing.  If the process fails, you want to release the semaphore to unblock the other workers.  This can cause a hang if an error occurs because the loop will never complete as other workers are held.  If you reach this state, force kill the parallel pool from the task manager.\n         <\/li>\n<li>Use <tt>Key=1<\/tt> and <tt>Value=1<\/tt> incrementing <i>Key<\/i> if you have multiple semaphores.  My only advice to Andrew is to make this a little more clear in the  help.\n         <\/li>\n<\/ul><\/div>\n<h3>Comments<a name=\"9\"><\/a><\/h3>\n<p>Give it a try and let us know what you think <a href=\"https:\/\/blogs.mathworks.com\/pick\/?p=8391#respond\">here<\/a> or leave a <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/45504-semaphore-posix-and-windows#comments\">comment<\/a> for Andrew.\n   <\/p>\n<p><script language=\"JavaScript\">\n<!--\n\n    function grabCode_e0c2868b05994561a9925f84a24d71ed() {\n        \/\/ Remember the title so we can use it in the new page\n        title = document.title;\n\n        \/\/ Break up these strings so that their presence\n        \/\/ in the Javascript doesn't mess up the search for\n        \/\/ the MATLAB code.\n        t1='e0c2868b05994561a9925f84a24d71ed ' + '##### ' + 'SOURCE BEGIN' + ' #####';\n        t2='##### ' + 'SOURCE END' + ' #####' + ' e0c2868b05994561a9925f84a24d71ed';\n    \n        b=document.getElementsByTagName('body')[0];\n        i1=b.innerHTML.indexOf(t1)+t1.length;\n        i2=b.innerHTML.indexOf(t2);\n \n        code_string = b.innerHTML.substring(i1, i2);\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\n\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \n        \/\/ in the XML parser.\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\n        \/\/ doesn't go ahead and substitute the less-than character. \n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\n\n        author = 'Sean de Wolski';\n        copyright = 'Copyright 2017 The MathWorks, Inc.';\n\n        w = window.open();\n        d = w.document;\n        d.write('\n\n<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\n\n\\n');\n      \n      d.title = title + ' (MATLAB code)';\n      d.close();\n      }   \n      \n-->\n<\/script><\/p>\n<p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><a href=\"javascript:grabCode_e0c2868b05994561a9925f84a24d71ed()\"><span style=\"font-size: x-small;        font-style: italic;\">Get<br \/>\n            the MATLAB code<br \/>\n            <noscript>(requires JavaScript)<\/noscript><\/span><\/a><\/p>\n<p>      Published with MATLAB&reg; R2016b<\/p>\n<\/div>\n<p><!--\ne0c2868b05994561a9925f84a24d71ed ##### SOURCE BEGIN #####\n%% Semaphore POSIX and? Windows\n%\n% <https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/3208495 Sean>'s pick this week is\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/45504-semaphore-posix-and-windows Semaphore POSIX and? Windows> by\n% <https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/4033217 Andrew Smart>.\n% \n\n%% Background\n% I've been working with someone to help them parallelize multiple simulations\n% of an external program.  The external program can be driven by it's COM\n% API on Windows using\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/actxserver.html |actxserver|>.\n% This is an ideal candidate for parallel computing because the simulation\n% takes minutes to hours to run and needs to be run for different\n% configurations where there are no dependencies between runs.  \n%\n% My first attempt at this was to use a\n% <https:\/\/www.mathworks.com\/help\/distcomp\/parfor.html |parfor|> loop,\n% looping over configurations in parallel.  It worked the first time(!),\n% but broke the second time and continued to be unreliable.  The problem\n% was that I cannot open the |actxserver| at the same time from multiple\n% parallel workers because a <https:\/\/en.wikipedia.org\/wiki\/Race_condition\n% race condition> is encountered.\n%\n% So the challenge: How to enforce that each parallel worker opens the\n% |actxserver| at a different time than the others, ideally immediately\n% after the other has finished.\n%\n% The way to do this is with a\n% <https:\/\/en.wikipedia.org\/wiki\/Semaphore_%28programming%29 semaphore>,\n% which MATLAB does not have built in.  A semaphore is used to control\n% access to a shared resource.  I vaguely remembered having seen this on\n% the File Exchange before and checked my Pick of the Week candidates list\n% and sure enough, there it was, waiting for a use-case!\n\n%% Using The Semaphore\n%\n% To use the semaphore, I first create it from the client MATLAB.  The\n% parallel workers grab it before opening the |actxserver| and release it\n% after.  The first worker to execute will grab the semaphore, making the other workers\n% enter a First-In-First-Out queue to repeat the process.  After a few\n% seconds of initialization time, all of the workers will be running the\n% lengthy simulation in parallel.\n\n%%\n% Open parallel computing pool.  This pool has two workers because I have a dual core laptop.\ngcp \n\n%%\n% Create semaphore with key 1 and value 1.  The value here matters, use 1.\nsemkey = 1;\nsemaphore('create',semkey,1)\n\n%%\n% Run the |parfor|-loop\n\nparfor ii = 1:4\n    try        \n        semaphore('wait',semkey)\n        disp(string('Iteration ') + ii + ' Started: ' + string(datetime('now')))    \n        pause(2) % Proxy for actxserver()\n        semaphore('post',semkey)\n        disp(string('Iteration ') + ii + ' Finished: ' + string(datetime('now')))        \n        % Run the simulation here        \n        \n    catch\n        % In case something goes wrong, release the semaphore\n        semaphore('post',semkey)\n        \n    end\nend \n\n%%\n% If you look at the times, you will see that iteration XX started at YY\n% seconds, and finished two seconds later (|parfor| iterations do not run in\n% sorted order).  Iteration XX starts immediately after XX and finishes two\n% seconds later.  I'm not actually running the simulation so we see\n% iteration XX start immediately after XX-1 etc.\n%\n% Here's an annotated image:\n%\n% <<parfortiming.png>>\n\n\n%%\n% Clean up after.\nsemaphore('destroy',semkey)\n\n%%\n% I was able to get this working in just a few minutes but did learn a\n% couple lessons the hard way.  A few things to note:\n%\n% * Use |try\/catch| around the operations you're doing.  If the process\n% fails, you want to release the semaphore to unblock the other workers.\n% This can cause a hang if an error occurs because the loop will never\n% complete as other workers are held.  If you reach this state, force kill\n% the parallel pool from the task manager.\n% * Use |Key=1| and |Value=1| incrementing _Key_ if you have multiple semaphores.\n%  My only advice to Andrew is to make this a little more clear in the\n%  help.\n\n\n%% Comments\n% \n% Give it a try and let us know what you think\n% <https:\/\/blogs.mathworks.com\/pick\/?p=8391#respond here> or leave a\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/45504-semaphore-posix-and-windows#comments\n% comment> for Andrew.\n%\n \n\n##### SOURCE END ##### e0c2868b05994561a9925f84a24d71ed\n--><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/parfortiming.png\" onError=\"this.style.display ='none';\" \/><\/div>\n<p>Sean&#8216;s pick this week is Semaphore POSIX and Windows by Andrew Smart.<\/p>\n<p>Background<br \/>\nI&#8217;ve been working with someone to help them parallelize multiple simulations of an&#8230; <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/pick\/2017\/02\/10\/semaphore-posix-and%e2%80%8b-windows\/\">read more >><\/a><\/p>\n","protected":false},"author":87,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[16],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/8391"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/users\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/comments?post=8391"}],"version-history":[{"count":11,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/8391\/revisions"}],"predecessor-version":[{"id":8403,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/8391\/revisions\/8403"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/media?parent=8391"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/categories?post=8391"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/tags?post=8391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}