<p>Students should understand the importance of the memory hierarchy, including how caches use temporal and spatial locality to tremendously speed up memory accesses. Otherwise, a student would not know there is any difference between:</p>

<pre><code>for (int i = 0; i &lt; 1000000; i++) {
    for (int j = 0; j &lt; 1000000; j++) {
        arr[i] += j;
    }
}
</code></pre>

<p>and the logically equivalent reordered code:</p>

<pre><code>for (int j = 0; j &lt; 1000000; j++) {
    for (int i = 0; i &lt; 1000000; i++) {
        arr[i] += j;
    }
}
</code></pre>

<p>The difference is that, in the first piece of code, each array element is retrieved from memory once and placed in either a register or the cache, from which it is operated on a million times. Ignoring spatial locality (which would apply equally to both versions), the total number of reads from memory would be 1,000,000, and the total number of writes would be 1,000,000.</p>

<p>With the second version of code, each array element is fetched from memory once for each value of <code>j</code>. The total number of reads from memory would be 1,000,000 x 1,000,000 (10^12); the total number of writes would be the same.</p>

<p>Per <a href="https://gist.github.com/jboner/2841832" rel="nofollow noreferrer">Latency Numbers Every Programmer Should Know</a>, a main memory access takes about 100 ns; an L1-cache reference takes .5 ns. Accessing a register adds no time to instruction execution.</p>

<p>Ignoring the times for the writes (which may not be in the critical path) and spatial locality (which applies the same to both versions) and assuming that <code>a[i]</code> is stored in a register, the data memory access time for the first is 10^6 * 100 ns = .1 s. The data memory access time for the second is 10^12 * 100 ns = 10^5 s.</p>

CC BY-SA 3.0
2017-06-20T10:16:57.270Z
Okay, I'll bite. Why? With only two values, wouldn't they both be stored in registers? Or would `i` be in the accumulator directly,and thereby somehow get us to the address faster?
Ben I.
CC BY-SA 3.0
2017-06-20T17:17:08.237Z
@BenI. I'll add an explanation.
Ellen Spertus
CC BY-SA 3.0
2017-06-20T17:32:32.277Z
Oh, duh!  *Slaps forehead.*  Thank you, that is a beautiful explanation.  I feel dumb right now for not seeing that :P
Ben I.
CC BY-SA 3.0
2017-06-20T17:58:20.757Z
As I tell my students, for every person asking a question, there are several more wondering the same thing, so thanks for encouraging me to be more explicit.
Ellen Spertus
CC BY-SA 3.0
2017-06-20T02:43:51.643Z
2017-06-20T17:30:27.403Z
2017-06-20T17:30:27.403Z
Ellen Spertus
<p>A touch of some minimal explanation of logic gates, binary numbers, state machines and the processor-memory divide helps make computing seem less like magic, and more like technology (something of which they could become designers in the future).</p>

<p>One doesn't need to teach actually using assembly language to explain how a basic fetch execute cycle works.  Etc.</p>

CC BY-SA 3.0
2017-06-18T23:42:53.290Z
2017-06-19T01:39:22.673Z
2017-06-19T01:39:22.673Z
hotpaw2
<p>Describing the low level architecture at the level of what the machine is able to do can greatly help some students to identify with the task of coding. If you do this, I think you also need to consider how to describe the link between this internal machine architecture, and the external (analogue) world. I don't think it's necessary to go into great detail, just describe the basic load/store/add as a very simple process which is powerful because it can be performed extremely rapidly.</p>

<p>I'm dubious about the value of going down to the level of logic gates or transistors. These are not the elements that processors are designed with (not for maybe 20 years), and seem like a little bit too much detail to present until you are at a point where manipulating and minimising logical equations makes sense. A simple assembly code expresses the right sort of low level unit, and there are plenty of examples of mechanical programmable machines that you can draw on (via you-tube) to demonstrate that the magic is realisable.</p>

CC BY-SA 3.0
2017-06-19T08:08:19.213Z
2017-06-19T08:08:19.213Z
Sean Houlihane
<p>Regarding architecture specifically, I don't see a tremendous benefit in high-school level programming classes.  However, at just one level or so of higher abstraction, discussing the principles of memory management as it applies to programs they write (such as stack and heap operation, how function calls are handled, etc) can make a big difference.</p>

<p>It is very hard to describe why tail recursion is important, or the operational output of <code>(mystring == mystring2)</code> in Java, or even what the code below accomplishes without discussing some lower level operation of the computer:</p>

<pre><code>public static void main(String[] args) {
    int[] v = new int[1];
    v[0] = 5;
    mystery(v);
    System.out.println(v[0]);
}

public static void mystery(int[] a){
    a[0] = 7;
    a = new int[10];
    a[0] = 10;
}
</code></pre>

CC BY-SA 3.0
2017-06-18T17:36:54.960Z
2017-06-18T17:36:54.960Z
Ben I.
<p><strong>TL;DR Understanding the levels of abstraction in a computer</strong></p>

<hr>

<p>My AP Computer Science Principles course teaches three languages: Scratch, C, and Python. One of the 7 Big Ideas for the course is <strong>abstraction</strong>. At the end of the course, I emphasize how Scratch exists at the highest level of abstraction relative to the other two as a block-based language and how the Python interpreter we use is written in C. Connecting this to lower levels of a computer, we form a chain that looks like this (from high to low):</p>

<pre><code>Scratch
Python
C
Assembly Language
Machine Code
Logic Gates
</code></pre>

<p>Obviously for the purposes of the class, it is a bit of a simplification as we don't cover instruction sets or adders and ALUs or assembly language specifically. However, as an introduction, students can begin to form a conception as to how a computer operates at each level. This lays the foundation for further study as students look ahead to pursuing computer science in college.</p>

<p>Despite any potential future benefit, I take this more philosophical approach to this topic: <strong>there is an intrinsic benefit and reward to looking "under the hood" at how things <em>actually</em> work; in that sense learning lower levels of computer architecture is an end in and of itself.</strong></p>

<p>To contextualize my class as a whole, I use the following quote at the top of my syllabus:</p>

<blockquote>
  <p>"Any sufficiently advanced technology is indistinguishable from
  magic." -Arthur C. Clarke</p>
</blockquote>

<p>Learning how charges of electricity on transistors can be constructed to form logic gates, which in turn form the building blocks for computer architecture -- that is magical. </p>

CC BY-SA 3.0
2017-06-18T17:39:15.960Z
I love that quote. Well played.
ItamarG3
CC BY-SA 3.0
2017-06-18T17:01:41.447Z
2017-06-18T17:01:41.447Z
Peter
<p>When teaching an intermediate or advanced highschool programming class that also touches on general CS concepts (algorithms, etc), what are the benefits of explaining low-level computer architecture? How much added understanding of programming/computer science does a student get when learning about logic gates, for example?</p>

<p>My question isn't a duplicate of <a href="https://cseducators.stackexchange.com/questions/212/is-it-more-effective-to-teach-low-level-languages-before-high-level-ones-or-vice">Is it more effective to teach low level languages before high level ones or vice versa?</a> as it's asking about logic gates, registers, instruction set architectures, etc, and the benefits of teaching those in a programming class, not about low level programming languages in particular.</p>

CC BY-SA 3.0
2017-06-18T15:02:43.527Z
Possible duplicate of [Is it more effective to teach low level languages before high level ones or vice versa?](https://cseducators.stackexchange.com/questions/212/is-it-more-effective-to-teach-low-level-languages-before-high-level-ones-or-vice)
thesecretmaster
<curriculum-design><secondary-education><architecture>
Benefits of explaining low-level architecture in a programming class
# Benefits of explaining low-level architecture in a programming class

(Asked by: username_0 on 2017-06-18)

When teaching an intermediate or advanced highschool programming class that also touches on general CS concepts (algorithms, etc), what are the benefits of explaining low-level computer architecture? How much added understanding of programming/computer science does a student get when learning about logic gates, for example?

My question isn't a duplicate of [Is it more effective to teach low level languages before high level ones or vice versa?](https://cseducators.stackexchange.com/questions/212/is-it-more-effective-to-teach-low-level-languages-before-high-level-ones-or-vice) as it's asking about logic gates, registers, instruction set architectures, etc, and the benefits of teaching those in a programming class, not about low level programming languages in particular.

**Tags:** curriculum-design, secondary-education, architecture

> **Comments:**
> **username_1**: Possible duplicate of [Is it more effective to teach low level languages before high level ones or vice versa?](https://cseducators.stackexchange.com/questions/212/is-it-more-effective-to-teach-low-level-languages-before-high-level-ones-or-vice)  

---

## 5 answers

### Answer by username_6 on 2017-06-18. Score: 3 | Accepted answer

TL;DR Understanding the levels of abstraction in a computer

My AP Computer Science Principles course teaches three languages: Scratch, C, and Python. One of the 7 Big Ideas for the course is abstraction. At the end of the course, I emphasize how Scratch exists at the highest level of abstraction relative to the other two as a block-based language and how the Python interpreter we use is written in C. Connecting this to lower levels of a computer, we form a chain that looks like this (from high to low):
Scratch
Python
C
Assembly Language
Machine Code
Logic Gates

Obviously for the purposes of the class, it is a bit of a simplification as we don't cover instruction sets or adders and ALUs or assembly language specifically. However, as an introduction, students can begin to form a conception as to how a computer operates at each level. This lays the foundation for further study as students look ahead to pursuing computer science in college.
Despite any potential future benefit, I take this more philosophical approach to this topic: there is an intrinsic benefit and reward to looking "under the hood" at how things actually work; in that sense learning lower levels of computer architecture is an end in and of itself.
To contextualize my class as a whole, I use the following quote at the top of my syllabus:

"Any sufficiently advanced technology is indistinguishable from
  magic." -Arthur C. Clarke

Learning how charges of electricity on transistors can be constructed to form logic gates, which in turn form the building blocks for computer architecture -- that is magical.

> **Comments:**
> **username_7**: I love that quote. Well played.  

---

### Answer by username_2 on 2017-06-20. Score: 4

Students should understand the importance of the memory hierarchy, including how caches use temporal and spatial locality to tremendously speed up memory accesses. Otherwise, a student would not know there is any difference between:
for (int i = 0; i < 1000000; i++) {
    for (int j = 0; j < 1000000; j++) {
        arr[i] += j;
    }
}

and the logically equivalent reordered code:
for (int j = 0; j < 1000000; j++) {
    for (int i = 0; i < 1000000; i++) {
        arr[i] += j;
    }
}

The difference is that, in the first piece of code, each array element is retrieved from memory once and placed in either a register or the cache, from which it is operated on a million times. Ignoring spatial locality (which would apply equally to both versions), the total number of reads from memory would be 1,000,000, and the total number of writes would be 1,000,000.
With the second version of code, each array element is fetched from memory once for each value of j. The total number of reads from memory would be 1,000,000 x 1,000,000 (10^12); the total number of writes would be the same.
Per Latency Numbers Every Programmer Should Know, a main memory access takes about 100 ns; an L1-cache reference takes .5 ns. Accessing a register adds no time to instruction execution.
Ignoring the times for the writes (which may not be in the critical path) and spatial locality (which applies the same to both versions) and assuming that a[i] is stored in a register, the data memory access time for the first is 10^6 * 100 ns = .1 s. The data memory access time for the second is 10^12 * 100 ns = 10^5 s.

> **Comments:**
> **username_3**: Okay, I'll bite. Why? With only two values, wouldn't they both be stored in registers? Or would `i` be in the accumulator directly,and thereby somehow get us to the address faster?  
> **username_2**: @BenI. I'll add an explanation.  
> **username_3**: Oh, duh!  *Slaps forehead.*  Thank you, that is a beautiful explanation.  I feel dumb right now for not seeing that :P  
> **username_2**: As I tell my students, for every person asking a question, there are several more wondering the same thing, so thanks for encouraging me to be more explicit.  

---

### Answer by username_4 on 2017-06-18. Score: 2

A touch of some minimal explanation of logic gates, binary numbers, state machines and the processor-memory divide helps make computing seem less like magic, and more like technology (something of which they could become designers in the future).

One doesn't need to teach actually using assembly language to explain how a basic fetch execute cycle works. Etc.


---

### Answer by username_5 on 2017-06-19. Score: 2

Describing the low level architecture at the level of what the machine is able to do can greatly help some students to identify with the task of coding. If you do this, I think you also need to consider how to describe the link between this internal machine architecture, and the external (analogue) world. I don't think it's necessary to go into great detail, just describe the basic load/store/add as a very simple process which is powerful because it can be performed extremely rapidly.

I'm dubious about the value of going down to the level of logic gates or transistors. These are not the elements that processors are designed with (not for maybe 20 years), and seem like a little bit too much detail to present until you are at a point where manipulating and minimising logical equations makes sense. A simple assembly code expresses the right sort of low level unit, and there are plenty of examples of mechanical programmable machines that you can draw on (via you-tube) to demonstrate that the magic is realisable.


---

### Answer by username_3 on 2017-06-18. Score: 1

Regarding architecture specifically, I don't see a tremendous benefit in high-school level programming classes.  However, at just one level or so of higher abstraction, discussing the principles of memory management as it applies to programs they write (such as stack and heap operation, how function calls are handled, etc) can make a big difference.
It is very hard to describe why tail recursion is important, or the operational output of (mystring == mystring2) in Java, or even what the code below accomplishes without discussing some lower level operation of the computer:
public static void main(String[] args) {
    int[] v = new int[1];
    v[0] = 5;
    mystery(v);
    System.out.println(v[0]);
}

public static void mystery(int[] a){
    a[0] = 7;
    a = new int[10];
    a[0] = 10;
}


---

