{"id":129,"date":"2011-03-18T19:55:16","date_gmt":"2011-03-18T19:55:16","guid":{"rendered":"https:\/\/blogs.mathworks.com\/seth\/2011\/03\/18\/different-results-in-accelerated-mode-versus-normal-mode\/"},"modified":"2011-03-22T18:54:55","modified_gmt":"2011-03-22T18:54:55","slug":"different-results-in-accelerated-mode-versus-normal-mode","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/simulink\/2011\/03\/18\/different-results-in-accelerated-mode-versus-normal-mode\/","title":{"rendered":"Different Results in Accelerated Mode Versus Normal Mode"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/seth\/guy_rouleau_small.png\" alt=\"Blogger, Guy Rouleau\" style=\"float: left; margin-right: 1em;\">By <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/31651\">Guy Rouleau<\/a><br><br>\r\n\r\nThis week I received a large model giving different results when used as a <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/toolbox\/simulink\/ug\/bq_5wvg-1.html\">referenced model<\/a> in <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/toolbox\/simulink\/ug\/bsp24op-1.html\">Accelerated mode<\/a>, compared to the <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/toolbox\/simulink\/ug\/bsp24op-1.html\">Normal Mode<\/a>. To give you an idea, the top model in this application looked like this:<\/p>\r\n\r\n<p><img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/seth\/2011Q1\/theModel.png\" alt=\"Model representing the issue\"><\/p>\r\n\r\n<p>After a quick inspection of the model, I found nothing obvious.  Accelerated mode uses code generation technology to run the simulation. Real-Time Workshop Embedded Coder offers the <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/toolbox\/ecoder\/ug\/br9mwb6-1.html\">Code Generation Verification (CGV) API<\/a> to verify the numerical equivalence of generated code and the simulation results.  Using this API, I decided to test the code generated for this referenced model. Here is how it works.<\/p>\r\n\r\n<p><strong>Log Input Data<\/strong><\/p>\r\n\r\n<p>To begin, I <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/toolbox\/simulink\/ug\/brh7636.html#f15-109419\">enabled signal logging<\/a> for the signals entering the referenced model in Normal mode. Then I played the top model. This data will allow me to test the Controller subsystem alone, without the plant model.<\/p>\r\n\r\n<p><img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/seth\/2011Q1\/theModelWithLogging.png\" alt=\"Logging controller input data\"><\/p>\r\n\r\n<p><strong>Setup the model to be analyzed<\/strong><\/p>\r\n\r\n<p>From now on, I only need the referenced model. In this model, I <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/toolbox\/simulink\/ug\/f11-46817.html#bru8m5v\">enabled data import<\/a> from the model configuration, so that the previously logged data can be read by the Inport block.<\/p>\r\n\r\n<p>Then I <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/toolbox\/simulink\/ug\/brh7636.html\">enabled signal logging<\/a> for the signals I want to compare. For a first run, I logged only the controller output, to confirm that this setup reproduces the issue.<\/p>\r\n\r\n<p><strong>Write a test script for SIL testing<\/strong><\/p>\r\n\r\n<p>The CGV API is designed to perform Software In the Loop (SIL) and Processor In the Loop (PIL) testing for a model. To write a script validating the numerical equivalence of the generated code, I started with the documentation section <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/toolbox\/ecoder\/ug\/br9mwb6-1.html#br9seym-1\">Example of Verifying Numerical Equivalence Between Two Modes of Execution of a Model<\/a>. Based on this example it took me only a few minutes to write the following:<\/p>\r\n\r\n<style type=\"text\/css\">\r\n\r\npre.codeinput {\r\n  background: #EEEEEE;\r\n  padding: 10px;\r\n}\r\n@media print {\r\n  pre.codeinput {word-wrap:break-word; width:100%;}\r\n} \r\n\r\nspan.keyword {color: #0000FF}\r\nspan.comment {color: #228B22}\r\nspan.string {color: #A020F0}\r\nspan.untermstring {color: #B20000}\r\nspan.syscmd {color: #B28C00}\r\n\r\npre.codeoutput {\r\n  color: #666666;\r\n  padding: 10px;\r\n}\r\n\r\npre.error {\r\n  color: red;\r\n}\r\n\r\np.footer {\r\n  text-align: right;\r\n  font-size: xx-small;\r\n  font-weight: lighter;\r\n  font-style: italic;\r\n  color: gray;\r\n}\r\n\r\n<\/style>\r\n\r\n<div class=\"content\"><pre class=\"codeinput\">cgvModel = <span class=\"string\">'Isolated'<\/span>;\r\n\r\n<span class=\"comment\">% Configure the model<\/span>\r\ncgvCfg = cgv.Config( cgvModel, <span class=\"string\">'Connectivity'<\/span>, <span class=\"string\">'sil'<\/span>)\r\ncgvCfg.configModel();\r\n\r\n<span class=\"comment\">% Execute the simulation<\/span>\r\ncgvSim = cgv.CGV( cgvModel, <span class=\"string\">'Connectivity'<\/span>, <span class=\"string\">'sim'<\/span>)\r\nresult1 = cgvSim.run()\r\n\r\n<span class=\"comment\">% Execute the generated code<\/span>\r\ncgvSil = cgv.CGV( cgvModel, <span class=\"string\">'Connectivity'<\/span>, <span class=\"string\">'sil'<\/span>)\r\nresult2 = cgvSil.run()\r\n\r\n<span class=\"comment\">% Get the output data<\/span>\r\nsimData   = cgvSim.getOutputData(1);\r\nsilData   = cgvSil.getOutputData(1);\r\n\r\n<span class=\"comment\">% Compare results<\/span>\r\n[matchNames, ~, mismatchNames, ~] = <span class=\"keyword\">...<\/span>\r\n    cgv.CGV.compare( simData, silData, <span class=\"string\">'Plot'<\/span>, <span class=\"string\">'mismatch'<\/span>)\r\n<\/pre>\r\n\r\n<br>\r\n\r\n<p>At the completion of this script, the following figure appeared, confirming that the results from the generated code are different from the simulation.<\/p>\r\n\r\n<p><img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/seth\/2011Q1\/resultMismatch.png\" alt=\"CGV output showing result mismatch\"><\/p>\r\n\r\n<p><strong>Identify the origin of the difference<\/strong><\/p>\r\n\r\n<p>To identify the origin of the difference, I enabled logging for more signals in the model. After a few iterations, <em>without modifying the above script<\/em> I identified the following subsystem where the input was identical, but the output was different:<\/p>\r\n\r\n<p><img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/seth\/2011Q1\/problemSS.png\" alt=\"the problematic subsystem\"><\/p>\r\n\r\n<p>When looking at the generated code, I found out that the line for this subsystem is:<\/p>\r\n\r\n<code>(*rty_Out2) = 400.0F * (*rtu_In1) * 100.0F;<\/code>\r\n\r\n<p>I made a quick test and manually changed the code to:<\/p>\r\n\r\n<code>float tmp;<br>\r\ntmp = 400.0F * (*rtu_In1);<br>\r\n(*rty_Out2) = tmp * 100.0F;<\/code>\r\n\r\n<p>Surprisingly, this modified code produces results identical to simulation!<\/p>\r\n\r\n<p><ins datetime=\"2011-03-22T18:00:00+00:00\">Updated 2011-03-22: Note, this doesn't always work.  More information below.<\/ins><\/p>\r\n\r\n<p><strong>Consult an expert<\/strong><\/p>\r\n\r\n<p>I have to admit, I had no idea how these two similar codes could lead to different results, so I asked one of our experts in numerical computation.<\/p>\r\n\r\n<p>I learned that some compilers use a technology called <a href=\"http:\/\/en.wikipedia.org\/wiki\/Extended_precision\">extended precision<\/a>. With this technology, when you have a line of code including more than one operation, the compiler can use a larger container to store intermediary results. The goal of this technology is to provide more accurate results, however in this case it also leads to surprises.<\/p>\r\n\r\n<p>After understanding this behavior, we recommended to the user a few options to avoid this type of <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/toolbox\/rtw\/ug\/f26829.html#f15538\">expression folding<\/a> in the generated code and consequently avoid this behavior of the compiler.<\/p>\r\n\r\n<p><ins datetime=\"2011-03-22T18:00:00+00:00\">Updated 2011-03-22: Note, the root cause of this difference is not the RTW Expression Folding option, that just happens to work around the behavior of the compiler.  The right way to prevent the compiler from using extended precision is to provide the compiler flags that force it to do the computation as written.<\/ins><\/p> \r\n\r\n<p><strong>Conclusion<\/strong><\/p> \r\n\r\n<p>Without the Code Generation Verification API, I would have spent a lot of time wiring debugging signals in the model. This tool helped me to quickly identify the root cause of the problem without modifying the model. Note that the CGV API can do a lot more than what I showed here. Look at the <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/toolbox\/ecoder\/ug\/br9mwb6-1.html\">CGV documentation<\/a> for more details.<\/p>\r\n\r\n<p><strong>Now it's your turn<\/strong><\/p>\r\n\r\n<p>How do you verify that the generated code is numerically equivalent to your model? Leave a <a href=\"https:\/\/blogs.mathworks.com\/seth\/?p=129&#comment\">comment here<\/a>.<\/p>\r\n \r\n","protected":false},"excerpt":{"rendered":"<p>By Guy Rouleau\r\n\r\nThis week I received a large model giving different results when used as a referenced model in Accelerated mode, compared to the Normal Mode. To give you an idea, the top model in... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/simulink\/2011\/03\/18\/different-results-in-accelerated-mode-versus-normal-mode\/\">read more >><\/a><\/p>","protected":false},"author":41,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[121,21,15,43,76,63],"tags":[185,184],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/simulink\/wp-json\/wp\/v2\/posts\/129"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/simulink\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/simulink\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/simulink\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/simulink\/wp-json\/wp\/v2\/comments?post=129"}],"version-history":[{"count":0,"href":"https:\/\/blogs.mathworks.com\/simulink\/wp-json\/wp\/v2\/posts\/129\/revisions"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/simulink\/wp-json\/wp\/v2\/media?parent=129"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/simulink\/wp-json\/wp\/v2\/categories?post=129"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/simulink\/wp-json\/wp\/v2\/tags?post=129"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}