{"id":1351,"date":"2015-04-12T11:18:15","date_gmt":"2015-04-12T15:18:15","guid":{"rendered":"http:\/\/codinggorilla.domemtech.com\/?p=1351"},"modified":"2015-04-14T08:09:01","modified_gmt":"2015-04-14T12:09:01","slug":"synchronization-using-barrier-for-tasks-in-the-net-task-parallel-library","status":"publish","type":"post","link":"http:\/\/165.227.223.229\/index.php\/2015\/04\/12\/synchronization-using-barrier-for-tasks-in-the-net-task-parallel-library\/","title":{"rendered":"Synchronization Using Barrier for Tasks in the .NET Task Parallel Library"},"content":{"rendered":"<p>Lately I have been\u00c2\u00a0converting some\u00c2\u00a0GPGPU algorithms from CUDA into C# and the Task Parallel Library, e.g., tiled reduction. However, I noticed a significant problem in the efficiency of the System.Threading.Barrier class for task synchronization. This problem was also noted by Andrea Esuli\u00c2\u00a0<a href=\"http:\/\/www.esuli.it\/2013\/12\/12\/on-the-efficiency-of-synchronizing-tasks-with-a-barrier\/\" target=\"_blank\">here<\/a>, who proposed an incomplete solution.<\/p>\n<p>As stated\u00c2\u00a0in the <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.threading.barrier%28v=vs.110%29.aspx\" target=\"_blank\">documentation<\/a>, &#8220;[Barrier] enables multiple <strong>tasks<\/strong> to cooperatively work on an algorithm in parallel through multiple phases.&#8221; Although it does work with\u00c2\u00a0System.Threading.Tasks.Task, when the participant\u00c2\u00a0count for the Barrier is more\u00c2\u00a0than four&#8211;the number of cores in my CPU&#8211;the method\u00c2\u00a0SignalAndWait() blocks with a time out of one second, probably because Barrier blocks a thread serving multiple task. The example below illustrates the problem using Barrier and Task with a large\u00c2\u00a0number of tasks spawned. Notwithstanding the efficiency, Barrier.SignalAndWait() is correct.<\/p>\n<p>As noted by Esuli, a solution is to try to coerce\u00c2\u00a0each\u00c2\u00a0task to be in its own thread using\u00c2\u00a0TaskCreationOptions.LongRunning during construction. Unfortunately, this seems to only work outside a debugging session, or for problems with a\u00c2\u00a0participant\u00c2\u00a0count up to 8 when debugging the program. This limits its use. Esuli also notes to use\u00c2\u00a0ManualResetEvent instead of Barrier. Unfortunately, that solution\u00c2\u00a0isn&#8217;t correct because\u00c2\u00a0ManualResetEvent.Set() does not block the execution of the code following the Set() in a task the same way as Barrier.<\/p>\n<p>The best solution I came up with is a task-level barrier, implemented as follows. (1) Replace &#8220;SignalAndWait();&#8221; in each\u00c2\u00a0task with &#8220;await Task.Yield();&#8221;. (2) Create a custom task scheduler that maintains a special queue for the execution of the asynchronous continuation tasks. The scheduler examines the context of the call to QueueTask(Task task). If the call is for a continuation, place the task on a special queue to be executed after all &#8220;normal&#8221; tasks. (3) When the final continuation task has been queued, transfer the continuation tasks the the normal queue. (4) Wait for all normal tasks to complete using Task.WaitAll(&#8230;). (5) Complete all continuation tasks using RunSynchronously().<\/p>\n\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lately I have been\u00c2\u00a0converting some\u00c2\u00a0GPGPU algorithms from CUDA into C# and the Task Parallel Library, e.g., tiled reduction. However, I noticed a significant problem in the efficiency of the System.Threading.Barrier class for task synchronization. This problem was also noted by Andrea Esuli\u00c2\u00a0here, who proposed an incomplete solution. As stated\u00c2\u00a0in the documentation, &#8220;[Barrier] enables multiple tasks &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/165.227.223.229\/index.php\/2015\/04\/12\/synchronization-using-barrier-for-tasks-in-the-net-task-parallel-library\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Synchronization Using Barrier for Tasks in the .NET Task Parallel Library&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[],"tags":[],"_links":{"self":[{"href":"http:\/\/165.227.223.229\/index.php\/wp-json\/wp\/v2\/posts\/1351"}],"collection":[{"href":"http:\/\/165.227.223.229\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/165.227.223.229\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/165.227.223.229\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/165.227.223.229\/index.php\/wp-json\/wp\/v2\/comments?post=1351"}],"version-history":[{"count":0,"href":"http:\/\/165.227.223.229\/index.php\/wp-json\/wp\/v2\/posts\/1351\/revisions"}],"wp:attachment":[{"href":"http:\/\/165.227.223.229\/index.php\/wp-json\/wp\/v2\/media?parent=1351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/165.227.223.229\/index.php\/wp-json\/wp\/v2\/categories?post=1351"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/165.227.223.229\/index.php\/wp-json\/wp\/v2\/tags?post=1351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}