<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tecca Yu</title>
    <description>The latest articles on DEV Community by Tecca Yu (@pykedot).</description>
    <link>https://dev.to/pykedot</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F703126%2F06a45f70-ac8b-4fe0-9802-9140dc295163.png</url>
      <title>DEV Community: Tecca Yu</title>
      <link>https://dev.to/pykedot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pykedot"/>
    <language>en</language>
    <item>
      <title>Project stage 3 - Analysis</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Tue, 19 Apr 2022 17:21:42 +0000</pubDate>
      <link>https://dev.to/pykedot/4-19-fic</link>
      <guid>https://dev.to/pykedot/4-19-fic</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi, this is Tecca, and this post is a summary of the project, for more details check previous posts about &lt;a href="https://dev.to/pykedot/111-46d"&gt;stage1&lt;/a&gt; and &lt;a href="https://dev.to/pykedot/4-6-44e4"&gt;stage2&lt;/a&gt; of the project.&lt;/p&gt;

&lt;p&gt;In stage 2, I implemented auto-vectorization to the project and in this post I will go over some details and see if there are places that auto-vectorization was not applied and why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Re-cap
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Before applying auto-vectorization running djpeg
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xk-SPnCQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oawsgix3c00u4oak9138.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xk-SPnCQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oawsgix3c00u4oak9138.png" alt="Image description" width="880" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  After applying auto-vectorization and running djpeg on qemu-aarch64
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x5glnQ7n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y8qa6h9q2zj1farjaj5z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x5glnQ7n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y8qa6h9q2zj1farjaj5z.png" alt="Image description" width="880" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  number of whilelo after applying auto-vectorization
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BQjGZgKI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ox2ogmik2kjpdylp6b31.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BQjGZgKI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ox2ogmik2kjpdylp6b31.png" alt="Image description" width="880" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I assumed the above screen shots evidently show that auto-vectorization was successfully applied to the project and the original function djpeg works fine without crashing. But I wonder if all the necessary locations were auto-vectorized.&lt;/p&gt;

&lt;p&gt;I believe my implementation will actually run slower than the original code if I test it on qemu-aarch64 due to the nature of qEmu-aarch64 that it will allow regular code to run at full speed on processors, and run SVE2 instructions at a slower speed.&lt;/p&gt;

&lt;p&gt;Anyways, to get a log of all the vectorized file and not vectorized file, I need to rebuild the project the way I did in stage 2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make -j$((`nproc`+1)) |&amp;amp; tee make.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Through this we are storing the make process detail in the make.log file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jbw0ZK-r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sfavzyqg8bnjvk3hc9dd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jbw0ZK-r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sfavzyqg8bnjvk3hc9dd.png" alt="Image description" width="880" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can tell from the log that there are definitely places that were "missed" from auto-vectorization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Detail of not vectorized files
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hBX_FNoS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lcw9a4htgafam1phogcx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hBX_FNoS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lcw9a4htgafam1phogcx.png" alt="Image description" width="880" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qSYQgOpx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xim1lyvatoar4y3j4szx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qSYQgOpx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xim1lyvatoar4y3j4szx.png" alt="Image description" width="714" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can tell from the above screen shot, the amount of files vectorized are way less than the files that are not vectorized.&lt;/p&gt;

&lt;p&gt;My guess is that only the files with loops that will process large amount of data will get optimized by auto-vectorization, because optimizing the loops that does not process large amount of data will very unlikely benefit from auto-vectorization. And it make sense that the important loops are way less than the less important ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different vectorization
&lt;/h2&gt;

&lt;p&gt;two types of vectors were used variable length and specified byte  vector&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nYh3p4iV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/clnw624mlv9fiqcizvk3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nYh3p4iV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/clnw624mlv9fiqcizvk3.png" alt="Image description" width="880" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Trying to look into not vectorized code and apply modifications
&lt;/h2&gt;

&lt;p&gt;I tried to modify the codes that are not vectorized and try to see if I could manually auto-vectorize them. But none of the methods I try work, and there could be various reasons to that and it was actually explained in to make.log.&lt;/p&gt;

&lt;p&gt;I did a bit of research and some say in most cases, a C/C++ compiler cannot vectorize the for-loop because it cannot match its structure to a predefined vectorization template.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Throughout the 3 stages, I selected candidate open-source package for optimization, in stage 3 I tried adding SVE2 support manually but I couldn't add more vectorization through modifying the source code, but I successfully added auto-vectorization in stage 2 to presumably all the necessary locations in the library by modifying compiler options.&lt;/p&gt;

</description>
      <category>spo600</category>
    </item>
    <item>
      <title>Project stage 2 - Implementation (part 2)</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Wed, 06 Apr 2022 10:47:18 +0000</pubDate>
      <link>https://dev.to/pykedot/4-6-44e4</link>
      <guid>https://dev.to/pykedot/4-6-44e4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi，this is Tecca, this post is for the purpose of SPO600 project stage 2, to understand it more please check &lt;a href="https://dev.to/pykedot/4-5-4lc2"&gt;part 1&lt;/a&gt;. In this post, I will be adding auto-vectorization as SVE2 support for project libjpeg-turbo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 2: Implementing auto-vectorization
&lt;/h2&gt;

&lt;p&gt;Last time, I successfully set up our environment and executed one of the executable(djpeg) with the option(-fast) in Unix system.&lt;/p&gt;

&lt;p&gt;This time, I will start by adding the new compiler options to the entire program.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--23HWEnR1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2x7np8qnns1npw4pguyx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--23HWEnR1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2x7np8qnns1npw4pguyx.png" alt="Image description" width="880" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The default compile option was set to -O3 -DNDEBUG as you can see on the above image.&lt;/p&gt;

&lt;p&gt;What I need to do is to modify it to adapt SVE2 implementation. After a bit of research online and through the project directories. I found out that Compiler flags and CMAKE_ASM_FLAGS both resides in the CMakeCache.txt file which is generated after first run of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmake -G"Unix Makefiles"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Flags used by the C compiler during all build types.
CMAKE_C_FLAGS:STRING=
...
//Flags used by the C compiler during RELEASE builds.
CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
...
//Flags used by the ASM compiler during all build types.
CMAKE_ASM_FLAGS:STRING=
...
//Flags used by the ASM compiler during RELEASE builds.
CMAKE_ASM_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can either modify the CMAKE_ASM_FLAGS_RELEASE:STRING and CMAKE_ASM_FLAGS_RELEASE:STRING in the CMakeCache.txt file manually or export CFLAGS as environment variable before running cmake for the first time.&lt;/p&gt;

&lt;p&gt;Modifiying CMAKE_C_FLAGS would take affect on all build types, but since we are only working with release build at this time it would be better for us to only modify the ones that will be used by C compiler during RELEASE builds.&lt;/p&gt;

&lt;p&gt;Example command for exporting CFLAGS as environment variable&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export CFLAGS="-g -fopt-info-vec-all -march=armv8-a+sve2"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After changing the compiler options to the one we need and cmake again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NNPlxXGS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pv5le64niwbscqjfqwny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NNPlxXGS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pv5le64niwbscqjfqwny.png" alt="Image description" width="880" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that both compiler flags are changed to the one we want for SVE2.&lt;/p&gt;

&lt;p&gt;Now we &lt;strong&gt;make&lt;/strong&gt; again just like we did in part 1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make -j$((`nproc`+1))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pa7_Tloq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/203job464wj04xz43g9e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pa7_Tloq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/203job464wj04xz43g9e.png" alt="Image description" width="880" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The build was successful.&lt;br&gt;
Now we need to see if the whilelo instructions are applied in all possible locations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6h2SA5Im--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03cfboxpyae19vzfwmk6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6h2SA5Im--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03cfboxpyae19vzfwmk6.png" alt="Image description" width="880" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The find and grep was able to fetch 1972 whilelo instructions among all possible locations. Which means that we have build the project correctly. Now let's see if &lt;strong&gt;djpeg&lt;/strong&gt; works fine as how we did in part 1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; We can't run it the same way we did in part 1 since currently there is no hardware that supports SVE2 instructions, We now have to use &lt;strong&gt;qemu-aarch64&lt;/strong&gt; which will allow us to use SVE2 instructions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u9g0hy_w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e867ynfl93plvltowtn9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u9g0hy_w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e867ynfl93plvltowtn9.png" alt="Image description" width="880" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The testimgint.jpg was successfully decompressed and generated a new decompressed.pgm just like what we've done in part 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, we've successfully add SVE2(auto-vectorization)support to the project and run with qumu-aarch64 without breaking anything.&lt;/p&gt;

</description>
      <category>spo600</category>
      <category>stage2</category>
    </item>
    <item>
      <title>Project stage 2 - Implementation (part 1)</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Tue, 05 Apr 2022 15:39:39 +0000</pubDate>
      <link>https://dev.to/pykedot/4-5-4lc2</link>
      <guid>https://dev.to/pykedot/4-5-4lc2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi，this is Tecca, this post is for the purpose of SPO600 project stage 2, to understand it more please check &lt;a href="https://dev.to/pykedot/111-46d"&gt;previous post&lt;/a&gt;. I decided to add auto-vectorization as SVE2 support in the package libjpeg-turbo of the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 2: Setting up environment
&lt;/h2&gt;

&lt;p&gt;First thing is to set up the package for the Unix environment and compile the project to get everything running as it is suppose to be before making auto-vectorization implementation.&lt;/p&gt;

&lt;p&gt;After cloning the repo, let's take a look at all the files first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BcD8xdvZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3uh9njx7blzs9vfq4d12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BcD8xdvZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3uh9njx7blzs9vfq4d12.png" alt="Image description" width="880" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Within the &lt;strong&gt;BUILDING.md&lt;/strong&gt; file, it tells us the building procedure we need to take in order to build the project for our Unix system. I will build it with default flags first to see if everything is working properly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yy3n7fnQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1i0e8xukt56ondsl8tb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yy3n7fnQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1i0e8xukt56ondsl8tb.jpg" alt="Image description" width="880" height="452"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmake -G"Unix Makefiles"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running the above building procedure command:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xtim9qmb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpnpy9nvpo5zx1c2lpvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xtim9qmb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpnpy9nvpo5zx1c2lpvw.png" alt="Image description" width="880" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cmpKoTI3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v75iqgv8r0q8z4m3zpne.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cmpKoTI3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v75iqgv8r0q8z4m3zpne.png" alt="Image description" width="880" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the default &lt;strong&gt;Compiler flags&lt;/strong&gt; = -03 -DNDEBUG, this tells us that with that optimization level it allows all normal optimization.&lt;/p&gt;

&lt;p&gt;Just in case you are curious about the -DNDEBUG, it is actually used to disable assert(), If the macro &lt;strong&gt;NDEBUG&lt;/strong&gt; is defined as a macro name at the point in the source code where  or  is included, then assert does nothing. After a bit of research, in general people use it to signal a release/debug switch. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.cppreference.com/w/cpp/error/assert"&gt;Resource&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets run the command &lt;code&gt;make&lt;/code&gt; to build the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make -j$((`nproc`+1))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-j&lt;/code&gt; indicates how many jobs it will run in parallel. &lt;code&gt;nproc&lt;/code&gt; will return the number of cores on your machine. By wrapping it in the ticks, the nproc command will execute first, return a number and that number will be passed into make. In this case, I used core-count + 1 by recommendation for faster compile time also making sure all cores are loaded, you can use define core to use ranging from core-count+1 to core-count*2. so -j$((&lt;code&gt;nproc&lt;/code&gt;+1))  means it will run number of core I have on this system + 1 jobs in parallel at a time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://unix.stackexchange.com/questions/208568/how-to-determine-the-maximum-number-to-pass-to-make-j-option"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1WQHaK9H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0matc8iv0u360vt9du4t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1WQHaK9H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0matc8iv0u360vt9du4t.png" alt="Image description" width="880" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I'm running on a 16 core system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nGYRzWtQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vekprzaofuwkg4vffgs6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nGYRzWtQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vekprzaofuwkg4vffgs6.png" alt="Image description" width="731" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seems like everything is successfully build, lets look at the generated executable files before we move onto the next step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s0Gta1TD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ca03srvsqvqeq5gqp2kj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s0Gta1TD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ca03srvsqvqeq5gqp2kj.png" alt="Image description" width="880" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The files in green are the executables and we can also use the following command to list only executables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;find . -executable -type f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tAFNcr5z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/djghbll6nornlu98dtzk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tAFNcr5z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/djghbll6nornlu98dtzk.png" alt="Image description" width="880" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Within the usage.txt it has guidance on how to use the executables and what is their purpose. I will go with &lt;strong&gt;djpeg&lt;/strong&gt; executable, which decompress a JPEG file back into a conventional image format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GENERAL USAGE

We provide two programs, cjpeg to compress an image file into JPEG format,
and djpeg to decompress a JPEG file back into a conventional image format.

On most systems, you say:
        cjpeg [switches] [imagefile] &amp;gt;jpegfile
or
        djpeg [switches] [jpegfile]  &amp;gt;imagefile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I will also try the &lt;strong&gt;-fast&lt;/strong&gt; option they mentioned in the usage.txt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; -fast           Select recommended processing options for fast, low
                        quality output.  (The default options are chosen for
                        highest quality output.)  Currently, this is equivalent
                        to "-dct fast -nosmooth -onepass -dither ordered".
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I will be using test images in the /testimages directory to test out &lt;strong&gt;djpeg&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RocbkaSR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x0pad2o1ezfyecs3nst9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RocbkaSR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x0pad2o1ezfyecs3nst9.png" alt="Image description" width="802" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After running the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./djpeg -fast ./testimages/testimgint.jpg &amp;gt; decompressed.pgm

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I9hzNPvQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6ilg2qzgrpal53p3yir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I9hzNPvQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6ilg2qzgrpal53p3yir.png" alt="Image description" width="880" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We got a new decompressed pgm file from the testimgint.jpg file!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EiXpCjJx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rwluaeawljf2vidfv6dz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EiXpCjJx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rwluaeawljf2vidfv6dz.png" alt="Image description" width="880" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By comparing the size of the decompressed pgm file and orginal jpg file, we can tell from the increased size that djep was successfully executed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, we've successfully set up our environment and executed one of the executable(djpeg) with the option(-fast) in Unix system, I will be moving onto implementing the auto-vectorization in the up coming post soon.&lt;/p&gt;

</description>
      <category>spo600</category>
      <category>autovectorization</category>
    </item>
    <item>
      <title>SPO600 Project - Candidate Selection final summary</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Tue, 29 Mar 2022 02:40:34 +0000</pubDate>
      <link>https://dev.to/pykedot/111-46d</link>
      <guid>https://dev.to/pykedot/111-46d</guid>
      <description>&lt;p&gt;Hello, this is Tecca, with regard to previous post, in this &lt;a href="https://dev.to/pykedot/11-24m9"&gt;post&lt;/a&gt; I will do an update on two candidate packages that I was looking into, and summarize with what my approaches are towards optimization in the end.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;FFmpeg&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;FFmpeg is a collection of libraries and tools to process multimedia content such as audio, video, subtitles and related metadata.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://ffmpeg.org/"&gt;FFmpeg website&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/FFmpeg/FFmpeg"&gt;FFmpeg Github repo&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rtm - Realtime Math&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;This library is geared towards realtime applications that require their math to be as fast as possible. Much care was taken to maximize inlining opportunities and for code generation to be optimal when a function isn't inlined by passing values in registers whenever possible. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/nfrechette/rtm"&gt;Rtm Github repo&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;libjpeg-turbo&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;libjpeg-turbo is a JPEG image codec that uses SIMD instructions to accelerate baseline JPEG compression and decompression on x86, x86-64, Arm, PowerPC, and MIPS systems, as well as progressive JPEG compression on x86, x86-64, and Arm systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/libjpeg-turbo/libjpeg-turbo"&gt;libjpeg-turbo repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I came across these three packages feeling they could greatly benefit from utilizing sve2, both of them does not have SVE/SVE2 optimization implemented. After doing a bit of research, I decided to go with libjpeg for this project. &lt;/p&gt;

&lt;p&gt;This(libjpet-turbo) package utilizes SIMD operations, and is already supporting SIMD instructions (MMX, SSE2, AVX2, Neon, AltiVec) and ARM64 architectures. Implementing SVE2 for ARM-v9 seems to be a valid optimization.&lt;/p&gt;

&lt;h1&gt;
  
  
  Strategy - optimization approach
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Three options implementing SVE2 optimizations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;auto vectorization&lt;/li&gt;
&lt;li&gt;inline assembler&lt;/li&gt;
&lt;li&gt;using SVE2 intrinsic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My plan is to start with something small, within the file that utilizes SIMD operation, I will try to implement auto vectorization to it.&lt;/p&gt;

</description>
      <category>spo600</category>
      <category>projectstage1</category>
    </item>
    <item>
      <title>SPO600 Project - Candidate Selection</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Sat, 26 Mar 2022 07:02:42 +0000</pubDate>
      <link>https://dev.to/pykedot/11-24m9</link>
      <guid>https://dev.to/pykedot/11-24m9</guid>
      <description>&lt;p&gt;Hi this is Tecca, this post is meant to be an update on progress of me finding a candidate package for the SPO600 project stage 1.&lt;/p&gt;

&lt;h1&gt;
  
  
  Stages of the project
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Stage 1: Selection
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Searching and selecting candidate packages to optimize, pick an approach to optimize the current code in the package.
## Stage 2: Implementation&lt;/li&gt;
&lt;li&gt;Implementing the approach of optimizations mentioned in Stage 1, and testing the program to ensure that it uses the SVE2 instructions without crashing the program.
## Stage 3: Upstreaming&lt;/li&gt;
&lt;li&gt;submitting changes into the upstream codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What I need
&lt;/h1&gt;

&lt;p&gt;I need to be able to find a package that is open-source and use SIMD(Single Input, Multiple Data) implementation at the library-level, and making sure they don't already have SVE or SVE2 optimizations already implemented.&lt;/p&gt;

</description>
      <category>spo600</category>
      <category>stage1</category>
    </item>
    <item>
      <title>SVE2 (Scalable Vector Extension version 2) - LAB 6 part 2</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Sat, 26 Mar 2022 07:02:25 +0000</pubDate>
      <link>https://dev.to/pykedot/project-stage-1-591l</link>
      <guid>https://dev.to/pykedot/project-stage-1-591l</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Welcome back to part 2 of SVE2(Scalable Vector Extension version 2). If you are not sure about what this post is about, you can see the &lt;a href="https://dev.to/pykedot/lab6-3pdd"&gt;part 1&lt;/a&gt; to have a better idea.&lt;/p&gt;

&lt;h1&gt;
  
  
  Source code (vol1.c) for conversion to adapt SVE2
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdbool.h&amp;gt;
#include "vol.h"

int16_t scale_sample(int16_t sample, int volume) {

        return ((((int32_t) sample) * ((int32_t) (32767 * volume / 100) &amp;lt;&amp;lt;1) ) &amp;gt;&amp;gt; 16);
}

int main() {
        int             x;
        int             ttl=0;

// ---- Create in[] and out[] arrays
        int16_t*        in;
        int16_t*        out;
        in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
        out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));

// ---- Create dummy samples in in[]
        vol_createsample(in, SAMPLES);

// ---- This is the part we're interested in!
// ---- Scale the samples from in[], placing results in out[]
        for (x = 0; x &amp;lt; SAMPLES; x++) {
                out[x]=scale_sample(in[x], VOLUME);
        }

// ---- This part sums the samples.

        for (x = 0; x &amp;lt; SAMPLES; x++) {
                ttl=(ttl+out[x])%1000;
        }

// ---- Print the sum of the samples.

        printf("Result: %d\n", ttl);

        return 0;

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can tell, this is vol1 from &lt;a href="https://dev.to/pykedot/lab-5-1omi"&gt;previous post&lt;/a&gt; about algorithm selection.&lt;br&gt;
Note that vol1 utilizes a fixed-point calculation. This avoids the cost of repetitively casting between integer and floating point.&lt;/p&gt;
&lt;h1&gt;
  
  
  Converting
&lt;/h1&gt;
&lt;h2&gt;
  
  
  C Compiler Options
&lt;/h2&gt;

&lt;p&gt;most compilers do not have a specific target for Armv9 systems. Therefore, to build code that includes SVE2 instructions, we will need to instruct the complier to emit code for an Armv8-a processor that also understands the SVE2 instructions; on the GCC compiler, this is performed using the -march= option&lt;/p&gt;

&lt;p&gt;we have to instruct the compiler to emit code for an Armv8a processor to make it understand SVE2 to do that we need to invoke the autovectorizer in GCC version 11, we must use -O3 or the appropriate feature options&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcc -O3 -march=armv8-a+sve2 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our case, we will be working with vol1&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcc -o3 -march=armv8-a+sve2 vol1.c vol_createsample.c -o vol1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we can execute the program by emulating with the QEMU usermode system. This will trap SVE2 instructions and emulate them in software, while executing Armv8a instructions directly on the hardware:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;qemu-aarch64 ./vol1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Result:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p_xbujIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wat8oc4hzcocq8com9we.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p_xbujIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wat8oc4hzcocq8com9we.png" alt="Image description" width="730" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Converted code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.arch armv8-a+sve2
        .file   "vol1.c"
        .text
        .align  2
        .p2align 4,,11
        .global scale_sample
        .type   scale_sample, %function
scale_sample:
.LFB24:
        .cfi_startproc
        lsl     w2, w1, 15
        mov     w3, 34079
        sub     w1, w2, w1
        movk    w3, 0x51eb, lsl 16
        sxth    w0, w0
        smull   x3, w1, w3
        asr     x3, x3, 37
        sub     w1, w3, w1, asr 31
        lsl     w1, w1, 1
        mul     w0, w1, w0
        lsr     w0, w0, 16
        ret
        .cfi_endproc
.LFE24:
        .size   scale_sample, .-scale_sample
        .section        .rodata.str1.8,"aMS",@progbits,1
        .align  3
.LC0:
        .string "Total Time: %2.9f\n"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Understanding converted code
&lt;/h1&gt;

&lt;h2&gt;
  
  
  SVE2 instructions
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; .cfi_startproc
        lsl     w2, w1, 15
        mov     w3, 34079
        sub     w1, w2, w1
        movk    w3, 0x51eb, lsl 16
        sxth    w0, w0
        smull   x3, w1, w3
        asr     x3, x3, 37
        sub     w1, w3, w1, asr 31
        lsl     w1, w1, 1
        mul     w0, w1, w0
        lsr     w0, w0, 16
        ret
        .cfi_endproc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  corresponding C code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return ((((int32_t) sample) * ((int32_t) (32767 * volume / 100) &amp;lt;&amp;lt;1) ) &amp;gt;&amp;gt; 16);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;‘movk w3, 0x51eb, lsl 16’ contains an ‘lsl 16’ instruction, indicating that the bits are to be shifted left by 16 bits.&lt;/li&gt;
&lt;li&gt;‘sxth ’ tells register w0 to sign the least-significant element of itself.&lt;/li&gt;
&lt;li&gt;‘smull x3, w1, w3’ refers to the multiplication of the value of ‘volume’ by 32767.&lt;/li&gt;
&lt;li&gt;‘lsl w1, w1, 1’ refers to the shifting left one bit at the end.&lt;/li&gt;
&lt;li&gt;‘mul w0, w1, w0’ turns the result of multiplying the sample into a signed 32-bit integer.&lt;/li&gt;
&lt;li&gt;‘lsr w0, w0, 16’ shifts the final resulting integer’s bits to the right 16 times.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;We've done experimenting with SVE2 instructions to the volume adjusting algorithm(vol1). Since SVE2 is very new at the moment and has practically no systems developed for it. And we must use an emulator to run the program. I wasn't able to find a way to test the SVE2 performance of the assembly code. &lt;br&gt;
The most challenging part of the lab I found was when after converting the C code into SVE2 instructions, trying to relate the instructions from SVE2 with the code in the original C file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://wiki.cdot.senecacollege.ca/wiki/SVE2"&gt;SVE2&lt;/a&gt;&lt;/p&gt;

</description>
      <category>spo600</category>
      <category>lab6</category>
    </item>
    <item>
      <title>SVE2 (Scalable Vector Extension version 2) - LAB 6 part 1</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Tue, 22 Mar 2022 07:52:11 +0000</pubDate>
      <link>https://dev.to/pykedot/lab6-3pdd</link>
      <guid>https://dev.to/pykedot/lab6-3pdd</guid>
      <description>&lt;p&gt;Hi, this is Tecca. In this post I will be going over SVE2 which stands for (Scalable Vector Extension version 2) &lt;/p&gt;

&lt;p&gt;SVE2 is an SIMD (Single Input, Multiple Data) instruction set that is only used in the AArch64 computer architecture. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://wiki.cdot.senecacollege.ca/wiki/SVE2"&gt;SVE2&lt;/a&gt; enable vectorization of loops for High Performance Computing, basically means making the program to run faster!&lt;/p&gt;

&lt;p&gt;By applying SVE enables software that process large amount of data to be ported more easily (for example the volume scaling lab). The greatest advantage of using SVE is the ability to write and build software only once, then we can run program on different AArch64 hardware with those binaries. &lt;/p&gt;

&lt;p&gt;The main difference between SVE2 and SVE is the functional coverage of the instruction set. SVE was designed for HPC and ML applications. SVE2 extends the SVE instruction set to enable data-processing domains beyond HPC and ML. The SVE2 instruction set can also accelerate the common algorithms that are used in the following applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Computer vision&lt;/li&gt;
&lt;li&gt;Multimedia&lt;/li&gt;
&lt;li&gt;Long-Term Evolution (LTE) baseband processing&lt;/li&gt;
&lt;li&gt;Genomics&lt;/li&gt;
&lt;li&gt;In-memory database&lt;/li&gt;
&lt;li&gt;Web serving&lt;/li&gt;
&lt;li&gt;General-purpose software&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Source from: &lt;a href="https://developer.arm.com/documentation/102340/0001/Introducing-SVE2?lang=en"&gt;Introducing SVE2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal&lt;/strong&gt; of this experiment is to try to convert our code from &lt;a href="https://dev.to/pykedot/lab-5-1omi"&gt;previous post&lt;/a&gt; # Source code to be converted to adapt SVE.&lt;/p&gt;

&lt;p&gt;In the next post, I will be applying the conversion and verify the result.&lt;/p&gt;

</description>
      <category>spo600</category>
      <category>lab6</category>
      <category>sve2</category>
    </item>
    <item>
      <title>Algorithm Selection LAB 5 in x86_64 and AArch64 - part 2</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Mon, 14 Mar 2022 17:09:21 +0000</pubDate>
      <link>https://dev.to/pykedot/1-19nd</link>
      <guid>https://dev.to/pykedot/1-19nd</guid>
      <description>&lt;p&gt;Hi this is Tecca, this post will be a continuation of last &lt;a href="https://dev.to/pykedot/lab-5-1omi"&gt;post&lt;/a&gt; for comparing the relative performance of various algorithms on a same machine across several implementations of AArch64 and x86_64 systems.&lt;/p&gt;

&lt;p&gt;In this post I will be demonstrating the result of the performance of each algorithms mentions in last &lt;a href="https://dev.to/pykedot/lab-5-1omi"&gt;post&lt;/a&gt;. And going over some questions relate to the algorithms.&lt;/p&gt;

&lt;p&gt;We want to measure the performance of each algorithm specifically and nothing else should be in the way in order to give a correct measurement of the time elapsed performing the algorithm.&lt;/p&gt;

&lt;p&gt;In order to do that we need to make some modification to all the files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;time.h&amp;gt;

        clock_t         start_t, end_t;

        start_t = clock();

// ---- This is the part we're interested in!
// ---- Scale the samples from in[], placing results in out[]
        for (x = 0; x &amp;lt; SAMPLES; x++) {
                out[x]=scale_sample(in[x], VOLUME);
        }

        end_t = clock();
        printf("Time elapsed: %f\n", ((double)start_t - end_t)/CLOCKS_PER_SEC);

every other code goes blow..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key point is to wrap the for loop which performs the scaling of the samples to get the most accurate result of the algorithm when it runs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Declaration for testing&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each file was compiled with the gcc compiler with 
&lt;code&gt;gcc -g -O2 -fopt-info-vec-all -fno-lto -fno-tree-vectorize -fno-tree-loop-vectorize&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;1,500,000,000 Sample was define for each algorithm to test.&lt;/li&gt;
&lt;li&gt;Each algorithm/file was tested 15 times.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example running vol0 in x86_64 systems&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2NPOygyb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9lwaq2sov4209ygoqc4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2NPOygyb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9lwaq2sov4209ygoqc4.png" alt="Image description" width="554" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benchmarking Result running in x86_64 systems&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;vol0&lt;/th&gt;
&lt;th&gt;vol1&lt;/th&gt;
&lt;th&gt;vol2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2.696961&lt;/td&gt;
&lt;td&gt;2.655414&lt;/td&gt;
&lt;td&gt;3.370985&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2.666739&lt;/td&gt;
&lt;td&gt;2.649839&lt;/td&gt;
&lt;td&gt;3.302379&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2.671609&lt;/td&gt;
&lt;td&gt;2.648382&lt;/td&gt;
&lt;td&gt;3.30752&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2.664414&lt;/td&gt;
&lt;td&gt;2.653646&lt;/td&gt;
&lt;td&gt;3.327133&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2.660572&lt;/td&gt;
&lt;td&gt;2.679785&lt;/td&gt;
&lt;td&gt;3.285885&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;2.671767&lt;/td&gt;
&lt;td&gt;2.639657&lt;/td&gt;
&lt;td&gt;3.302924&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;2.685051&lt;/td&gt;
&lt;td&gt;2.633608&lt;/td&gt;
&lt;td&gt;3.396682&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;2.674105&lt;/td&gt;
&lt;td&gt;2.663188&lt;/td&gt;
&lt;td&gt;3.352611&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;2.675021&lt;/td&gt;
&lt;td&gt;2.663653&lt;/td&gt;
&lt;td&gt;3.331424&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;2.677584&lt;/td&gt;
&lt;td&gt;2.651484&lt;/td&gt;
&lt;td&gt;3.291357&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;2.655889&lt;/td&gt;
&lt;td&gt;2.653947&lt;/td&gt;
&lt;td&gt;3.314665&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;2.659099&lt;/td&gt;
&lt;td&gt;2.634871&lt;/td&gt;
&lt;td&gt;3.287128&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;2.591898&lt;/td&gt;
&lt;td&gt;2.66246&lt;/td&gt;
&lt;td&gt;3.283349&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;2.645027&lt;/td&gt;
&lt;td&gt;2.662764&lt;/td&gt;
&lt;td&gt;3.327623&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;2.582574&lt;/td&gt;
&lt;td&gt;2.662238&lt;/td&gt;
&lt;td&gt;3.298565&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;average&lt;/td&gt;
&lt;td&gt;2.658554&lt;/td&gt;
&lt;td&gt;2.654329067&lt;/td&gt;
&lt;td&gt;3.318682&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;median&lt;/td&gt;
&lt;td&gt;2.666739&lt;/td&gt;
&lt;td&gt;2.653947&lt;/td&gt;
&lt;td&gt;3.30752&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In the x86_64 system vol1 algorithm is the fastest, second comes vol0, and vol2 is the slowest out of all three. As what I was expecting in the previous post, because vol2 pre-calculates all results, and looking up answers for each input value afterward absolutely will cost more resources than the others and vol1 beats vol0 by a little by using fixed-point calculation. Which avoids the cost of repetitively casting between integer and floating point.&lt;/p&gt;

&lt;p&gt;We will be testing algorithms in vol4 and vol5 in AArch64 system because the utilize SIMD instructions the programs used are written unique to the AArch64 system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benchmarking result running in AArch64 systems&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;vol0&lt;/th&gt;
&lt;th&gt;vol1&lt;/th&gt;
&lt;th&gt;vol2&lt;/th&gt;
&lt;th&gt;vol4&lt;/th&gt;
&lt;th&gt;vol5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;4.980222&lt;/td&gt;
&lt;td&gt;4.313869&lt;/td&gt;
&lt;td&gt;10.567804&lt;/td&gt;
&lt;td&gt;3.481179&lt;/td&gt;
&lt;td&gt;4.04965&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4.968114&lt;/td&gt;
&lt;td&gt;4.323427&lt;/td&gt;
&lt;td&gt;10.560218&lt;/td&gt;
&lt;td&gt;3.456832&lt;/td&gt;
&lt;td&gt;4.045124&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;4.959307&lt;/td&gt;
&lt;td&gt;4.30239&lt;/td&gt;
&lt;td&gt;10.59247&lt;/td&gt;
&lt;td&gt;3.460554&lt;/td&gt;
&lt;td&gt;4.045296&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4.973315&lt;/td&gt;
&lt;td&gt;4.325246&lt;/td&gt;
&lt;td&gt;10.590718&lt;/td&gt;
&lt;td&gt;3.469896&lt;/td&gt;
&lt;td&gt;4.028074&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;4.961954&lt;/td&gt;
&lt;td&gt;4.31275&lt;/td&gt;
&lt;td&gt;10.585899&lt;/td&gt;
&lt;td&gt;3.493608&lt;/td&gt;
&lt;td&gt;4.039965&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;4.976137&lt;/td&gt;
&lt;td&gt;4.320063&lt;/td&gt;
&lt;td&gt;10.532851&lt;/td&gt;
&lt;td&gt;3.438831&lt;/td&gt;
&lt;td&gt;4.040304&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;4.959057&lt;/td&gt;
&lt;td&gt;4.349743&lt;/td&gt;
&lt;td&gt;10.642468&lt;/td&gt;
&lt;td&gt;3.482111&lt;/td&gt;
&lt;td&gt;4.055758&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;4.960718&lt;/td&gt;
&lt;td&gt;4.317437&lt;/td&gt;
&lt;td&gt;10.534451&lt;/td&gt;
&lt;td&gt;3.469382&lt;/td&gt;
&lt;td&gt;4.150955&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;4.95485&lt;/td&gt;
&lt;td&gt;4.336698&lt;/td&gt;
&lt;td&gt;10.548297&lt;/td&gt;
&lt;td&gt;3.451517&lt;/td&gt;
&lt;td&gt;4.085376&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;4.960642&lt;/td&gt;
&lt;td&gt;4.329521&lt;/td&gt;
&lt;td&gt;10.552774&lt;/td&gt;
&lt;td&gt;3.455712&lt;/td&gt;
&lt;td&gt;4.022335&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;4.952321&lt;/td&gt;
&lt;td&gt;4.332141&lt;/td&gt;
&lt;td&gt;10.550225&lt;/td&gt;
&lt;td&gt;3.384459&lt;/td&gt;
&lt;td&gt;4.041784&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;4.990002&lt;/td&gt;
&lt;td&gt;4.334904&lt;/td&gt;
&lt;td&gt;10.572559&lt;/td&gt;
&lt;td&gt;3.423148&lt;/td&gt;
&lt;td&gt;4.058293&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;4.942643&lt;/td&gt;
&lt;td&gt;4.326342&lt;/td&gt;
&lt;td&gt;10.545258&lt;/td&gt;
&lt;td&gt;3.420771&lt;/td&gt;
&lt;td&gt;4.096189&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;4.957297&lt;/td&gt;
&lt;td&gt;4.317604&lt;/td&gt;
&lt;td&gt;10.548684&lt;/td&gt;
&lt;td&gt;3.391878&lt;/td&gt;
&lt;td&gt;4.020974&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;4.967439&lt;/td&gt;
&lt;td&gt;4.317819&lt;/td&gt;
&lt;td&gt;10.558838&lt;/td&gt;
&lt;td&gt;3.433111&lt;/td&gt;
&lt;td&gt;4.062904&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;average&lt;/td&gt;
&lt;td&gt;4.964267867&lt;/td&gt;
&lt;td&gt;4.323996933&lt;/td&gt;
&lt;td&gt;10.5655676&lt;/td&gt;
&lt;td&gt;3.4475326&lt;/td&gt;
&lt;td&gt;4.056198733&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;median&lt;/td&gt;
&lt;td&gt;4.960718&lt;/td&gt;
&lt;td&gt;4.323427&lt;/td&gt;
&lt;td&gt;10.558838&lt;/td&gt;
&lt;td&gt;3.455712&lt;/td&gt;
&lt;td&gt;4.045296&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Looking at the results from running vol0, vol1, vol2, vol4, vol5.&lt;/p&gt;

&lt;p&gt;In the previous post, we assumed the algorithms that use SIMD instructions would perform faster than others(vol4 and vol5). We can observe that vol4 and vol5 algorithms definitely outperform others. The performance difference between the two come very close to each other. I believe it is because both algorithm inline assembly and compiler intrinsic are almost equally fast.&lt;/p&gt;

&lt;p&gt;vol1 still has a better performance than vol0 in AArch64 as well. &lt;/p&gt;

&lt;p&gt;vol2 algorithm became significantly slower than other algorithms.  This result could possibly mean that the CPU is slow at reading the memory when looking over the pre-calculated values.&lt;/p&gt;

&lt;h1&gt;
  
  
  QUESTIONS SPECIFIC TO ALGORITHMS
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Q: Why is this code needed?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (x = 0; x &amp;lt; SAMPLES; x++) {
                ttl=(ttl+out[x])%1000;
        }

 printf("Result: %d\n", ttl);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code prints out the number of scaled samples in the time the program was run. This is meant to be a post-processing value that is displayed to the user, which can be used to determine how long a certain algorithm takes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Q: What does this next block do? Why?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ifeq ($(shell echo | gcc -E -dM - | grep -c aarch64),1)
        BINARIES:=vol0 vol1 vol2 vol3 vol4 vol5
else
        BINARIES:=vol0 vol1 vol2 vol3
Endif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This block within the Makefile validates which architecture the user is currently in and changes “BINARIES” to different values.&lt;br&gt;
Since vol4.c and vol5.c are design in a way that can only be run in AArch64，it is important to remove it from the BINARIES if the user is not in a aarch64 system to prevent it from building and causing error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Q: What is the purpose of the cast to unint16_t in the next line?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;precalc[(uint16_t) x] = (int16_t) ((float) x * VOLUME / 100.0);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I guess this is some kind of casting to the values to stay the same size (16-bit) even if it is in a different system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Q: What's the point of this dummy program? How does it help with benchmarking?
&lt;/h2&gt;

&lt;p&gt;The dummy program(vol3.c) helps the calculation of each algorithm by doing nothing but creating the samples and count the results. Basically everything but algorithm. Which means it's a baseline in terms of processing time to all the other files that contains different algorithms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Q: what is the purpose of these next two lines?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;in_cursor = in;
        out_cursor = out;
        limit = in + SAMPLES;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two lines prepare the two int16_t pointers and points them to the in and out arrays respectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Q: Are the results usable? Are they accurate?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;printf("Result: %d\n", ttl);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results for vol5 and vol4 are the same, but when comparing them to the naïve implementation the results vary by a lot so I'm not too sure about the accuracy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Q: Why is the increment below 8 instead of 16 or some other value?
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Q: Why is this line not needed in the inline assembler version of this program?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; in_cursor += 8;
 out_cursor += 8;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Incrementing the in_cursor and out_cursor by 8 is because the values are 8 bits apart from each other. &lt;/p&gt;

&lt;p&gt;In the inline assembler version, chances are the assembly code automatically does it within its logic. But with C language, we have to be specific about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Q: what does it mean to "duplicate" values in the next line?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;__asm__ ("dup v1.8h,%w0"::"r"(vol_int)); // duplicate vol_int into v1.8h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;dup&lt;/code&gt; loads the scaling factor and loads it into a 128-bits wide register.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In the end, the measurement of the performance of each algorithm is done to test the assumptions made in the part-1 post of this lab. &lt;br&gt;
As expected, the algorithms(vol4&amp;amp;vol5 in this case) that use SIMD instructions appear to outperform others as they are best at processing multiple data simultaneously.&lt;/p&gt;

</description>
      <category>spo600</category>
      <category>lab5</category>
    </item>
    <item>
      <title>Algorithm Selection LAB 5 in x86_64 and AArch64 - part 1</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Fri, 11 Mar 2022 01:35:51 +0000</pubDate>
      <link>https://dev.to/pykedot/lab-5-1omi</link>
      <guid>https://dev.to/pykedot/lab-5-1omi</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hi this is Tecca, and in this post I will be comparing the relative performance of various algorithms on a same machine across several implementations of AArch64 and x86_64 systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source code&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;vol.h&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* This is the number of samples to be processed */
#define SAMPLES 16

/* This is the volume scaling factor to be used */
#define VOLUME 50.0 // Percent of original volume

/* Function prototype to fill an array sample of
 * length sample_count with random int16_t numbers
 * to simulate an audio buffer */
void vol_createsample(int16_t* sample, int32_t sample_count);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vol.h controls the number of samples(16) to be processed and the volume level(50) to be used&lt;/p&gt;

&lt;p&gt;In vol.h a large number of sample for the algorithms to process seems to be reasonable, because it will allow us to analyze the differences in terms of performance much easier. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vol0.c&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdbool.h&amp;gt;
#include "vol.h"

int16_t scale_sample(int16_t sample, int volume) {
        return (int16_t) ((float) (volume/100.0) * (float) sample);
}

int main() {
        int             x;
        int             ttl=0;

// ---- Create in[] and out[] arrays
        int16_t*        in;
        int16_t*        out;
        in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
        out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));

// ---- Create dummy samples in in[]
        vol_createsample(in, SAMPLES);


// ---- Scale the samples from in[], placing results in out[]
        for (x = 0; x &amp;lt; SAMPLES; x++) {
                out[x]=scale_sample(in[x], VOLUME);
        }

// ---- This part sums the samples
        for (x = 0; x &amp;lt; SAMPLES; x++) {
                ttl=(ttl+out[x])%1000;
        }

// ---- Print the sum of the samples
        printf("Result: %d\n", ttl);
        return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In vol0.c, Audio samples are multiplied by the volume scaling factor, casting between signed 16-bit integers and floating-point values. This way takes up a lot of &lt;em&gt;resources&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vol1.c&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdbool.h&amp;gt;
#include "vol.h"

int16_t scale_sample(int16_t sample, int volume) {
        return ((((int32_t) sample) * ((int32_t) (32767 * volume / 100) &amp;lt;&amp;lt;1) ) &amp;gt;&amp;gt; 16);
}

int main() {
        int             x;
        int             ttl=0;

// ---- Create in[] and out[] arrays
        int16_t*        in;
        int16_t*        out;
        in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
        out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));

// ---- Create dummy samples in in[]
        vol_createsample(in, SAMPLES);

// ---- Scale the samples from in[], placing results in out[]
        for (x = 0; x &amp;lt; SAMPLES; x++) {
                out[x]=scale_sample(in[x], VOLUME);
        }

// ---- This part sums the samples
        for (x = 0; x &amp;lt; SAMPLES; x++) {
                ttl=(ttl+out[x])%1000;
        }

// ---- Print the sum of the samples
        printf("Result: %d\n", ttl);
        return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vol1.c utilizes a fixed-point calculation. This avoids the cost of repetitively casting between integer and floating point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vol2.c&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdbool.h&amp;gt;
#include "vol.h"

int main() {
        int             x;
        int             ttl=0;

// ---- Create in[] and out[] arrays
        int16_t*        in;
        int16_t*        out;
        in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
        out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));

        static int16_t* precalc;

// ---- Create dummy samples in in[]
        vol_createsample(in, SAMPLES);

// ---- Scale the samples from in[], placing results in out[]

        precalc = (int16_t*) calloc(65536,2);
        if (precalc == NULL) {
                printf("malloc failed!\n");
                return 1;
        }

        for (x = -32768; x &amp;lt;= 32767; x++) {
                precalc[(uint16_t) x] = (int16_t) ((float) x * VOLUME / 100.0);
        }

        for (x = 0; x &amp;lt; SAMPLES; x++) {
                out[x]=precalc[(uint16_t) in[x]];
        }

// ---- This part sums the samples
        for (x = 0; x &amp;lt; SAMPLES; x++) {
                ttl=(ttl+out[x])%1000;
        }

// ---- Print the sum of the samples
        printf("Result: %d\n", ttl);
        return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike vol0.c and vol1.c, vol2.c pre-calculates all 65535 results, looking up answers for each input value afterward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vol3.c&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdbool.h&amp;gt;
#include "vol.h"

int16_t scale_sample(int16_t sample, int volume) {
        return (int16_t) 100;
}

int main() {
        int             x;
        int             ttl=0;

// ---- Create in[] and out[] arrays
        int16_t*        in;
        int16_t*        out;
        in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
        out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));

// ---- Create dummy samples in in[]
        vol_createsample(in, SAMPLES);

// ---- Scale the samples from in[], placing results in out[]
        for (x = 0; x &amp;lt; SAMPLES; x++) {
                out[x]=scale_sample(in[x], VOLUME);
        }

// ---- This part sum the samples
        for (x = 0; x &amp;lt; SAMPLES; x++) {
                ttl=(ttl+out[x])%1000;
        }

// ---- Print the sum of the samples
        printf("Result: %d\n", ttl);
        return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vol3.c returns an identical sample value, the purpose of this program seems to be a baseline to compare to the other scaling volume algorithm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vol4.c&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include "vol.h"

int main() {

#ifndef __aarch64__
        printf("Wrong architecture - written for aarch64 only.\n");
#else
        // these variables will also be accessed by our assembler code
        int16_t*        in_cursor;              // input cursor
        int16_t*        out_cursor;             // output cursor
        int16_t         vol_int;                // volume as int16_t

        int16_t*        limit;                  // end of input array

        int             x;                      // array interator
        int             ttl=0 ;                 // array total

// ---- Create in[] and out[] arrays
        int16_t*        in;
        int16_t*        out;
        in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
        out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));

// ---- Create dummy samples in in[]
        vol_createsample(in, SAMPLES);

// ---- Scale the samples from in[], placing results in out[]
        // set vol_int to fixed-point representation of the volume factor
        vol_int = (int16_t)(VOLUME/100.0 * 32767.0);

        in_cursor = in;
        out_cursor = out;
        limit = in + SAMPLES;

        __asm__ ("dup v1.8h,%w0"::"r"(vol_int)); // duplicate vol_int into v1.8h

        while ( in_cursor &amp;lt; limit ) {
                __asm__ (
                        "ldr q0, [%[in_cursor]], #16    \n\t"
                        // load eight samples into q0 (same as v0.8h)
                        // from [in_cursor]
                        // post-increment in_cursor by 16 bytes
                        // ans store back into the pointer register

                        "sqrdmulh v0.8h, v0.8h, v1.8h   \n\t"
                        // with 32 signed integer output,
                        // multiply each lane in v0 * v1 * 2
                        // saturate results
                        // store upper 16 bits of results into
                        // the corresponding lane in v0

                        "str q0, [%[out_cursor]],#16            \n\t"
                        // store eight samples to [out_cursor]
                        // post-increment out_cursor by 16 bytes
                        // and store back into the pointer register

                        : [in_cursor]"+r"(in_cursor), [out_cursor]"+r"(out_cursor)
                        : "r"(in_cursor),"r"(out_cursor)
                        : "memory"
                        );
        }

// --------------------------------------------------------------------

        for (x = 0; x &amp;lt; SAMPLES; x++) {
                ttl=(ttl+out[x])%1000;
        }

        printf("Result: %d\n", ttl);
        return 0;

#endif
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vol4.c uses the SIMD (Single Input, Multiple Data) instructions accessed through inline assembly. Which is only available on AArch64 architectures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vol5.c&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdint.h&amp;gt;
#ifdef __aarch64__
#include &amp;lt;arm_neon.h&amp;gt;
#endif
#include "vol.h"

int main() {

#ifndef __aarch64__
        printf("Wrong architecture - written for aarch64 only.\n");
#else

        register int16_t*       in_cursor       asm("r20");     // input cursor (pointer)
        register int16_t*       out_cursor      asm("r21");     // output cursor (pointer)
        register int16_t        vol_int         asm("r22");     // volume as int16_t

        int16_t*                limit;          // end of input array

        int                     x;              // array interator
        int                     ttl=0;          // array total

// ---- Create in[] and out[] arrays
        int16_t*        in;
        int16_t*        out;
        in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
        out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));

// ---- Create dummy samples in in[]
        vol_createsample(in, SAMPLES);


// ---- Scale the samples from in[], placing results in out[]
        vol_int = (int16_t) (VOLUME/100.0 * 32767.0);

        in_cursor = in;
        out_cursor = out;
        limit = in + SAMPLES ;

        while ( in_cursor &amp;lt; limit ) {
                vst1q_s16(out_cursor, vqrdmulhq_s16(vld1q_s16(in_cursor), vdupq_n_s16(vol_int)));


                in_cursor += 8;
                out_cursor += 8;
        }

// --------------------------------------------------------------------

        for (x = 0; x &amp;lt; SAMPLES; x++) {
                ttl=(ttl+out[x])%1000;
        }


        printf("Result: %d\n", ttl);
        return 0;
#endif
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vol5.c like vol4.c also utilize SIMD instruction but with complier intrinsic built into the compiler. vol5.c is also specific to AArch64 due to usage of unique instructions of AArch64 architecture.&lt;/p&gt;

&lt;p&gt;Above code from vol0.c to vol5.c implement the various algorithms that will be use to test the performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vol_createsample.c&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include "vol.h"

void vol_createsample(int16_t* sample, int32_t sample_count) {
        int i;
        for (i=0; i&amp;lt;sample_count; i++) {
                sample[i] = (rand()%65536)-32768;
        }
        return;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vol_createsample.c contains the function vol_createsample(int16_t* sample, int32_t sample_count) that will be use to create dummy samples for the algorithms to run with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Conclusion&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
In this post we've examine a couple of algorithms for adjusting volume samples. We are aware of how each algorithm differed in their approach of achieving the same goal. In the next post, we will see how the performance of each program is and benchmarking it to prove the expectation.&lt;/p&gt;

</description>
      <category>spo600</category>
      <category>lab5</category>
    </item>
    <item>
      <title>LAB4 - Continued</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Mon, 28 Feb 2022 21:47:48 +0000</pubDate>
      <link>https://dev.to/pykedot/lab4-continued-311i</link>
      <guid>https://dev.to/pykedot/lab4-continued-311i</guid>
      <description>&lt;p&gt;In the previous &lt;a href="https://dev.to/pykedot/lab4-1o2i"&gt;post&lt;/a&gt;, the code was able to loop and print from 0 to 9 onto the screen with both Aarch64 and x84_64.&lt;/p&gt;

&lt;p&gt;In order to print numbers beyond that meaning two digit numbers, modifications to the code needs to be made.&lt;/p&gt;

&lt;p&gt;Expected result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Loop: 00
Loop: 01
Loop: 02
Loop: 03
Loop: 04
...
Loop: 30
etc.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The strategy is to store both the quotient and remainder of the number when it is divided by 10. This allows to also display the number that goes beyond 10 when we display the quotient and remainder side by side onto the screen. &lt;/p&gt;

&lt;p&gt;partial code in x84_64&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;loop:
        movq     $0, %rdx                        /* clearing reminder for division */
        movq     %r15, %rax                      /* set rax to be divide */
        movq     $10, %r10                       /* set divisor 10 */
        div      %r10                            /* perform division */
        movq     %rax, %r14                      /* store quotient to the register*/
        movq     %rdx, %r13                      /* store remainder to the register*/

        add      $0x30, %r14                     /* converting quotient to ASCII */
        add      $0x30, %r13                     /* converting remainder to ASCII */
        mov      %r13b, msg+8                    /* Extra byte in msg with remainder than quotient */
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above takes care of performing the division of the number by 10. Stores the quotient and remainder to the register, converting both of them into ASCII code and later to be set to the position of msg.&lt;br&gt;
Complete Source Code in x84_64:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.text
.globl  _start


_start:

        movq     $0, %r15                        /* Loop counter */
        movq     $0x30, %r12                     /* value of 0 in Ascii */

loop:
        movq     $0, %rdx                        /* clearing reminder for division */
        movq     %r15, %rax                      /* set rax to be divide */
        movq     $10, %r10                       /* set divisor 10 */
        div      %r10                            /* perform division */
        movq     %rax, %r14                      /* store quotient to the register*/
        movq     %rdx, %r13                      /* store remainder to the register*/

        add      $0x30, %r14                     /* converting quotient to ascii */
        add      $0x30, %r13                     /* converting remainder to ascii */
        mov      %r13b, msg+8                    /* Modify 1 byte inmsg with remainder */

        cmp      %r12, %r14
        mov      %r14b, msg+7                    /* Modify 1 byte in msg with quotient */

        movq     $len, %rdx                      /* message length */
        movq     $msg, %rsi                      /* message location */
        movq     $1, %rdi                                /* file descriptor stdout */
        movq     $1, %rax                                /* syscall sys_write */
        syscall

        inc     %r15                            /* increment counter */
        cmp     $31, %r15                               /* see if we're done */
        jne     loop                            /* if not, loop */

        movq     $0, %rdi                                /* exit status */
        movq     $60, %rax                       /* syscall sys_exit */
        syscall

.section .data

        msg:    .ascii   "Loop :   \n"
        len = . - msg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Complete Source Code in Aarch64:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.text
.globl _start


_start:

        mov     x19, 0
        mov     x17, 10

loop:
        mov     x0, 1           /* file descriptor: 1 is stdout */
        adr     x1, msg         /* message location (memory address) */
        mov     x2, len         /* message length (bytes) */

        mov     x18, x19        
        udiv    x9, x18, x17
        add     x13, x9, 0x30
        msub    x10, x9, x17, x18   
        add     x14, x10, 0x30
        adr     x15, msg
        strb    w13, [x15, 7]

        strb    w14, [x15, 8]
        mov     x8, 64          /* write is syscall #64 */
        svc     0               /* invoke syscall */

        add     x19, x19, 1
        cmp     x19, 31
        b.ne    loop

.data

msg:    .ascii      "Loop : #\n"
len=    . - msg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QIUwauqR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gwe74vvmydv56dd1lv59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QIUwauqR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gwe74vvmydv56dd1lv59.png" alt="Image description" width="457" height="613"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Conclusion:&lt;br&gt;
Personally the biggest challenge I found in this lab was to figure out how to perform the division and store the values from the division into two registers and placing then into the msg.&lt;/p&gt;

</description>
      <category>spo600</category>
      <category>assemblylanguage</category>
      <category>lab</category>
    </item>
    <item>
      <title>LAB3 - continued</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Mon, 28 Feb 2022 01:31:44 +0000</pubDate>
      <link>https://dev.to/pykedot/lab3-continued-18m6</link>
      <guid>https://dev.to/pykedot/lab3-continued-18m6</guid>
      <description>&lt;p&gt;In the previous &lt;a href="https://dev.to/joycew414/spo600-lab3-6502-assembly-language-math-lab-1iba"&gt;post&lt;/a&gt;, a drawing program was successfully run on 6502 Emulator, now I want to create a kaleidoscope drawing program.&lt;/p&gt;

&lt;p&gt;My plan is to allow the user to only draw on the second quadrant which is the top left quadrant in the 6502 display and reflecting whatever the user draw on it to the other three quadrant to create an kaleidoscope effect.&lt;/p&gt;

&lt;p&gt;A couple more things needs to be done in order to achieve this.&lt;/p&gt;

&lt;p&gt;First it needs to restrict the cursor's movement to only allow user draw on the second quadrant, in drawing cursor by setting the range of row and column to [$00 : $0F] will make this happen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;drawing_cursor:
    lda ROW     ; ensure ROW is in range 0:0F
    and #$0f
    sta ROW

    lda COL     ; ensure COL is in range 0:0F
    and #$0f
    sta COL

    ldy ROW     ; load POINTER with start-of-row
    lda table_low,y
    sta POINTER
    lda table_high,y
    sta POINTER_H

    ldy COL     ; store CURSOR at POINTER plus COL
    lda #CURSOR
    sta (POINTER),y

    rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then whatever pixels that are in the second quadrant should be reflected to other three quadrant. This is done by storing a copy of the current position  and adding the x or y offset to the cursor every time user moves the cursor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;drawing_other_quads:     
    LDA POINTER ;; save the pointer to the
    PHA     ;; original location in top_left_quad
    LDA POINTER_H
    PHA

; top right quadrant
    LDA #$10
    CLC
    SBC COL
    CLC
    ADC #$10
    TAY
    LDA DOT
    STA (POINTER),y

    TYA
    PHA     ; save the y offset

; bottom left quadrant  
    lda #$10    ; load POINTER with start-of-row
    CLC
    SBC ROW
    CLC
    ADC #$10
    TAY

    lda table_low,y
    sta POINTER
    lda table_high,y
    sta POINTER_H

    ldy COL     ; store CURSOR at POINTER plus COL
    lda DOT
    sta (POINTER),y

    PLA
    TAY

; bottom right quadrant 
    lda DOT
    sta (POINTER),y

    PLA
    STA POINTER_H
    PLA
    STA POINTER

    RTS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Complete source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; zero-page variable locations
 define ROW     $20 ; current row
 define COL     $21 ; current column
 define POINTER     $10 ; ptr: start of row
 define POINTER_H   $11

 ; constants
 define DOT     $01 ; dot colour location
 define CURSOR      $04 ; purple colour


setup:  lda #$0f    ; set initial ROW,COL
    sta ROW
    sta COL
    LDA #$01
    STA DOT

draw:   jsr drawing_cursor

getkey:
    ldx #$00    ; clear out the key buffer
    lda $ff     ; get a keystroke
    stx $ff

    cmp #$30
    bmi getkey
    cmp #$40
    bpl continue

    SEC
    sbc #$30
    tay
    lda color_pallete, y
    sta DOT
    jmp done

continue:   
    cmp #$43    ; handle C or c
    beq clear
    cmp #$63
    beq clear

    cmp #$80    ; if not a cursor key, ignore
    bmi getkey
    cmp #$84
    bpl getkey

    pha     ; save A

    lda DOT ; set current position to DOT
    sta (POINTER),y
    jsr drawing_other_quads

    pla     ; restore A

    cmp #$80    ; check key == up
    bne check1

    dec ROW     ; ... if yes, decrement ROW
    jmp done

 check1:    
    cmp #$81    ; check key == right
    bne check2

    inc COL     ; ... if yes, increment COL
    jmp done

 check2:    
    cmp #$82    ; check if key == down
    bne check3

    inc ROW     ; ... if yes, increment ROW
    jmp done

 check3:    
    cmp #$83    ; check if key == left
    bne done

    dec COL     ; ... if yes, decrement COL
    clc
    bcc done

 clear: 
    lda table_low   ; clear the screen
    sta POINTER
    lda table_high
    sta POINTER_H

    ldy #$00
    tya

 c_loop:    
    sta (POINTER),y
    iny
    bne c_loop

    inc POINTER_H
    ldx POINTER_H
    cpx #$06
    bne c_loop

 done:  
    clc     ; repeat
    bcc draw


 drawing_cursor:
    lda ROW     ; ensure ROW is in range 0:0F
    and #$0f
    sta ROW

    lda COL     ; ensure COL is in range 0:0F
    and #$0f
    sta COL

    ldy ROW     ; load POINTER with start-of-row
    lda table_low,y
    sta POINTER
    lda table_high,y
    sta POINTER_H

    ldy COL     ; store CURSOR at POINTER plus COL
    lda #CURSOR
    sta (POINTER),y

    rts

 drawing_other_quads:     
    LDA POINTER ;; save the pointer to the
    PHA     ;; original location in top_left_quad
    LDA POINTER_H
    PHA

; top right quadrant
    LDA #$10
    CLC
    SBC COL
    CLC
    ADC #$10
    TAY
    LDA DOT
    STA (POINTER),y

    TYA
    PHA     ; save the y offset

; bottom left quadrant  
    lda #$10    ; load POINTER with start-of-row
    CLC
    SBC ROW
    CLC
    ADC #$10
    TAY

    lda table_low,y
    sta POINTER
    lda table_high,y
    sta POINTER_H

    ldy COL     ; store CURSOR at POINTER plus COL
    lda DOT
    sta (POINTER),y

    PLA
    TAY

; bottom right quadrant 
    lda DOT
    sta (POINTER),y

    PLA
    STA POINTER_H
    PLA
    STA POINTER

    RTS

 ; these two tables contain the high and low bytes
 ; of the addresses of the start of each row

 table_high:
 dcb $02,$02,$02,$02,$02,$02,$02,$02
 dcb $03,$03,$03,$03,$03,$03,$03,$03
 dcb $04,$04,$04,$04,$04,$04,$04,$04
 dcb $05,$05,$05,$05,$05,$05,$05,$05,

 table_low:
 dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
 dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
 dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
 dcb $00,$20,$40,$60,$80,$a0,$c0,$e0

color_pallete:
dcb $01,$02,$03,$04,$05,$06,$07,$08,$09,$0a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VWgHzv7a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jurfpj9esevf6axwhvk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VWgHzv7a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jurfpj9esevf6axwhvk.png" alt="Image description" width="160" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mG3F-OE_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7u65ssggmpu94esh8x9n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mG3F-OE_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7u65ssggmpu94esh8x9n.png" alt="Image description" width="160" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>spo600</category>
      <category>lab</category>
    </item>
    <item>
      <title>LAB4 - Aarch64 VS. X84_64</title>
      <dc:creator>Tecca Yu</dc:creator>
      <pubDate>Mon, 28 Feb 2022 01:04:43 +0000</pubDate>
      <link>https://dev.to/pykedot/lab4-1o2i</link>
      <guid>https://dev.to/pykedot/lab4-1o2i</guid>
      <description>&lt;p&gt;Hi this is Tecca, and in this post I will be demonstrating my findings with assembly language in the AArch64, an ARM architecture, and x86_64, an x86 architecture.&lt;/p&gt;

&lt;p&gt;The goal of this lab is to generate output like the following in both AArch64 and x86_64:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Loop: 0
Loop: 1
Loop: 2
Loop: 3
Loop: 4
...
Loop: 30
etc.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Source code for this lab in x86_64&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.text
.globl  _start


_start:


print:  mov     $0,%r15                 /* loop index */

loop:   mov %r15,%r14
    add $'0',%r14
    movb    %r14b,msg+6

    movq    $len,%rdx                       /* message length */
        movq    $msg,%rsi                       /* message location */
        movq    $1,%rdi                         /* file descriptor stdout */
        movq    $1,%rax                         /* syscall sys_write */
        syscall

        inc     %r15                /* increment the index */
        cmp     $10,%r15           /* check if we're done */
        jne     loop                /* keep looping if we're not */

        movq    $0,%rdi                         /* exit status */
        movq    $60,%rax                        /* syscall sys_exit */
        syscall

.section .data

msg:    .ascii      "Loop: #\n"
        len = . - msg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EH05J3bp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gc3hy3g3v65czirr51f1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EH05J3bp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gc3hy3g3v65czirr51f1.png" alt="Image description" width="525" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moving onto AArch64 source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.text
.globl _start

_start:

        mov     x19, 0

loop:
        add     x20, x19, '0'   // Create digit character
        adr     x17, msg+6      // Get a pointer to desired location of digit
        strb    w20, [x17]      // Put digit to desired location

        mov     x0, 1           /* file descriptor: 1 is stdout */
        adr     x1, msg         /* message location (memory address) */
        mov     x2, len         /* message length (bytes) */

        mov     x8, 64          
        svc     0               /* invoke syscall */

        add     x19, x19, 1
        cmp     x19, 10
        b.ne    loop

        mov     x0, 0           /* status -&amp;gt; 0 */
        mov     x8, 93          /* exit is syscall #93 */
        svc     0               /* invoke syscall */

.data
       msg:    .ascii      "Loop: #\n"
       len=    . - msg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is done from storing value defined from the given range into a register, an ASCII value is then converted from the value within the register.&lt;br&gt;
The value ‘0’ is stored into a register, which in turn is converted into an ASCII value of 48 in decimal. After the loop incremented it to 10, the program would not print an integer character as expected, there is no associated ASCII reference for '10'. &lt;/p&gt;

&lt;p&gt;I've tried adding 10 to the ASCII value of ‘0’, the resulting ASCII value prints out a colon “:” instead of the expected number 10 because 48+10=58 and 58 is a ":".&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eQ5Zvg-p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y44j4o2l4v9ia7k1dokp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eQ5Zvg-p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y44j4o2l4v9ia7k1dokp.png" alt="Image description" width="501" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'll focus on making it loop past 10 and onward in the next post.&lt;/p&gt;

</description>
      <category>spo600</category>
      <category>lab</category>
      <category>assemblylangua</category>
    </item>
  </channel>
</rss>
