{"id":5635,"date":"2020-05-06T09:14:04","date_gmt":"2020-05-06T16:14:04","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=5635"},"modified":"2020-05-06T09:14:04","modified_gmt":"2020-05-06T16:14:04","slug":"optimizing-test-resources-with-read-write-bursts","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/arm\/tests\/resources\/bursts\/","title":{"rendered":"Optimizing Test Resources with Read\/Write Bursts"},"content":{"rendered":"<p>This tutorial shows how to improve the performance of the Test Resources\u00a0 (files on the host machine accessed from your embedded unit tests) using the read\/write bursts.<\/p>\n<p>We will start with a basic demo project showing the test resources and will update it to use bursts for better performance. Before you begin, follow our <a href=\"http:\/\/visualgdb.com\/tutorials\/arm\/tests\/resources\">Embedded Test Resources Tutorial<\/a> to create a basic project that uses test resources. Alternatively, you can clone the sample project from our <a href=\"https:\/\/github.com\/sysprogs\/tutorials\/tree\/master\/visualgdb\/ARM\/TestResourcesDemo\">Github repository<\/a>.<\/p>\n<ol>\n<li>Open the project created per the Embedded Test Resources Tutorial and locate the <strong>GenerateTestData()<\/strong> function that generates the <strong>inputs.dat<\/strong> and <strong>outputs.dat<\/strong> files. See how the function produces a chunk of data an then sends it to the host by calling <strong>TRMWriteFile()<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/time1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5636\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/time1.png\" alt=\"\" width=\"1605\" height=\"202\" \/><\/a>you can verify this by stepping into <strong>TRMWriteFile()<\/strong> and seeing that it is simply a wrapper around the <strong>RunBlockingFastSemihostingCall()<\/strong> function:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/01-write.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5640\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/01-write.png\" alt=\"\" width=\"1224\" height=\"821\" \/><\/a><\/li>\n<li>Now we will modify the GenerateTestData() function to use the burst API instead of calling <strong>TRMWriteFile()<\/strong>. Add the following calls before the main loop:\n<pre class=\"\">    auto hInputsBurst = TRMBeginWriteBurst(hInputs);\r\n    auto hOutputsBurst = TRMBeginWriteBurst(hOutputs);<\/pre>\n<p>End the bursts after the main loop and before closing the files:<\/p>\n<pre class=\"\">\u00a0   auto hInputsBurst = TRMBeginWriteBurst(hInputs);\r\n    auto hOutputsBurst = TRMBeginWriteBurst(hOutputs);<\/pre>\n<p>Reduce the size of buf1 and buf2 to <strong>32<\/strong> change the loop count from 256 to <strong>1024 * 1024 \/ sizeof (buf1):<\/strong><\/p>\n<pre class=\"\">    float buf1[32], buf2[32];\r\n    for (int block = 0; block &lt; 1024 * 1024 \/ sizeof(buf1); block++)\r\n    {\r\n        \/\/...\r\n    }<\/pre>\n<p>Finally, replace the calls to <strong>TRMWriteFile()<\/strong> with <strong>TRMWriteFileCached()<\/strong> and change the first argument of each call to the burst handle:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/02-cached-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5643\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/02-cached-1.png\" alt=\"\" width=\"1224\" height=\"821\" \/><\/a><\/li>\n<li>Now instead of waiting for the host to receive the data, TRMWriteFileCached() will quickly copy it to the semihosting buffer and will return control to GenerateTestData(). VisualGDB will then read the previous chunk of data while the embedded code is computing the next one:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/time2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5645\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/time2.png\" alt=\"\" width=\"1605\" height=\"253\" \/><\/a><\/li>\n<li>You can control the size of the semihosting buffer via <strong>VisualGDB Project Properties -&gt; Embedded Frameworks -&gt; Semihosting -&gt; Buffer Size<\/strong>:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/03-buffer.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5642\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/03-buffer.png\" alt=\"\" width=\"932\" height=\"742\" \/><\/a><\/li>\n<li>Try deleting the <strong>inputs.dat<\/strong> and <strong>outputs.dat<\/strong> files from the <strong>TestResources<\/strong> directory and run a regular debug session again (with F5). Observe how they will get re-created faster, as long as you are using a large semihosting buffer.<\/li>\n<li>Now we will show how to use read bursts to speed up the reading of data by the test program. Locate the <strong>SineTest<\/strong> method that reads the data from the test files.<\/li>\n<li>Read bursts require declaring a temporary buffer for each burst where VisualGDB will prefetch the data from the file.\u00a0 Add the following code before the main loop:\n<pre class=\"\">\u00a0   char workArea1[4096], workArea2[4096];\r\n    auto hInputsBurst = TRMBeginReadBurst(hInputs, workArea1, sizeof(workArea1));\r\n    auto hOutputsBurst = TRMBeginReadBurst(hOutputs, workArea2, sizeof(workArea2));<\/pre>\n<p>End the bursts after the main loop:<\/p>\n<pre class=\"\">\u00a0   TRMEndReadBurst(hInputsBurst);\r\n    TRMEndReadBurst(hOutputsBurst);<\/pre>\n<p>As soon as you call TRMBeginReadBurst(), VisualGDB will start filling the work area with the contents of the read file and will continue until the buffer is full. To read the data from the buffer, automatically waiting for it to be filled, replace the calls to TRMReadFile() with TRMReadFileCached():<\/p>\n<pre class=\"\">\u00a0       ssize_t done = TRMReadFileCached(hInputsBurst, buf1, sizeof(buf1), 0);<\/pre>\n<p>The final version of the code should look like shown below:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/04-read.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5646\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/04-read.png\" alt=\"\" width=\"1224\" height=\"821\" \/><\/a><\/li>\n<li>Run the test and make sure it succeeds:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/05-debug-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5648\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/05-debug-1.png\" alt=\"\" width=\"1224\" height=\"821\" \/><\/a><\/li>\n<li>The read bursts can be further optimized by using the <strong>TRMBeginReadFileCached()<\/strong>\/<strong>TRMEndReadFileCached()<\/strong> instead of <strong>TRMReadFileCached()<\/strong>. Instead of copying the data from the work area into <strong>buf1<\/strong> or <strong>buf2<\/strong>, those calls will return a pointer inside the work area that contains the data fetched by VisualGDB. You can access it directly from your test logic and call <strong>TRMEndReadFileCached() <\/strong>to release it, so that VisualGDB could rewrite it with the next portion:\n<pre class=\"\">    for (;;)\r\n    {\r\n        size_t done1, done2;\r\n        float *pBuf1 = (float *)TRMBeginReadFileCached(hInputsBurst, &amp;done1, 1);\r\n        float *pBuf2 = (float *)TRMBeginReadFileCached(hOutputsBurst, &amp;done2, 1);\r\n        if (!pBuf1 || !pBuf2)\r\n        {\r\n            CHECK(!pBuf1 &amp;&amp; !pBuf2);\r\n            break;\r\n        }\r\n        size_t todo = std::min(done1, done2);\r\n        CHECK(todo &gt; 0);\r\n        for (int i = 0; i &lt; (todo \/ sizeof(*pBuf1)); i++)\r\n        {\r\n            float error = fabsf(pBuf2[i] - sinf(pBuf1[i]));\r\n            CHECK(error &lt; 0.001F);\r\n        }\r\n        TRMEndReadFileCached(hInputsBurst, pBuf1, todo);\r\n        TRMEndReadFileCached(hOutputsBurst, pBuf2, todo);\r\n        total += todo;\r\n        g_Progress = total;\r\n    }<\/pre>\n<\/li>\n<li>Try running the test now, it will complete slightly faster than the previous version:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/06-fast.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5649\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/03\/06-fast.png\" alt=\"\" width=\"1224\" height=\"821\" \/><\/a>You can find a detailed overview of the Test Resource Manager API in the <a href=\"https:\/\/visualgdb.com\/documentation\/semihosting\/_t_r_m_a_p_i.html\">official documentation page<\/a>.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to improve the performance of the Test Resources\u00a0 (files on the host machine accessed from your<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[128],"tags":[53,168,129],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/5635"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=5635"}],"version-history":[{"count":2,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/5635\/revisions"}],"predecessor-version":[{"id":5650,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/5635\/revisions\/5650"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=5635"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=5635"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=5635"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}