{"id":4855,"date":"2016-08-18T07:27:29","date_gmt":"2016-08-18T07:27:29","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/ongoing-optimization-a-data-race-with-cppmem\/"},"modified":"2023-06-26T12:45:38","modified_gmt":"2023-06-26T12:45:38","slug":"ongoing-optimization-a-data-race-with-cppmem","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/ongoing-optimization-a-data-race-with-cppmem\/","title":{"rendered":"Ongoing Optimization: A Data Race with CppMem"},"content":{"rendered":"<p>But we can improve and further improve the acquire-release semantics of the<a href=\"https:\/\/www.modernescpp.com\/index.php\/ongoing-optimization-acquire-release-semantic-with-cppmem\"> last post<\/a>. Why should x be atomic? There is no reason. That was my first but incorrect assumption. See why?<\/p>\n<p><!--more--><\/p>\n<p>A<a href=\"https:\/\/www.modernescpp.com\/index.php\/acquire-release-semantic-the-typical-misunderstanding\">&nbsp;typical misunderstanding<\/a> in applying the acquire-release semantic is to assume that the acquire operation is waiting for the release operation. So based on this assumption, you may think that x has not be an atomic variable. So we can further optimize the program.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ ongoingOptimizationAcquireReleaseBroken.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;atomic&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;thread&gt;<\/span>\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> x= 0;\r\nstd::atomic&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; y{0};\r\n\r\n<span style=\"color: #2b91af;\">void<\/span> writing(){  \r\n  x= 2000;  \r\n  y.store(11,std::memory_order_release);\r\n}\r\n\r\n<span style=\"color: #2b91af;\">void<\/span> reading(){  \r\n  std::cout &lt;&lt; y.load(std::memory_order_acquire) &lt;&lt; <span style=\"color: #a31515;\">\" \"<\/span>;  \r\n  std::cout &lt;&lt; x &lt;&lt; std::endl;\r\n}\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n  std::<span style=\"color: #0000ff;\">thread<\/span> thread1(writing);\r\n  std::<span style=\"color: #0000ff;\">thread<\/span> thread2(reading);\r\n  thread1.join();\r\n  thread2.join();\r\n};\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The program has a <a href=\"https:\/\/www.modernescpp.com\/index.php\/threads-sharing-data\">data race<\/a> on x and has, therefore, undefined behavior. If <span style=\"font-family: courier new,courier;\">y.store(11,std::memory_order_release)<\/span> (line 12) is executed before&nbsp; <span style=\"font-family: courier new,courier;\">y.load(std::memory_order_acquire)<\/span> (line 16), the acquire-release semantic guarantees that <span style=\"font-family: courier new,courier;\">x= 2000<\/span> (line 11) is executed before the reading of x in line 17. But if not. In this case, the reading of x will be executed simultaneously as the writing of x. So we have&nbsp;concurrent access to a shared variable, one of them is a write. That&#8217;s, per definition, a data race.&nbsp;<span style=\"font-family: courier new,courier;\"> <\/span><\/p>\n<\/p>\n<p>The table puts it in a nutshell.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4840\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/08\/undefinedEng.png\" alt=\"undefinedEng\" style=\"margin: 15px;\" width=\"343\" height=\"240\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/08\/undefinedEng.png 343w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/08\/undefinedEng-300x210.png 300w\" sizes=\"auto, (max-width: 343px) 100vw, 343px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>I made this mistake in my presentation &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php?option=com_content&amp;view=article&amp;id=12;oeffentliche-vortraege&amp;catid=27;vortraege&amp;Itemid=201\">Multithreading done right?<\/a>&#8221; in<a href=\"https:\/\/www.modernescpp.com\/index.php?option=com_content&amp;view=article&amp;id=12;oeffentliche-vortraege&amp;catid=27;vortraege&amp;Itemid=201#MultithreadingDoneRightBerlin\"> Berlin<\/a>. In <a href=\"https:\/\/www.modernescpp.com\/index.php?option=com_content&amp;view=article&amp;id=12;oeffentliche-vortraege&amp;catid=27;vortraege&amp;Itemid=201#MultithreadingDoneRightMoskau\">Moscow<\/a>, I did it right. I never claimed that the C++ memory model is a piece of cake.<\/p>\n<p>Now it&#8217;s time for CppMem. Let&#8217;s see what CppMem finds out.<\/p>\n<h3>CppMem<\/h3>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #2b91af;\">int<\/span> main(){\r\n  <span style=\"color: #2b91af;\">int<\/span> x= 0;\r\n  atomic_int y= 0;\r\n  {{{ { \r\n      x= 2000;\r\n      y.store(11,memory_order_release);\r\n      }\r\n  ||| {\r\n      y.load(memory_order_acquire);\r\n      x;\r\n      }\r\n  }}}\r\n}\r\n<\/pre>\n<\/div>\n<p>The&nbsp;<a href=\"https:\/\/www.modernescpp.com\/index.php?option=com_content&amp;view=article&amp;id=70;threads-teilen-daten&amp;catid=35;c&amp;Itemid=101#KritischerWettlauf\">data race<\/a> occurs if one thread writes x= 2000 and the other reads x. The graph shows a <span style=\"color: #ddb70e;\"><strong>dr<\/strong><\/span> symbol (data race) on the arrow. <em><\/em><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4854\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/08\/raceAcquireRelease.png\" alt=\"raceAcquireRelease\" style=\"margin: 15px;\" width=\"398\" height=\"230\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/08\/raceAcquireRelease.png 398w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/08\/raceAcquireRelease-300x173.png 300w\" sizes=\"auto, (max-width: 398px) 100vw, 398px\" \/><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>The ultimate step in the process of ongoing optimization is still missing. In the<a href=\"https:\/\/www.modernescpp.com\/index.php\/ongoing-optimization-relaxed-semantic-with-cppmem\"> next post<\/a>, I will use the relaxed semantic.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>But we can improve and further improve the acquire-release semantics of the last post. Why should x be atomic? There is no reason. That was my first but incorrect assumption. See why?<\/p>\n","protected":false},"author":21,"featured_media":4840,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[369],"tags":[505,434,486,521],"class_list":["post-4855","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-multithreading-application","tag-acquire-release-semantic","tag-atomics","tag-cppmem","tag-ongoing-optimization"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4855","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=4855"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4855\/revisions"}],"predecessor-version":[{"id":6954,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4855\/revisions\/6954"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/4840"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=4855"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=4855"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=4855"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}