<?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: Qzhang125</title>
    <description>The latest articles on DEV Community by Qzhang125 (@qzhang125).</description>
    <link>https://dev.to/qzhang125</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%2F720105%2Fc10d301c-73bb-4a3c-9660-60b1c79bbb87.jpeg</url>
      <title>DEV Community: Qzhang125</title>
      <link>https://dev.to/qzhang125</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/qzhang125"/>
    <language>en</language>
    <item>
      <title>week 14 Project Stage 3: SVE2</title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Wed, 15 Dec 2021 23:25:54 +0000</pubDate>
      <link>https://dev.to/qzhang125/week-14-project-stage-3-sve2-15ig</link>
      <guid>https://dev.to/qzhang125/week-14-project-stage-3-sve2-15ig</guid>
      <description>&lt;p&gt;Hello my friend, welcome to the last project stage of &lt;a href="https://wiki.cdot.senecacollege.ca/wiki/SPO600"&gt;SPO600&lt;/a&gt;. In this project, we will discuss how to extend SIMD(Single instruction, multiple data) Neon package to support Scalable Vector Extensions v2(&lt;a href="https://en.wikipedia.org/wiki/AArch64#ARMv9-A"&gt;SVE2&lt;/a&gt;) on the opensource software that I chose from the project &lt;a href="https://dev.to/qzhang125/week-13-project-phase-2-316j"&gt;stage 2&lt;/a&gt;. Before I start stage 3, let's do a short review of what we did in project stage 2. In stage 2, I chose an open-source software which is &lt;a href="https://ffmpeg.org/"&gt;FFmpeg&lt;/a&gt;, it is a cross-platform software to record, stream, and convert video and audio. It used a lot of SIMD methods to accelerate data processing but the Neon architecture extension of SIMD only has a fixed 128-bit vector length for the instruction set. For this case, Arm designed the SVE to improve SIMD implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SVE
&lt;/h2&gt;

&lt;p&gt;We all know that the 128-bit vector instruction set could operate the data which is inside 128 bits. To improve that, SVE allows choosing a suitable vector length between 128 bits and 2048 bits. Beyond this, SVE design enables developers to write and build software once and then the software can be used on different AArch64 hardware regardless of the length of the hardware’s vector implementation. Also, SVE includes: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Per-lane prediction.&lt;/li&gt;
&lt;li&gt;Gather-load and scatter-store&lt;/li&gt;
&lt;li&gt;Speculative vectorization&lt;/li&gt;
&lt;li&gt;These features help to vectorize and optimize 5. loops for large datasets.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  SVE 2
&lt;/h2&gt;

&lt;p&gt;The main difference between SVE and SVE 2 is the functional coverage of the instruction set. SVE improves the suitability of the architecture for High-Performance Computing(HPC) and Machine learning(ML). SVE 2 expands the domain of data processing and accelerate the common algorithms that are used in the areas below:&lt;/p&gt;

&lt;ol&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;/ol&gt;

&lt;h2&gt;
  
  
  SVE2 usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; int16x8_t q0s16, q2s16, q3s16, q8s16, q10s16, q11s16, q13s16;
    int16x8_t q14s16, q15s16, qzs16;
    int16x4_t d0s16, d2s16, d3s16, dzs16;
    uint16x8_t q1u16, q9u16;
    uint16x4_t d1u16;

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

&lt;/div&gt;



&lt;p&gt;Now let’s talk about how to extend the open-source software to support SVE2. In project stage 2 we discussed the mpegvideo.c file, this file is working with MPEG to compress and decompress moving pictures by using the Neon. The SVE2 could improve this procedure, to help the compiler with vectorization, the SVE2 adds a new feature which is Vector Length Agnostic(VLA). The VLA could save so much time for the compiler when it is working with the picture elements. For the FFmpeg to be extended to support and take advantage of SVE2, the FFmpeg developer could consider adding inline assemblers into the package to support SVE2 because SVE2 provides 32 scalable vector registers. Then add the SVE2 assembly syntax to invoke the instruction set. &lt;/p&gt;

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

&lt;p&gt;In this project, we discussed the many algorithms including SIMD and its instruction set SVE2. To extend the FFmpeg to support SVE2, the software that runs on the system has to be Neon and then the developer should add inline assemblers and change the old vector length for SVE2. Since this is the last blog for this course, I would say this is one of the hardest courses that I have ever taken so far. I learned a lot about how the program works under high-level programming languages and how to benchmark an application. Lastly, I got a picture of how the compiler optimizes programs using SIMD and many other algorithms. It is a fun and valuable experience for me and it helps me to create a picture of the relationship between machine, compiler, and my program. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Week 13 Project Stage 2 </title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Sun, 12 Dec 2021 04:33:35 +0000</pubDate>
      <link>https://dev.to/qzhang125/week-13-project-phase-2-316j</link>
      <guid>https://dev.to/qzhang125/week-13-project-phase-2-316j</guid>
      <description>&lt;p&gt;Hello everyone, welcome to the week 13 project blog, this is the second phase of the SPO600(Software Portability and Optimization) project, click &lt;a href="https://dev.to/qzhang125/spo600-assignment-1-algorithm-selection-for-optimization-4n9o"&gt;here&lt;/a&gt; to check phase 1. I this blog we are going to pick an open-source software and locate the SIMD code from the source code of the software and then determine the SIMD code usage in a certain program.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Instruction
&lt;/h2&gt;

&lt;p&gt;For my blog, I choose &lt;a href="https://ffmpeg.org/about.html"&gt;FFmpeg&lt;/a&gt;. FFmpeg is a cross-platform framework to record, convert, and stream video and audio, it provides an easy way to convert video and audio to other formats.&lt;/p&gt;

&lt;p&gt;FFmpeg is a very active open-source package with daily updates and debugging on &lt;a href="https://github.com/FFmpeg/FFmpeg"&gt;Github&lt;/a&gt;. This is a short log of the recent updates of FFmpeg below, or you can click &lt;a href="https://git.ffmpeg.org/gitweb/ffmpeg.git/shortlog"&gt;here&lt;/a&gt; to catch more updates history. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nato7S25--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n3101akanaz3jtupg4jk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nato7S25--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n3101akanaz3jtupg4jk.png" alt="Image description" width="880" height="584"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Single Instruction, Multiple Data Units
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.sciencedirect.com/topics/computer-science/single-instruction-multiple-data"&gt;SIMD&lt;/a&gt;(Single Instruction, Multiple Data) is a kind of high-performance embedded computing. The concept of SIMD is a single instruction that does one operation but we could improve it to process multiple data in parallel. To get more information about SIMD, you can also check my last blog for &lt;a href="https://dev.to/qzhang125/week11-reflection-1iai"&gt;week 11&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Mz07kmW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6c4my0m235j6pen17epl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Mz07kmW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6c4my0m235j6pen17epl.png" alt="The logic of SIMD" width="334" height="212"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  SIMD Usage
&lt;/h2&gt;

&lt;p&gt;To get the source code of FFmpeg, you can simply go to &lt;a href="https://github.com/FFmpeg/FFmpeg"&gt;FFmeg’s github&lt;/a&gt; and then clone the git onto AArch64 or x86_64 system. Let's take a look at the code snippet I found from /FFmpeg/libavcodec/neon/mpegvideo.c file.&lt;br&gt;
This SIMD implementation is only working on AArch64 systems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;static void inline ff_dct_unquantize_h263_neon(int qscale, int qadd, int nCoeffs,
                                               int16_t *block)
{
    int16x8_t q0s16, q2s16, q3s16, q8s16, q10s16, q11s16, q13s16;
    int16x8_t q14s16, q15s16, qzs16;
    int16x4_t d0s16, d2s16, d3s16, dzs16;
    uint16x8_t q1u16, q9u16;
    uint16x4_t d1u16;

    dzs16 = vdup_n_s16(0);
    qzs16 = vdupq_n_s16(0);

    q15s16 = vdupq_n_s16(qscale &amp;lt;&amp;lt; 1);
    q14s16 = vdupq_n_s16(qadd);
    q13s16 = vnegq_s16(q14s16);

    if (nCoeffs &amp;gt; 4) {
        for (; nCoeffs &amp;gt; 8; nCoeffs -= 16, block += 16) {
            q0s16 = vld1q_s16(block);
            q3s16 = vreinterpretq_s16_u16(vcltq_s16(q0s16, qzs16));
            q8s16 = vld1q_s16(block + 8);
            q1u16 = vceqq_s16(q0s16, qzs16);
            q2s16 = vmulq_s16(q0s16, q15s16);
            q11s16 = vreinterpretq_s16_u16(vcltq_s16(q8s16, qzs16));
            q10s16 = vmulq_s16(q8s16, q15s16);
            q3s16 = vbslq_s16(vreinterpretq_u16_s16(q3s16), q13s16, q14s16);
            q11s16 = vbslq_s16(vreinterpretq_u16_s16(q11s16), q13s16, q14s16);
            q2s16 = vaddq_s16(q2s16, q3s16);
            q9u16 = vceqq_s16(q8s16, qzs16);
            q10s16 = vaddq_s16(q10s16, q11s16);
            q0s16 = vbslq_s16(q1u16, q0s16, q2s16);
            q8s16 = vbslq_s16(q9u16, q8s16, q10s16);
            vst1q_s16(block, q0s16);
            vst1q_s16(block + 8, q8s16);
        }
    }
    if (nCoeffs &amp;lt;= 0)
        return;

    d0s16 = vld1_s16(block);
    d3s16 = vreinterpret_s16_u16(vclt_s16(d0s16, dzs16));
    d1u16 = vceq_s16(d0s16, dzs16);
    d2s16 = vmul_s16(d0s16, vget_high_s16(q15s16));
    d3s16 = vbsl_s16(vreinterpret_u16_s16(d3s16),
                     vget_high_s16(q13s16), vget_high_s16(q14s16));
    d2s16 = vadd_s16(d2s16, d3s16);
    d0s16 = vbsl_s16(d1u16, d0s16, d2s16);
    vst1_s16(block, d0s16);
}

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

&lt;/div&gt;



&lt;p&gt;This code snippet is for AArch64 systems, it is using the Neon instruction set at the beginning of this code. It defines a couple of registers as integer or unsigned integer types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int16x8_t q0s16, q2s16, q3s16, q8s16, q10s16, q11s16, q13s16;
    int16x8_t q14s16, q15s16, qzs16;
    int16x4_t d0s16, d2s16, d3s16, dzs16;
    uint16x8_t q1u16, q9u16;
    uint16x4_t d1u16;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, load the values to the registers that we discussed before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dzs16 = vdup_n_s16(0);
    qzs16 = vdupq_n_s16(0);

    q15s16 = vdupq_n_s16(qscale &amp;lt;&amp;lt; 1);
    q14s16 = vdupq_n_s16(qadd);
    q13s16 = vnegq_s16(q14s16);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Afterward, SIMD is being used from here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (nCoeffs &amp;gt; 4) {
        for (; nCoeffs &amp;gt; 8; nCoeffs -= 16, block += 16) {
            q0s16 = vld1q_s16(block);
            q3s16 = vreinterpretq_s16_u16(vcltq_s16(q0s16, qzs16));
            q8s16 = vld1q_s16(block + 8);
            q1u16 = vceqq_s16(q0s16, qzs16);
            q2s16 = vmulq_s16(q0s16, q15s16);
            q11s16 = vreinterpretq_s16_u16(vcltq_s16(q8s16, qzs16));
            q10s16 = vmulq_s16(q8s16, q15s16);
            q3s16 = vbslq_s16(vreinterpretq_u16_s16(q3s16), q13s16, q14s16);
            q11s16 = vbslq_s16(vreinterpretq_u16_s16(q11s16), q13s16, q14s16);
            q2s16 = vaddq_s16(q2s16, q3s16);
            q9u16 = vceqq_s16(q8s16, qzs16);
            q10s16 = vaddq_s16(q10s16, q11s16);
            q0s16 = vbslq_s16(q1u16, q0s16, q2s16);
            q8s16 = vbslq_s16(q9u16, q8s16, q10s16);
            vst1q_s16(block, q0s16);
            vst1q_s16(block + 8, q8s16);
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This part of the code snippet is using if-condition and for-loop to load values, multiply two values that were stored in the registers. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;q0s16 = vld1q_s16(block); //load
q2s16 = vmulq_s16(q0s16, q15s16); //pub unsafe fn vmulq_s16(a: int16x8_t, b: int16x8_t) -&amp;gt; int16x8_t
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at this way the SIMD is being used in this part of code, we could find that the intrinsic is also being used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;q3s16 = vreinterpretq_s16_u16(vcltq_s16(q0s16, qzs16));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at the inside part first, vcltq_s16 is a method to compare each vector element in the first register q0s16 with the corresponding vector element in the second register qzs16 and if the first signed integer value is greater than the second signed integer value, sets every bit of the corresponding vector element into the destination register to 1 otherwise sets every bit of the corresponding vector element into the destination register to 0. And the vreinterpretq_s16_u16 method is a reinterpret-cast operation as an outer function for the intrinsics.&lt;br&gt;
After calculation, use loop condition swap algorithm to store the result to the register:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (nCoeffs &amp;lt;= 0)
        return;

    d0s16 = vld1_s16(block);
    d3s16 = vreinterpret_s16_u16(vclt_s16(d0s16, dzs16));
    d1u16 = vceq_s16(d0s16, dzs16);
    d2s16 = vmul_s16(d0s16, vget_high_s16(q15s16));
    d3s16 = vbsl_s16(vreinterpret_u16_s16(d3s16),
                     vget_high_s16(q13s16), vget_high_s16(q14s16));
    d2s16 = vadd_s16(d2s16, d3s16);
    d0s16 = vbsl_s16(d1u16, d0s16, d2s16);
    vst1_s16(block, d0s16);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After my examination, the SIMD implementation for mpegvideo.c file is for compression and decompression. It is selected during compile-time and then calculates tons of elements without macros in different vectors at the same time and also puts all of the SIMD methods into a for loop to execute. The ff_dct_unquantize_h263_neon function saved a lot of time for the package to calculate.&lt;/p&gt;

&lt;p&gt;Looking at the SIMD implementation, FFmpeg explicitly creates a folder for the Neon instruction set: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ci49Rr6Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3cb0x1d3htw2eflz5bl0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ci49Rr6Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3cb0x1d3htw2eflz5bl0.png" alt="Image description" width="541" height="86"&gt;&lt;/a&gt;&lt;br&gt;
In the Neon directory we got this:&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q2G7hFAs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i7ibwwo2qyqtfjhxm2p6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q2G7hFAs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i7ibwwo2qyqtfjhxm2p6.png" alt="Image description" width="531" height="81"&gt;&lt;/a&gt;&lt;br&gt;
We could see that the SIMD implementation for this part of the functionality is separated from other SIMD implementations. &lt;/p&gt;

&lt;p&gt;The SIMD is also working on x86 systems. I found the code snippet from /FFmpeg/libavcodec/x86/lpc.c :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;static void lpc_compute_autocorr_sse2(const double *data, int len, int lag,
                                      double *autoc)
{
    int j;

    if((x86_reg)data &amp;amp; 15)
        data++;

    for(j=0; j&amp;lt;lag; j+=2){
        x86_reg i = -len*sizeof(double);
        if(j == lag-2) {
            __asm__ volatile(
                "movsd    "MANGLE(pd_1)", %%xmm0    \n\t"
                "movsd    "MANGLE(pd_1)", %%xmm1    \n\t"
                "movsd    "MANGLE(pd_1)", %%xmm2    \n\t"
                "1:                                 \n\t"
                "movapd   (%2,%0), %%xmm3           \n\t"
                "movupd -8(%3,%0), %%xmm4           \n\t"
                "movapd   (%3,%0), %%xmm5           \n\t"
                "mulpd     %%xmm3, %%xmm4           \n\t"
                "mulpd     %%xmm3, %%xmm5           \n\t"
                "mulpd -16(%3,%0), %%xmm3           \n\t"
                "addpd     %%xmm4, %%xmm1           \n\t"
                "addpd     %%xmm5, %%xmm0           \n\t"
                "addpd     %%xmm3, %%xmm2           \n\t"
                "add       $16,    %0               \n\t"
                "jl 1b                              \n\t"
                "movhlps   %%xmm0, %%xmm3           \n\t"
                "movhlps   %%xmm1, %%xmm4           \n\t"
                "movhlps   %%xmm2, %%xmm5           \n\t"
                "addsd     %%xmm3, %%xmm0           \n\t"
                "addsd     %%xmm4, %%xmm1           \n\t"
                "addsd     %%xmm5, %%xmm2           \n\t"
                "movsd     %%xmm0,   (%1)           \n\t"
                "movsd     %%xmm1,  8(%1)           \n\t"
                "movsd     %%xmm2, 16(%1)           \n\t"
                :"+&amp;amp;r"(i)
                :"r"(autoc+j), "r"(data+len), "r"(data+len-j)
                 NAMED_CONSTRAINTS_ARRAY_ADD(pd_1)
                :"memory"
            );
        } else {
            __asm__ volatile(
                "movsd    "MANGLE(pd_1)", %%xmm0    \n\t"
                "movsd    "MANGLE(pd_1)", %%xmm1    \n\t"
                "1:                                 \n\t"
                "movapd   (%3,%0), %%xmm3           \n\t"
                "movupd -8(%4,%0), %%xmm4           \n\t"
                "mulpd     %%xmm3, %%xmm4           \n\t"
                "mulpd    (%4,%0), %%xmm3           \n\t"
                "addpd     %%xmm4, %%xmm1           \n\t"
                "addpd     %%xmm3, %%xmm0           \n\t"
                "add       $16,    %0               \n\t"
                "jl 1b                              \n\t"
                "movhlps   %%xmm0, %%xmm3           \n\t"
                "movhlps   %%xmm1, %%xmm4           \n\t"
                "addsd     %%xmm3, %%xmm0           \n\t"
                "addsd     %%xmm4, %%xmm1           \n\t"
                "movsd     %%xmm0, %1               \n\t"
                "movsd     %%xmm1, %2               \n\t"
                :"+&amp;amp;r"(i), "=m"(autoc[j]), "=m"(autoc[j+1])
                :"r"(data+len), "r"(data+len-j)
                 NAMED_CONSTRAINTS_ARRAY_ADD(pd_1)
            );
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function, it is using an inline assembler at runtime because it is located in a .c file. This is for x86 systems to use &lt;a href="https://en.wikipedia.org/wiki/SSE2"&gt;SSE2&lt;/a&gt; to do the calculation and data transformation.&lt;/p&gt;

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

&lt;p&gt;To conclude the usage of SIMD in FFmpeg, I only used two examples from AArch64 and x86 systems but I would say that FFmpeg takes full advantage of SIMD implementation. It saves a lot of time for this package when the software converts videos and audio to another format. It could calculate multiple data simultaneously by using the SIMD instruction set. For the code structure, after this project, I got a brief picture of the structure management of FFmpeg. I would say FFmpeg is well structured because FFmpeg decided to put the SIMD implementation in separate folders, it provides me with an idea which is that the separate code implementation is very helpful to debug and locate the error position when the program gets into an issue. Also, it provides a chance to reuse some of the code that they developed before. To improve the code structure, I would say maybe use more loop condition swaps to avoid some unnecessary loop procedures.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Week 12 Reflection: Paged Memory System</title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Fri, 10 Dec 2021 03:13:31 +0000</pubDate>
      <link>https://dev.to/qzhang125/week-12-reflection-1i0p</link>
      <guid>https://dev.to/qzhang125/week-12-reflection-1i0p</guid>
      <description>&lt;p&gt;Hello everyone, welcome back to the SPO600(Software Portability and Optimization) week 12 blog. In this blog, we will find something fun with the paged memory system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instruction
&lt;/h2&gt;

&lt;p&gt;Most modern systems use page memory. It means the physical memory of the system is divided into pages and these pages can then be arranged via memory table or memory map into a memory configuration that is viewed by a process. It allows us to present a different view of memory to different processes and thus isolate some areas of memory that are visible from one process but invisible for another process and it also allows us to share memory between processes.&lt;/p&gt;

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

&lt;p&gt;This diagram here shows the relationship between physical memory and logical memory or virtual memory. In this diagram the current process is a game process. So we noticed that on the left hand side we have the view of memory that is visible to that process. So the game process appears to have 4 pages of virtual memory corresponding to three pages of physical memory and they don't have to be contiguous in physical memory like where they are located in virtual memory. The size of each page in the x86_64 system is commonly 4k or 1M, in the AArch64 system it is usually 4k or 64k.&lt;/p&gt;

&lt;h2&gt;
  
  
  How much memory is process using
&lt;/h2&gt;

&lt;p&gt;To define how much memory a process uses is a  quite difficult question because we need a standard counter to calculate the size that a process page is presenting and has been allocated at that moment. So we have two different standard sizes VSS(Virtual Set Size) and RSS(Resident Set Size). The VSS all of the pages that are present in the virtual memory or logical memory for that process. It actually counts all of the memory no matter if the page has been allocated or not, it is the worst case to calculate the size. There's also the RSS, the resident set size only counts the pages that are physically present in memory, it excludes the pages which haven't yet been loaded from disk or haven't been swapped out to disk. It would give us a more accurate picture of the actual physical usage of memory by a particular process.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like
&lt;/h2&gt;

&lt;p&gt;To see what it looks like on an actual operating system, we need to use this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;top 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For my personal laptop, I got this result below:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GxYrtEIe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f8ha0a0100kd94hn9fwp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GxYrtEIe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f8ha0a0100kd94hn9fwp.png" alt="Image description" width="644" height="115"&gt;&lt;/a&gt;&lt;br&gt;
As we can see, I got 11946.7 mebibytes in total, 5615.7 mebibytes for free, 740.6 mebibytes in use, and 5588.7 mebibytes for buff and catch.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jwfOByNa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fxlhnfse2y968jpqwu3q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jwfOByNa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fxlhnfse2y968jpqwu3q.png" alt="Image description" width="686" height="83"&gt;&lt;/a&gt;&lt;br&gt;
Below this, we could see individual processes. I used the top command which has VIRT(Virtual Set Size), RES(Resident Set Size), and SHR(Share Memory Size).&lt;/p&gt;

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

&lt;p&gt;This week we learned almost the last topic of this course. To be honest, this course is the hardest course for me so far because the programming level of this course is lower than the other computer science classes that I took before like C++, Java, JavaScript, etc. However, it is fun to look at how and where a program actually works and what the compiler and systems could do to run the program that we created. In this course, I worked with 6502 assembly language, assembly language in x86_64 and AArch64 systems, and algorithms to speed up a program. I think I have got a picture of how to run a program at a lower level and I hope I could explore more about it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Week 11 Reflection SIMD</title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Fri, 10 Dec 2021 03:13:20 +0000</pubDate>
      <link>https://dev.to/qzhang125/week11-reflection-1iai</link>
      <guid>https://dev.to/qzhang125/week11-reflection-1iai</guid>
      <description>&lt;p&gt;Hello my friend, welcome back to the week 11 blog about SPO600(Software Portability and Optimization). In this blog, I'm going to blog about SIMD.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/SIMD"&gt;SIMD&lt;/a&gt;(Single instruction multiple data) also called vectorization. The concept of SIMD is a single instruction which does one operation but we could improve it to process multiple data in parallel. It is an ability that many modern processors have. It is also called vectorization which is working with vectors. Vectors are arrays of values, typically one dimensional arrays then apply the same operation to different parts of the array simultaneously. For example, &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CiY7Opk8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hrl2smgcd9aspwtd4hl2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CiY7Opk8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hrl2smgcd9aspwtd4hl2.png" alt="Image description" width="334" height="212"&gt;&lt;/a&gt;&lt;br&gt;
In the diagram above, the SIMD unit could calculate multiple values from vector A and vector B with the same operation and then put the result into the vector C in parallel which means it is executing four operations simultaneously. &lt;/p&gt;
&lt;h2&gt;
  
  
  MMX instruction set
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/MMX_%28instruction_set%29#:~:text=Pentium%20with%20MMX.%20MMX%20is%20a%20single%20instruction%2C,of%20microprocessors%2C%20designated%20as%20%22Pentium%20with%20MMX%20Technology%22."&gt;MMX&lt;/a&gt; defines 8 processor registers, named from MM0 to MM7, and operations that operate on them. Each register is 64 bits wide and can be used to hold either one 64-bit integer or multiple smaller integer: one instruction can be applied to two 32-bit integers, or four 16-bit integers or eight 8-bit integers at once.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to check SIMD instruction
&lt;/h2&gt;

&lt;p&gt;Before using the SIMD instruction set, we need help from the processor and compiler. I used my personal laptop as an example:&lt;br&gt;
Check SIMD instruction sets that are supported by the CPU:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /proc/cpuinfo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then find the flags, we could find the instruction set that the CPU supports.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check SIMD instruction sets which are supported by GCC&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcc -march=native -c -Q --help=target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could see the instruction set which is enabled or disabled.&lt;br&gt;
For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The following options are target specific:
  -m128bit-long-double                  [enabled]
  -m16                                  [disabled]
  -m32                                  [disabled]
  -m3dnow                               [disabled]
  -m3dnowa                              [disabled]
  -m64                                  [enabled]
  -m80387                               [enabled]
  -m8bit-idiv                           [disabled]
  -m96bit-long-double                   [disabled]
  -mabi=                                sysv
  -mabm                                 [disabled]
  -maccumulate-outgoing-args            [disabled]
  -maddress-mode=                       long
  -madx                                 [disabled]
  -maes                                 [disabled]
  -malign-data=                         compat
  -malign-double                        [disabled]
  -malign-functions=                    0
  -malign-jumps=                        0
  -malign-loops=                        0
  -malign-stringops                     [enabled]
  -mamx-bf16                            [disabled]
  -mamx-int8                            [disabled]
  -mamx-tile                            [disabled]
  -mandroid                             [disabled]
  -march=                               nehalem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;SIMD is a very significant ability that the modern processor should have. It helps to process multiple data simultaneously and saves a lot of time. In the &lt;a href="https://dev.to/qzhang125/spo600-assignment-1-algorithm-selection-for-optimization-4n9o"&gt;Lab6(aka project 1)&lt;/a&gt; we explored more and test how much time the SIMD saved for the program. It is fun to learn and actually test how it works.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>SPO600 Project Stage 1: Algorithm Selection for Optimization </title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Sun, 05 Dec 2021 04:53:23 +0000</pubDate>
      <link>https://dev.to/qzhang125/spo600-assignment-1-algorithm-selection-for-optimization-4n9o</link>
      <guid>https://dev.to/qzhang125/spo600-assignment-1-algorithm-selection-for-optimization-4n9o</guid>
      <description>&lt;p&gt;Hello everyone, welcome to assignment phase 1 of SPO600(Software Portability and optimization). In this phase, we will benchmark 6 different algorithms in the c program. &lt;/p&gt;

&lt;h1&gt;
  
  
  Background
&lt;/h1&gt;

&lt;p&gt;Digital sound is typically represented, uncompressed, assigned 16-bit integer signal samples. There are two streams of samples, one each for the left and right stereo channels, at typical sample rates of 44.1 or 48 thousand samples per second per channel, for a total of 88.2 or 96 thousand samples per second (kHz). Since there are 16 bits (2 bytes) per sample, the data rate is 88.2 * 1000 * 2 = 176,400 bytes/second (~172 KiB/sec) or 96 * 1000 * 2 = 192,000 bytes/second (~187.5 KiB/sec).&lt;br&gt;
To change the volume of sound, each sample can be scaled (multiplied) by a volume factor, in the range of 0.00 (silence) to 1.00 (full volume).&lt;br&gt;
On a mobile device, the amount of processing required to scale sound will affect battery life.&lt;/p&gt;
&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;We got 6 approaches that use different algorithms: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;vol0.c is the basic or naive algorithm. This approach multiplies each sound sample by the volume scaling factor, casting from signed 16-bit integer to floating point and back again. Casting between integer and floating points can be an expensive operation.&lt;/li&gt;
&lt;li&gt;vol1.c does the math using fixed-point calculations. This avoids the overhead of casting between integer and floating-point and back again.&lt;/li&gt;
&lt;li&gt;vol2.c pre-calculates all 65536 different results and then looks up the answer for each input value.&lt;/li&gt;
&lt;li&gt;vol3.c is a dummy program - it doesn't scale the volume at all. It can be used to determine some of the overhead of the rest of the processing (besides scaling the volume) done by the other programs.&lt;/li&gt;
&lt;li&gt;vol4.c uses Single Instruction, Multiple Data (SIMD) instructions accessed through inline assembly (assembly language code inserted into a C program). This program is specific to the AArch64 architecture and will not be built for x86_64.&lt;/li&gt;
&lt;li&gt;vol5.c uses SIMD instructions accessed through Compiler Intrinsics. This program is also specific to AArch64.
For more details, please &lt;a href="https://wiki.cdot.senecacollege.ca/wiki/SPO600_Algorithm_Selection_Lab"&gt;click here&lt;/a&gt;. &lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;
  
  
  Procedure
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Unpack the archive /public/spo600-volume-examples.tgz&lt;/li&gt;
&lt;li&gt;Make a prediction of the relative performance of each scaling algorithm.&lt;/li&gt;
&lt;li&gt;Build and test each of the programs.&lt;/li&gt;
&lt;li&gt;Test the performance of each program.&lt;/li&gt;
&lt;li&gt;Find a way to measure performance without the time taken to perform the test setup pre-processing (generating the samples) and post-processing (summing the results) so that you can measure only the time taken to scale the samples.&lt;/li&gt;
&lt;li&gt;Increase performance by changing the compiler option (via the Makefile).&lt;/li&gt;
&lt;li&gt;Answer the question in the code.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;
  
  
  AArch64(Israel)
&lt;/h1&gt;
&lt;h3&gt;
  
  
  My prediction
&lt;/h3&gt;

&lt;p&gt;My prediction of the performance is the fastest program is vol5 because of the &lt;a href="https://www.sciencedirect.com/topics/computer-science/single-instruction-multiple-data"&gt;SIMD&lt;/a&gt; and the slowest program is vol2. &lt;/p&gt;
&lt;h3&gt;
  
  
  Build &amp;amp; test each program
&lt;/h3&gt;

&lt;p&gt;This is what we got in the vol.h file:&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
#include &amp;lt;stdint.h&amp;gt;
/* 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;In this header file, it defined 16 samples we got for the programs to process. &lt;br&gt;
Now, let's build and test each of the programs:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i4Qwr7XU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zta5nyytddmuy9wwqzxo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i4Qwr7XU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zta5nyytddmuy9wwqzxo.png" alt="Image description" width="402" height="297"&gt;&lt;/a&gt;&lt;br&gt;
As you can see here, most of the results are the same but we also got different outputs from the vol1 and vol3 programs. In all of the programs we got the same number of samples but different algorithms, so the algorithm is the only factor that affects different outputs.&lt;/p&gt;
&lt;h3&gt;
  
  
  Benchmarking
&lt;/h3&gt;

&lt;p&gt;In this part, I designed a function using system time to calculate the time of execution in milliseconds. To complete this test, we also need to add&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;sys/time.h&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct timeval  start , end;
gettimeofday(&amp;amp;start,0);
//loop goes here for testing
gettimeofday(&amp;amp;end,0);
float duration = (end.tv_sec - start.tv_sec) * 1000.0f + (end.tv_usec -start.tv_usec)/1000.0f;
printf("Time used: %f milisec\n", duration);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Results:&lt;br&gt;
For a number of samples: 1000000000&lt;br&gt;
vol0.c(Using the basic algorithm)&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iteration&lt;/th&gt;
&lt;th&gt;Duration(millisecond)&lt;/th&gt;
&lt;th&gt;result&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;3295.242920&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3280.395996&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3295.914062&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3287.457031&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;3309.891113&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The average execution time of execution is 16,468.901122 / 5 = 3,293.7802244 milliseconds.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iteration&lt;/th&gt;
&lt;th&gt;Duration(millisecond)&lt;/th&gt;
&lt;th&gt;result&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;2871.633057&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2862.878906&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2855.055908&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2868.831055&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2853.552002&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The average execution time of vol2.c is 14,311.950928/5 = 2,862.3901856 milliseconds and it is 431.3900388 milliseconds faster than the basic algorithm.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iteration&lt;/th&gt;
&lt;th&gt;Duration(millisecond)&lt;/th&gt;
&lt;th&gt;result&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;7004.999023&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;6997.184082&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;6996.041992&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;6994.092773&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;6983.860840&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The average execution time of vol2.c is 34,976.169917 / 5 = 6,995.2339834 milliseconds.&lt;br&gt;
vol2.c is so much slower than the other programs because of the pre-calculation.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iteration&lt;/th&gt;
&lt;th&gt;Duration(millisecond)&lt;/th&gt;
&lt;th&gt;result&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;2193.116943&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2192.761963&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2193.154053&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2191.714111&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2193.959961&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The average execution time of vol3.c is 10,964.707031 / 5 = 2,192.9414062 milliseconds.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iteration&lt;/th&gt;
&lt;th&gt;Duration(millisecond)&lt;/th&gt;
&lt;th&gt;result&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;1704.156982&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1701.747070&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1755.469971&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1753.229980&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;1736.984009&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The average execution time of vol4.c is 8,651.588012 / 5 = 1,730.3176024 milliseconds which is the fastest so far.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iteration&lt;/th&gt;
&lt;th&gt;Duration(millisecond)&lt;/th&gt;
&lt;th&gt;result&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;1738.630005&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1756.073975&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1754.686035&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1788.035034&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;1703.054932&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The average execution time of vol5.c is 8,740.479981 / 5 = 1,748.0959962 milliseconds. &lt;/p&gt;
&lt;h3&gt;
  
  
  Relative Memory Usage
&lt;/h3&gt;

&lt;p&gt;To check the memory usage, I used this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;free -m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the result of memory usage on the Israel server in the AArch64 systems:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bT_pVxlg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/23ay5pd4r4ravy3gvrhn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bT_pVxlg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/23ay5pd4r4ravy3gvrhn.png" alt="Image description" width="656" height="66"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  x86_64(Portugal)
&lt;/h1&gt;
&lt;h3&gt;
  
  
  My prediction
&lt;/h3&gt;

&lt;p&gt;My prediction of performance for these programs is that vol3.c is the fastest and vol2.c is the slowest.&lt;/p&gt;
&lt;h3&gt;
  
  
  Build &amp;amp; test each program
&lt;/h3&gt;

&lt;p&gt;In the x86_64 system, we only got vol0.c through vol3.c because vol4.c and vol5.c are only for the AArch64 system. &lt;br&gt;
This is the initial build with 16 samples:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XYfJbKSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ncmcf9st1kg7iba98iir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XYfJbKSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ncmcf9st1kg7iba98iir.png" alt="Image description" width="291" height="149"&gt;&lt;/a&gt;&lt;br&gt;
Compared to the previous initial build, the result is the same as the result that we got from the AArch64 system.&lt;/p&gt;
&lt;h3&gt;
  
  
  Benchmarking
&lt;/h3&gt;

&lt;p&gt;For the program in the x86_64 system, I choose to use the same function that we used to test the execution time in the AArch64 system. Feel free to copy the previous code to test on the Portugal server. &lt;/p&gt;

&lt;p&gt;First of all, let's test the vol0 which uses the basic algorithm.&lt;br&gt;
Results:&lt;br&gt;
For a number of samples: 1000000000&lt;br&gt;
vol0.c(Using the basic algorithm)&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iteration&lt;/th&gt;
&lt;th&gt;Duration(millisecond)&lt;/th&gt;
&lt;th&gt;result&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;1689.119019&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1656.987061&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1658.895996&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1681.101074&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;1662.795044&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The average execution time of vol0.c is 8,348.898194 / 5 = 1,669.7796388 milliseconds.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iteration&lt;/th&gt;
&lt;th&gt;Duration(millisecond)&lt;/th&gt;
&lt;th&gt;result&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;1657.718994&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1659.477051&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1655.046021&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1662.978027&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;1654.200928&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The average execution time of vol1.c is 8,289.421021 / 5 = 1,657.8842042 milliseconds.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iteration&lt;/th&gt;
&lt;th&gt;Duration(millisecond)&lt;/th&gt;
&lt;th&gt;result&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;2163.916992&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2120.509033&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2119.781006&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2122.691895&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2131.298096&lt;/td&gt;
&lt;td&gt;289&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The average execution time of vol2.c is 10,658.197022 / 5 = 2,131.6394044 milliseconds which is considerably slower than other programs in x86_64 systems.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iteration&lt;/th&gt;
&lt;th&gt;Duration(millisecond)&lt;/th&gt;
&lt;th&gt;result&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;1311.255981&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1292.249023&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1297.120972&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1300.192017&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;1299.275024&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The average execution time of vol3.c is 6,500.093017 / 5 = 1,300.0186034 milliseconds. It is the fastest program. &lt;/p&gt;
&lt;h3&gt;
  
  
  Relative Memory Usage
&lt;/h3&gt;

&lt;p&gt;Same as before, use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;free -m 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;command to check the memory usage on the Portugal server.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tFLYXqMt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ekn33p660ly7ajlzrgvk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tFLYXqMt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ekn33p660ly7ajlzrgvk.png" alt="Image description" width="673" height="66"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Questions
&lt;/h1&gt;

&lt;p&gt;In this part, I will answer all of the questions which are marked with Q in all the source files.&lt;br&gt;
Q1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ---- This part sums the samples. (Why is this needed?)
        for (x = 0; x &amp;lt; SAMPLES; x++) {
                ttl=(ttl+out[x])%1000;
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason that we need this part is that it is used to go through out of the SAMPLES that we defined in vol. h. Then assigned all of the results from out[] array to ttl property which then could be used to print out on as the result.&lt;/p&gt;

&lt;p&gt;Q2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ---- Print the sum of the samples. (Why is this needed?)
        printf("Result: %d\n", ttl);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason that we need this part is because it is used to print the result that we went through the SAMPLE then assigned from the out[] array. &lt;/p&gt;

&lt;p&gt;Q3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Q: What's the point of this dummy program? How does it help
// with benchmarking?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dummy program does not scale the volume, it is used to determine the processing that has been done by other programs.&lt;/p&gt;

&lt;p&gt;Q4:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Q: What is the purpose of the cast to unint16_t in the next line?
                precalc[(uint16_t) x] = (int16_t) ((float) x * VOLUME / 100.0);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason to cast uint16_t is because it will explicitly define the number of bits, and it also ensures that the result is going to be an unsigned 16-bit integer.&lt;/p&gt;

&lt;p&gt;Q5:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; // Q: should we use 32767 or 32768 in the next line? why?
        vol_int = (int16_t)(VOLUME/100.0 * 32767.0);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should use 32767 in the next line because we have defined the limit of the sample, so the sample will start at the minimum value of a 16-bit signed integer to the maximum value of the 16-bit signed integer. &lt;/p&gt;

&lt;p&gt;Q6:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Q: what is the purpose of these next two lines?
        in_cursor = in;
        out_cursor = out;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The purpose of the first line is to assign the input cursor to the in[] array and the second line is going to assign the output cursor to the out[] array.&lt;/p&gt;

&lt;p&gt;Q7:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; // Q: what does it mean to "duplicate" values in the next line?
        __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;A duplicate of the value is stored in a vector which will act as an array of equal size. The value to duplicate is %w0 and the duplicate value will be sent to the dupv1.8h.&lt;/p&gt;

&lt;p&gt;Q8:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Q: What do these next three lines do?
                        : [in_cursor]"+r"(in_cursor), [out_cursor]"+r"(out_cursor)
                        : "r"(in_cursor),"r"(out_cursor)
                        : "memory"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These three lines are used to get the value from the input cursor and output cursor then store them into the system memory.&lt;/p&gt;

&lt;p&gt;Q9:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        // Q: are the results usable? are they correct?
        printf("Result: %d\n", ttl);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This result is only usable in the AArch64 system because this program is only usable in the AArch64 system. It is correct if we use it in the AArch64 system and it does work properly. &lt;/p&gt;

&lt;p&gt;Q10:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; // Q: Are the results usable? Are they accurate?
        printf("Result: %d\n", ttl);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same with the Q9, this result is only usable in the AArch64 system because the vol5.c is only usable in AArch64. However, it works properly in the AAcrh64 system.&lt;/p&gt;

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

&lt;p&gt;Click &lt;a href="https://docs.google.com/spreadsheets/d/1YeKniPHGNQaQB3xNNaP_fdV1z9pUvYDxQjQV9MFWEe8/edit?usp=sharing"&gt;here&lt;/a&gt; to check the full list of comparisons.&lt;br&gt;
In this assignment, my prediction of the performance is the fastest program is vol5.c in among all of the programs because of the SIMD. It was accelerated through the compiler. In the x86_64 the vol3.c is the fastest program. My prediction is correct. Based on what we discovered, the x86_64 system executes the same program with the same number of samples two times faster than the AArch64. Looking at the differences between the programs themselves, the different algorithms could perform huge differences and save a lot of time for a little program.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Week10 Lab 5: Assembler Lab</title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Thu, 25 Nov 2021 04:48:42 +0000</pubDate>
      <link>https://dev.to/qzhang125/spo600-64-bit-lab-5-assembler-lab-20gl</link>
      <guid>https://dev.to/qzhang125/spo600-64-bit-lab-5-assembler-lab-20gl</guid>
      <description>&lt;p&gt;Welcome back to week 10 of SPO600(Software Portability and Optimization) blog. This week we will work on lab 5. In this lab, we are going to write a simple program to make a loop that will run 30 times and display a number from 0 to 30 in AArch64 and x86_64 systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  x86_64 system
&lt;/h2&gt;



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


_start:

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

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

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

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

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

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

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

.section .data

        msg:    .ascii   "Loop:   \n"
        len = . - msg

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  AArch64 system
&lt;/h2&gt;



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

        mov     x4, 0           /* file descriptor: 1 is stdout */
        mov     w10, 0x3        /* Value of 0 in ascii */

loop:
        add     w24, w4, 0x30   /* Converting iterator to ascii  */
        mov     x11, 10         /* Using 10 as a divider  */
        udiv    x12, x4, x11    /* Getting equitent  */
        msub    x13, x11, x12, x4       /* Getting the remainder  */

        add     w14, w12, 0x30  /* Ascii conversion  */
        add     w15, w13, 0x30  /* Ascii conversion  */

        adr     x16, msg        /* Storing the message  */
        strb    w15, [x16, 7]   /* Storing remainder into msg at byte 7  */
        cmp     w14, w10        /* Is 0  */
        strb    w14, [x16, 6]   /* Storing quotient in msg at byte 6  */

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

        mov     x8, 64          /* write is syscall #64 */
        svc     0               /* invoke syscall */

        add     x4, x4, 1
        cmp     x4, 31          /* Checks if the iterator equals 31  */
        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;The result is same on both systems:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jn7ETRW5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1fjhnqfuubx8j1jpgg9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jn7ETRW5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1fjhnqfuubx8j1jpgg9j.png" alt="Image description" width="227" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflection
&lt;/h2&gt;

&lt;p&gt;This lab is the first lab that we actually step on the programming of x86_64 and AArch64 systems. It is considerably hard because my group and I are completely unfamiliar with it and we had no idea how to do programming with it. However, it is fun to see the difference between the 6502 assembly language and the x86_64 and AArch64 assembly language. They are quite different but as an assembly language, it is not hard to find something similar from the coding style and programming logic, I will definitely explore more about in the future.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>SPO600 Week 9 reflection</title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Wed, 24 Nov 2021 05:08:09 +0000</pubDate>
      <link>https://dev.to/qzhang125/spo600-week-9-reflection-1858</link>
      <guid>https://dev.to/qzhang125/spo600-week-9-reflection-1858</guid>
      <description>&lt;p&gt;Hello, welcome to the week 9 of SPO600(Software Portability and Optimization) blog. In this week we will discuss the benchmarking and profiling. &lt;/p&gt;

&lt;h1&gt;
  
  
  Test a C program
&lt;/h1&gt;

&lt;p&gt;This part we will do a very simple profiling test, we got 2 c-language programs: &lt;br&gt;
The first is hello.c file&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;stdio.h&amp;gt;

int main() {
        printf("Hello World!\n");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second is hello2.c file&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;unistd.h&amp;gt;

int main() {
        write(1,"Hello World!\n",13);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could use a simple command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;time make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to retrieve how much time it is spending in each function or program.&lt;br&gt;
Let's look at the result below: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Hh6UT0vs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yelz6au78y138j4bvp42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hh6UT0vs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yelz6au78y138j4bvp42.png" alt="Image description" width="615" height="137"&gt;&lt;/a&gt;&lt;br&gt;
As what we see above, the time has been divided up into 3 parts: real, user, and sys. The real time corresponds to the wall clock time, in this test it is 0.372 second. The user time is how much time this program is executing on my behalf, it is the time that the program is directly executing with my normal permissions, in this test it is 0.276 second. The system time(sys) is the amount of time that the kernel was doing stuff on behalf of this program, in this test it is 0.092 second. If we add the user time and system time together, the result should be very close to what we got for the real time of this test. &lt;/p&gt;
&lt;h1&gt;
  
  
  Fun things to know
&lt;/h1&gt;

&lt;p&gt;Type command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;less /proc/cpuinfo 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h1&gt;
  
  
  Reflection
&lt;/h1&gt;

&lt;p&gt;This week we worked on benchmarking and profiling. Benchmarking and profiling is super useful in real programming life. It provides a clear view to identify how much time that a program will consume, it helps programmers to pick up the best solution from tons of ideas. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>SPO600 Week 8 reflection</title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Wed, 24 Nov 2021 05:07:40 +0000</pubDate>
      <link>https://dev.to/qzhang125/spo600-week-8-reflection-1kjc</link>
      <guid>https://dev.to/qzhang125/spo600-week-8-reflection-1kjc</guid>
      <description>&lt;p&gt;Hello my friends, welcome to the week 8 of SPO600(Software Portability and Optimization) blog. In  this blog, let’s talk about the registers in the x86_64 framework. &lt;/p&gt;

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

&lt;h1&gt;
  
  
  Instruction
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---IYtmDcA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebqq9j7mszr21utkfbf7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---IYtmDcA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebqq9j7mszr21utkfbf7.png" alt="Image description" width="575" height="607"&gt;&lt;/a&gt;&lt;br&gt;
Remember that the x86_64 processor family is based on a long long series of processors that date back to the 1970s. So originally on these processors we had a small number of registers, like the X and Y register of the &lt;a href="http://6502.org/tutorials/6502opcodes.html"&gt;6502 assembly language&lt;/a&gt; on the x86 family. The mean registers in x86_64 are A, B, C, D registers. Through the years, the register family has been extended, we still have the A, B, C, D registers but now they are called RAX, RBX, RCX, RDX which mean the extended registers of A, B, C, D and they are 64-bits wide. Beyond this, we also get RBP which means the register base pointer to store the start of the stack, and then we get RSP which stores the stack pointer, RSI and RDI are typically used for copy operation. RSI stores the source index which is pointing to the source that you want to copy and the RDI stores the destination index where you want to place the copy to.  X64 also added another 8 (R8-R15) registers. Since some of x86’s registers have special implicit meanings and are not used as general-purpose. &lt;/p&gt;

&lt;h1&gt;
  
  
  Passing Argument
&lt;/h1&gt;

&lt;p&gt;In this blog, I only focus on integer arguments. For example, 7 integer arguments to a function are passed in registers. The first integer is placed in RDI, the second integer is placed in RSI, the third integer is placed in RDX, the fourth integer is placed in RCX, and then R8 and R9. only the 7th integer is passed on the stack.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reflection
&lt;/h1&gt;

&lt;p&gt;This is the second week that we step on X86_64 and the AArch64 framework. In this blog we only discuss the registers in x86_64 but in the future I will also blog more about the AArch64 framework. This week I learned that modern processors are super fast because they often "guess" the outcome of an operation and store the results of "guess" into the registers that we talked about above. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>SPO600 String lab option 2: Color Selector</title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Wed, 24 Nov 2021 05:05:23 +0000</pubDate>
      <link>https://dev.to/qzhang125/spo600-string-lab-option-2-color-selector-24n5</link>
      <guid>https://dev.to/qzhang125/spo600-string-lab-option-2-color-selector-24n5</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Hello my friend, welcome back to the second part of the string lab. In this lab, we decided to create 2 programs and split it into &lt;a href="https://dev.to/qzhang125/spo600-lab4-6502-string-lab-option-1-adding-calculator-17m8"&gt;part 1&lt;/a&gt; and part 2 using 6502 assembly language. In the first part, we created an adding calculator and now what you are reading is the second part of this lab. In this part, we decided to create a color selector. This program allows the user to choose the color on the right side screen by using keystroke, then the program will print the certain color on the screen.&lt;/p&gt;

&lt;h1&gt;
  
  
  Steps
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Create a ROM to print the color string on the screen.&lt;/li&gt;
&lt;li&gt;Create the up key and down key then assign the functionality. It will allow users to select the color string on the screen.&lt;/li&gt;
&lt;li&gt;Print the title of the color string.&lt;/li&gt;
&lt;li&gt;Print 15 color strings using loop&lt;/li&gt;
&lt;li&gt;Use a loop to highlight the name string that the user has selected.&lt;/li&gt;
&lt;li&gt;Use draw_screen loop to change the color of the pixels.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Code
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;define SCINIT  $ff81 ; initialize/clear screen
define CHROUT  $ffd2 ; output character to screen

define COLOUR  $10
define COLOUR_INDEX $11
define POINTER  $40
define POINTER_H $41
define UP_KEY  $80
define DOWN_KEY $82

 lda #$00 
 sta COLOUR
 sta COLOUR_INDEX 

 jsr initializePrint

getKey:
 lda $ff
 sty $ff

 cmp #UP_KEY
 beq decrementKey

 cmp #DOWN_KEY 
 beq incrementKey

 jmp getKey

decrementKey:
 lda COLOUR
 cmp #$01
 bpl decrementColour

 jmp getKey

decrementColour:
 dec COLOUR

 jsr initializePrint
 jsr initializePaint
 jmp getKey

incrementKey:
 lda COLOUR
 cmp #$0f
 bmi incrementColour

 jmp getKey

incrementColour:
 inc COLOUR
 jsr initializePrint
 jsr initializePaint
 jmp getKey

initializePrint:
 jsr SCINIT
        ldy #$00

writeTitle:
 lda title,y
        beq titleDone
        jsr CHROUT
        iny
        bne writeTitle

titleDone:
 lda #$00
 sta COLOUR_INDEX

startColour:
 ora #$00
 ldy #$00

colourName:
 jsr selectedColour
 beq afterWriting
 jsr highlightLine

 jsr CHROUT

 iny
 bne colourName

afterWriting:
 inc COLOUR_INDEX
 lda COLOUR_INDEX
 cmp #$10
 bne startColour

selectedColour:
 lda COLOUR_INDEX

 cmp #$00
 beq printColour0

 cmp #$01
 beq printColour1

 cmp #$02
 beq printColour2

 cmp #$03
 beq printColour3

 cmp #$04
 beq printColour4

 cmp #$05
 beq printColour5

 cmp #$06
 beq printColour6

 cmp #$07
 beq printColour7

 cmp #$08
 beq printColour8

 cmp #$09
 beq printColour9

 cmp #$0a
 beq printColour10

 cmp #$0b
 beq printColour11

 cmp #$0c
 beq printColour12

 cmp #$0d
 beq printColour13

 cmp #$0e
 beq printColour14

 cmp #$0f
 beq printColour15

 rts

printColour0:
 lda colour0,y
 rts

printColour1:
 lda colour1,y
 rts

printColour2:
 lda colour2,y
 rts

printColour3:
 lda colour3,y
 rts

printColour4:
 lda colour4,y
 rts

printColour5:
 lda colour5,y
 rts

printColour6:
 lda colour6,y
 rts

printColour7:
 lda colour7,y
 rts

printColour8:
 lda colour8,y
 rts

printColour9:
 lda colour9,y
 rts

printColour10:
 lda colour10,y
 rts

printColour11:
 lda colour11,y
 rts

printColour12:
 lda colour12,y
 rts

printColour13:
 lda colour13,y
 rts

printColour14:
 lda colour14,y
 rts

printColour15: 
 lda colour15,y
 rts

highlightLine:
 ldx COLOUR_INDEX
 cpx COLOUR
 beq highlight

 ora #$00
 rts

highlight:
 ora #$80
 rts

initializePaint:
 lda #$00         ; set a pointer at $40 to point to $0200
        sta POINTER
        lda #$02
        sta POINTER_H

 ldy #$00

 lda COLOUR

draw_screen:
  sta ($40), y     ; set pixel

        iny              ; increment index
        bne draw_screen  ; continue until done the page

        inc $41          ; increment the page
        ldx $41          ; get the page
        cpx #$06         ; compare with 6
        bne draw_screen  ; continue until done all pages

 rts

title:
dcb "L","i","s","t",32,"o","f",32,"C","o","l","o","u","r","s",":",13
dcb 00

colour0:
dcb "B","l","a","c","k",13
dcb 00

colour1:
dcb "W","h","i","t","e",13
dcb 00

colour2:
dcb "R","e","d",13
dcb 00

colour3:
dcb "C","y","a","n",13
dcb 00

colour4:
dcb "P","u","r","p","l","e",13
dcb 00

colour5:
dcb "G","r","e","e","n",13
dcb 00

colour6:
dcb "B","l","u","e",13
dcb 00

colour7:
dcb "Y","e","l","l","o","w",13
dcb 00

colour8:
dcb "O","r","a","n","g","e",13
dcb 00

colour9:
dcb "B","r","o","w","n",13
dcb 00

colour10:
dcb "L","i","g","h","t",32,"r","e","d",13
dcb 00

colour11:
dcb "D","a","r","k",32,"g","r","e","y",13
dcb 00

colour12:
dcb "G","r","e","y",13
dcb 00

colour13:
dcb "L","i","g","h","t",32,"g","r","e","e","n",13
dcb 00

colour14:
dcb "L","i","g","h","t",32,"b","l","u","e",13
dcb 00

colour15:
dcb "L","i","g","h","t",32,"g","r","e","y",13
dcb 00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sample results :&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nDW0m_lV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qf3qdq2zyw43e89zwhcs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nDW0m_lV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qf3qdq2zyw43e89zwhcs.png" alt="Image description" width="764" height="460"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sT-bnM9d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fg81inopikg39y7cn5x2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sT-bnM9d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fg81inopikg39y7cn5x2.png" alt="Image description" width="777" height="449"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lewk_ci---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qub8kpevrufg9l72sct5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lewk_ci---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qub8kpevrufg9l72sct5.png" alt="Image description" width="778" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Reflection
&lt;/h1&gt;

&lt;p&gt;In lab 4 part 2, we created a color selector using assembly language. It is a new challenge for us. The most tedious thing is to use different loops to print the color strings and highlight the user selections. Afterwards, we also have to use a loop to change the color pixels. The assembly language is hard for me as a beginner to learn and work with it in 4 different labs. I can not say I'm a master of it because I’m not hundred-percent familiar with the syntax and the coding logic like other higher programming languages. But I’m glad to learn and work on it for almost the whole semester and it shows me a view of a low level programming language that I never touched before, it also helps me to understand the higher-level programming language deeply on the storage and ram view. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>SPO600 Lab4 String lab Option 1: Adding Calculator </title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Wed, 24 Nov 2021 02:53:04 +0000</pubDate>
      <link>https://dev.to/qzhang125/spo600-lab4-6502-string-lab-option-1-adding-calculator-17m8</link>
      <guid>https://dev.to/qzhang125/spo600-lab4-6502-string-lab-option-1-adding-calculator-17m8</guid>
      <description>&lt;p&gt;Hello, welcome to lab 4 for the SPO600(Software Portability and Optimization).This is a lab for the &lt;a href="https://dev.to/qzhang125/week-5-spo666-52n8"&gt;week 4&lt;/a&gt; materials. My team chose to work on option 1 and option 4.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;This blog is for option 1, we created an adding calculator using 6502 assembly language. I will create a subroutine for the user to insert 2 numbers and add them together. &lt;/p&gt;

&lt;h1&gt;
  
  
  Requirements
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Create a subroutine which enables the user to enter two numbers of up to two digits. Indicate where the cursor is, and allow the user to use the digit keys (0-9), backspace, and enter keys. Return the user's input value in the accumulator (A) register.&lt;/li&gt;
&lt;li&gt;Using this subroutine, write a program which add the two numbers (each of which is in the range 0-99) and print the result.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Coding
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;define  SCINIT  $ff81 ; initialize/clear screen
define  CHRIN  $ffcf ; input character from keyboard
define  CHROUT  $ffd2 ; output character to screen
define  SCREEN  $ffed ; get screen size
define  PLOT    $fff0 ; get/set cursor coordinates

define RIGHT  $81
define LEFT  $83
define ENTER  $0d
define BACKSPACE $08

define NUM1    $15;
define  NUM2    $16;

jsr SCINIT

ldy #$00
jsr firstNumPrint ; ask for input for first number
jsr getNum; get the first number
jsr storeFirstNum  ; then store the first number
ldy #$00
jsr secondNumPrint  ; ask for input for second number
jsr getNum; get the second number
jsr storeSecondNum  ; store the second number
ldy #$00
jsr resultPrintString  ; print a string 'Result'
jsr printResult ; print the result
jmp mainLoop  ; go back to the first step

getNum:
     sec
     jsr PLOT
     ldx #$15
     clc
     jsr PLOT

getNumLoop:
     sec
     jsr PLOT
     jsr CHRIN


charCheck: 
     cmp #BACKSPACE ; if user enter backspace, it erase the #$15 digit
     beq move_back

     cmp #RIGHT ; if user enter right arrow, it goes to the first digit
     beq move_right

     cmp #LEFT ; if user enter left arrow, it goes to the second digit
     beq move_left

     cmp #ENTER ; if user enter enter, it goes to the next process
     beq move

printNum:
     cmp #$30
     bcc getNumLoop

     clc
     cmp #$3a
     bcs getNumLoop

     jsr CHROUT

     sec
     jsr PLOT
     cpx #$17
     bne getNumLoop
     dex
     clc
     jsr PLOT
     jmp getNumLoop

move_back:
 cpx #$15
 beq getNumLoop
 jsr CHROUT
 jmp getNumLoop

move_left: 
     cpx #$15 ; first digit
     beq getNumLoop
     jsr CHROUT
     jmp getNumLoop

move_right: 
 cpx #$16 ; second digit
     beq getNumLoop
     jsr CHROUT
     jmp getNumLoop

move:
     sec
     jsr PLOT
     ldx #$15 ; first digit
     clc
     jsr PLOT
     sec
     jsr PLOT

     clc
     sbc #$2F ; to calculate it, it should be subtracted by #$2f

     asl
     asl
     asl
     asl

     pha

     ldx #$16
     clc
     jsr PLOT
     sec
     jsr PLOT

     clc
     sbc #$2F ; to calculate it, it should be subtracted by #$2f
     pha

     ldx #$00
     iny
     clc
     jsr PLOT
     sec
     jsr PLOT

     pla
     tax
     pla

     rts

storeFirstNum:
     sta NUM1
     txa
     eor NUM1
     sta NUM1
     rts

storeSecondNum:
     sta NUM2
     txa
     eor NUM2
     sta NUM2
     rts

printResult:
     sec
     jsr PLOT
     ldx #$15
     clc
     jsr PLOT
     sec
     jsr PLOT

     sed
     lda NUM1
     adc NUM2
     cld
     pha

     bcc outputAddition
     ldx #$14
     clc
     jsr PLOT
     sec
     jsr PLOT
     lda #$31
     jsr CHROUT

outputAddition:
     lsr
     lsr
     lsr
     lsr
     clc
     adc #$30 ; as the received number does not fit for ASCII, it needs to add 
     jsr CHROUT

     pla
     and #$0F
     clc
     adc #$30 ; as the received number does not fit for ASCII, it needs to add 
     jsr CHROUT

     sec
     jsr PLOT
     ldx #$00
     iny
     clc
     jsr PLOT

     rts

firstNumPrint:
     lda firstNum,y
     beq goback_main
     jsr CHROUT
     iny
     bne firstNumPrint

secondNumPrint:
 lda secondNum,y
        beq goback_main
        jsr CHROUT
        iny
        bne secondNumPrint

resultPrintString:
 lda result,y
        beq goback_main
        jsr CHROUT
        iny
        bne resultPrintString

goback_main:
     rts

firstNum:
dcb "E","N","T","E","R",32,"F","I","R","S","T",32,"N","U","M","B","E","R",":",32,32,"0","0"
dcb 00


secondNum:
dcb "E","N","T","E","R",32,"S","E","C","O","N","D",32,"N","U","M","B","E","R",":",32,"0","0"
dcb 00

result:
dcb "R","E","S","U","L","T",":"
dcb 00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the results:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mvsCrsTz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/90so45icwwmn77bqw2tb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mvsCrsTz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/90so45icwwmn77bqw2tb.png" alt="Image description" width="170" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Thoughts &amp;amp; reflection
&lt;/h1&gt;

&lt;p&gt;The assembly language program is getting harder than before, even harder than the third lab. In this lab, I spent a lot of time on how to get the user input, store the two numbers and the results, and display the results on the screen. As I said in each blog about the 6502 assembly language, It is a very low level programming language and it frequently accesses the memory and registers. The operation that we designed for this program is quite easy in any higher level language. But in assembler language, I'm still not familiar with the syntax. I hope more and more practices would help me to solve the problem easily. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>SPO600 Lab3 - Math Lab Update Kaleidoscope</title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Tue, 23 Nov 2021 23:06:12 +0000</pubDate>
      <link>https://dev.to/qzhang125/spo600-lab3-math-lab-update-kaleidoscope-5b2i</link>
      <guid>https://dev.to/qzhang125/spo600-lab3-math-lab-update-kaleidoscope-5b2i</guid>
      <description>&lt;p&gt;Hello my friend, good to see you again here. Today I'm going to update the lab 3 that I started a couple weeks ago. Unfortunately, my group mates and I are unable to solve the Pong game by using 6502 Assembly language. Our problem is we are not sure how to make it bounce on a wall. So we decided to start a new project, if you are still interested in the Pong game and want to explore it further, &lt;a href="https://dev.to/qzhang125/lab3-math-lab-200b"&gt;click here&lt;/a&gt;. But now the new project is Kaleidoscope.&lt;/p&gt;

&lt;p&gt;For this project we needed to create a project to draw the same shape in each quarter of the screen when pressing the arrow keys. This is the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;define POINTER     $10      ;ptr: start of row
 define POINTER_H   $11 
define ROW     $20      ;current row
 define COL     $21         ; current column
 define DOT     $01         ; dot colour location
 define CURSOR      $05     ; green colour
setup: lda #$0f         ; initial ROW,COL
    sta ROW
    sta COL
    LDA #$01
    STA DOT
 draw:  jsr draw_cursor
 getkey:    lda $ff         ; get the keystroke
    ldx #$00            ; clear the key buffer
    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    
    beq clear
    cmp #$63
    beq clear
    cmp #$80    
    bmi getkey
    cmp #$84
    bpl getkey
    pha    
    lda DOT
    sta (POINTER),y
    jsr draw_on_quads
    pla
    cmp #$80
    bne check1
    dec ROW  
    jmp done

 check1:    cmp #$81    ; right key
    bne check2
    inc COL     ; increment COL
    jmp done

 check2:    cmp #$82    ; down key
    bne check3
    inc ROW     ; increment ROW
    jmp done

 check3:    cmp #$83    ; left key
    bne done
    dec COL     ; decrement COL
    clc
    bcc done

 clear: lda table_low   ; clear 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   
    bcc draw

 draw_cursor:
    lda ROW     
    and #$0f
    sta ROW
    lda COL     
    and #$0f
    sta COL
    ldy ROW     
    lda table_low,y
    sta POINTER
    lda table_high,y
    sta POINTER_H
    ldy COL     
    lda #CURSOR
    sta (POINTER),y
    rts

 draw_on_quads:     
    LDA POINTER 
    PHA         
    LDA POINTER_H
    PHA
    LDA #$10
    CLC
    SBC COL
    CLC
    ADC #$10
    TAY
    LDA DOT
    STA (POINTER),y
    TYA
    PHA 
    lda #$10    
    CLC
    SBC ROW
    CLC
    ADC #$10
    TAY
    lda table_low,y
    sta POINTER
    lda table_high,y
    sta POINTER_H
    ldy COL     
    lda DOT
    sta (POINTER),y
    PLA
    TAY
    lda DOT
    sta (POINTER),y
    PLA
    STA POINTER_H
    PLA
    STA POINTER
    RTS
 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;This is a sample of the result:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FN_LP_k_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3z8i35y70c7hu89vpcko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FN_LP_k_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3z8i35y70c7hu89vpcko.png" alt="Image description" width="200" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflection
&lt;/h2&gt;

&lt;p&gt;In this lab, we actually worked on a fully functional program, this program is available to receive user’s input and draw out a diagram. After I finished this lab, I learned how to work on subroutines and understand the syntax and logic of assembly language deeply. Assembly language is a low-level programming language which frequently and explicitly accesses the memory and registers.  I hope this practice will help me to work on 6502 assembly language easier in the future. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>SPO 600 Week 7 Reflection </title>
      <dc:creator>Qzhang125</dc:creator>
      <pubDate>Wed, 27 Oct 2021 18:47:05 +0000</pubDate>
      <link>https://dev.to/qzhang125/spo-600-week-7-reflection-4h22</link>
      <guid>https://dev.to/qzhang125/spo-600-week-7-reflection-4h22</guid>
      <description>&lt;p&gt;Hello my friend, welcome to the week 7 of SPO600(Software Portability and Optimization) blog. In this blog we will discuss about the compiler optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Compiler optimizations are alternations that are made by a compiler to keep the same result as the original code but achieve the best performance. It usually means reducing execution time, reducing code size, and improving execution speed. In other words, compiler optimization is going to make the code as efficient as it could.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance##
&lt;/h2&gt;

&lt;p&gt;Let's look at an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void foo(int size) {
    for (int i = 0; i &amp;lt; 5; i++) {
        if (size == 10) {
            std::cout &amp;lt;&amp;lt; "Size is 10" &amp;lt;&amp;lt; std::endl;
        }
        else {
            std::cout &amp;lt;&amp;lt; "Keep going" &amp;lt;&amp;lt; std::endl;
        }
    }
}

void betterFoo(int size) {
    if (size == 10) {
        for (int i = 0; i &amp;lt; 5; i++) {
            std::cout &amp;lt;&amp;lt; "Size is 10" &amp;lt;&amp;lt; std::endl;
        }
    }
    else {
        for (int i = 0; i &amp;lt; 5; i++) {
            std::cout &amp;lt;&amp;lt; "Keep going" &amp;lt;&amp;lt; std::endl;
        }
    }
}



int main() {
    cout &amp;lt;&amp;lt; "Foo" &amp;lt;&amp;lt; endl;
    foo(10);
    cout &amp;lt;&amp;lt; "better foo" &amp;lt;&amp;lt; endl;
    betterFoo(10);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Z_gXmO---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2f9r6j16t1kfu5c5hbr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Z_gXmO---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2f9r6j16t1kfu5c5hbr.png" alt="Image description" width="280" height="209"&gt;&lt;/a&gt;&lt;br&gt;
In this c++ program, I created 2 functions. The first function foo is going to print 5 times if the “size is 10” or “keep going”  message. The second function betterFoo is doing the same thing. The difference between them is the “size” value is never changed and it is executed 5 times in the loop. In the betterFoo function, the size is only checked once before doing the loop.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Reflection
&lt;/h2&gt;

&lt;p&gt;In this week, we worked on many different compiler optimizations, each of them looks tiny but they are able to improve our program to be faster and time efficient because the algorithm is super important for a program. It controls the sequence of execution between each method and functions, every tiny improvement will make the final solution to be a bit better. &lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
