├── .gitignore
├── docs
├── OS
│ ├── Chap01.md
│ ├── Chap07.md
│ ├── index.md
│ ├── Chap02.md
│ ├── final.md
│ ├── Chap09.md
│ ├── Chap04.md
│ ├── Chap06.md
│ └── Chap08.md
├── assets
│ ├── os
│ │ ├── RR.png
│ │ ├── 2.1.png
│ │ ├── 2.5.png
│ │ ├── 2.6.png
│ │ ├── 2.7.png
│ │ ├── 3.1.png
│ │ ├── 3.10.png
│ │ ├── 3.12.png
│ │ ├── 3.19.png
│ │ ├── 3.2.png
│ │ ├── 3.20.png
│ │ ├── 3.23.png
│ │ ├── 3.24.png
│ │ ├── 3.4.png
│ │ ├── 3.5.png
│ │ ├── 3.6.png
│ │ ├── 3.7.png
│ │ ├── 3.8.png
│ │ ├── 4.1.png
│ │ ├── 4.13.png
│ │ ├── 4.14.png
│ │ ├── 4.2.png
│ │ ├── 4.3.png
│ │ ├── 4.4.png
│ │ ├── 4.5.png
│ │ ├── 4.6.png
│ │ ├── 4.7.png
│ │ ├── 4.8.png
│ │ ├── 5.17.png
│ │ ├── 6.1.png
│ │ ├── 6.17.png
│ │ ├── 6.18.png
│ │ ├── 6.19.png
│ │ ├── 6.6.png
│ │ ├── 6.9.png
│ │ ├── 8.1.png
│ │ ├── 8.10.png
│ │ ├── 8.11.png
│ │ ├── 8.14.png
│ │ ├── 8.18.png
│ │ ├── 8.19.png
│ │ ├── 8.2.png
│ │ ├── 8.20.png
│ │ ├── 8.21.png
│ │ ├── 8.22.png
│ │ ├── 8.23.png
│ │ ├── 8.24.png
│ │ ├── 8.3.png
│ │ ├── 8.4.png
│ │ ├── 8.5.png
│ │ ├── 8.6.png
│ │ ├── 8.8.png
│ │ ├── 9.10.png
│ │ ├── 9.12.png
│ │ ├── 9.14.png
│ │ ├── 9.17.png
│ │ ├── 9.6.png
│ │ ├── FCFS.png
│ │ ├── SJF.png
│ │ ├── VAX.png
│ │ ├── libc.png
│ │ ├── page.png
│ │ ├── FCFS-2.png
│ │ ├── IA-32.png
│ │ ├── SJF-2.png
│ │ ├── page2.png
│ │ ├── pagesize.png
│ │ ├── priority.png
│ │ └── 2015midterm.png
│ └── favicon.png
├── css
│ ├── style.css
│ └── katex.css
├── js
│ └── katex.js
├── ML
│ ├── index.md
│ ├── 06.md
│ ├── 08.md
│ ├── 02.md
│ ├── 09.md
│ ├── 07.md
│ ├── 01.md
│ ├── 04.md
│ ├── 03.md
│ └── 05.md
├── JavaScript
│ ├── 03
│ │ ├── insertionSort.md
│ │ ├── selectionSort.md
│ │ ├── bubbleSort.md
│ │ ├── mergeSort.md
│ │ └── quickSort.md
│ ├── index.md
│ ├── 01
│ │ ├── divideAndConquer.md
│ │ ├── slidingWindow.md
│ │ ├── multiplePointers.md
│ │ └── frequencyCounters.md
│ ├── 02
│ │ ├── recursionEasy.md
│ │ └── recursionHard.md
│ ├── 04
│ │ ├── MaxBinaryHeap.md
│ │ ├── MaxPriorityQueue.md
│ │ ├── BinarySearchTree.md
│ │ ├── SinglyLinkedList.md
│ │ └── DoublyLinkedList.md
│ └── 05
│ │ ├── Graph.md
│ │ └── Dijkstra.md
├── PCP
│ ├── index.md
│ ├── 2-3.md
│ ├── 1-3.md
│ ├── 1-2.md
│ ├── 2-2.md
│ ├── 1-4.md
│ ├── 1-5.md
│ └── 2-1.md
└── index.md
├── .gitattributes
├── custom
└── main.html
├── README.md
└── mkdocs.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | site/
3 |
--------------------------------------------------------------------------------
/docs/OS/Chap01.md:
--------------------------------------------------------------------------------
1 | # Chapter 1 Introduction
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.md linguist-detectable=true
2 | *.md linguist-documentation=false
3 |
--------------------------------------------------------------------------------
/docs/assets/os/RR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/RR.png
--------------------------------------------------------------------------------
/docs/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/favicon.png
--------------------------------------------------------------------------------
/docs/assets/os/2.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/2.1.png
--------------------------------------------------------------------------------
/docs/assets/os/2.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/2.5.png
--------------------------------------------------------------------------------
/docs/assets/os/2.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/2.6.png
--------------------------------------------------------------------------------
/docs/assets/os/2.7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/2.7.png
--------------------------------------------------------------------------------
/docs/assets/os/3.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.1.png
--------------------------------------------------------------------------------
/docs/assets/os/3.10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.10.png
--------------------------------------------------------------------------------
/docs/assets/os/3.12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.12.png
--------------------------------------------------------------------------------
/docs/assets/os/3.19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.19.png
--------------------------------------------------------------------------------
/docs/assets/os/3.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.2.png
--------------------------------------------------------------------------------
/docs/assets/os/3.20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.20.png
--------------------------------------------------------------------------------
/docs/assets/os/3.23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.23.png
--------------------------------------------------------------------------------
/docs/assets/os/3.24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.24.png
--------------------------------------------------------------------------------
/docs/assets/os/3.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.4.png
--------------------------------------------------------------------------------
/docs/assets/os/3.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.5.png
--------------------------------------------------------------------------------
/docs/assets/os/3.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.6.png
--------------------------------------------------------------------------------
/docs/assets/os/3.7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.7.png
--------------------------------------------------------------------------------
/docs/assets/os/3.8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/3.8.png
--------------------------------------------------------------------------------
/docs/assets/os/4.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/4.1.png
--------------------------------------------------------------------------------
/docs/assets/os/4.13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/4.13.png
--------------------------------------------------------------------------------
/docs/assets/os/4.14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/4.14.png
--------------------------------------------------------------------------------
/docs/assets/os/4.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/4.2.png
--------------------------------------------------------------------------------
/docs/assets/os/4.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/4.3.png
--------------------------------------------------------------------------------
/docs/assets/os/4.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/4.4.png
--------------------------------------------------------------------------------
/docs/assets/os/4.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/4.5.png
--------------------------------------------------------------------------------
/docs/assets/os/4.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/4.6.png
--------------------------------------------------------------------------------
/docs/assets/os/4.7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/4.7.png
--------------------------------------------------------------------------------
/docs/assets/os/4.8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/4.8.png
--------------------------------------------------------------------------------
/docs/assets/os/5.17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/5.17.png
--------------------------------------------------------------------------------
/docs/assets/os/6.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/6.1.png
--------------------------------------------------------------------------------
/docs/assets/os/6.17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/6.17.png
--------------------------------------------------------------------------------
/docs/assets/os/6.18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/6.18.png
--------------------------------------------------------------------------------
/docs/assets/os/6.19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/6.19.png
--------------------------------------------------------------------------------
/docs/assets/os/6.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/6.6.png
--------------------------------------------------------------------------------
/docs/assets/os/6.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/6.9.png
--------------------------------------------------------------------------------
/docs/assets/os/8.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.1.png
--------------------------------------------------------------------------------
/docs/assets/os/8.10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.10.png
--------------------------------------------------------------------------------
/docs/assets/os/8.11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.11.png
--------------------------------------------------------------------------------
/docs/assets/os/8.14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.14.png
--------------------------------------------------------------------------------
/docs/assets/os/8.18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.18.png
--------------------------------------------------------------------------------
/docs/assets/os/8.19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.19.png
--------------------------------------------------------------------------------
/docs/assets/os/8.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.2.png
--------------------------------------------------------------------------------
/docs/assets/os/8.20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.20.png
--------------------------------------------------------------------------------
/docs/assets/os/8.21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.21.png
--------------------------------------------------------------------------------
/docs/assets/os/8.22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.22.png
--------------------------------------------------------------------------------
/docs/assets/os/8.23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.23.png
--------------------------------------------------------------------------------
/docs/assets/os/8.24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.24.png
--------------------------------------------------------------------------------
/docs/assets/os/8.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.3.png
--------------------------------------------------------------------------------
/docs/assets/os/8.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.4.png
--------------------------------------------------------------------------------
/docs/assets/os/8.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.5.png
--------------------------------------------------------------------------------
/docs/assets/os/8.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.6.png
--------------------------------------------------------------------------------
/docs/assets/os/8.8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/8.8.png
--------------------------------------------------------------------------------
/docs/assets/os/9.10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/9.10.png
--------------------------------------------------------------------------------
/docs/assets/os/9.12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/9.12.png
--------------------------------------------------------------------------------
/docs/assets/os/9.14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/9.14.png
--------------------------------------------------------------------------------
/docs/assets/os/9.17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/9.17.png
--------------------------------------------------------------------------------
/docs/assets/os/9.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/9.6.png
--------------------------------------------------------------------------------
/docs/assets/os/FCFS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/FCFS.png
--------------------------------------------------------------------------------
/docs/assets/os/SJF.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/SJF.png
--------------------------------------------------------------------------------
/docs/assets/os/VAX.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/VAX.png
--------------------------------------------------------------------------------
/docs/assets/os/libc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/libc.png
--------------------------------------------------------------------------------
/docs/assets/os/page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/page.png
--------------------------------------------------------------------------------
/docs/assets/os/FCFS-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/FCFS-2.png
--------------------------------------------------------------------------------
/docs/assets/os/IA-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/IA-32.png
--------------------------------------------------------------------------------
/docs/assets/os/SJF-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/SJF-2.png
--------------------------------------------------------------------------------
/docs/assets/os/page2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/page2.png
--------------------------------------------------------------------------------
/docs/assets/os/pagesize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/pagesize.png
--------------------------------------------------------------------------------
/docs/assets/os/priority.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/priority.png
--------------------------------------------------------------------------------
/docs/assets/os/2015midterm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walkccc/CS/HEAD/docs/assets/os/2015midterm.png
--------------------------------------------------------------------------------
/docs/css/style.css:
--------------------------------------------------------------------------------
1 | img[alt=normal] {
2 | width: 80%;
3 | }
4 |
5 | img[alt=small] {
6 | width: 50%;
7 | }
--------------------------------------------------------------------------------
/docs/OS/Chap07.md:
--------------------------------------------------------------------------------
1 | # Chapter 7 Deadlocks
2 |
3 | ## 7.1 System Model
4 |
5 | ## 7.2 Deadlock Characterization
6 |
7 | ### 7.2.1 Necessary Conditions
8 |
9 | ### 7.2.2 Resource-Allocation Graph
--------------------------------------------------------------------------------
/custom/main.html:
--------------------------------------------------------------------------------
1 |
2 | {% extends "base.html" %}
3 |
4 | {% block site_meta %}
5 | {{ super() }}
6 |
7 | {% endblock %}
8 |
--------------------------------------------------------------------------------
/docs/js/katex.js:
--------------------------------------------------------------------------------
1 | document.addEventListener("DOMContentLoaded", function() {
2 | renderMathInElement(document.body, {
3 | delimiters: [
4 | {left: "$$", right: "$$", display: true},
5 | {left: "$", right: "$", display: false}
6 | ]
7 | });
8 | });
--------------------------------------------------------------------------------
/docs/ML/index.md:
--------------------------------------------------------------------------------
1 | # Machine Learning | notes
2 |
3 | In this page, I'll work on my notes when I watched the [Machine Learning course video](https://www.youtube.com/playlist?list=PLJV_el3uVTsPy9oCRY30oBPNLCo89yu49) provided by Professor [Hung-yi Lee](http://speech.ee.ntu.edu.tw/~tlkagk/index.html).
4 |
--------------------------------------------------------------------------------
/docs/JavaScript/03/insertionSort.md:
--------------------------------------------------------------------------------
1 | # Insertion Sort
2 |
3 | ## `insertionSort(arr)`
4 |
5 | ```js
6 | const insertionSort = arr => {
7 | for (let i = 1; i < arr.length; i++) {
8 | let curr = arr[i];
9 |
10 | for (var j = i - 1; j >= 0 && arr[j] > curr; j--)
11 | arr[j + 1] = arr[j];
12 |
13 | arr[j + 1] = curr;
14 | }
15 |
16 | return arr;
17 | };
18 | ```
19 |
--------------------------------------------------------------------------------
/docs/JavaScript/index.md:
--------------------------------------------------------------------------------
1 | # JavaScript Data Structures and Algorithms
2 |
3 | This page contains notes from the course: [JavaScript Algorithms and Data Structures Masterclass](https://www.udemy.com/js-algorithms-and-data-structures-masterclass/learn/v4/content) taught by Colt Steele.
4 |
5 | All codes are written in ES9 fashion and are formatted by [prettier](https://github.com/prettier/prettier).
6 |
--------------------------------------------------------------------------------
/docs/css/katex.css:
--------------------------------------------------------------------------------
1 | .katex {
2 | font-size: 1.1em !important;
3 | font: normal 1.1em KaTeX_Main, Times New Roman, serif;
4 | line-height: 1.2;
5 | white-space: normal;
6 | text-indent: 0;
7 | }
8 |
9 | .katex-display > .katex {
10 | display: inline-block;
11 | white-space: nowrap;
12 | max-width: 100%;
13 | text-align: initial;
14 | }
15 |
16 | .katex-html {
17 | overflow-y: hidden;
18 | }
19 |
--------------------------------------------------------------------------------
/docs/PCP/index.md:
--------------------------------------------------------------------------------
1 | # Parallel and Concurrent Programming with C++
2 |
3 | This page contains notes from the course: [Parallel and Concurrent Programming with C++](https://www.linkedin.com/learning/parallel-and-concurrent-programming-with-c-plus-plus-part-1/learn-parallel-programming-basics?u=2131553) taught by Barron Stone and Olivia Chiu Stone in LinkedIn Learning.
4 |
5 | I use highlight here to indicate important knowledge.
6 |
--------------------------------------------------------------------------------
/docs/OS/index.md:
--------------------------------------------------------------------------------
1 | # Operating System | notes
2 |
3 | In this page, I'll work on my notes when I had class of [Operating System, Spring 2018](http://newslab.csie.ntu.edu.tw/course/OS2018/index.php) by Professor [Tei-Wei Kuo](https://www.csie.ntu.edu.tw/~ktw/eng-index.htm). Professor Kuo has also upload the course videos to [YouTube](https://www.youtube.com/playlist?list=PLco3ZjBUnBUKNn0ANhQ1N7aJbYUmMlgc8).
4 |
5 | The materials are mainly from the [Operating System Concepts, 9th Edition](https://www.amazon.com/Operating-System-Concepts-Abraham-Silberschatz-ebook/dp/B00APSZCEQ).
6 |
--------------------------------------------------------------------------------
/docs/JavaScript/03/selectionSort.md:
--------------------------------------------------------------------------------
1 | # Selection Sort
2 |
3 | ## `swap(arr, i, j)`
4 |
5 | ```js
6 | const swap = (arr, i, j) => {
7 | [arr[i], arr[j]] = [arr[j], arr[i]];
8 | };
9 | ```
10 |
11 | ## `selectionSort(arr)`
12 |
13 | ```js
14 | const selectionSort = arr => {
15 | for (let i = 0; i < arr.length; i++) {
16 | let smallest = i;
17 | for (let j = i + 1; j < arr.length; j++) {
18 | if (arr[smallest] > arr[j]) {
19 | smallest = j;
20 | }
21 | }
22 | if (i !== smallest) swap(arr, i, smallest);
23 | }
24 | return arr;
25 | };
26 | ```
27 |
--------------------------------------------------------------------------------
/docs/JavaScript/03/bubbleSort.md:
--------------------------------------------------------------------------------
1 | # Bubble Sort
2 |
3 | ## `swap(arr, i, j)`
4 |
5 | ```js
6 | const swap = (arr, i, j) => {
7 | [arr[i], arr[j]] = [arr[j], arr[i]];
8 | };
9 | ```
10 |
11 | ## `bubbleSort(arr)`
12 |
13 | ```js
14 | const bubbleSort = arr => {
15 | for (let i = arr.length - 1; i > 0; i--) {
16 | let noSwaps = true;
17 |
18 | for (let j = 0; j < i; j++) {
19 | if (arr[j] > arr[j + 1]) {
20 | swap(arr, j, j + 1);
21 | noSwaps = false;
22 | }
23 | }
24 |
25 | if (noSwaps) break;
26 | }
27 |
28 | return arr;
29 | };
30 | ```
31 |
--------------------------------------------------------------------------------
/docs/JavaScript/03/mergeSort.md:
--------------------------------------------------------------------------------
1 | # Merge Sort
2 |
3 | ## `merge(arr1, arr2)`
4 |
5 | ```js
6 | const merge = (arr1, arr2) => {
7 | let ret = [];
8 | let i = 0;
9 | let j = 0;
10 |
11 | while (i < arr1.length && j < arr2.length) {
12 | if (arr1[i] < arr2[j]) ret.push(arr1[i++]);
13 | else ret.push(arr2[j++]);
14 | }
15 |
16 | while (i < arr1.length) ret.push(arr1[i++]);
17 | while (j < arr2.length) ret.push(arr2[j++]);
18 |
19 | return ret;
20 | };
21 | ```
22 |
23 | ## `mergeSort(arr)`
24 |
25 | ```js
26 | const mergeSort = arr => {
27 | if (arr.length <= 1) return arr;
28 |
29 | let mid = Math.floor(arr.length / 2);
30 | let left = mergeSort(arr.slice(0, mid));
31 | let right = mergeSort(arr.slice(mid));
32 |
33 | return merge(left, right);
34 | };
35 | ```
36 |
--------------------------------------------------------------------------------
/docs/JavaScript/03/quickSort.md:
--------------------------------------------------------------------------------
1 | # Quick Sort
2 |
3 | ## `pivot(arr, left = 0, right = arr.length - 1)`
4 |
5 | ```js
6 | const pivot = (arr, left, right) => {
7 | const swap = (arr, i, j) => {
8 | [arr[i], arr[j]] = [arr[j], arr[i]];
9 | };
10 |
11 | let pivot = arr[left];
12 | let swapIndex = left;
13 |
14 | for (let i = left + 1; i <= right; i++)
15 | if (pivot > arr[i])
16 | swap(arr, ++swapIndex, i);
17 | swap(arr, left, swapIndex);
18 |
19 | return swapIndex;
20 | };
21 | ```
22 |
23 | ## `quickSort(arr)`
24 |
25 | ```js
26 | const quickSort = (arr, left = 0, right = arr.length - 1) => {
27 | if (left < right) {
28 | let pivotIndex = pivot(arr, left, right);
29 | quickSort(arr, left, pivotIndex - 1);
30 | quickSort(arr, pivotIndex + 1, right);
31 | }
32 |
33 | return arr;
34 | };
35 | ```
36 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # Computer Science Notes
2 |
3 | ## Getting Started
4 |
5 | In this website, I'll work on my notes about several topics:
6 |
7 | - [Parallel and Concurrent Programming with C++](./PCP/)
8 | - [Operating System](./OS/)
9 | - [Maching Learning](./ML/)
10 | - [JavaScript Data Structures and Algorithms](./JavaScript/)
11 |
12 | ## How I generate this website
13 |
14 | I use the static site generator [MkDocs](http://www.mkdocs.org/) and the beautiful theme [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) to build this website!
15 |
16 | All mathematical equations are rendered by [KaTeX](https://katex.org/), and I added `overflow-x: auto` to prevent overflow issue on small screen devices, so you can scroll horizontally in some math display equations.
17 |
18 | ## More Informations
19 |
20 | For more informations please visit [**my GitHub site**](https://github.com/walkccc).
21 |
22 | By Jay Chen on May 14, 2018.
23 |
--------------------------------------------------------------------------------
/docs/ML/06.md:
--------------------------------------------------------------------------------
1 | # Deep Learning
2 |
3 | ## Three Steps
4 |
5 | ### Step 1: Function Set
6 |
7 | [Lecture 5](../5) 提到的,我們可以將多個 logistic regression models 連接起來,而每一個 model 就像是一個 neuron,給定了網路架構,就定義了一個 function set。
8 |
9 | 給定了架構,再給上每個 neuron 的參數($w^l, b^l$),整個網路就像是一個 function。
10 |
11 | 
12 |
13 | 每個 $W^l$ 都是一個矩陣,都是我們可以用 GPU 的平行運算去加速矩陣運算:
14 |
15 | $$
16 | \begin{aligned}
17 | y & = f(x) \\\\
18 | & = \sigma(W^L \cdots \sigma(W^2 \sigma(W^1x + b^1) + b^2) \cdots + b^L)
19 | \end{aligned}
20 | $$
21 |
22 | #### Output Layer
23 |
24 | 
25 |
26 | ### Step 2: Goodness of Function
27 |
28 | 
29 |
30 | 
31 |
32 | ### Step 3: Find the best function
33 |
34 | 我們一樣可以用 Gradient Descent 來求解,這用到 [Backpropagation](../7) 的原理。
35 |
36 | 
37 |
38 | 其中,
39 |
40 | $$
41 | \nabla L = \left[ \begin{array} { c } { \frac { \partial L } { \partial w _ { 1 } } } \\\\ { \frac { \partial L } { \partial w _ { 2 } } } \\\\ { \vdots } \\\\ { \frac { \partial L } { \partial b _ { 1 } } } \\\\ { \vdots } \end{array} \right]
42 | $$
--------------------------------------------------------------------------------
/docs/PCP/2-3.md:
--------------------------------------------------------------------------------
1 | # Asynchronous
2 |
3 | ## Thread pool
4 |
5 | === "begin"
6 |
7 | ```cpp
8 | // Chopping vegetables with a thread pool
9 | #include
10 |
11 | void vegetable_chopper(int vegetable_id) {
12 | printf("Thread %d chopped vegetable %d.\n", std::this_thread::get_id(),
13 | vegetable_id);
14 | }
15 |
16 | int main() {
17 | std::thread choppers[100];
18 | for (int i = 0; i < 100; i++) {
19 | choppers[i] = std::thread(vegetable_chopper, i);
20 | }
21 | for (auto& c : choppers) {
22 | c.join();
23 | }
24 | }
25 | ```
26 |
27 | === "end"
28 |
29 | ```cpp hl_lines="2 10 12"
30 | // Chopping vegetables with a thread pool
31 | #include
32 |
33 | void vegetable_chopper(int vegetable_id) {
34 | printf("Thread %d chopped vegetable %d.\n", std::this_thread::get_id(),
35 | vegetable_id);
36 | }
37 |
38 | int main() {
39 | boost::asio::thread_pool pool(4); // 4 threads
40 | for (int i = 0; i < 100; i++) {
41 | boost::asio::post(pool, [i]() { vegetable_chopper(i); });
42 | }
43 | pool.join();
44 | }
45 | ```
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Computer Science Notes
2 |
3 | ## Getting Started
4 |
5 | In this website, I'll work on my notes about several topics:
6 |
7 | - [Operating System](https://walkccc.github.io/CS/OS/)
8 | - [Maching Learning](https://walkccc.github.io/CS/ML/)
9 | - [JavaScript Data Structures and Algorithms](https://walkccc.github.io/CS/JavaScript/)
10 |
11 | Feel free to give me your feedback if any adjustment is needed with the sorted solutions. You can press the "pencil icon" in the upper right corner to edit the contents or simply [open an issue](https://github.com/walkccc/CS/issues/new) in [my repository](https://github.com/walkccc/CS/).
12 |
13 | ## How I generate this website
14 |
15 | I use the static site generator [MkDocs](http://www.mkdocs.org/) and the beautiful theme [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) to build this website!
16 |
17 | All mathematical equations are rendered by [KaTeX](https://katex.org/), and I added `overflow-x: auto` to prevent overflow issue on small screen devices, so you can scroll horizontally in some math display equations.
18 |
19 | ## More Informations
20 |
21 | For more informations please visit [**my GitHub site**](https://github.com/walkccc).
22 |
23 | By Jay Chen on May 14, 2018.
24 |
--------------------------------------------------------------------------------
/docs/ML/08.md:
--------------------------------------------------------------------------------
1 | # "Hello world" of deep learning
2 |
3 | ## Three Steps
4 |
5 | - Step 1: define a set of function
6 | - Step 2: goodness of function
7 | - Step 3: pick the best function
8 |
9 | 老師課堂上的 task 是使用 [Keras](https://keras.io/)
10 |
11 | ```python
12 | model = Sequential() # declare a model
13 | model.add(Dense(input_dim=28*28, output_dim=500)) # Dense: Fully connected
14 | model.add(Activation('sigmoid'))
15 | model.add(Dense(units=500, activation='relu'))
16 | model.add(Dense(units=10, activation='softmax')) # output between 0 and 1
17 | model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
18 | model.fit(s_train, y_train, batch_size=100, epochs=20) # pick the best function
19 | ```
20 |
21 | ## Mini-batch
22 |
23 | **Pseudo code:**
24 |
25 | 1. Randomly initialize network parameters
26 | 2. while (!all mini-batches have been picked)
27 |
28 | pick the $i^\text{th}$ batch $L' = C^1 + C^{31} + \cdots$
29 | update parameters once
30 |
31 | 每跑一次 while-loop,即是一個 epoch。
32 |
33 | - 如果 batch_size = 1:SGP
34 | - 如果 batch_size = #training data:(full batch)Gradient Descent
35 |
36 | ## Matrix Operation
37 |
38 | ### Stochastic Gradient Descent
39 |
40 | 
41 |
42 | ### Mini-batch
43 |
44 | 
45 |
46 | GPU 的加速,就是因為取 batch 後,能夠平行運算,所以若沒有 batch_size,是無法用 GPU 加速的。
--------------------------------------------------------------------------------
/docs/JavaScript/01/divideAndConquer.md:
--------------------------------------------------------------------------------
1 | # Divide and Conquer Pattern
2 |
3 | This pattern involves dividing a data set into smaller chunks and then repeating a process with a subset of data.
4 |
5 | This pattern can tremendously **decrease time complexity**.
6 |
7 | ---
8 |
9 | ## `search(arr, val)`
10 |
11 | > Given a **sorted** array of integers, write a function called `search`, that accepts a value and returns the index where the value passed to the function is located. If the value is not found, return -1.
12 |
13 | ```js
14 | search([1, 2, 3, 4, 5, 6], 4); // 3
15 | search([1, 2, 3, 4, 5, 6], 6); // 5
16 | search([1, 2, 3, 4, 5, 6], 11); // -1
17 | ```
18 |
19 | - Solution 1 (naive)
20 |
21 | - Time: $O(n)$
22 |
23 | ```js
24 | const search = (arr, val) => {
25 | for (let i = 0; i < arr.length; i++)
26 | if (arr[i] === val)
27 | return i;
28 | return -1;
29 | };
30 | ```
31 |
32 | - Solution 2 (binary search)
33 |
34 | - Time: $O(\log n)$
35 |
36 | ```js
37 | const search = (arr, val) => {
38 | let left = 0;
39 | let right = arr.length - 1;
40 |
41 | while (left <= right) {
42 | let mid = Math.floor((left + right) / 2);
43 | let curr = arr[mid];
44 |
45 | if (arr[mid] < val) {
46 | left = mid + 1;
47 | } else if (arr[mid] > val) {
48 | right = mid - 1;
49 | } else {
50 | return mid;
51 | }
52 | }
53 |
54 | return -1;
55 | };
56 | ```
57 |
--------------------------------------------------------------------------------
/docs/ML/02.md:
--------------------------------------------------------------------------------
1 | # Lecture 2: Where does the error come from?
2 |
3 | ## Bias and Variance of Estimator
4 |
5 | Error 有兩種來源:
6 |
7 | - bias
8 | - variance
9 |
10 | 分析 error 的來源,可以挑選適當的方法改善 model。
11 |
12 | 以進化前的寶可夢為輸入,以進化後的真實 CP 值為輸出,真實的函數記為 $\hat f$(上帝視角才知道)
13 |
14 | 從訓練數據,我們找到 $f^\*$($\hat f$ 的估計)
15 |
16 | 
17 |
18 | 用表格來看
19 |
20 | | | 簡單模型 | 複雜模型 |
21 | |:--:|:--:|:--:|
22 | | variance | 小 | 大 |
23 | | bias | 大 | 小 |
24 |
25 | - 簡單模型更少受 training data 影響。
26 | - 複雜模型會盡力去擬合 training data 的變化。
27 |
28 | Bias 即 $d(\bar f, \hat f)$
29 |
30 | 簡單模型的 model space 較小,可能根本沒有包含到 target。
31 |
32 | - 在 underfitting 的情況下,error 大部分來自 bias。
33 | - 在 overfitting 的情況下,error 大部分來自 variance。
34 |
35 | ---
36 |
37 | - 如果 model 連 training data 都 fit 不好,那就是 underfitting
38 | - 如果 model 可以 fit training data,但 testing error 大,那就是 overfitting
39 |
40 | ---
41 |
42 | - 在 bias 大的情況下,需要重新設計 model,例如增加更多 features,或著讓 model 更複雜
43 | - 在 variance 大的情況下,需要更多資料,或者 regularization。More data 很有效,但卻不一定可行,regularization 希望曲線平滑,但可能會損害 bias,造成 model space 無法包含 target $\hat f$。
44 |
45 | ## Model Selection
46 |
47 | 在選擇模型時,要考慮 2 種 error 的折衷,使 total error 最小。
48 |
49 | 不應這樣做:
50 |
51 | 
52 |
53 | 因為這樣做,在 public testing error 的表現不能完全的反應在 private testing error。
54 |
55 | ### Cross Validation
56 |
57 | 
58 |
59 | 將 training set 分成 training set 和 validation set,在 training set 上訓練 model 1-3,選擇在 validation set 上 error 最小的 model。
60 |
61 | 如果嫌 training set 中 data 太少的話,可以在確定 model 後在全部 training set 上再訓練一遍該 model。
62 |
63 | 這樣做,在 public testing set 上的 error 才會代表在 private testing set 上的 error。
64 |
65 | 不能用 public testing set 去調整 model!
66 |
67 | ### $N$-fold Cross Validation
68 |
69 | 
70 |
71 | 將 training set 分成 $N$ 折,每次只有一折作為 validation set,其它折作為 training set,在各 model 中選擇 $N$ 次訓練得到的 $N$ 個 validation error 均值最小的 model。
72 |
--------------------------------------------------------------------------------
/docs/JavaScript/02/recursionEasy.md:
--------------------------------------------------------------------------------
1 | # Recursion Problem Set (easy)
2 |
3 | ## `power(n, x)`
4 |
5 | > Write a function called `power` which accepts a base and an exponent. The function should return the power of the base to the exponent.
6 | > This function should mimic the functionality of `Math.pow()` - do not worry about negative bases and exponents.
7 |
8 | ```js
9 | const power = (n, x) => {
10 | if (x == 0) return 1;
11 | if (x == 1) return n;
12 | let t = power(n, Math.floor(x / 2));
13 | return t * t * power(n, x % 2);
14 | };
15 | ```
16 |
17 | ## `factorial(n)`
18 |
19 | > Write a function `factorial` which accepts a number and returns the factorial of that number. A factorial is the product of an integer and all the integers below it; e.g., factorial four (4!) is equal to 24, because 4 \* 3 \* 2 \* 1 equals 24. **factorial zero (0!) is always 1.**
20 |
21 | ```js
22 | const factorial = n => {
23 | if (n == 0) return 1;
24 | return n * factorial(n - 1);
25 | };
26 | ```
27 |
28 | ## `productOfArray(arr)`
29 |
30 | > Write a function called `productOfArray` which takes in an array of numbers and returns the product of them all.
31 |
32 | ```js
33 | const productOfArray = arr => {
34 | if (arr.length == 0) return 1;
35 | return arr[0] * productOfArray(arr.splice(1));
36 | };
37 | ```
38 |
39 | ## `recursiveRange(num)`
40 |
41 | > Write a function called `recursiveRange` which accepts a number and adds up all the numbers from 0 to the number passed to the function.
42 |
43 | ```js
44 | const recursiveRange = num => {
45 | if (num == 0) return 0;
46 | return num + recursiveRange(num - 1);
47 | };
48 | ```
49 |
50 | ## `fib(num)`
51 |
52 | > Write a recursive function called `fib` which accepts a number and returns the nth number in the Fibonacci sequence. Recall that the Fibonacci sequence is the sequence of whole numbers 1, 1, 2, 3, 5, 8, which starts with 1 and 1, and where every number thereafter is equal to the sum of the previous two numbers.
53 |
54 | ```js
55 | const fib = num => {
56 | if (num == 1 || num == 2) return 1;
57 | return fib(num - 1) + fib(num - 2);
58 | };
59 | ```
60 |
--------------------------------------------------------------------------------
/docs/JavaScript/04/MaxBinaryHeap.md:
--------------------------------------------------------------------------------
1 | ```js
2 | class MaxBinaryHeap {
3 | constructor() {
4 | this.arr = [];
5 | }
6 |
7 | insert(elem) {
8 | this.arr = [...this.arr, elem];
9 | this.bubbleUp();
10 | }
11 |
12 | bubbleUp() {
13 | let index = this.arr.length - 1;
14 | const elem = this.arr[index];
15 |
16 | while (index > 0) {
17 | let parentIndex = Math.floor((index - 1) / 2);
18 | let parent = this.arr[parentIndex];
19 |
20 | if (elem <= parent) break;
21 |
22 | this.arr[parentIndex] = elem;
23 | this.arr[index] = parent;
24 | index = parentIndex;
25 | }
26 | }
27 |
28 | extractMax() {
29 | const max = this.arr[0];
30 | const end = this.arr.pop();
31 |
32 | if (this.arr.length > 0) {
33 | this.arr[0] = end;
34 | this.sinkDown();
35 | }
36 |
37 | return max;
38 | }
39 |
40 | sinkDown() {
41 | let index = 0;
42 | const { length } = this.arr;
43 | const elem = this.arr[index];
44 |
45 | while (true) {
46 | let leftChildIndex = 2 * index + 1;
47 | let rightChildIndex = 2 * index + 2;
48 | let leftChild = null;
49 | let rightChild = null;
50 | let swap = null;
51 |
52 | if (leftChildIndex < length) {
53 | leftChild = this.arr[leftChildIndex];
54 | if (leftChild > elem) {
55 | swap = leftChildIndex;
56 | }
57 | }
58 |
59 | if (rightChildIndex < length) {
60 | rightChild = this.arr[rightChildIndex];
61 | if (
62 | (swap === null && rightChild > elem) ||
63 | (swap !== null && rightChild > leftChild)
64 | ) {
65 | swap = rightChildIndex;
66 | }
67 | }
68 |
69 | if (swap === null) break;
70 |
71 | this.arr[index] = this.arr[swap];
72 | this.arr[swap] = elem;
73 | index = swap;
74 | }
75 | }
76 | }
77 | ```
78 |
79 | ```js
80 | let heap = new MaxBinaryHeap();
81 |
82 | heap.insert(41);
83 | heap.insert(39);
84 | heap.insert(33);
85 | heap.insert(18);
86 | heap.insert(27);
87 | heap.insert(12);
88 | heap.insert(55);
89 | // [55, 39, 41, 18, 27, 12, 33]
90 |
91 | heap.extractMax(); // [41, 39, 33, 18, 27, 12]
92 | ```
93 |
--------------------------------------------------------------------------------
/docs/JavaScript/04/MaxPriorityQueue.md:
--------------------------------------------------------------------------------
1 | ```js
2 | class Node {
3 | constructor(val, priority) {
4 | this.val = val;
5 | this.priority = priority;
6 | }
7 | }
8 | ```
9 |
10 | ```js
11 | class MaxPriorityQueue {
12 | constructor() {
13 | this.arr = [];
14 | }
15 |
16 | enqueue(val, priority) {
17 | const newNode = new Node(val, priority);
18 | this.arr = [...this.arr, newNode];
19 | this.bubbleUp();
20 | }
21 |
22 | bubbleUp() {
23 | let index = this.arr.length - 1;
24 | const elem = this.arr[index];
25 |
26 | while (index > 0) {
27 | let parentIndex = Math.floor((index - 1) / 2);
28 | let parent = this.arr[parentIndex];
29 |
30 | if (elem.priority <= parent.priority) break;
31 |
32 | this.arr[parentIndex] = elem;
33 | this.arr[index] = parent;
34 | index = parentIndex;
35 | }
36 | }
37 |
38 | dequeue() {
39 | const max = this.arr[0];
40 | const end = this.arr.pop();
41 |
42 | if (this.arr.length > 0) {
43 | this.arr[0] = end;
44 | this.sinkDown();
45 | }
46 |
47 | return max;
48 | }
49 |
50 | sinkDown() {
51 | let index = 0;
52 | const { length } = this.arr;
53 | const elem = this.arr[index];
54 |
55 | while (true) {
56 | let leftChildIndex = 2 * index + 1;
57 | let rightChildIndex = 2 * index + 2;
58 | let leftChild = null;
59 | let rightChild = null;
60 | let swap = null;
61 |
62 | if (leftChildIndex < length) {
63 | leftChild = this.arr[leftChildIndex];
64 | if (leftChild.priority > elem.priority) {
65 | swap = leftChildIndex;
66 | }
67 | }
68 |
69 | if (rightChildIndex < length) {
70 | rightChild = this.arr[rightChildIndex];
71 | if (
72 | (swap === null && rightChild.priority > elem.priority) ||
73 | (swap !== null && rightChild.priority > leftChild.priority)
74 | ) {
75 | swap = rightChildIndex;
76 | }
77 | }
78 |
79 | if (swap === null) break;
80 |
81 | this.arr[index] = this.arr[swap];
82 | this.arr[swap] = elem;
83 | index = swap;
84 | }
85 | }
86 | }
87 | ```
88 |
89 | ```js
90 | let queue = new MaxPriorityQueue();
91 |
92 | queue.enqueue('Drink water', 1);
93 | queue.enqueue('Sleep', 5);
94 | queue.enqueue('Eat', 2);
95 | ```
96 |
--------------------------------------------------------------------------------
/docs/ML/09.md:
--------------------------------------------------------------------------------
1 | # Tips for Deep Learning
2 |
3 | ## Recipe of Deep Learning
4 |
5 | 
6 |
7 | ## Vanishing Gradient Problem
8 |
9 | 
10 |
11 | 
12 |
13 | 以上圖的例子來看:由於通過神經元的 sigmoid function,數值大的 input 會被壓縮到 $0$ 到 $1$ 之間,以至於彼此明明差異很大的 input,在 output 時的差異卻沒像本來那麼明顯。
14 |
15 | ## ReLU (Rectified Linear Unit)
16 |
17 | 
18 |
19 | pros:
20 |
21 | 1. fast to compute
22 | 2. biological reason
23 | 3. infinite sigmoid with different biases
24 | 4. **vanishing gradient problem**
25 |
26 | ### variant
27 |
28 | | Leack ReLU | Parametric ReLU |
29 | | :--------------------------------: | :--------------------------------: |
30 | |  |  |
31 |
32 | $\alpha$ 會由 gradient descent 中學習。
33 |
34 | ## Maxout
35 |
36 | ***ReLU is a special cases of Maxout***
37 |
38 | - Learnable activation function
39 |
40 | - Activation function in maxout network can be any piecewise linear convex function
41 | - How many pieces depending on how many elements in a group
42 |
43 | ## Adaptive Learning Rate
44 |
45 | ### RMSProp
46 |
47 | $$
48 | \begin{array} { c l }
49 | { w ^ { 1 } \leftarrow w ^ { 0 } - \frac { \eta } { \sigma ^ { 0 } } g ^ { 0 } } & { \sigma ^ { 0 } = g ^ { 0 } } \\\\
50 | { w ^ { 2 } \leftarrow w ^ { 1 } - \frac { \eta } { \sigma ^ { 1 } } g ^ { 1 } } & { \sigma ^ { 1 } = \sqrt { \alpha \left( \sigma ^ { 0 } \right) ^ { 2 } + ( 1 - \alpha ) \left( g ^ { 2 } \right) ^ { 2 } } } \\\\
51 | { w ^ { 3 } \leftarrow w ^ { 2 } - \frac { \eta } { \sigma ^ { 2 } } g ^ { 2 } } & { \sigma ^ { 2 } = \sqrt { \alpha \left( \sigma ^ { 1 } \right) ^ { 2 } + ( 1 - \alpha ) \left( g ^ { 2 } \right) ^ { 2 } } } \\\\
52 | { \vdots } & { \vdots } \\\\
53 | { w ^ { t + 1 } \leftarrow w ^ { t } - \frac { \eta } { \sigma ^ { t } } g ^ { t } } & { \sigma ^ { t } = \sqrt { \alpha \left( \sigma ^ { t - 1 } \right) ^ { 2 } + ( 1 - \alpha ) \left( g ^ { t } \right) ^ { 2 } } }
54 | \end{array}
55 | $$
56 |
57 | Root Mean Square of the gradients with previous gradients being decayed.
58 |
59 | ### Momentum
60 |
61 | 
62 |
63 | ### Adam
64 |
65 | Adam = RMSProp + Momentum
66 |
67 | ## Early Stopping
68 |
69 | ## Regularization
70 |
71 | ## Dropout
--------------------------------------------------------------------------------
/docs/ML/07.md:
--------------------------------------------------------------------------------
1 | # Backpropagation
2 |
3 | Backpropagation 是一種能有效計算梯度的方法。
4 |
5 | 我們的網路:
6 |
7 | $$x^n \to \text{NN}(\theta) \to y^n \leftrightarrow_{C^n} \hat y^n$$
8 |
9 | ## Gradient Descent Review
10 |
11 | 假設我們有以下參數:$\theta = \\{w_1, w_2, \dots, b_1, b_2, \dots\\}$
12 |
13 | 我們會逐次更新參數如下:$\theta^0 \to \theta^1 \to \theta^2 \to \cdots$
14 |
15 | 但因為有太多參數,所以我們必需「有效地」更新參數。
16 |
17 | 給定 loss function:
18 |
19 | $$
20 | \begin{aligned}
21 | L ( \theta ) & = \sum _ { n = 1 } ^ { N } C ^ { n } ( \theta ) \\\\
22 | \to \frac { \partial L ( \theta ) } { \partial w } & = \sum _ { n = 1 } ^ { N } \frac { \partial C ^ { n } ( \theta ) } { \partial w }
23 | \end{aligned}
24 | $$
25 |
26 | ## Backpropagation
27 |
28 | 
29 |
30 | 假設只考慮其中一個 neuron,則 $z = x_1w_1 + x_2w_2 + b$,我們所要求的是:
31 |
32 | $$\frac { \partial C } { \partial w } = \frac { \partial z } { \partial w } \frac { \partial C } { \partial z }$$
33 |
34 | 透過 forward pass 和 backward pass 可分別算出:
35 |
36 | - Forward pass: Compute $\partial z / \partial w$ for all parameters
37 | - Backward pass: Compute $\partial C / \partial z$ for all activation function inputs $z$
38 |
39 | ### Forward pass
40 |
41 | - $\partial z / \partial w_1 = x_1$
42 | - $\partial z / \partial w_2 = x_2$
43 |
44 | 其實就是 input value 前面所接的值。
45 |
46 | 你要算出這個 neural network 裡面的每一個 weight 對它的 activation function 的 input $z$ 的偏微分,你就把你的 input 丟進去。然後,計算每一個 neuron 的 output 就結束了。
47 |
48 | ### Backward pass
49 |
50 | 要計算出 $\frac { \partial C } { \partial z }$ 是非常複雜的,但我們可以透過 chain rule 做些拆解:
51 |
52 | 
53 |
54 | $$
55 | \begin{aligned}
56 | \frac { \partial C } { \partial z } & = \frac { \partial a } { \partial z } \frac { \partial C } { \partial a } \\\\
57 | & = \sigma ^ { \prime } ( z ) \left[ \frac { \partial z ^ { \prime } } { \partial a } \frac { \partial C } { \partial z ^ { \prime } } + \frac { \partial z ^ { \prime \prime } } { \partial a } \frac { \partial C } { \partial z ^ { \prime \prime } } \right] \\\\
58 | & = \sigma ^ { \prime } ( z ) \left[ w _ { 3 } \frac { \partial C } { \partial z ^ { \prime } } + w _ { 4 } \frac { \partial C } { \partial z ^ { \prime \prime } } \right]
59 | \end{aligned}
60 | $$
61 |
62 | 想像有另一個 network,方向是反過來的,下面這個網路即和上式所代表的意義一樣:
63 |
64 | 
65 |
66 | #### Case 1. Output Layer
67 |
68 | 
69 |
70 | $$
71 | \begin{aligned}
72 | \frac { \partial C } { \partial z ^ { \prime } } & = \frac { \partial y _ { 1 } } { \partial z ^ { \prime } } \frac { \partial C } { \partial y _ { 1 } } \\\\
73 | \frac { \partial C } { \partial z ^ { \prime \prime } } & = \frac { \partial y _ { 2 } } { \partial z ^ { \prime \prime } } \frac { \partial C } { \partial y _ { 2 } }
74 | \end{aligned}
75 | $$
76 |
77 | #### Case 2. Not Output Layer
78 |
79 | 
80 |
81 | Compute $\partial C / \partial z$ recursively until we reach the output layer.
82 |
83 | ## Summary
84 |
85 | 
--------------------------------------------------------------------------------
/docs/JavaScript/05/Graph.md:
--------------------------------------------------------------------------------
1 | ```js
2 | class Graph {
3 | constructor() {
4 | this.adjList = {};
5 | }
6 |
7 | addVertex(vertex) {
8 | if (!this.adjList[vertex]) this.adjList[vertex] = [];
9 | }
10 |
11 | addEdge(v1, v2) {
12 | this.adjList[v1] = [...this.adjList[v1], v2];
13 | this.adjList[v2] = [...this.adjList[v2], v1];
14 | }
15 |
16 | removeEdge(v1, v2) {
17 | this.adjList[v1] = this.adjList[v1].filter(v => v !== v2);
18 | this.adjList[v2] = this.adjList[v2].filter(v => v !== v1);
19 | }
20 |
21 | removeVertex(vertex) {
22 | while (this.adjList[vertex].length) {
23 | const adjVertex = this.adjList[vertex].pop();
24 | this.removeEdge(vertex, adjVertex);
25 | }
26 | delete this.adjList[vertex];
27 | }
28 |
29 | dfsRecursive(start) {
30 | const ret = [];
31 | const visited = {};
32 | const adjList = this.adjList;
33 |
34 | (function dfs(vertex) {
35 | if (!vertex) return null;
36 |
37 | visited[vertex] = true;
38 | ret.push(vertex);
39 |
40 | adjList[vertex].forEach(neighbor => {
41 | if (!visited[neighbor]) {
42 | return dfs(neighbor);
43 | }
44 | });
45 | })(start);
46 |
47 | return ret;
48 | }
49 |
50 | dfsIterative(start) {
51 | const ret = [];
52 | const visited = {};
53 | const stack = [start];
54 | let currVertex;
55 |
56 | visited[start] = true;
57 |
58 | while (stack.length) {
59 | currVertex = stack.pop();
60 | ret.push(currVertex);
61 |
62 | this.adjList[currVertex].forEach(neighbor => {
63 | if (!visited[neighbor]) {
64 | visited[neighbor] = true;
65 | stack.push(neighbor);
66 | }
67 | });
68 | }
69 |
70 | return ret;
71 | }
72 |
73 | bfs(start) {
74 | const ret = [];
75 | const visited = {};
76 | const queue = [start];
77 | let currVertex;
78 |
79 | visited[start] = true;
80 |
81 | while (queue.length) {
82 | currVertex = queue.shift();
83 | ret.push(currVertex);
84 |
85 | this.adjList[currVertex].forEach(neighbor => {
86 | if (!visited[neighbor]) {
87 | visited[neighbor] = true;
88 | queue.push(neighbor);
89 | }
90 | });
91 | }
92 |
93 | return ret;
94 | }
95 | }
96 | ```
97 |
98 | ```js
99 | let g = new Graph();
100 |
101 | g.addVertex('A');
102 | g.addVertex('B');
103 | g.addVertex('C');
104 | g.addVertex('D');
105 | g.addVertex('E');
106 | g.addVertex('F');
107 |
108 | g.addEdge('A', 'B');
109 | g.addEdge('A', 'C');
110 | g.addEdge('B', 'D');
111 | g.addEdge('C', 'E');
112 | g.addEdge('D', 'E');
113 | g.addEdge('D', 'F');
114 | g.addEdge('E', 'F');
115 |
116 | // A
117 | // / \
118 | // B C
119 | // | |
120 | // D - E
121 | // \ /
122 | // F
123 |
124 | g.dfsRecursive('A'); // ['A', 'B', 'D', 'E', 'C', 'F']
125 | g.dfsIterative('A'); // ['A', 'C', 'E', 'F', 'D', 'B']
126 | g.bfs('A'); // ['A', 'B', 'C', 'D', 'E', 'F']
127 | ```
128 |
--------------------------------------------------------------------------------
/docs/JavaScript/02/recursionHard.md:
--------------------------------------------------------------------------------
1 | # Recursion Problem Set (hard)
2 |
3 | ## `reverse(str)`
4 |
5 | > Write a recursive function called `reverse` which accepts a string and returns a new string in reverse.
6 |
7 | ```js
8 | reverse('awesome'); // 'emosewa'
9 | reverse('rithmschool'); // 'loohcsmhtir'
10 | ```
11 |
12 | - Solution:
13 |
14 | ```js
15 | const reverse = str => {
16 | if (str.length <= 1) return str;
17 | return reverse(str.slice(1)) + str[0];
18 | };
19 | ```
20 |
21 | ## `isPalindrome(str)`
22 |
23 | > Write a recursive function called `isPalindrome` which returns true if the string passed to it is a palindrome (reads the same forward and backward). Otherwise it returns false.
24 |
25 | ```js
26 | isPalindrome('awesome'); // false
27 | isPalindrome('foobar'); // false
28 | isPalindrome('tacocat'); // true
29 | isPalindrome('amanaplanacanalpanama'); // true
30 | isPalindrome('amanaplanacanalpandemonium'); // false
31 | ```
32 |
33 | - Solution:
34 |
35 | ```js
36 | const isPalindrome = str => {
37 | if (str.length == 1) return true;
38 | if (str.length == 2) return str[0] == str[1];
39 | if (str[0] === str.slice(-1)) return isPalindrome(str.slice(1, -1));
40 | return false;
41 | };
42 | ```
43 |
44 | ## `someRecursive(arr, callback)`
45 |
46 | > Write a recursive function called `someRecursive` which accepts an array and a callback. The function returns true if a single value in the array returns true when passed to the callback. Otherwise it returns false.
47 |
48 | ```js
49 | const isOdd = val => val % 2 !== 0;
50 | someRecursive([1, 2, 3, 4], isOdd); // true
51 | someRecursive([4, 6, 8, 9], isOdd); // true
52 | someRecursive([4, 6, 8], isOdd); // false
53 | someRecursive([4, 6, 8], val => val > 10); // false
54 | ```
55 |
56 | - Solution:
57 |
58 | ```js
59 | const someRecursive = (arr, callback) => {
60 | if (callback(arr[0])) return true;
61 | if (arr.length == 1) return callback(arr[0]);
62 | return someRecursive(arr.slice(1), callback);
63 | };
64 | ```
65 |
66 | ## `flatten`
67 |
68 | > Write a recursive function called `flatten` which accepts an array of arrays and returns a new array with all values flattened.
69 |
70 | ```js
71 | flatten([1, 2, 3, [4, 5]]); // [1, 2, 3, 4, 5]
72 | flatten([1, [2, [3, 4], [[5]]]]); // [1, 2, 3, 4, 5]
73 | flatten([[1], [2], [3]]); // [1, 2, 3]
74 | flatten([[[[1], [[[2]]], [[[[[[[3]]]]]]]]]]); // [1, 2, 3]
75 | ```
76 |
77 | - Solution:
78 |
79 | ```js
80 | const flatten = oldArr => {
81 | let newArr = [];
82 | for (let i = 0; i < oldArr.length; i++) {
83 | if (Array.isArray(oldArr[i])) {
84 | newArr = newArr.concat(flatten(oldArr[i]));
85 | } else {
86 | newArr = [...newArr, oldArr[i]];
87 | }
88 | }
89 | return newArr;
90 | };
91 | ```
92 |
93 | ## `capitalizeFirst`
94 |
95 | > Write a recursive function called `capitalizeFirst`. Given an array of strings, capitalize the first letter of each string in the array.
96 |
97 | ```js
98 | capitalizeFirst(['car', 'taco', 'banana']); // ['Car', 'Taco', 'Banana']
99 | ```
100 |
101 | - Solution:
102 |
103 | ```
104 |
105 | ```
106 |
--------------------------------------------------------------------------------
/docs/PCP/1-3.md:
--------------------------------------------------------------------------------
1 | # 3. Mutual Exclusion
2 |
3 | ## Data race
4 |
5 | === "begin"
6 |
7 | ```cpp
8 | // Two shoppers adding items to a shared notepad
9 | #include
10 |
11 | unsigned int garlic_count = 0;
12 |
13 | void shopper() {
14 | for (int i = 0; i < 10; ++i) {
15 | ++garlic_count;
16 | }
17 | }
18 |
19 | int main() {
20 | std::thread barron(shopper);
21 | std::thread olivia(shopper);
22 | barron.join();
23 | olivia.join();
24 | printf("We should buy %u garlic.\n", garlic_count);
25 | }
26 | ```
27 |
28 | === "end"
29 |
30 | ```cpp hl_lines="7"
31 | // Two shoppers adding items to a shared notepad
32 | #include
33 |
34 | unsigned int garlic_count = 0;
35 |
36 | void shopper() {
37 | for (int i = 0; i < 10000000; ++i) {
38 | ++garlic_count;
39 | }
40 | }
41 |
42 | int main() {
43 | std::thread barron(shopper);
44 | std::thread olivia(shopper);
45 | barron.join();
46 | olivia.join();
47 | printf("We should buy %u garlic.\n", garlic_count);
48 | }
49 | ```
50 |
51 | ## Mutual exclusion
52 |
53 | === "begin"
54 |
55 | ```cpp
56 | // Two shoppers adding items to a shared notepad
57 |
58 | #include
59 | #include
60 |
61 | unsigned int garlic_count = 0;
62 | std::mutex pencil;
63 |
64 | void shopper() {
65 | pencil.lock();
66 | for (int i = 0; i < 10000000; ++i) {
67 | ++garlic_count;
68 | }
69 | pencil.unlock();
70 | }
71 |
72 | int main() {
73 | std::thread barron(shopper);
74 | std::thread olivia(shopper);
75 | barron.join();
76 | olivia.join();
77 | printf("We should buy %u garlic.\n", garlic_count);
78 | }
79 | ```
80 |
81 | === "end"
82 |
83 | ```cpp hl_lines="15 16 17"
84 | /**
85 | * Two shoppers adding items to a shared notepad
86 | */
87 | #include
88 | #include
89 | #include
90 |
91 | unsigned int garlic_count = 0;
92 | std::mutex pencil;
93 |
94 | void shopper() {
95 | for (int i = 0; i < 5; ++i) {
96 | printf("Shopper %d is thinking...\n", std::this_thread::get_id());
97 | std::this_thread::sleep_for(std::chrono::milliseconds(500));
98 | pencil.lock();
99 | ++garlic_count;
100 | pencil.unlock();
101 | }
102 | }
103 |
104 | int main() {
105 | std::thread barron(shopper);
106 | std::thread olivia(shopper);
107 | barron.join();
108 | olivia.join();
109 | printf("We should buy %u garlic.\n", garlic_count);
110 | }
111 | ```
112 |
113 | ## Atomic objects
114 |
115 | === "begin"
116 |
117 | ```cpp
118 | // Two shoppers adding items to a shared notepad
119 | #include
120 |
121 | unsigned int garlic_count = 0;
122 |
123 | void shopper() {
124 | for (int i = 0; i < 10000000; ++i) {
125 | ++garlic_count;
126 | }
127 | }
128 |
129 | int main() {
130 | std::thread barron(shopper);
131 | std::thread olivia(shopper);
132 | barron.join();
133 | olivia.join();
134 | printf("We should buy %u garlic.\n", garlic_count);
135 | }
136 | ```
137 |
138 | === "end"
139 |
140 | ```cpp hl_lines="2 5"
141 | // Two shoppers adding items to a shared notepad
142 | #include
143 | #include
144 |
145 | std::atomic garlic_count(0);
146 |
147 | void shopper() {
148 | for (int i = 0; i < 10000000; ++i) {
149 | ++garlic_count;
150 | }
151 | }
152 |
153 | int main() {
154 | std::thread barron(shopper);
155 | std::thread olivia(shopper);
156 | barron.join();
157 | olivia.join();
158 | printf("We should buy %u garlic.\n", garlic_count.load());
159 | }
160 | ```
161 |
--------------------------------------------------------------------------------
/docs/JavaScript/04/BinarySearchTree.md:
--------------------------------------------------------------------------------
1 | ```js
2 | class Node {
3 | constructor(val) {
4 | this.val = val;
5 | this.left = null;
6 | this.right = null;
7 | }
8 | }
9 | ```
10 |
11 | ```js
12 | class BinarySearchTree {
13 | constructor() {
14 | this.root = null;
15 | }
16 |
17 | insert(val) {
18 | const newNode = new Node(val);
19 |
20 | if (this.root === null) {
21 | this.root = newNode;
22 | return this;
23 | }
24 |
25 | let curr = this.root;
26 |
27 | while (true) {
28 | if (val === curr.val) return undefined;
29 | if (val < curr.val) {
30 | if (curr.left === null) {
31 | curr.left = newNode;
32 | return this;
33 | }
34 | curr = curr.left;
35 | } else {
36 | if (curr.right === null) {
37 | curr.right = newNode;
38 | return this;
39 | }
40 | curr = curr.right;
41 | }
42 | }
43 | }
44 |
45 | find(val) {
46 | if (this.root === null) return false;
47 |
48 | let curr = this.root;
49 | let found = false;
50 |
51 | while (curr && !found) {
52 | if (val < curr.val) {
53 | curr = curr.left;
54 | } else if (val > curr.val) {
55 | curr = curr.right;
56 | } else {
57 | found = true;
58 | }
59 | }
60 |
61 | if (!found) return undefined;
62 | return curr;
63 | }
64 |
65 | contains(val) {
66 | if (this.root === null) return false;
67 |
68 | let curr = this.root;
69 | let found = false;
70 |
71 | while (curr && !found) {
72 | if (val < curr.val) {
73 | curr = curr.left;
74 | } else if (val > curr.val) {
75 | curr = curr.right;
76 | } else {
77 | return true;
78 | }
79 | }
80 |
81 | return false;
82 | }
83 |
84 | bfs() {
85 | let node = this.root;
86 | const ret = [];
87 | const queue = [node];
88 |
89 | while (queue.length) {
90 | node = queue.shift();
91 | ret.push(node.val);
92 | if (node.left) queue.push(node.left);
93 | if (node.right) queue.push(node.right);
94 | }
95 |
96 | return ret;
97 | }
98 |
99 | dfs() {
100 | let node = this.root;
101 | const ret = [];
102 | const stack = [node];
103 |
104 | while (stack.length) {
105 | node = stack.pop();
106 | ret.push(node.val);
107 | if (node.right) stack.push(node.right);
108 | if (node.left) stack.push(node.left);
109 | }
110 |
111 | return ret;
112 | }
113 |
114 | preOrder() {
115 | const ret = [];
116 |
117 | const traverse = node => {
118 | ret.push(node.val);
119 | if (node.left) traverse(node.left);
120 | if (node.right) traverse(node.right);
121 | };
122 |
123 | traverse(this.root);
124 |
125 | return ret;
126 | }
127 |
128 | postOrder() {
129 | const ret = [];
130 |
131 | const traverse = node => {
132 | if (node.left) traverse(node.left);
133 | if (node.right) traverse(node.right);
134 | ret.push(node.val);
135 | };
136 |
137 | traverse(this.root);
138 |
139 | return ret;
140 | }
141 |
142 | inOrder() {
143 | const ret = [];
144 |
145 | const traverse = node => {
146 | if (node.left) traverse(node.left);
147 | ret.push(node.val);
148 | if (node.right) traverse(node.right);
149 | };
150 |
151 | traverse(this.root);
152 |
153 | return ret;
154 | }
155 | }
156 | ```
157 |
158 | ```js
159 | var tree = new BinarySearchTree();
160 |
161 | tree.insert(10);
162 | tree.insert(6);
163 | tree.insert(3);
164 | tree.insert(8);
165 | tree.insert(15);
166 | tree.insert(20);
167 |
168 | // 10
169 | // 6 15
170 | // 3 8 20
171 |
172 | tree.bfs(); // [10, 6, 15, 3, 8, 20]
173 | tree.dfs(); // [10, 6, 3, 8, 15, 20]
174 | tree.preOrder(); // [10, 6, 3, 8, 15, 20]
175 | tree.postOrder(); // [3, 8, 6, 20, 15, 10]
176 | tree.inOrder(); // [3, 6, 8, 10, 15, 20]
177 | ```
178 |
--------------------------------------------------------------------------------
/docs/JavaScript/04/SinglyLinkedList.md:
--------------------------------------------------------------------------------
1 | ```js
2 | class Node {
3 | constructor(val) {
4 | this.val = val;
5 | this.next = null;
6 | }
7 | }
8 | ```
9 |
10 | ```js
11 | class SinglyLinkedList {
12 | constructor() {
13 | this.head = null;
14 | this.tail = null;
15 | this.length = 0;
16 | }
17 |
18 | push(val) {
19 | const newNode = new Node(val);
20 |
21 | if (!this.head) {
22 | this.head = newNode;
23 | this.tail = this.head;
24 | } else {
25 | this.tail.next = newNode;
26 | this.tail = newNode;
27 | }
28 |
29 | this.length++;
30 | return this;
31 | }
32 |
33 | pop() {
34 | if (!this.head) return undefined;
35 |
36 | let poppedNode = this.head;
37 | let newTail = poppedNode;
38 |
39 | if (this.length === 1) {
40 | this.head = null;
41 | this.tail = null;
42 | } else {
43 | while (poppedNode.next) {
44 | newTail = poppedNode;
45 | poppedNode = poppedNode.next;
46 | }
47 | this.tail = newTail;
48 | this.tail.next = null;
49 | }
50 |
51 | this.length--;
52 | return poppedNode;
53 | }
54 |
55 | shift() {
56 | if (this.length === 0) return undefined;
57 |
58 | let oldHead = this.head;
59 |
60 | if (this.length === 1) {
61 | this.head = null;
62 | this.tail = null;
63 | } else {
64 | this.head = oldHead.next;
65 | oldHead.next = null;
66 | }
67 |
68 | this.length--;
69 | return oldHead;
70 | }
71 |
72 | unshift(val) {
73 | const newNode = new Node(val);
74 |
75 | if (this.length === 0) {
76 | this.head = newNode;
77 | this.tail = newNode;
78 | } else {
79 | newNode.next = this.head;
80 | this.head = newNode;
81 | }
82 |
83 | this.length++;
84 | return this;
85 | }
86 |
87 | get(index) {
88 | if (index < 0 || index >= this.length) return null;
89 |
90 | let count = 0;
91 | let curr = this.head;
92 |
93 | while (count !== index) {
94 | curr = curr.next;
95 | count++;
96 | }
97 |
98 | return curr;
99 | }
100 |
101 | set(index, val) {
102 | let foundNode = this.get(index);
103 |
104 | if (foundNode) {
105 | foundNode.val = val;
106 | return true;
107 | }
108 |
109 | return false;
110 | }
111 |
112 | insert(index, val) {
113 | if (index < 0 || index > this.length) return false;
114 | if (index === 0) return this.unshift(val);
115 | if (index === this.length) return [...this, val];
116 |
117 | const newNode = new Node(val);
118 | let prev = this.get(index - 1);
119 | let next = prev.next;
120 |
121 | prev.next = newNode;
122 | newNode.next = next;
123 |
124 | this.length++;
125 | return true;
126 | }
127 |
128 | remove(index) {
129 | if (index < 0 || index >= this.length) return undefined;
130 | if (index === 0) return this.shift();
131 | if (index === this.length - 1) return this.pop();
132 |
133 | let prev = this.get(index - 1);
134 | let removedNode = prev.next;
135 |
136 | prev.next = removedNode.next;
137 | removedNode.next = null;
138 |
139 | this.length--;
140 | return removedNode;
141 | }
142 |
143 | reverse() {
144 | let node = this.head;
145 | this.head = this.tail;
146 | this.tail = node;
147 |
148 | let oldNext;
149 | let prev = null;
150 |
151 | for (let i = 0; i < this.length; i++) {
152 | oldNext = node.next;
153 | node.next = prev;
154 | prev = node;
155 | node = oldNext;
156 | }
157 |
158 | return this;
159 | }
160 |
161 | print() {
162 | const arr = [];
163 | let curr = this.head;
164 |
165 | while (curr) {
166 | arr.push(curr.val);
167 | curr = curr.next;
168 | }
169 |
170 | console.log(arr);
171 | }
172 | }
173 | ```
174 |
175 | ```js
176 | let list = new SinglyLinkedList();
177 |
178 | for (let i = 0; i < 5; i++) list.push(i);
179 | ```
180 |
--------------------------------------------------------------------------------
/docs/JavaScript/04/DoublyLinkedList.md:
--------------------------------------------------------------------------------
1 | ```js
2 | class Node {
3 | constructor(val) {
4 | this.val = val;
5 | this.next = null;
6 | this.prev = null;
7 | }
8 | }
9 | ```
10 |
11 | ```js
12 | class DoublyLinkedList {
13 | constructor() {
14 | this.head = null;
15 | this.tail = null;
16 | this.length = 0;
17 | }
18 |
19 | push(val) {
20 | const newNode = new Node(val);
21 |
22 | if (this.length === 0) {
23 | this.head = newNode;
24 | this.tail = newNode;
25 | } else {
26 | this.tail.next = newNode;
27 | newNode.prev = this.tail;
28 | this.tail = newNode;
29 | }
30 |
31 | this.length++;
32 | return this;
33 | }
34 |
35 | pop() {
36 | if (!this.head) return undefined;
37 |
38 | let poppedNode = this.tail;
39 |
40 | if (this.length === 1) {
41 | this.head = null;
42 | this.tail = null;
43 | } else {
44 | this.tail = poppedNode.prev;
45 | this.tail.next = null;
46 | poppedNode.prev = null;
47 | }
48 |
49 | this.length--;
50 | return poppedNode;
51 | }
52 |
53 | shift() {
54 | if (this.length === 0) return undefined;
55 |
56 | let oldHead = this.head;
57 |
58 | if (this.length === 1) {
59 | this.head = null;
60 | this.tail = null;
61 | } else {
62 | this.head = oldHead.next;
63 | this.head.prev = null;
64 | oldHead.next = null;
65 | }
66 |
67 | this.length--;
68 | return oldHead;
69 | }
70 |
71 | unshift(val) {
72 | const newNode = new Node(val);
73 |
74 | if (this.length === 0) {
75 | this.head = newNode;
76 | this.tail = newNode;
77 | } else {
78 | this.head.prev = newNode;
79 | newNode.next = this.head;
80 | this.head = newNode;
81 | }
82 |
83 | this.length++;
84 | return this;
85 | }
86 |
87 | get(index) {
88 | if (index < 0 || index >= this.length) return null;
89 |
90 | let curr = null;
91 | if (index <= this.length / 2) {
92 | let count = 0;
93 | curr = this.head;
94 | while (count !== index) {
95 | curr = curr.next;
96 | count++;
97 | }
98 | } else {
99 | let count = this.length - 1;
100 | curr = this.tail;
101 | while (count !== index) {
102 | curr = curr.prev;
103 | count--;
104 | }
105 | }
106 |
107 | return curr;
108 | }
109 |
110 | set(index, val) {
111 | let foundNode = this.get(index);
112 |
113 | if (foundNode) {
114 | foundNode.val = val;
115 | return true;
116 | }
117 |
118 | return false;
119 | }
120 |
121 | insert(index, val) {
122 | if (index < 0 || index > this.length) return false;
123 | if (index === 0) return this.unshift(val);
124 | if (index === this.length) return [...this, val];
125 |
126 | const newNode = new Node(val);
127 | let prev = this.get(index - 1);
128 | let next = prev.next;
129 |
130 | (prev.next = newNode), (newNode.prev = prev);
131 | (newNode.next = next), (next.prev = newNode);
132 |
133 | this.length++;
134 | return true;
135 | }
136 |
137 | remove(index) {
138 | if (index < 0 || index >= this.length) return undefined;
139 | if (index === 0) return this.shift();
140 | if (index === this.length) return this.pop();
141 |
142 | let removedNode = this.get(index);
143 |
144 | removedNode.prev.next = removedNode.next;
145 | removedNode.next.prev = removedNode.prev;
146 | removedNode.next = null;
147 | removedNode.prev = null;
148 |
149 | this.length--;
150 | return removedNode;
151 | }
152 |
153 | print() {
154 | const arr = [];
155 | let curr = this.head;
156 |
157 | while (curr) {
158 | arr.push(curr.val);
159 | curr = curr.next;
160 | }
161 |
162 | console.log(arr);
163 | }
164 | }
165 | ```
166 |
167 | ```js
168 | let list = new DoublyLinkedList();
169 |
170 | for (let i = 0; i < 5; i++) list.push(i);
171 | ```
172 |
--------------------------------------------------------------------------------
/docs/JavaScript/01/slidingWindow.md:
--------------------------------------------------------------------------------
1 | # Sliding Window Pattern
2 |
3 | This pattern involves creating a **window** which can either be an array or number from one position to another.
4 |
5 | Depending on a certain condition, the window either increases or closes (and a new window is created).
6 |
7 | Very useful for keeping track of a subset of data in an array/string etc.
8 |
9 | ---
10 |
11 | ## `maxSubarraySum(arr, n)`
12 |
13 | > Write a function called `maxSubarraySum` which accepts an array of integers and a number called **n**. The function should calculate the maximum sum of **n** consecutive elements in the array.
14 |
15 | ```js
16 | maxSubarraySum([1, 2, 5, 2, 8, 1, 5], 2); // 10
17 | maxSubarraySum([1, 2, 5, 2, 8, 1, 5], 4); // 17
18 | maxSubarraySum([4, 2, 1, 6], 1); // 6
19 | maxSubarraySum([], 4); // null
20 | ```
21 |
22 | - Solution 1 (naive):
23 |
24 | - Time: $O(n^2)$
25 |
26 | ```js
27 | const maxSubarraySum = (arr, n) => {
28 | if (n > arr.length) return null;
29 |
30 | let ret = -Infinity;
31 |
32 | for (let i = 0; i < arr.length - n + 1; i++) {
33 | let temp = 0;
34 | for (let j = 0; j < n; j++)
35 | temp += arr[i + j];
36 |
37 | ret = Math.max(ret, temp);
38 | }
39 |
40 | return ret;
41 | };
42 | ```
43 |
44 | - Solution 2 (refactor):
45 |
46 | - Time: $O(n)$
47 | - Space: $O(1)$
48 |
49 | ```js
50 | const maxSubarraySum = (arr, n) => {
51 | if (arr.length < n) return null;
52 |
53 | let ret = 0;
54 | let temp = 0;
55 |
56 | for (let i = 0; i < n; i++) ret += arr[i];
57 |
58 | temp = ret;
59 | for (let i = n; i < arr.length; i++) {
60 | temp = temp - arr[i - n] + arr[i];
61 | ret = Math.max(ret, temp);
62 | }
63 |
64 | return ret;
65 | };
66 | ```
67 |
68 | ## `minSubArrayLen(arr, num)`
69 |
70 | > Write a function called `minSubArrayLen` which accepts two parameters - an array of positive integers and a positive integer.
71 | >
72 | > This function should return the minimal length of a contiguous subarray of which the sum is greater than or equal to the integer passed to the function. If there isn’t one, return 0 instead.
73 |
74 | ```js
75 | minSubArrayLen([2, 3, 1, 2, 4, 3], 7); // 2 -> because [4, 3] is the smallest subarray
76 | minSubArrayLen([2, 1, 6, 5, 4], 9); // 2 -> because [5, 4] is the smallest subarray
77 | minSubArrayLen([3, 1, 62, 19], 52); // 1 -> because [62] is greater than 52
78 | ```
79 |
80 | - Solution
81 |
82 | - Time: $O(n)$
83 | - Space: $O(1)$
84 |
85 | ```js
86 | const minSubArrayLen = (arr, num) => {
87 | let i = 0; // start
88 | let j = 0; // end
89 | let sum = 0;
90 | let ret = Infinity;
91 |
92 | while (i < arr.length) {
93 | if (sum < num && j < arr.length) {
94 | sum += arr[j];
95 | j++;
96 | } else if (sum >= num) {
97 | ret = Math.min(ret, j - i);
98 | sum -= arr[i];
99 | i++;
100 | } else {
101 | break;
102 | }
103 | }
104 |
105 | return ret === Infinity ? 0 : ret;
106 | };
107 | ```
108 |
109 | ## `findLongestSubstring(str)`
110 |
111 | > Write a function called `findLongestSubstring`, which accepts a string and returns the length of the longest substring with all distinct characters.
112 |
113 | ```js
114 | findLongestSubstring(''); // 0
115 | findLongestSubstring('rithmschool'); // 7
116 | findLongestSubstring('thecatinthehat'); // 7
117 | findLongestSubstring('bbbbbb'); // 1
118 | ```
119 |
120 | - Solution:
121 |
122 | - Time: $O(n)$
123 |
124 | ```js
125 | const findLongestSubstring = str => {
126 | let ret = 0;
127 | let seen = {};
128 | let i = 0;
129 |
130 | for (let j = 0; j < str.length; j++) {
131 | let char = str[j];
132 | if (seen[char]) i = Math.max(i, seen[char]);
133 | ret = Math.max(ret, j - i + 1);
134 | seen[char] = j + 1;
135 | }
136 |
137 | return ret;
138 | };
139 | ```
140 |
--------------------------------------------------------------------------------
/docs/JavaScript/05/Dijkstra.md:
--------------------------------------------------------------------------------
1 | ```js
2 | class Node {
3 | constructor(val, priority) {
4 | this.val = val;
5 | this.priority = priority;
6 | }
7 | }
8 | ```
9 |
10 | ```js
11 | class MinPriorityQueue {
12 | constructor() {
13 | this.arr = [];
14 | }
15 |
16 | enqueue(val, priority) {
17 | const newNode = new Node(val, priority);
18 | this.arr = [...this.arr, newNode];
19 | this.bubbleUp();
20 | }
21 |
22 | bubbleUp() {
23 | let index = this.arr.length - 1;
24 | const elem = this.arr[index];
25 |
26 | while (index > 0) {
27 | let parentIndex = Math.floor((index - 1) / 2);
28 | let parent = this.arr[parentIndex];
29 |
30 | if (elem.priority >= parent.priority) break;
31 |
32 | this.arr[parentIndex] = elem;
33 | this.arr[index] = parent;
34 | index = parentIndex;
35 | }
36 | }
37 |
38 | dequeue() {
39 | const min = this.arr[0];
40 | const end = this.arr.pop();
41 |
42 | if (this.arr.length > 0) {
43 | this.arr[0] = end;
44 | this.sinkDown();
45 | }
46 |
47 | return min;
48 | }
49 |
50 | sinkDown() {
51 | let index = 0;
52 | const { length } = this.arr;
53 | const elem = this.arr[index];
54 |
55 | while (true) {
56 | let leftChildIndex = 2 * index + 1;
57 | let rightChildIndex = 2 * index + 2;
58 | let leftChild = null;
59 | let rightChild = null;
60 | let swap = null;
61 |
62 | if (leftChildIndex < length) {
63 | leftChild = this.arr[leftChildIndex];
64 | if (leftChild.priority < elem.priority) {
65 | swap = leftChildIndex;
66 | }
67 | }
68 |
69 | if (rightChildIndex < length) {
70 | rightChild = this.arr[rightChildIndex];
71 | if (
72 | (swap === null && rightChild.priority < elem.priority) ||
73 | (swap !== null && rightChild.priority < leftChild.priority)
74 | ) {
75 | swap = rightChildIndex;
76 | }
77 | }
78 |
79 | if (swap === null) break;
80 |
81 | this.arr[index] = this.arr[swap];
82 | this.arr[swap] = elem;
83 | index = swap;
84 | }
85 | }
86 | }
87 | ```
88 |
89 | ```js
90 | class WeightedGraph {
91 | constructor() {
92 | this.adjList = {};
93 | }
94 |
95 | addVertex(vertex) {
96 | if (!this.adjList[vertex]) this.adjList[vertex] = [];
97 | }
98 |
99 | addEdge(v1, v2, weight) {
100 | this.adjList[v1] = [...this.adjList[v1], { node: v2, weight }];
101 | this.adjList[v2] = [...this.adjList[v2], { node: v1, weight }];
102 | }
103 |
104 | Dijkstra(start, end) {
105 | const nodes = new MinPriorityQueue();
106 | const dist = {};
107 | const prev = {};
108 | let path = [];
109 | let smallest;
110 |
111 | for (let vertex in this.adjList) {
112 | if (vertex === start) {
113 | dist[vertex] = 0;
114 | nodes.enqueue(vertex, 0);
115 | } else {
116 | dist[vertex] = Infinity;
117 | nodes.enqueue(vertex, Infinity);
118 | }
119 | prev[vertex] = null;
120 | }
121 |
122 | while (nodes.arr.length) {
123 | smallest = nodes.dequeue().val;
124 | if (smallest === end) {
125 | while (prev[smallest]) {
126 | path.push(smallest);
127 | smallest = prev[smallest];
128 | }
129 | break;
130 | }
131 |
132 | if (smallest || dist[smallest] !== Infinity) {
133 | for (let neighbor in this.adjList[smallest]) {
134 | let nextNode = this.adjList[smallest][neighbor];
135 | let candidate = dist[smallest] + nextNode.weight;
136 | let nextNeighbor = nextNode.node;
137 |
138 | if (candidate < dist[nextNeighbor]) {
139 | dist[nextNeighbor] = candidate;
140 | prev[nextNeighbor] = smallest;
141 | nodes.enqueue(nextNeighbor, candidate);
142 | }
143 | }
144 | }
145 | }
146 |
147 | return path.concat(smallest).reverse();
148 | }
149 | }
150 | ```
151 |
152 | ```js
153 | let g = new WeightedGraph();
154 |
155 | g.addVertex('A');
156 | g.addVertex('B');
157 | g.addVertex('C');
158 | g.addVertex('D');
159 | g.addVertex('E');
160 | g.addVertex('F');
161 |
162 | g.addEdge('A', 'B', 4);
163 | g.addEdge('A', 'C', 2);
164 | g.addEdge('B', 'E', 3);
165 | g.addEdge('C', 'D', 2);
166 | g.addEdge('C', 'F', 4);
167 | g.addEdge('D', 'E', 3);
168 | g.addEdge('D', 'F', 1);
169 | g.addEdge('E', 'F', 1);
170 |
171 | g.Dijkstra('A', 'E'); // ['A', 'C', 'D', 'F', 'E']
172 | ```
173 |
--------------------------------------------------------------------------------
/docs/JavaScript/01/multiplePointers.md:
--------------------------------------------------------------------------------
1 | # Multiple Pointers Pattern
2 |
3 | Creating **pointers** or values that correspond to an index or position and move towards the beginning, end or middle based on a certain condition.
4 |
5 | **Very** efficient for solving problems with minimal Space as well.
6 |
7 | ---
8 |
9 | ## `sumZero(arr)`
10 |
11 | > Write a function called `sumZero` which accepts a **sorted** array of integers. The function should find the **first** pair where the sum is 0. Return an array that includes both values that sum to zero or undefined if a pair does not exist.
12 |
13 | ```js
14 | sumZero([-3, -2, -1, 0, 1, 2, 3]); // [-3, 3]
15 | sumZero([-2, 0, 1, 3]); // undefined
16 | sumZero([1, 2, 3]); // undefined
17 | ```
18 |
19 | - Solution 1 (naive)
20 |
21 | - Time: $O(n^2)$
22 | - Space: $O(1)$
23 |
24 | ```js
25 | const sumZero = arr => {
26 | for (let i = 0; i < arr.length; i++)
27 | for (let j = i + 1; j < arr.length; j++)
28 | if (arr[i] + arr[j] === 0)
29 | return [arr[i], arr[j]];
30 | };
31 | ```
32 |
33 | - Solution 2 (refactor):
34 |
35 | - Time: $O(n)$
36 | - Space: $O(1)$
37 |
38 | ```js
39 | const sumZero = arr => {
40 | let left = 0;
41 | let right = arr.length - 1;
42 |
43 | while (left < right) {
44 | let sum = arr[left] + arr[right];
45 |
46 | if (sum === 0) return [arr[left], arr[right]];
47 | else if (sum < 0) left++;
48 | else right--;
49 | }
50 | };
51 | ```
52 |
53 | ## `countUniqueValues(arr)`
54 |
55 | > Implement a function called `countUniqueValues`, which accepts a sorted array, and counts the unique values in the array. There can be negative numbers in the array, but it will always be sorted.
56 |
57 | ```js
58 | countUniqueValues([1, 1, 1, 1, 1, 2]); // 2
59 | countUniqueValues([-2, -1, -1, 0, 1]); // 4
60 | countUniqueValues([]); // 0
61 | ```
62 |
63 | - Solution:
64 |
65 | - Time: $O(n)$
66 | - Space: $O(1)$
67 |
68 | ```js
69 | const countUniqueValues = arr => {
70 | if (arr.length === 0) return 0;
71 |
72 | let i = 0;
73 | for (let j = 1; j < arr.length; j++)
74 | if (arr[i] !== arr[j])
75 | arr[++i] = arr[j];
76 |
77 | return i + 1;
78 | };
79 | ```
80 |
81 | ## `averagePair(arr, val)`
82 |
83 | > Write a function called `averagePair`. Given a sorted array of integers and a target average, determine if there is a pair of values in the array where the average of the pair equals the target average. There may be more than one pair that matches the average target.
84 |
85 | ```js
86 | averagePair([1, 2, 3], 2.5); // true
87 | averagePair([1, 3, 3, 5, 6, 7, 10, 12, 19], 8); // true
88 | averagePair([-1, 0, 3, 4, 5, 6], 4.1); // false
89 | averagePair([], 4); // false
90 | ```
91 |
92 | - Solution:
93 |
94 | - Time: $O(n)$
95 | - Space: $O(1)$
96 |
97 | ```js
98 | const averagePair = (arr, num) => {
99 | let left = 0;
100 | let right = arr.length - 1;
101 |
102 | while (left < right) {
103 | let average = (arr[left] + arr[right]) / 2;
104 |
105 | if (average === num) return true;
106 | else if (average < num) left++;
107 | else right--;
108 | }
109 |
110 | return false;
111 | };
112 | ```
113 |
114 | ## `isSubsequence(str1, str2)`
115 |
116 | > Write a function called `isSubsequence` which takes in two strings and checks whether the characters in the first string form a subsequence of the characters in the second string. In other words, the function should check whether the characters in the first string appear somewhere in the second string, **without their order changing**.
117 |
118 | ```js
119 | isSubsequence('hello', 'hello world'); // true
120 | isSubsequence('sing', 'sting'); // true
121 | isSubsequence('abc', 'acb'); // false (order matters)
122 | ```
123 |
124 | - Solution 1 (iterative):
125 |
126 | - Time: $O(n + m)$
127 | - Space: $O(1)$
128 |
129 | ```js
130 | const isSubsequence = (str1, str2) => {
131 | if (!str1) return true;
132 |
133 | let i = 0;
134 | for (let j = 0; j < str2.length; j++) {
135 | if (i == str1.length - 1) return true;
136 | if (str1[i] === str2[j]) i++;
137 | }
138 |
139 | return false;
140 | };
141 | ```
142 |
143 | - Solution 2 (recursive but not $O(1)$ space):
144 |
145 | ```js
146 | const isSubsequence = (str1, str2) => {
147 | if (str1.length === 0) return true;
148 | if (str2.length === 0) return false;
149 | if (str2[0] === str1[0]) return isSubsequence(str1.slice(1), str2.slice(1));
150 | return isSubsequence(str1, str2.slice(1));
151 | };
152 | ```
153 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | # Project information
2 | site_name: Computer Science Notes
3 | site_description: Computer Science Notes, Operating System, Machine Learning, Parallel and Concurrent Programming with C++
4 | site_author: Jay Chen
5 | site_url: https://walkccc.github.io/CS
6 |
7 | # Repository
8 | repo_name: walkccc/CS
9 | repo_url: https://github.com/walkccc/CS
10 |
11 | # Copyright
12 | copyright: Built by Jay Chen © 2017 - 2020
13 |
14 | # Configuration
15 | theme:
16 | name: material
17 | language: en
18 | custom_dir: custom/
19 | favicon: assets/favicon.png
20 | palette:
21 | primary: indigo
22 | accent: blue
23 | font:
24 | text: Roboto
25 | code: Roboto Mono
26 | icon:
27 | logo: material/console
28 | repo: fontawesome/brands/github
29 | features:
30 | - tabs
31 |
32 | # Customization
33 | extra:
34 | social:
35 | - icon: fontawesome/brands/github-square
36 | link: https://github.com/walkccc
37 | - icon: fontawesome/brands/linkedin
38 | link: https://www.linkedin.com/in/walkccc/
39 | - icon: fontawesome/solid/code
40 | link: https://walkccc.github.io/LeetCode
41 |
42 | extra_css:
43 | - css/katex.css
44 | - css/custom.css
45 | - https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css
46 |
47 | extra_javascript:
48 | - js/katex.js
49 | - https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js
50 | - https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/auto-render.min.js
51 |
52 | # Extensions
53 | markdown_extensions:
54 | - pymdownx.highlight:
55 | linenums: true
56 | linenums_style: pymdownx.table
57 | - pymdownx.superfences
58 | - pymdownx.tabbed
59 | - admonition
60 | - toc:
61 | permalink: true
62 |
63 | nav:
64 | - Preface: index.md
65 | - Parallel and Concurrent Programming:
66 | - Preface: PCP/index.md
67 | - Part 1:
68 | - 2. Threads and Processes: PCP/1-2.md
69 | - 3. Mutual Exclusion: PCP/1-3.md
70 | - 4. Locks: PCP/1-4.md
71 | - 5. Liveness: PCP/1-5.md
72 | - Part 2:
73 | - 1. Synchronization: PCP/2-1.md
74 | - 2. Barriers: PCP/2-2.md
75 | - 3. Asynchronous: PCP/2-3.md
76 | - OS:
77 | - Preface: OS/index.md
78 | - PART ONE | OVERVIEW:
79 | - Chapter 1 Introduction: OS/Chap01.md
80 | - Chapter 2 Operating-System Structures: OS/Chap02.md
81 | - PART TWO | PROCESS MANAGEMENT:
82 | - Chapter 3 Processes: OS/Chap03.md
83 | - Chapter 4 Threads: OS/Chap04.md
84 | - Chapter 5 Process Synchronization: OS/Chap05.md
85 | - Chapter 6 CPU Scheduling: OS/Chap06.md
86 | - Chapter 7 Deadlocks: OS/Chap07.md
87 | - PART THREE | MEMORY MANAGEMENT:
88 | - Chapter 8 Main Memory: OS/Chap08.md
89 | - Chapter 9 Virtual Memory: OS/Chap09.md
90 | - Previous Exams:
91 | - Midterm: OS/midterm.md
92 | - Final: OS/final.md
93 | - ML:
94 | - Preface: ML/index.md
95 | - Lec 1 - Regression - Case Study: ML/01.md
96 | - Lec 2 - Where does the error com from?: ML/02.md
97 | - Lec 3 - Gradient Descent: ML/03.md
98 | - Lec 4 - Classification: ML/04.md
99 | - Lec 5 - Logistic Regression: ML/05.md
100 | - Lec 6 - Deep Learning: ML/06.md
101 | - Lec 7 - Backpropagation: ML/07.md
102 | - 'Lec 8 - "Hello world" of Deep Learning': ML/08.md
103 | - Lec 9 - Tips for Deep Learning: ML/09.md
104 | - JavaScript DSA:
105 | - Preface: JavaScript/index.md
106 | - 01 - Problem Solving Patterns:
107 | - Frequency Counters: JavaScript/01/frequencyCounters.md
108 | - Multiple Pointers: JavaScript/01/multiplePointers.md
109 | - Sliding Window: JavaScript/01/slidingWindow.md
110 | - Divide and Conquer: JavaScript/01/divideAndConquer.md
111 | - 02 - Recursion Problem Set:
112 | - Recursion Problem Set (easy): JavaScript/02/recursionEasy.md
113 | - Recursion Problem Set (hard): JavaScript/02/recursionHard.md
114 | - 03 - Sorting Algorithms:
115 | - Bubble Sort: JavaScript/03/bubbleSort.md
116 | - Selection Sort: JavaScript/03/selectionSort.md
117 | - Insertion Sort: JavaScript/03/insertionSort.md
118 | - Merge Sort: JavaScript/03/mergeSort.md
119 | - Quick Sort: JavaScript/03/quickSort.md
120 | - 04 - Data Structures:
121 | - Singly Linked List: JavaScript/04/SinglyLinkedList.md
122 | - Doubly Linked List: JavaScript/04/DoublyLinkedList.md
123 | - Binary Search Tree: JavaScript/04/BinarySearchTree.md
124 | - Max Binary Heap: JavaScript/04/MaxBinaryHeap.md
125 | - Max Priority Queue: JavaScript/04/MaxPriorityQueue.md
126 | - 05 - Graphs:
127 | - Graph: JavaScript/05/Graph.md
128 | - Dijkstra Algorithm: JavaScript/05/Dijkstra.md
129 |
--------------------------------------------------------------------------------
/docs/PCP/1-2.md:
--------------------------------------------------------------------------------
1 | # 2. Threads and Processes
2 |
3 | ## Thread versus process
4 |
5 | ```cpp
6 | // Threads that waste CPU cycles
7 | #include
8 | #include
9 | #include
10 |
11 | // a simple function that wastes CPU cycles "forever"
12 | void cpu_waster() {
13 | printf("CPU Waster Process ID: %d\n", getpid());
14 | printf("CPU Waster Thread ID %d\n", std::this_thread::get_id());
15 | while (true) continue;
16 | }
17 |
18 | int main() {
19 | printf("Main Process ID: %d\n", getpid());
20 | printf("Main Thread ID: %d\n", std::this_thread::get_id());
21 | std::thread thread1(cpu_waster);
22 | std::thread thread2(cpu_waster);
23 |
24 | while (true) { // keep the main thread alive "forever"
25 | std::this_thread::sleep_for(std::chrono::seconds(1));
26 | }
27 | }
28 | ```
29 |
30 | ## Execution scheduling
31 |
32 | ```cpp
33 | // Two threads chopping vegetables
34 | #include
35 | #include
36 |
37 | bool chopping = true;
38 |
39 | void vegetable_chopper(const char* name) {
40 | unsigned int vegetable_count = 0;
41 | while (chopping) {
42 | ++vegetable_count;
43 | }
44 | printf("%s chopped %u vegetables.\n", name, vegetable_count);
45 | }
46 |
47 | int main() {
48 | std::thread olivia(vegetable_chopper, "Olivia");
49 | std::thread barron(vegetable_chopper, "Barron");
50 |
51 | printf("Barron and Olivia are chopping vegetables...\n");
52 | std::this_thread::sleep_for(std::chrono::seconds(1));
53 | chopping = false;
54 | barron.join();
55 | olivia.join();
56 | }
57 | ```
58 |
59 | ## Thread life cycle
60 |
61 | === "begin"
62 |
63 | ```cpp
64 | // Two threads cooking soup
65 | #include
66 | #include
67 |
68 | void chef_olivia() {
69 | printf("Olivia started & waiting for sausage to thaw...\n");
70 | std::this_thread::sleep_for(std::chrono::seconds(3));
71 | printf("Olivia is done cutting sausage.\n");
72 | }
73 |
74 | int main() {
75 | printf("Barron requests Olivia's help.\n");
76 | std::thread olivia(chef_olivia);
77 |
78 | printf("Barron continues cooking soup.\n");
79 | std::this_thread::sleep_for(std::chrono::seconds(1));
80 |
81 | printf("Barron patiently waits for Olivia to finish and join...\n");
82 | olivia.join();
83 |
84 | printf("Barron and Olivia are both done!\n");
85 | }
86 | ```
87 |
88 | === "end"
89 |
90 | ```cpp hl_lines="14 18 22"
91 | // Two threads cooking soup
92 | #include
93 | #include
94 |
95 | void chef_olivia() {
96 | printf("Olivia started & waiting for sausage to thaw...\n");
97 | std::this_thread::sleep_for(std::chrono::seconds(3));
98 | printf("Olivia is done cutting sausage.\n");
99 | }
100 |
101 | int main() {
102 | printf("Barron requests Olivia's help.\n");
103 | std::thread olivia(chef_olivia);
104 | printf(" Olivia is joinable? %s\n", olivia.joinable() ? "true" : "false");
105 |
106 | printf("Barron continues cooking soup.\n");
107 | std::this_thread::sleep_for(std::chrono::seconds(1));
108 | printf(" Olivia is joinable? %s\n", olivia.joinable() ? "true" : "false");
109 |
110 | printf("Barron patiently waits for Olivia to finish and join...\n");
111 | olivia.join();
112 | printf(" Olivia is joinable? %s\n", olivia.joinable() ? "true" : "false");
113 |
114 | printf("Barron and Olivia are both done!\n");
115 | }
116 | ```
117 |
118 | ## Detached thread
119 |
120 | === "begin"
121 |
122 | ```cpp
123 | // Barron finishes cooking while Olivia cleans
124 | #include
125 | #include
126 |
127 | void kitchen_cleaner() {
128 | while (true) {
129 | printf("Olivia cleaned the kitchen.\n");
130 | std::this_thread::sleep_for(std::chrono::seconds(1));
131 | }
132 | }
133 |
134 | int main() {
135 | std::thread olivia(kitchen_cleaner);
136 | for (int i = 0; i < 3; ++i) {
137 | printf("Barron is cooking...\n");
138 | std::this_thread::sleep_for(std::chrono::milliseconds(600));
139 | }
140 | printf("Barron is done!\n");
141 | olivia.join();
142 | }
143 | ```
144 |
145 | === "end"
146 |
147 | ```cpp hl_lines="14"
148 | // Barron finishes cooking while Olivia cleans
149 | #include
150 | #include
151 |
152 | void kitchen_cleaner() {
153 | while (true) {
154 | printf("Olivia cleaned the kitchen.\n");
155 | std::this_thread::sleep_for(std::chrono::seconds(1));
156 | }
157 | }
158 |
159 | int main() {
160 | std::thread olivia(kitchen_cleaner);
161 | olivia.detach();
162 | for (int i = 0; i < 3; ++i) {
163 | printf("Barron is cooking...\n");
164 | std::this_thread::sleep_for(std::chrono::milliseconds(600));
165 | }
166 | printf("Barron is done!\n");
167 | }
168 | ```
169 |
--------------------------------------------------------------------------------
/docs/OS/Chap02.md:
--------------------------------------------------------------------------------
1 | # Chapter 2 Operating-System Structures
2 |
3 | Objectives:
4 |
5 | - To describe the services an operating system provides to users, processes, and other systems.
6 | - To discuss the various ways of structuring an operating system.
7 | - To explain how operating systems are installed and customized and how they boot.
8 |
9 | ## 2.1 Operating-System Services
10 |
11 | 
12 |
13 | - User interface (UI)
14 | - command-line interface (CLI)
15 | - batch interface
16 | - graphical user interface
17 |
18 | - Program execution. OS load a program into memory $\to$ run that program $\to$ end execution
19 | - normally
20 | - abnormally (error)
21 |
22 | - I/O operations. A running program may require I/O:
23 | - file
24 | - I/O device: recording to a CD or DVD ...
25 |
26 | - File-system manipulation.
27 | - read/write files
28 | - create/delete them by name
29 | - search
30 | - list file (ls)
31 |
32 | - Communications.
33 | - shared memory
34 | - message passing: packets of information in predefined formats are moved between processes by the operating system
35 |
36 | - Error detection
37 | - Resource allocation
38 | - Accounting. users can be billed
39 | - Protection and security
40 |
41 | ## 2.2 User and Operating-System Interface
42 |
43 | ### 2.2.1 Command Interpreters
44 |
45 | On systems with multiple command interpreters to choose from, the interpreters are known as **shells**.
46 |
47 | Two approaches:
48 |
49 | 1. the command interpreter itself contains the code to execute the command.
50 | - fast but the interpreter tends to be big! $\to$ painful in revision!
51 | - e.g. `cd`, `ls`, `del`
52 | 2. the command interpreter merely uses the command to identify a file to be loaded into memory and executed $\to$ search exec files
53 | - parameter passing
54 | - being slow
55 | - inconsistent interpretation of parameters
56 | - e.g. `rm`
57 |
58 | ### 2.2.2 Graphical User Interfaces
59 |
60 | - desktop
61 | - icons
62 | - folder
63 | - mouse
64 | - gestures on the touchscreen
65 |
66 | ### 2.2.3 Choice of Interface
67 |
68 | - shell scripts
69 | - e.g. `UNIX` and `Linux`.
70 |
71 | ## 2.3 Systems Calls
72 |
73 | 
74 |
75 | System calls provide an interface to the services made available by an operating system.
76 |
77 | e.g. writing a simple program to read data from one file and copy them to another file causes a lot of system calls!
78 |
79 | - C/C++
80 |
81 | Each read and write must return status information regarding various possible error conditions.
82 |
83 | - application programming interface (API): it specifies a set of functions
84 | - Windows API
85 | - POSIX API
86 | - UNIX
87 | - Linux
88 | - macOS
89 | - Java API
90 |
91 | **libc**: UNIX and Linux for programs written in C
92 |
93 | Why prefer API rather than invoking actual system calls?
94 |
95 | - protability (expected to run on any system)
96 | - actual system calls can be more difficult to learn
97 |
98 | The relationship between an **API**, the **system-call interface**, and the **OS**
99 |
100 | 
101 |
102 | The caller need know nothing about how the system call is implemented or what it does during execution. Rather, the caller need only obey the API and understand what the operating system will do as a result of the execution of that system call.
103 |
104 | *Make explicit to implicit*.
105 |
106 | Three general methods are used to pass parameters to the operating system.
107 |
108 | - through registers (Linux and Solaris)
109 | - block,
110 | - table,
111 | - memory,
112 | - and the address of the
113 |
114 | - placed or pushed onto the stack $\to$ popped off the stack by the OS
115 |
116 | 
117 |
118 | ## 2.4 Types of System Calls
119 |
120 | ### 2.4.1 Process Control
121 |
122 | A running program halts either
123 |
124 | - normally: `end()`
125 | - abnormally: `abort()`
126 |
127 | error $\to$ dump (written to disk, may be examined by a debugger)
128 |
129 | More severe errors can be indicated by a higher-level error parameter.
130 |
131 | e.g. Standard C Library
132 |
133 | 
134 |
135 | ### 2.4.2 File Management
136 |
137 | ### 2.4.3 Device Management
138 |
139 | ### 2.4.4 Information Maintenance
140 |
141 | Many systems provide system calls to `dump()` memory. This provision is useful for debugging. A program trace lists each system call as it is executed. Even microprocessors provide a CPU mode known as single step, in which a trap is executed by the CPU after every instruction. The trap is usually caught by a debugger.
142 |
143 | ### 2.4.5 Communication
144 |
145 | ### 2.4.6 Protection
146 |
147 | ## 2.5 System Programs
148 |
149 | ## 2.6 Operating-System Design and Implementation
150 |
151 | ### 2.6.1 Design Goals
152 |
153 | ### 2.6.2 Mechanisms and Policies
154 |
155 | ### 2.6.3 Implementation
--------------------------------------------------------------------------------
/docs/JavaScript/01/frequencyCounters.md:
--------------------------------------------------------------------------------
1 | # Frequency Counters Pattern
2 |
3 | This pattern uses objects or sets to collect values/frequencies of values.
4 |
5 | This can often avoid the need for nested loops or $O(n^2)$ operations with arrays/strings.
6 |
7 | ---
8 |
9 | ## `same(arr1, arr2)`
10 |
11 | > Write a function called `same`, which accepts two arrays. The function should return true if every value in the array has it's corresponding value squared in the second array. The frequency of values must be the same.
12 |
13 | ```js
14 | same([1, 2, 3], [4, 1, 9]); // true
15 | same([1, 2, 3], [1, 9]); // false
16 | same([1, 2, 1], [4, 4, 1]); // false (must be same frequency)
17 | ```
18 |
19 | - Solution 1 (naive)
20 |
21 | - Time: $O(n^2)$
22 | - Space: $O(1)$
23 |
24 | ```js
25 | const same = (arr1, arr2) => {
26 | if (arr1.length !== arr2.length) return false;
27 |
28 | for (let i = 0; i < arr1.length; i++) {
29 | let correctIndex = arr2.indexOf(arr1[i] ** 2);
30 | if (correctIndex === -1) return false;
31 | arr2.splice(correctIndex, 1);
32 | }
33 |
34 | return true;
35 | };
36 | ```
37 |
38 | - Solution 2 (refactor)
39 |
40 | - Time: $O(n)$
41 | - Space: $O(n)$
42 |
43 | ```js
44 | const same = (arr1, arr2) => {
45 | if (arr1.length !== arr2.length) return false;
46 |
47 | const freqCount1 = {};
48 | const freqCount2 = {};
49 |
50 | for (let val of arr1) freqCount1[val] = (freqCount1[val] || 0) + 1;
51 | for (let val of arr2) freqCount2[val] = (freqCount2[val] || 0) + 1;
52 | for (let key in freqCount1) {
53 | if (!(key ** 2 in freqCount2)) return false;
54 | if (freqCount1[key] !== freqCount2[key ** 2]) return false;
55 | }
56 |
57 | return true;
58 | };
59 | ```
60 |
61 | ## `validAnagram(arr1, arr2)`
62 |
63 | > Given two strings, write a function called `validAnagram` to determine if the second string is an anagram of the first. An anagram is a word, phrase, or name formed by rearranging the letters of another, such as _cinema_, formed from _iceman_.
64 |
65 | ```js
66 | validAnagram('', ''); // true
67 | validAnagram('aaz', 'zza'); // false
68 | validAnagram('anagram', 'nagaram'); // true
69 | ```
70 |
71 | - Solution
72 |
73 | - Time: $O(n)$
74 | - Space: $O(n)$
75 |
76 | ```js
77 | const validAnagram = (arr1, arr2) => {
78 | if (arr1.length !== arr2.length) return false;
79 |
80 | const freqCount1 = {};
81 |
82 | for (let val of arr1) freqCount1[val] = (freqCount1[val] || 0) + 1;
83 | for (let val of arr2) {
84 | if (!freqCount1[val]) return false;
85 | freqCount1[val]--;
86 | }
87 |
88 | return true;
89 | };
90 | ```
91 |
92 | ## `sameFrequency(num1, num2)`
93 |
94 | > Write a function called `sameFrequency`. Given two positive integers, find out if the two numbers have the same frequency of digits.
95 |
96 | ```js
97 | sameFrequency(182, 281); // true
98 | sameFrequency(3589578, 5879385); // true
99 | sameFrequency(34, 14); // false
100 | sameFrequency(22, 222); // false
101 | ```
102 |
103 | - Solution
104 |
105 | - Time: $O(n)$
106 |
107 | ```js
108 | const sameFrequency = (num1, num2) => {
109 | strNum1 = num1.toString();
110 | strNum2 = num2.toString();
111 |
112 | if (strNum1.length !== strNum2.length) return false;
113 |
114 | const freqCount1 = {};
115 |
116 | for (let val of strNum1) freqCount1[val] = (freqCount1[val] || 0) + 1;
117 | for (let val of strNum2) {
118 | if (!freqCount1[val]) return false;
119 | freqCount1[val]--;
120 | }
121 |
122 | return true;
123 | };
124 | ```
125 |
126 | ## `areThereDuplicates(...args)`
127 |
128 | > Implement a function called, `areThereDuplicates` which accepts a variable number of arguments, and checks whether there are any duplicates among the arguments passed in. You can solve this using the frequency counter pattern OR the multiple pointers pattern.
129 |
130 | ```js
131 | areThereDuplicates(1, 2, 3); // false
132 | areThereDuplicates(1, 2, 2); // true
133 | areThereDuplicates('a', 'b', 'c', 'a'); // true
134 | ```
135 |
136 | - Solution 1 (frequency counter)
137 |
138 | - Time: $O(n)$
139 | - Space: $O(n)$
140 |
141 | ```js
142 | const areThereDuplicates = (...args) => {
143 | let lookup = {};
144 |
145 | for (let val of args) {
146 | if (lookup[val]) return true;
147 | lookup[val] = (lookup[val] || 0) + 1;
148 | }
149 |
150 | return false;
151 | };
152 | ```
153 |
154 | - Solution 2 (multiple pointers)
155 |
156 | - Time: $O(n\log n)$
157 | - Space: $O(1)$
158 |
159 | ```js
160 | const areThereDuplicates = (...args) => {
161 | args.sort();
162 |
163 | let i = 0;
164 |
165 | for (let j = 1; j < args.length; i++, j++)
166 | if (args[i] === args[j])
167 | return true;
168 |
169 | return false;
170 | };
171 | ```
172 |
173 | - Solution 3
174 |
175 | ```js
176 | const areThereDuplicates = () => {
177 | return new Set(arguments).size !== arguments.length;
178 | };
179 | ```
180 |
--------------------------------------------------------------------------------
/docs/ML/01.md:
--------------------------------------------------------------------------------
1 | # Lecture 1: Regression - Case Study
2 |
3 | ## Regression: Output a scalar
4 |
5 | Regression 的例子舉例有:
6 |
7 | - 道瓊斯指數預測
8 | - 自動駕駛中的方向盤角度預測
9 | - 推薦系統中購買可能性的預測
10 |
11 | ## Example Application
12 |
13 | - Estimating the Combat Power (CP) of a pokemon after evolution
14 |
15 | 一隻寶可夢可由 5 個參數表示:
16 |
17 | $$x = (x_{cp}, x_s, x_{hp}, x_w, x_h).$$
18 |
19 | 
20 |
21 | 我們希望能計算出,給定寶可夢的一些 features $x$,能過算出他進化後的 CP 值 $y$
22 |
23 | ## Machine Learning Steps
24 |
25 | Machine Learning 主要有三個步驟
26 |
27 | ### Step 1: Model
28 |
29 | 我們假設預測 $y$ 值的 function 為 $y = b + w \cdot x_{cp}$,許多不同的 $w$ 和 $b$ 可構成不同的 $f_1, f_2, \dots$,例如:
30 |
31 | $$
32 | \begin{aligned}
33 | f_1: y & = 10.0 + 9.0 \cdot x_{cp} \\\\
34 | f_2: y & = 9.8 + 9.2 \cdot x_{cp} \\\\
35 | f_3: y & = -0.8 - 1.2 \cdot x_{cp} \\\\
36 | & \vdots
37 | \end{aligned}
38 | $$
39 |
40 | 如此一來,我們就有了 linear model:
41 |
42 | $$y = b + \sum w_ib_i$$
43 |
44 | 其中,
45 |
46 | - $x_i: x_{cp}, x_s, x_{hp}, x_w, x_h$:寶可夢的 features
47 | - $w_i$:不同 features,給它不同的 weight
48 | - $b$:bias
49 |
50 | ### Step 2: Goodness of Function
51 |
52 | 有了一堆 functions 後,我們必需要知道,這些 functions 有多好?因此我們需要一個評比的標準,我們可以用 Loss function $L$,它的 input 為 $f$,output 為 how bad it is?
53 |
54 | loss function 可定義如下:
55 |
56 | $$
57 | \begin{aligned}
58 | L(f) & = \sum_{n = 1}^{10} (\hat y^n - f(x_{cp}^n))^2 \\\\
59 | L(w, b) & = \sum_{n = 1}^{10} (\hat y^n - (b + w \cdot x_{cp}^n))^2
60 | \end{aligned}
61 | $$
62 |
63 | ### Step 3: Best Function
64 |
65 | 最後,我們要選出 best function,即:選擇 loss 最小的 function(參數):
66 |
67 | $$
68 | \begin{aligned}
69 | f ^ { * } & = \arg \min _ { f } L ( f ) \\\\
70 | w ^ { * } , b ^ { * } & = \arg \min _ { w , b } L ( w , b ) \\\\
71 | & = \arg \min _ { w , b } \sum _ { n = 1 } ^ { 10 } \left( \hat { y } ^ { n } - \left( b + w \cdot x _ { c p } ^ { n } \right) \right) ^ { 2 }
72 | \end{aligned}
73 | $$
74 |
75 | 求解最佳參數的方法可以是 Gradient Descent。
76 |
77 | ## Gradient Descent
78 |
79 | 
80 |
81 | Gradient Descent 的步驟如下:
82 |
83 | 1. (隨機)選擇參數初始值(e.g. $w^0$),上標表示時間點
84 | 2. 計算 loss function $L(w)$ 在 $w = w^0$ 上時的 gradient,即:$\left. \frac { d L } { d w } \right| _ { w = w ^ { 0 } }$
85 |
86 | 3. 向負梯度方向迭代更新
87 |
88 | - $\frac{dL}{dw} \Big|_{w = w^0} < 0 \to$ Increase $w$
89 | - $\frac{dL}{dw} \Big|_{w = w^0} > 0 \to$ Decrease $w$
90 |
91 | \begin{align}
92 | w ^ { 1 } & \leftarrow w ^ { 0 } - \eta \left. \frac { d L } { d w } \right| _ { w = w ^ { 0 } } \\\\
93 | w ^ { 2 } & \leftarrow w ^ { 1 } - \eta \left. \frac { d L } { d w } \right| _ { w = w ^ { 1 } }
94 | \end{align}
95 |
96 | 其中,$\eta$ 為 learning rate,用來控制一次走多遠、學習速度
97 |
98 | 重複這 3 個步驟,直到 $w$ 在 local minima 收斂為止。
99 |
100 | 順帶一提,只有一個參數 $w$ 時,$\nabla L$ 就是 $\frac{\partial L}{\partial w}$ 為 $L$ 的 gradient,所以才叫 Gradient Descent。
101 |
102 | 若有兩個參數 $w, b$ 時,$\nabla L = \left[ \begin{array} { l } { \frac { \partial L } { \partial w } } \\\\ { \frac { \partial L } { \partial b } } \end{array} \right]$,本質上概念還是相同的
103 |
104 | Gradient Descent 可能使參數停在損失函數的局部最小值、微分為 $0$ 的點,或者微分為極小值的點。Linear regression 中不必擔心局部最小值的問題,因為 loss function 是 convex 的。
105 |
106 | 在得到 best function 之後,我們真正在意的是它**在 testing data 上的表現**。選擇不同的 model,會得到不同的 best function,它們在testing data 上有不同表現。
107 |
108 | 複雜模型的 model space 涵蓋了簡單模型的 model space,因此在 training data 上的錯誤率更小,但並不意味著在 testing data 上錯誤率也會小,因為 Model 太複雜有很高機率會出現 overfitting。
109 |
110 | ## What are the hidden factors?
111 |
112 | 如果我們收集更多寶可夢進化前後的 CP 值會發現,進化後的 CP 值不只依賴於進化前的 CP 值,可能還有其它的隱藏因素(例如:寶可夢所屬的物種)。同時考慮進化前 CP 值 $x_{cp}$ 和物種 $x_s$,我們可以回到 Step 1: Model 重新選擇新的 model:
113 |
114 | $$
115 | \begin{aligned}
116 | \text{if } & x_s = \text{pidgey}: & y = b_1 + w_1 \cdot x_{cp} \\\\
117 | \text{if } & x_s = \text{weedle}: & y = b_2 + w_2 \cdot x_{cp} \\\\
118 | \text{if } & x_s = \text{caterpie}: & y = b_3 + w_3 \cdot x_{cp} \\\\
119 | \text{if } & x_s = \text{eevee}: & y = b_4 + w_4 \cdot x_{cp}
120 | \end{aligned}
121 | $$
122 |
123 | 這仍是一個線性模型,因為它可以寫作:
124 |
125 | $$
126 | \begin{aligned}
127 | y = & b_1 \cdot \boldsymbol{\delta(x_s = \text{pidgey}) } & + & w_1 \cdot \boldsymbol{\delta(x_s = \text{pidgey}) \cdot x_{cp}} + \\\\
128 | & b_2 \cdot \boldsymbol{\delta(x_s = \text{weedle}) } & + & w_2 \cdot \boldsymbol{\delta(x_s = \text{weedle}) \cdot x_{cp}} + \\\\
129 | & b_3 \cdot \boldsymbol{\delta(x_s = \text{caterpie})} & + & w_3 \cdot \boldsymbol{\delta(x_s = \text{caterpie}) \cdot x_{cp}} + \\\\
130 | & b_4 \cdot \boldsymbol{\delta(x_s = \text{eevee}) } & + & w_4 \cdot \boldsymbol{\delta(x_s = \text{eevee}) \cdot x_{cp}}
131 | \end{aligned}
132 | $$
133 |
134 | 上式中的粗體項都是 linear model $y = b + \Sigma w_i \cdot x_i$ 中的 feature $x_i$。
135 |
136 | 這個模型在 testing data 上有更好的表現,如果同時考慮寶可夢的其它屬性,選一個很複雜的模型,結果可能會導致 overfitting。
137 |
138 | 對線性模型來說,我們希望選出的 best function 能平滑一點,也就是權重係數小一些,因為這樣的話,在 testing data 受 noise 影響時,預測值所受的影響會更小。
139 |
140 | 所以在 Step 2: Goodness of Function 設計 loss function 時,我們可以加一個正則項 $\lambda\Sigma w_i^2$:
141 |
142 | $$L = \sum _ { n } \left( \hat { y } ^ { n } - \left( b + \sum w _ { i } x _ { i }^n \right) \right) ^ { 2 } + \lambda \sum \left( w _ { i } \right) ^ { 2 }$$
143 |
144 | 越大的 $\lambda$,training error 可能會越大,但沒關係,我們希望函數平滑,但也不能太平滑,於是我們調整 $\lambda$,選擇使 testing error 最小的 $\lambda$。
145 |
--------------------------------------------------------------------------------
/docs/ML/04.md:
--------------------------------------------------------------------------------
1 | # Lecture 4: Classification: Probabilistic Generative Model
2 |
3 | 分類問題常被用在各種領域,例如:
4 |
5 | - 金融交易成功與否
6 | - 醫學診斷分類
7 | - 手寫辨識
8 | - 人臉辨試
9 |
10 | ---
11 |
12 | 課堂上的例子:根據寶可夢各屬性(features)去預測其類別(class)。
13 |
14 | Training data:寶可夢的各屬性(features)及其類別(class)。
15 |
16 | ## How to do Classification?
17 |
18 | ### Classification as Regression?
19 |
20 | 
21 |
22 | 像上圖右側,即使分類正確了,還是會因為遠大於 $1$,造成 loss 過大,因此不適合使用 regression。
23 |
24 | 此外,當類別超過 $2$ 種時,也會產生許多問題,因為這樣表示,各類別之間是有大小遠近關係的,但在分類問題這樣是不合理的。
25 |
26 | ## Ideal Alternatives
27 |
28 | - Function (Model):
29 |
30 | $$
31 | f(x) =
32 | \begin{cases}
33 | g(x) > 0 & \text{output: class 1}, \\\\
34 | \text{else} & \text{output: class 2}
35 | \end{cases}
36 | $$
37 |
38 | - Loss function:
39 |
40 | $$L(f) = \sum_n \delta(f(x^n) \ne \hat y^n)$$
41 |
42 | - Find the best function
43 |
44 | ### Bayes' Theorem
45 |
46 | 假設有兩個類別,我們想要估算來自 training data 的機率。
47 |
48 | 
49 |
50 | Given an $x$, which class does it belong to:
51 |
52 | $$
53 | P \left( C _ { 1 } | x \right) = \frac { P ( x | C _ { 1 } ) P \left( C _ { 1 } \right) } { P ( x | C _ { 1 } ) P \left( C _ { 1 } \right) + P ( x | C _ { 2 } ) P \left( C _ { 2 } \right) }
54 | $$
55 |
56 | Generative Model:
57 |
58 | $$
59 | P ( x ) = P ( x | C _ { 1 } ) P \left( C _ { 1 } \right) + P ( x | C _ { 2 } ) P \left( C _ { 2 } \right)
60 | $$
61 |
62 | ### Prior
63 |
64 | 舉例來說:我們挑選出 79 隻水系($C_1$)和 61 隻一般系($C_2$)的寶可夢,那麼
65 |
66 | \begin{align}
67 | P(C_1) & = 79 / (79 + 61) = 0.56 \\\\
68 | P(C_2) & = 61 / (79 + 61) = 0.44
69 | \end{align}
70 |
71 | ### Probability from Class
72 |
73 | 現在我們想要知道的事,從水系($C_1$)挑出一隻「海龜」的機率是多少?
74 |
75 | ### Probability from Class - Feature
76 |
77 | 因為寶可夢的 features 太多,為了方便,我們只考慮兩項,Defense 和 SP Defense,並假設這 79 隻水系寶可夢都是由 Gaussian distribution sample 出來的。
78 |
79 | ### Maximum Likelihood
80 |
81 | 
82 |
83 | 因為每個點 $x$ 是獨立的,所以我們可以透過以下連乘來得出 $L(\mu, \Sigma)$
84 |
85 | Likelihood of Gaussian with mean $\mu$ and covariance matrix $\Sigma$ = the probability of the Gaussian samples $x^1, x^2, x^3, \dots, x^{79}$:
86 |
87 | $$L(\mu, \Sigma) = f_{\mu, \Sigma}(x^1) f_{\mu, \Sigma}(x^2) f_{\mu, \Sigma}(x^3) \dots f_{\mu, \Sigma}(x^{79})$$
88 |
89 | 所以我們的目的是,找出一個 $(\mu^\*, \Sigma^\*)$ 能讓上式的 likelihood 最大:
90 |
91 | $$\mu^\*, \Sigma^\* = \arg \max_{\mu, \Sigma} L(\mu, \Sigma)$$
92 |
93 | 透過微分可得以下結果:
94 |
95 | $$
96 | \begin{aligned}
97 | \mu^\* & = \frac 1 {79} \sum_{n = 1}^{79} x^n \\\\
98 | \Sigma^\* & = \frac 1 {79} \sum_{n = 1}^{79} (x^n - \mu^\*)(x^n - \mu^\*)^T
99 | \end{aligned}
100 | $$
101 |
102 | 所以我們可計算出:
103 |
104 | 
105 |
106 | 現在可以開始分類了,
107 |
108 | $$P(C_1 \mid x) = \frac{P(x \mid C_1) P(C_1)}{P(x \mid C_1) P(C_1) + P(x \mid C_2) P(C_2)}$$
109 |
110 | 其中,
111 |
112 | - $P(C_1) = 79 / (79 + 61) = 0.56$
113 | - $P(C_2) = 61 / (79 + 61) = 0.44$
114 |
115 | $$P(x \mid C_1) = f_{\mu^1, \Sigma^1}(x) = \frac 1 {(2\pi)^{D / 2}} \frac 1 {|\Sigma^1|^{1 / 2}} exp \Big(- \frac 1 2 (x - \mu^1)^T (\Sigma^1)^{-1} (x - \mu^1) \Big)$$
116 |
117 | $$P(x \mid C_2) = f_{\mu^2, \Sigma^2}(x) = \frac 1 {(2\pi)^{D / 2}} \frac 1 {|\Sigma^2|^{1 / 2}} exp \Big(- \frac 1 2 (x - \mu^2)^T (\Sigma^2)^{-1} (x - \mu^2) \Big)$$
118 |
119 | 若 $P(C_1 \mid x) > 0.5$,$x$ 就屬於 class 1(水系)
120 |
121 | 但結果卻不怎麼樣,因為參數太多了,可能有 overfit 疑慮。
122 |
123 | ### Modifying Model
124 |
125 | 原本對兩個分佈(水系、一般系)都有對應的 covariance matrix ($\Sigma_1, \Sigma_2$),但這樣參數量太大,可能會 overfit,所以我們降低參數量去避免 overfit,只考慮一個 convariance matrix($\Sigma$),修改 loss function 如下:
126 |
127 | $$L(\mu^1, \mu^2, \Sigma) = f_{\mu^1, \Sigma}(x^1) f_{\mu^2, \Sigma}(x^2) \cdots f_{\mu^1, \Sigma}(x^{79}) \times f_{\mu^1, \Sigma}(x^{80}) f_{\mu^1, \Sigma}(x^{81}) \cdots f_{\mu^1, \Sigma}(x^{140})$$
128 |
129 | $\mu^1$ 和 $\mu^2$ 維持不變,$\Sigma = \frac{79}{140}\Sigma^1 + \frac{61}{140}\Sigma^2$
130 |
131 | ### Three Steps
132 |
133 | - Function Set (Model):
134 |
135 | 輸入一個 $x$:$P(C_1 \mid x) = \frac{P(x \mid C_1) P(C_1)}{P(x \mid C_1) P(C_1) + P(x \mid C_2) P(C_2)}$
136 |
137 | $$
138 | \begin{cases}
139 | P(C_1 \mid x) > 0.5 & \text{output: class 1}, \\\\
140 | \text{else} & \text{output: class 2}
141 | \end{cases}
142 | $$
143 |
144 | - Goodness of a function
145 |
146 | The mean $\mu$ and covariance $\Sigma$ that maximizing the likelihood (the probability of generating data)
147 |
148 | - Find the test function: easy
149 |
150 | ### Posterior Probability
151 |
152 | $$
153 | \begin{aligned}
154 | P(C_1 \mid x)
155 | & = \frac{P(x \mid C_1) P(C_1)}{P(x \mid C_1) P(C_1) + P(x \mid C_2) P(C_2)} \\\\
156 | & = \frac 1 {1 + \frac{P(x \mid C_2) P(C_2)}{P(x \mid C_1) P(C_1)}} \\\\
157 | & = \frac 1 {1 + e^{-z}} = \sigma(z)
158 | \end{aligned}
159 | $$
160 |
161 | 其中,$z = \ln \frac{P(x \mid C_1) P(C_1)}{P(x \mid C_2) P(C_2)}$ (sigmoid)
162 |
163 | 經過很長一段推導(這裡就不再贅述,可直接看老師[投影片](http://speech.ee.ntu.edu.tw/~tlkagk/courses/ML_2016/Lecture/Classification%20(v3).pdf)),可得出:
164 |
165 | $$
166 | \begin{aligned}
167 | P(C_1 \mid x) & = \sigma(z) \\\\
168 | & = \sigma(w \cdot x + b)
169 | \end{aligned}
170 | $$
171 |
172 | 其中,
173 |
174 | - $w^T = (\mu^1 - \mu^2)^T \Sigma^{-1}$
175 | - $b = -\frac 1 2 (\mu^1)^T \Sigma^{-1} \mu^1 + \frac 1 2 (\mu^2)^T \Sigma^{-1} \mu^2 + \ln \frac{N_1}{N_2}$
176 |
--------------------------------------------------------------------------------
/docs/PCP/2-2.md:
--------------------------------------------------------------------------------
1 | # Barriers
2 |
3 | ## Race condition
4 |
5 | ```cpp
6 | // Deciding how many bags of chips to buy for the party
7 | #include
8 | #include
9 |
10 | unsigned int bags_of_chips = 1; // start with one on the list
11 | std::mutex pencil;
12 |
13 | void cpu_work(unsigned long workUnits) {
14 | unsigned long x = 0;
15 | for (unsigned long i; i < workUnits * 1000000; ++i) {
16 | ++x;
17 | }
18 | }
19 |
20 | void barron_shopper() {
21 | cpu_work(1); // do a bit of work first
22 | std::scoped_lock lock(pencil);
23 | bags_of_chips *= 2;
24 | printf("Barron DOUBLED the bags of chips.\n");
25 | }
26 |
27 | void olivia_shopper() {
28 | cpu_work(1); // do a bit of work first
29 | std::scoped_lock lock(pencil);
30 | bags_of_chips += 3;
31 | printf("Olivia ADDED 3 bags of chips.\n");
32 | }
33 |
34 | int main() {
35 | std::thread shoppers[10];
36 | for (int i = 0; i < 10; i += 2) {
37 | shoppers[i] = std::thread(barron_shopper);
38 | shoppers[i + 1] = std::thread(olivia_shopper);
39 | }
40 | for (auto& s : shoppers) {
41 | s.join();
42 | }
43 | printf("We need to buy %u bags_of_chips.\n", bags_of_chips);
44 | }
45 | ```
46 |
47 | ## Barrier
48 |
49 | === "begin"
50 |
51 | ```cpp
52 | // Deciding how many bags of chips to buy for the party
53 | #include
54 | #include
55 |
56 | unsigned int bags_of_chips = 1; // start with one on the list
57 | std::mutex pencil;
58 |
59 | void cpu_work(unsigned long workUnits) {
60 | unsigned long x = 0;
61 | for (unsigned long i; i < workUnits * 1000000; ++i) {
62 | ++x;
63 | }
64 | }
65 |
66 | void barron_shopper() {
67 | cpu_work(1); // do a bit of work first
68 | std::scoped_lock lock(pencil);
69 | bags_of_chips *= 2;
70 | printf("Barron DOUBLED the bags of chips.\n");
71 | }
72 |
73 | void olivia_shopper() {
74 | cpu_work(1); // do a bit of work first
75 | std::scoped_lock lock(pencil);
76 | bags_of_chips += 3;
77 | printf("Olivia ADDED 3 bags of chips.\n");
78 | }
79 |
80 | int main() {
81 | std::thread shoppers[10];
82 | for (int i = 0; i < 10; i += 2) {
83 | shoppers[i] = std::thread(barron_shopper);
84 | shoppers[i + 1] = std::thread(olivia_shopper);
85 | }
86 | for (auto& s : shoppers) {
87 | s.join();
88 | }
89 | printf("We need to buy %u bags_of_chips.\n", bags_of_chips);
90 | }
91 | ```
92 |
93 | === "barrier"
94 |
95 | ```cpp hl_lines="2 8 19 27 28 29 30 32"
96 | // Deciding how many bags of chips to buy for the party
97 | #include
98 | #include
99 | #include
100 |
101 | unsigned int bags_of_chips = 1; // start with one on the list
102 | std::mutex pencil;
103 | boost::barrier fist_bump(10);
104 |
105 | void cpu_work(unsigned long workUnits) {
106 | unsigned long x = 0;
107 | for (unsigned long i; i < workUnits * 1000000; ++i) {
108 | ++x;
109 | }
110 | }
111 |
112 | void barron_shopper() {
113 | cpu_work(1); // do a bit of work first
114 | fist_bump.wait();
115 | std::scoped_lock lock(pencil);
116 | bags_of_chips *= 2;
117 | printf("Barron DOUBLED the bags of chips.\n");
118 | }
119 |
120 | void olivia_shopper() {
121 | cpu_work(1); // do a bit of work first
122 | {
123 | std::scoped_lock lock(pencil);
124 | bags_of_chips += 3;
125 | }
126 | printf("Olivia ADDED 3 bags of chips.\n");
127 | fist_bump.wait();
128 | }
129 |
130 | int main() {
131 | std::thread shoppers[10];
132 | for (int i = 0; i < 10; i += 2) {
133 | shoppers[i] = std::thread(barron_shopper);
134 | shoppers[i + 1] = std::thread(olivia_shopper);
135 | }
136 | for (auto& s : shoppers) {
137 | s.join();
138 | }
139 | printf("We need to buy %u bags_of_chips.\n", bags_of_chips);
140 | }
141 | ```
142 |
143 | === "latch"
144 |
145 | ```cpp hl_lines="2 8 32"
146 | // Deciding how many bags of chips to buy for the party
147 | #include
148 | #include
149 | #include
150 |
151 | unsigned int bags_of_chips = 1; // start with one on the list
152 | std::mutex pencil;
153 | boost::latch fist_bump(10);
154 |
155 | void cpu_work(unsigned long workUnits) {
156 | unsigned long x = 0;
157 | for (unsigned long i; i < workUnits * 1000000; ++i) {
158 | ++x;
159 | }
160 | }
161 |
162 | void barron_shopper() {
163 | cpu_work(1); // do a bit of work first
164 | fist_bump.wait();
165 | std::scoped_lock lock(pencil);
166 | bags_of_chips *= 2;
167 | printf("Barron DOUBLED the bags of chips.\n");
168 | }
169 |
170 | void olivia_shopper() {
171 | cpu_work(1); // do a bit of work first
172 | {
173 | std::scoped_lock lock(pencil);
174 | bags_of_chips += 3;
175 | }
176 | printf("Olivia ADDED 3 bags of chips.\n");
177 | fist_bump.count_down();
178 | }
179 |
180 | int main() {
181 | std::thread shoppers[10];
182 | for (int i = 0; i < 10; i += 2) {
183 | shoppers[i] = std::thread(barron_shopper);
184 | shoppers[i + 1] = std::thread(olivia_shopper);
185 | }
186 | for (auto& s : shoppers) {
187 | s.join();
188 | }
189 | printf("We need to buy %u bags_of_chips.\n", bags_of_chips);
190 | }
191 | ```
192 |
--------------------------------------------------------------------------------
/docs/OS/final.md:
--------------------------------------------------------------------------------
1 | # Previous Operating System Midterms at NTUCSIE
2 |
3 | ## [Spring 2011](https://www.ptt.cc/bbs/NTU-Exam/M.1340817215.A.742.html)
4 |
5 | The exam is 150 minutes long. The total score is 112pts. Please read the questions carefully.
6 |
7 | 1. Terminologies (21pts).
8 |
9 | - Condition Variable (Hint: Monitor)
10 |
11 | - Stable Storage
12 |
13 | - 50-Percent Rule for the First-Fit Algorithm (Hint: Dynamic Partitioning)
14 |
15 | - Virtual Memory
16 |
17 | - Lazy Swapper
18 |
19 | - Network Information Service (NIS or Yellow Pages from SUN)
20 |
21 | - Scan (or Elevator) Algorithm (Hint: Disk Scheduling)
22 |
23 |
24 | 2. Please answer the following question on process synchronization: (18pts)
25 |
26 | - Synchronization hardware might make programming easier for process synchronization. Please explain why interrupt disabling works for uniprocessor environments to avoid the race condition. (6pts)
27 |
28 | - There are three requirements for a solution to critical section problem. Please tell me which requirement might not be satisfied for solutions based on semaphores with priority-waiting queues. You must provide your arguments. (6pts)
29 |
30 | - When the Two-Phase Locking protocol (2PL) is adopted for process synchronization, and there is only exclusive lock, can we have a deadlock? You must provide your arguments. (6pts)
31 |
32 |
33 | 3. Given the following snapshot of the system: Please determine whether there exists a safe sequence. (5pts)
34 |
35 | 4. With binding at the compiling time, is it appropriate to have Paging? With binding at the loading time, is it appropriate to have Paging? You must provide explanation. (6pts)
36 |
37 | 5. Given a computer system with 64-bit virtual address and 8 bytes per page entry, let the physical address be of 48 bits, and the system is byte-addressable. Assume that every page is of 4KB. Please answer the following questions: (20pts).
38 |
39 | - What is the maximum number of frames? (5pts)
40 |
41 | - Suppose that we have multi-level paging. How many levels do we have in multi-level paging? (5pts)
42 |
43 | - Suppose that TLB is adopted for paging, and multi-level page tables are all in the main memory. Let the memory access time and TLB access time be 100ns and 10ns, respectively. What the TLB hit ratio should be so that the effective memory access time would be no more than 120ns? (5pts)
44 |
45 | - Continued with the previous question, What is the maximum number of entries for an inverted page table? (5pts)
46 |
47 | 6. Please answer the following questions for demand paging: (20pts)
48 |
49 | - What is the maximum number of pages needed for the following instruction: Add (R1)+, -(R2), +(R3) (4pts)
50 |
51 | - The effective access time is defined as (1 - p) * ma + p * pft, where p, ma, and pft are the probability of a page fault, the memory access time for paging, and the page fault time, respectively. Please give me two approaches to reduce the pft. Please give me two approaches to reduce p. (16pts)
52 |
53 | 7. Given the following reference string, which reference causes a page fault under the Second Chance (Clock) Algorithm. Please also show us which page is replaced when a page replacement occurs? Suppose that we have 3 available frames with 0, 1, and 3 as shown in the following graph, all reference bits are 0, and the selection pointer starts at Page 0. (10pts)
54 |
55 | $$1 \, 0 \, 3 \, 1 \, 4 \, 3 \, 2 \, 1 \, 3 \, 0 \, 2 \, 1 \, 5$$
56 |
57 | 8. Modern operating system often only recognize few file types. Please give two advantages why file types are usually supported by applications, instead of the operating system. (8pts)
58 |
59 | 9. Give me one reason when we need scheduling in I/O subsystem, beside performance improvement. (4pts)
60 |
61 | ## [Spring 2012](https://www.ptt.cc/bbs/NTU-Exam/M.1418545643.A.933.html)
62 |
63 | 1. Terminologies. (24pts)
64 |
65 | - **Deadlock**
66 |
67 | A set of process is in a deadlock state when every process in the set is waiting for an event that can be caused by only another process in the set.
68 |
69 | - **Segmentation**
70 |
71 | Segmentation is a memory management scheme that supports the user view of memory.
72 |
73 | - **Working Set** (Hint: Thrashing and Frame Allocation)
74 |
75 | The working set is an approximation of a program's locality.
76 |
77 | - **Optimal Algorithm for Page Replacement (OPT)**
78 |
79 | Replace the page that will not be used for the longest period of time.
80 |
81 | - **Hard Link** (Hint: Acyclic-Graph Directory)
82 |
83 | A hard link of a file name let its directory entry point to the i-node that describes the file's contents.
84 |
85 | - **Network-Attached Storage (NAS)**
86 |
87 | Clients access NAS via a remote procedure call interface such as NFS (for UNIX) or CIFS (for Windows) where NAS has a file system running on it.
88 |
89 | - **Raw Disk**
90 |
91 | Ans: A partition as a large sequential array of logical blocks.
92 |
93 | 2. Please provide one advantage and one disadvantage of a deadlock avoidance algorithm (such as the Banker's Algorithm), compared to a deadlock
94 | prevention algorithm (such as the one without "Hold-and-Wait"). (6pts)
95 |
96 | - Advantage: Better resource utilization and/or better system throughput/performance.
97 | - Dsadvantage: Processes must claim maximum usages of each resource.
98 |
99 | ## [Spring 2013](https://www.ptt.cc/bbs/NTU-Exam/M.1403667958.A.FA7.html)
100 |
101 | ## [Spring 2014](https://www.ptt.cc/bbs/NTU-Exam/M.1437210714.A.B8A.html)
102 |
103 | ## [Spring 2015](https://www.ptt.cc/bbs/NTU-Exam/M.1472670507.A.427.html)
--------------------------------------------------------------------------------
/docs/OS/Chap09.md:
--------------------------------------------------------------------------------
1 | # Chapter 9 Virtual Memory
2 |
3 | ## 9.1 Background
4 |
5 | > For instance, the routines on U.S. government computers that balance the budget have not been used in many years.
6 |
7 | !!! note "Virtual memory"
8 | It separates the logical memory perceived by users from physical memory.
9 |
10 | !!! note "Virtual address space"
11 | Logical (virtual) view of how a process is stored in memory.
12 |
13 | !!! note "Sparse address spaces"
14 | Virtual address spaces that include holes.
15 |
16 | ## 9.2 Demand Paging
17 |
18 | !!! note "Demand paging"
19 | A strategy to load pages only as they are needed.
20 |
21 | !!! note "Lazy swapper"
22 | A lazy swapper never swaps a page into memory unless that page will be needed.
23 |
24 | - swapper: entire processes
25 | - **pager**: individual pages of a process
26 |
27 | ### 9.2.1 Basic Concepts
28 |
29 | If the valid bit is set to "invalid", there are 2 possibilities:
30 |
31 | - the page is invalid
32 | - the page is valid but is currently on the dist.
33 |
34 | 
35 |
36 | !!! note "Pure demand paging"
37 | Never bring a page into memory until it is required.
38 |
39 | !!! note "Secondary memory"
40 | This memory holds those pages that are not present in main memory.
41 |
42 | ### 9.2.2 Performance of Demand Paging
43 |
44 | For most computer systems, the memory-access time, denoted $ma$, ranges from 10 to 200 nanoseconds.
45 |
46 | Let $p$ be the probability of a page fault ($0 \le p \le 1$). We would expect $p$ to be close to zero.
47 |
48 | $$\text{effective access time} = (1 - p) \times ma + p \times \text{page fault time}.$$
49 |
50 | ## 9.3 Copy-on-Write
51 |
52 | Many operating systems provide a pool of free pages for such requests.
53 |
54 | !!! note "Zero-fill-on-demand"
55 | Zero-fill-on-demand pages have been zeroed-out before being allocated, thus erasing the previous contents.
56 |
57 | !!! note "`vfork()` (virtual memory fork)"
58 | It operates differently from `fork()` with copy-on-write. With `vfork()`, the parent process is suspended, and the child process uses the address space of the parent.
59 |
60 | ## 9.4 Page Replacement
61 |
62 | ### 9.4.1 Basic Page Replacement
63 |
64 | 1. Find the location of the desired page on the disk.
65 | 2. Find a free frame:
66 |
67 | a. If there is a free frame, use it.
68 |
69 | b. If there is no free frame, use a page-replacement algorithm to select a **victim frame**.
70 |
71 | c. Write the victim frame to the disk; change the page and frame tables accordingly.
72 |
73 | 3. Read the desired page into the newly freed frame; change the page and frame tables.
74 | 4. Continue the user process from where the page fault occurred.
75 |
76 | 
77 |
78 | !!! note "Modify bit (dirty bit)"
79 | The modify bit for a page is set by the hardware whenever any byte in the page is written into.
80 |
81 | When we select a page for replacement.
82 |
83 | - If the modify bit is set, we must write the page to the disk.
84 | - If the modify bit is not set, we need not write the page to the disk.
85 |
86 | We must solve two major problems to implement demand paging:
87 |
88 | 1. frame-allocation algorithm: decide how many frames to allocate to each process.
89 | 2. page-replacement algorithm: when page replacement is required.
90 |
91 | !!! note "Reference string"
92 | The string of memory references.
93 |
94 | ### 9.4.2 FIFO Page Replacement
95 |
96 | 
97 |
98 | !!! note "Belady's anomaly"
99 | For some page-replacement algorithms, the page-fault rate may increase as the number of allocated frames increases.
100 |
101 | ### 9.4.3 Optimal Page Replacement
102 |
103 | !!! note "Optimal page-replacement algorithm"
104 | Replace the page that will not be used for the longest period of time, which will never suffer from Belady's anomaly.
105 |
106 | 
107 |
108 | ### 9.4.4 LRU Page Replacement
109 |
110 | The LRU policy is often used as a page-replacement algorithm and is considered to be good. The major problem is ***how*** to implement LRU replacement.
111 |
112 | - Counter
113 | - cons: overflow
114 | - Stack
115 |
116 | ### 9.4.5 LRU-Approximation Page Replacement
117 |
118 | #### 9.4.5.1 Additional-Reference-Bits Algorithm
119 |
120 | The operating system shifts the reference bit for each page into the high-order bit of its 8-bit byte, shifting the other bits right by 1 bit and discarding the low-order bit.
121 |
122 | These 8-bit shift registers contain the history of page use for the last eight time periods.
123 |
124 | e.g. A page with a history register value of 11000100 has been used more recently than one with a value of 01110111.
125 |
126 | #### 9.4.5.2 Second-Chance Algorithm
127 |
128 | 
129 |
130 | In the worst case, when all bits are set, the pointer cycles through the whole queue, giving each page a second chance. It clears all the reference bits before selecting the next page for replacement. ($\to$ FIFO)
131 |
132 | #### 9.4.5.3 Enhanced Second-Chance Algorithm
133 |
134 | ordered pair = (reference bit, modify bit)
135 |
136 | 1. (0, 0) neither recently used nor modified—best page to replace
137 | 2. (0, 1) not recently used but modified—not quite as good, because the page will need to be written out before replacement
138 | 3. (1, 0) recently used but clean—probably will be used again soon
139 | 4. (1, 1) recently used and modified—probably will be used again soon, and the page will be need to be written out to disk before it can be replaced
140 |
141 | ### 9.4.6 Counting-Based Page Replacement
142 |
143 | - least frequently used (LFU)
144 | - most frequently used (MFU)
145 |
146 | ### 9.4.7 Page-Buffering Algorithms
147 |
148 | Systems keep a pool of free frames
149 |
150 | 1. The desired page is read into a free frame from the pool before the victime is written out.
151 | 2. When the victim is later written out, its frame is added to the free-frame pool.
152 |
153 | There are two variations:
154 |
155 | 1. To maintain a list of modified pages.
156 | - Whenever the paging device is idle, a modified page is written to the dist and its modify bit is reset.
157 | 2. To keep a pool of free frames but to remember which page was in each frame.
158 | - No I/O is needed in this case $\to$ "Swapped-in" time is saved!
159 |
160 |
161 | ### 9.4.8 Applications and Page Replacement
--------------------------------------------------------------------------------
/docs/ML/03.md:
--------------------------------------------------------------------------------
1 | # Lecture 3: Gradient Descent
2 |
3 | ## Review: Gradient Descent
4 |
5 | 
6 |
7 | 在 Gradient Descent 中,我們想解決的是下列問題:
8 |
9 | $$
10 | \theta ^ { * } = \arg \min _ \theta L ( \theta )
11 | $$
12 |
13 | 其中,
14 |
15 | - $L$: loss function
16 | - $\theta$: parameters
17 |
18 | 假設 $\theta$ 有兩個參數 ${\theta_1, \theta_2}$,我們隨機選取 $\theta ^ { 0 } = \left[ \begin{array} { l } { \theta _ { 1 } ^ { 0 } } \\\\ { \theta _ { 2 } ^ { 0 } } \end{array} \right]$,所以 $\nabla L ( \theta ) = \left[ \begin{array} { l } { \partial L \left( \theta _ { 1 } \right) / \partial \theta _ { 1 } } \\\\ { \partial L \left( \theta _ { 2 } \right) / \partial \theta _ { 2 } } \end{array} \right]$
19 |
20 | $$
21 | \begin{aligned}
22 | \left[ \begin{array} { l } { \theta _ { 1 } ^ { 1 } } \\\\ { \theta _ { 2 } ^ { 1 } } \end{array} \right] = \left[ \begin{array} { c } { \theta _ { 1 } ^ { 0 } } \\\\ { \theta _ { 2 } ^ { 0 } } \end{array} \right] - \eta \left[ \begin{array} { l } { \partial L \left( \theta _ { 1 } ^ { 0 } \right) / \partial \theta _ { 1 } } \\\\ { \partial L \left( \theta _ { 2 } ^ { 0 } \right) / \partial \theta _ { 2 } } \end{array} \right] \to \theta ^ { 1 } = \theta ^ { 0 } - \eta \nabla L \left( \theta ^ { 0 } \right) \\\\
23 | \left[ \begin{array} { l } { \theta _ { 1 } ^ { 2 } } \\\\ { \theta _ { 2 } ^ { 2 } } \end{array} \right] = \left[ \begin{array} { c } { \theta _ { 1 } ^ { 1 } } \\\\ { \theta _ { 2 } ^ { 1 } } \end{array} \right] - \eta \left[ \begin{array} { l } { \partial L \left( \theta _ { 1 } ^ { 1 } \right) / \partial \theta _ { 1 } } \\\\ { \partial L \left( \theta _ { 2 } ^ { 1 } \right) / \partial \theta _ { 2 } } \end{array} \right] \to \theta ^ { 2 } = \theta ^ { 1 } - \eta \nabla L \left( \theta ^ { 1 } \right)
24 | \end{aligned}
25 | $$
26 |
27 | ## Tip 1: Tuning your learning rates
28 |
29 | 我們必需要小心的設我們的 learning rate $\eta$
30 |
31 | $$
32 | \theta ^i = \theta ^{i - 1} - \eta \nabla L \left( \theta ^{i - 1} \right)
33 | $$
34 |
35 | ### Adaptive Learning Rates
36 |
37 | 因為一開始 learning rate 更新的很慢,所以我們可以一開始先用較大的 learning rate 來加速,之後再逐漸下降 learning rate 來避免無法達到 loss 的 minimum,例如:$\eta^t = \eta / \sqrt{t + 1}$。
38 |
39 | #### Adagrad
40 |
41 | Adagrad 是一個常見的適性方法:Divide the learning rate of each parameter by the ***root mean square of its previous derivatives***
42 |
43 | - Vanilla Gradient Descent
44 |
45 | $$w^{t + 1} \leftarrow w^t - \eta^t g^t$$
46 |
47 | 其中,
48 |
49 | - $\eta ^ { t } = \frac \eta { \sqrt { t + 1 } }$
50 | - $g ^ { t } = \frac { \partial L \left( \theta ^ { t } \right) } { \partial w }$
51 |
52 | - Adagrad
53 |
54 | $$
55 | \begin{aligned}
56 | w^{t + 1} & \leftarrow w^t - \frac{\eta^t}{\sigma^t} g^t \\\\
57 | \equiv w^{t + 1} & \leftarrow w^t - \frac{\frac \eta { \sqrt { t + 1 } }}{\sqrt { \frac { 1 } { t + 1 } \sum _ { i = 0 } ^ { t } \left( g ^i \right) ^ { 2 } }} g^t \\\\
58 | \equiv w^{t + 1} & \leftarrow w^t - \frac{\eta}{\sqrt{\sum_{i = 0}^t (g^i)^2}} g^t \\\\
59 | \end{aligned}
60 | $$
61 |
62 | 其中,
63 |
64 | $\sigma^t$:***root mean square*** of the previous derivatives of parameter $w$
65 |
66 | $g^t$ 代表 first derivative,分母則是利用歷史的 first derivative 去估計 second derivative。
67 |
68 | ## Tip 2: Stochastic Gradient Descent
69 |
70 | - Gradient Descent
71 |
72 | Loss is the summation over all training examples:
73 |
74 | $$L = \sum_n \Big(\hat y^n - \Big(b + \sum w_i x_i^n \Big) \Big)^2$$
75 |
76 | 更新參數方式:
77 |
78 | $$\theta^i = \theta^{i - 1} - \eta \nabla L (\theta^{i - 1})$$
79 |
80 | - Stochastic Gradient Descent
81 |
82 | Pick an example $x^n$
83 |
84 | Loss for only one example:
85 |
86 | $$L = \Big(\hat y^n - \Big(b + \sum w_i x_i^n \Big) \Big)^2$$
87 |
88 | 更新參數方式:
89 |
90 | $$\theta ^i = \theta^{i - 1} - \eta \nabla L^n (\theta^{i - 1})$$
91 |
92 | Stochastic Gradient Descent 能夠加速訓練,一般 Gradient Descent 是在看到所有樣本(訓練數據)後,才計算出 $L$,再更新參數。而 Stochastic Gradient Descent 是每看到一次樣本 $n$ 就計算一次 $L^n$,並更新參數。
93 |
94 | ## Tip 3: Feature Scaling
95 |
96 | 例如我們的 model 為:$y = b + w_1x_1 + w_2x_2$
97 |
98 | 
99 |
100 | 將 features 從左圖 scaling 成右圖,能確保每一個 features 「貢獻」的數字,不會因為不同參數間的大小範圍而差太多。
101 |
102 | 
103 |
104 | 若不同參數的大小範圍差太多,那 loss function 等高線方向(負梯度、參數更新方向)不會指向 loss minimum。Feature scaling 讓不同參數的取相同區間範圍的值,變成正圓,更容易新參數。
105 |
106 | 做法如下,對 $x^1, x^2, x^3, \dots, x^r, \dots, x^R$ 共 $R$ 筆資料,每一個維度 $i$ 做標準化:
107 |
108 | 
109 |
110 | ## Theory
111 |
112 | 接下來要說說,為什麼 Gradient Descent 是可行的呢?
113 |
114 | 我們欲解的問題為:
115 |
116 | $$
117 | \theta ^ { * } = \arg \min _ { \theta } L ( \theta ) \quad \text { by gradient descent }
118 | $$
119 |
120 | 考慮以下陳述是否正確:
121 |
122 | > 每次更新參數,我們就得到 $\theta$ 使得 $L(\theta)$ 更小:
123 | >
124 | > $$L \left( \theta ^ { 0 } \right) > L \left( \theta ^ { 1 } \right) > L \left( \theta ^ { 2 } \right) > \cdots$$
125 |
126 | ### Formal Derivation
127 |
128 | 假設 $\theta$ 有兩個變數 $\{\theta_1, \theta_2\}$,我們如何輕易的找出給定一個點,離他最近最小的值?
129 |
130 | 
131 |
132 | ### Taylor Series
133 |
134 | #### Single-variable
135 |
136 | Let $h(x)$ be any function infinitely differentiable around $x = x_0$.
137 |
138 | $$
139 | \begin{aligned} { h } ( { x } ) & = \sum _ { k = 0 } ^ { \infty } \frac { { h } ^ { ( k ) } \left( x _ { 0 } \right) } { k ! } \left( x - x _ { 0 } \right) ^ { k } \\\\ & = h \left( x _ { 0 } \right) + h ^ { \prime } \left( x _ { 0 } \right) \left( x - x _ { 0 } \right) + \frac { h ^ { \prime \prime } \left( x _ { 0 } \right) } { 2 ! } \left( x - x _ { 0 } \right) ^ { 2 } + \cdots \end{aligned}
140 | $$
141 |
142 | 當 $x$ 接近 $x_0$ 時:$h(x) \approx h(x_0) + h'(x_0)(x - x_0)$
143 |
144 | #### Multi-variable
145 |
146 | Let $h(x)$ be any function infinitely differentiable around $x = x_0$ and $y = y_0$.
147 |
148 | $$
149 | h ( x , y ) = h \left( x _ { 0 } , y _ { 0 } \right) + \frac { \partial h \left( x _ { 0 } , y _ { 0 } \right) } { \partial x } \left( x - x _ { 0 } \right) + \frac { \partial h \left( x _ { 0 } , y _ { 0 } \right) } { \partial y } \left( y - y _ { 0 } \right)
150 | $$
151 |
152 | 當 $x$ 接近 $x_0$ 和 $y_0$ 時:$h ( x , y ) \approx h \left( x _ { 0 } , y _ { 0 } \right) + \frac { \partial h \left( x _ { 0 } , y _ { 0 } \right) } { \partial x } \left( x - x _ { 0 } \right) + \frac { \partial h \left( x _ { 0 } , y _ { 0 } \right) } { \partial y } \left( y - y _ { 0 } \right)$
153 |
154 | ### Back to Formal Derivation
155 |
156 | 
157 |
158 | Based on Taylor Series: If the red circle is ***small enough*** (i.e., $\theta_1$ and $\theta_2$ is close to $a$ and $b$), in the red circle
159 |
160 | $$
161 | \begin{aligned}
162 | { L } ( \theta ) & \approx { L } ( a , b ) + \frac { \partial { L } ( a , b ) } { \partial \theta _ { 1 } } \left( \theta _ { 1 } - a \right) + \frac { \partial { L } ( a , b ) } { \partial \theta _ { 2 } } \left( \theta _ { 2 } - b \right) \\\\
163 | & \approx s + u \left( \theta _ { 1 } - a \right) + v \left( \theta _ { 2 } - b \right)
164 | \end{aligned}
165 | $$
166 |
167 | 其中,
168 |
169 | - $s = L(a, b)$
170 | - $u = \frac { \partial { L } ( a , b ) } { \partial \theta _ { 1 } } , v = \frac { \partial { L } ( a , b ) } { \partial \theta _ { 2 } }$
171 |
172 | Goal: Find $\theta_1$ and $\theta_2$ in the *red circle* **minimizing** $L(\theta)$
173 |
174 | 在 red circle 內代表的是一個圓的方程式:
175 |
176 | $$
177 | \begin{aligned}
178 | \left( \theta _ { 1 } - a \right) ^ { 2 } + \left( \theta _ { 2 } - b \right) ^ { 2 } & \le d ^ { 2 } \\\\
179 | (\Delta \theta_1)^2 + (\Delta \theta_2)^2 & \le d^2
180 | \end{aligned}
181 | $$
182 |
183 | To minimize $L(\theta)$:
184 |
185 | $$
186 | \begin{aligned}
187 | \left[ \begin{array} { l } { \Delta \theta _ { 1 } } \\\\ { \Delta \theta _ { 2 } } \end{array} \right] & = - \eta \left[ \begin{array} { l } { u } \\\\ { v } \end{array} \right] \\\\
188 | \Rightarrow \left[ \begin{array} { l } { \theta _ { 1 } } \\\\ { \theta _ { 2 } } \end{array} \right] & = \left[ \begin{array} { l } { a } \\\\ { b } \end{array} \right] - \eta \left[ \begin{array} { l } { u } \\\\ { v } \end{array} \right] \\\\
189 | & = \left[ \begin{array} { l } { a } \\\\ { b } \end{array} \right] - \eta \left[ \begin{array} { c } { \frac { \partial { L } ( a , b ) } { \partial \theta _ { 1 } } } \\\\ { \frac { \partial { L } ( a , b ) } { \partial \theta _ { 2 } } } \end{array} \right]
190 | \end{aligned}
191 | $$
--------------------------------------------------------------------------------
/docs/PCP/1-4.md:
--------------------------------------------------------------------------------
1 | # 4. Locks
2 |
3 | ## Recursive mutex
4 |
5 | === "begin"
6 |
7 | ```cpp
8 | // Two shoppers adding garlic and potatoes to a shared notepad
9 | #include
10 | #include
11 |
12 | unsigned int garlic_count = 0;
13 | unsigned int potato_count = 0;
14 | std::mutex pencil;
15 |
16 | void add_garlic() {
17 | pencil.lock();
18 | ++garlic_count;
19 | pencil.unlock();
20 | }
21 |
22 | void add_potato() {
23 | pencil.lock();
24 | ++potato_count;
25 | pencil.unlock();
26 | }
27 |
28 | void shopper() {
29 | for (int i = 0; i < 10000; ++i) {
30 | add_garlic();
31 | add_potato();
32 | }
33 | }
34 |
35 | int main() {
36 | std::thread barron(shopper);
37 | std::thread olivia(shopper);
38 | barron.join();
39 | olivia.join();
40 | printf("We should buy %u garlic.\n", garlic_count);
41 | printf("We should buy %u potatoes.\n", potato_count);
42 | }
43 | ```
44 |
45 | === "end"
46 |
47 | ```cpp hl_lines="19"
48 | // Two shoppers adding garlic and potatoes to a shared notepad
49 |
50 | #include
51 | #include
52 |
53 | unsigned int garlic_count = 0;
54 | unsigned int potato_count = 0;
55 | std::recursive_mutex pencil;
56 |
57 | void add_garlic() {
58 | pencil.lock();
59 | ++garlic_count;
60 | pencil.unlock();
61 | }
62 |
63 | void add_potato() {
64 | pencil.lock();
65 | ++potato_count;
66 | add_garlic();
67 | pencil.unlock();
68 | }
69 |
70 | void shopper() {
71 | for (int i = 0; i < 10000; ++i) {
72 | add_garlic();
73 | add_potato();
74 | }
75 | }
76 |
77 | int main() {
78 | std::thread barron(shopper);
79 | std::thread olivia(shopper);
80 | barron.join();
81 | olivia.join();
82 | printf("We should buy %u garlic.\n", garlic_count);
83 | printf("We should buy %u potatoes.\n", potato_count);
84 | }
85 | ```
86 |
87 | ## Try lock
88 |
89 | === "begin"
90 |
91 | ```cpp
92 | // Two shoppers adding items to a shared notepad
93 | #include
94 | #include
95 | #include
96 |
97 | unsigned int items_on_notepad = 0;
98 | std::mutex pencil;
99 |
100 | void shopper(const char* name) {
101 | int items_to_add = 0;
102 | while (items_on_notepad <= 20) {
103 | if (items_to_add) { // add item(s) to shared items_on_notepad
104 | pencil.lock();
105 | items_on_notepad += items_to_add;
106 | printf("%s added %u item(s) to notepad.\n", name, items_to_add);
107 | items_to_add = 0;
108 | std::this_thread::sleep_for(
109 | std::chrono::milliseconds(300)); // time spent writing
110 | pencil.unlock();
111 | } else { // look for other things to buy
112 | std::this_thread::sleep_for(
113 | std::chrono::milliseconds(100)); // time spent searching
114 | ++items_to_add;
115 | printf("%s found something else to buy.\n", name);
116 | }
117 | }
118 | }
119 |
120 | int main() {
121 | auto start_time = std::chrono::steady_clock::now();
122 | std::thread barron(shopper, "Barron");
123 | std::thread olivia(shopper, "Olivia");
124 | barron.join();
125 | olivia.join();
126 | auto elapsed_time = std::chrono::duration_cast(
127 | std::chrono::steady_clock::now() - start_time)
128 | .count();
129 | printf("Elapsed Time: %.2f seconds\n", elapsed_time / 1000.0);
130 | }
131 | ```
132 |
133 | === "end"
134 |
135 | ```cpp hl_lines="13"
136 | // Two shoppers adding items to a shared notepad
137 | #include
138 | #include
139 | #include
140 |
141 | unsigned int items_on_notepad = 0;
142 | std::mutex pencil;
143 |
144 | void shopper(const char* name) {
145 | int items_to_add = 0;
146 | while (items_on_notepad <= 20) {
147 | if (items_to_add &&
148 | pencil.try_lock()) { // add item(s) to shared items_on_notepad
149 | items_on_notepad += items_to_add;
150 | printf("%s added %u item(s) to notepad.\n", name, items_to_add);
151 | items_to_add = 0;
152 | std::this_thread::sleep_for(
153 | std::chrono::milliseconds(300)); // time spent writing
154 | pencil.unlock();
155 | } else { // look for other things to buy
156 | std::this_thread::sleep_for(
157 | std::chrono::milliseconds(100)); // time spent searching
158 | ++items_to_add;
159 | printf("%s found something else to buy.\n", name);
160 | }
161 | }
162 | }
163 |
164 | int main() {
165 | auto start_time = std::chrono::steady_clock::now();
166 | std::thread barron(shopper, "Barron");
167 | std::thread olivia(shopper, "Olivia");
168 | barron.join();
169 | olivia.join();
170 | auto elapsed_time = std::chrono::duration_cast(
171 | std::chrono::steady_clock::now() - start_time)
172 | .count();
173 | printf("Elapsed Time: %.2f seconds\n", elapsed_time / 1000.0);
174 | }
175 | ```
176 |
177 | ## Shared mutext
178 |
179 | === "begin"
180 |
181 | ```cpp
182 | // Several users reading a calendar, but only a few users updating it
183 | #include
184 | #include
185 | #include
186 | #include
187 |
188 | char WEEKDAYS[7][10] = {"Sunday", "Monday", "Tuesday", "Wednesday",
189 | "Thursday", "Friday", "Saturday"};
190 | int today = 0;
191 | std::mutex marker;
192 |
193 | void calendar_reader(const int id) {
194 | for (int i = 0; i < 7; ++i) {
195 | marker.lock();
196 | printf("Reader-%d sees today is %s\n", id, WEEKDAYS[today]);
197 | std::this_thread::sleep_for(std::chrono::milliseconds(100));
198 | marker.unlock();
199 | }
200 | }
201 |
202 | void calendar_writer(const int id) {
203 | for (int i = 0; i < 7; ++i) {
204 | marker.lock();
205 | today = (today + 1) % 7;
206 | printf("Writer-%d updated date to %s\n", id, WEEKDAYS[today]);
207 | std::this_thread::sleep_for(std::chrono::milliseconds(100));
208 | marker.unlock();
209 | }
210 | }
211 |
212 | int main() {
213 | // create ten reader threads ...but only two writer threads
214 | std::array readers;
215 | for (unsigned int i = 0; i < readers.size(); ++i) {
216 | readers[i] = std::thread(calendar_reader, i);
217 | }
218 | std::array writers;
219 | for (unsigned int i = 0; i < writers.size(); ++i) {
220 | writers[i] = std::thread(calendar_writer, i);
221 | }
222 |
223 | // wait for readers and writers to finish
224 | for (unsigned int i = 0; i < readers.size(); ++i) {
225 | readers[i].join();
226 | }
227 | for (unsigned int i = 0; i < writers.size(); ++i) {
228 | writers[i].join();
229 | }
230 | }
231 | ```
232 |
233 | === "end"
234 |
235 | ```cpp hl_lines="5 11 15 18"
236 | // Several users reading a calendar, but only a few users updating it
237 | #include
238 | #include
239 | #include
240 | #include
241 | #include
242 |
243 | char WEEKDAYS[7][10] = {"Sunday", "Monday", "Tuesday", "Wednesday",
244 | "Thursday", "Friday", "Saturday"};
245 | int today = 0;
246 | std::shared_mutex marker;
247 |
248 | void calendar_reader(const int id) {
249 | for (int i = 0; i < 7; ++i) {
250 | marker.lock_shared();
251 | printf("Reader-%d sees today is %s\n", id, WEEKDAYS[today]);
252 | std::this_thread::sleep_for(std::chrono::milliseconds(100));
253 | marker.unlock_shared();
254 | }
255 | }
256 |
257 | void calendar_writer(const int id) {
258 | for (int i = 0; i < 7; ++i) {
259 | marker.lock();
260 | today = (today + 1) % 7;
261 | printf("Writer-%d updated date to %s\n", id, WEEKDAYS[today]);
262 | std::this_thread::sleep_for(std::chrono::milliseconds(100));
263 | marker.unlock();
264 | }
265 | }
266 |
267 | int main() {
268 | // create ten reader threads ...but only two writer threads
269 | std::array readers;
270 | for (unsigned int i = 0; i < readers.size(); ++i) {
271 | readers[i] = std::thread(calendar_reader, i);
272 | }
273 | std::array writers;
274 | for (unsigned int i = 0; i < writers.size(); ++i) {
275 | writers[i] = std::thread(calendar_writer, i);
276 | }
277 |
278 | // wait for readers and writers to finish
279 | for (unsigned int i = 0; i < readers.size(); ++i) {
280 | readers[i].join();
281 | }
282 | for (unsigned int i = 0; i < writers.size(); ++i) {
283 | writers[i].join();
284 | }
285 | }
286 | ```
287 |
--------------------------------------------------------------------------------
/docs/ML/05.md:
--------------------------------------------------------------------------------
1 | # Lecture 5: Logistic Regression
2 |
3 | ## Three Steps
4 |
5 | ### Step 1: Function Set
6 |
7 | 我們想找的是:$P_{w, b} (C_1 \mid x)$
8 |
9 | $$
10 | f_{w, b} =
11 | \begin{cases}
12 | P_{w, b} (C_1 \mid x) \ge 0.5 & \text{output: } C_1, \\\\
13 | \text{else} & \text{output: } C_2
14 | \end{cases}
15 | $$
16 |
17 | $$
18 | \begin{aligned}
19 | P_{w, b} (C_1 \mid x)
20 | & = \sigma(z) \\\\
21 | & = \sigma(w \cdot x + b)
22 | \end{aligned}
23 | $$
24 |
25 | 我們會有以下的 Function set(包含各種不同的 $w$ 和 $b$):
26 |
27 | $$f_{w, b}(x) = P_{w, b} (C_1 \mid x)$$
28 |
29 | 
30 |
31 | ### Step 2: Goodness of a Function
32 |
33 | 若 Training Data 為:
34 |
35 | $$
36 | \begin{array} { l l l l }
37 | { x ^ { 1 } } & { x ^ { 2 } } & { x ^ { 3 } } & \cdots & { x ^ { N } } \\\\
38 | { C _ { 1 } } & { C _ { 1 } } & { C _ { 2 } } & \cdots & { C _ { 1 } }
39 | \end{array}
40 | $$
41 |
42 | 接下來一樣要決定一個 function 的好壞,假設 data 是從 $f_{w, b}(x) = P_{w, b} (C_1 \mid x)$ 產生。
43 |
44 | Given a set of $w$ and $b$, what is its probability of generating the data?
45 |
46 | $$
47 | L ( w , b ) = f _ { w , b } \left( x ^ { 1 } \right) f _ { w , b } \left( x ^ { 2 } \right) \left( 1 - f _ { w , b } \left( x ^ { 3 } \right) \right) \cdots f _ { w , b } \left( x ^ { N } \right)
48 | $$
49 |
50 | The most likely $w^\*$ and $b^\*$ is the one with the largest $L(w, b)$:
51 |
52 | $$
53 | w ^ { * } , b ^ { * } = \arg \max _ { w , b } L ( w , b )
54 | $$
55 |
56 | 求上式等同於求:
57 |
58 | $$
59 | \begin{aligned}
60 | w ^ { * } , b ^ { * } & = \arg \min _ { w , b } - \ln L ( w , b ) \\\\
61 | & = \arg \min _ { w , b } - \ln f _ { w , b } \left( x ^ { 1 } \right) - \ln f _ { w , b } \left( x ^ { 2 } \right) - \ln \left( 1 - f _ { w , b } \left( x ^ { 3 } \right) \right) \cdots - \ln f _ { w , b } \left( x ^ { N } \right) \\\\
62 | & = \arg \min _ { w , b } \sum _ { n } - \left[ \hat { y } ^ { n } \ln f _ { w , b } \left( x ^ { n } \right) + \left( 1 - \hat { y } ^ { n } \right) \ln \left( 1 - f _ { w , b } \left( x ^ { n } \right) \right) \right]
63 | \end{aligned}
64 | $$
65 |
66 | 其中,
67 |
68 | - $\hat y^n$:$1$ for $C_1$, $0$ for $C_2$
69 |
70 | $\Sigma_n$ 項等同於求以下兩個分佈 $p$、$q$ 的 cross entropy
71 |
72 | - Distribution $p$:
73 |
74 | $$
75 | \begin{array} { l } { p ( x = 1 ) = \hat { y } ^ { n } } \\\\ { p ( x = 0 ) = 1 - \hat { y } ^ { n } } \end{array}
76 | $$
77 |
78 | - Distribution $q$:
79 |
80 | $$
81 | \begin{array} { l } {{ q } ( x = 1 ) = f \left( x ^ { n } \right) } \\\\ {{ q } ( x = 0 ) = 1 - f \left( x ^ { n } \right) } \end{array}
82 | $$
83 |
84 | $$
85 | H ( p , q ) = - \sum _ { x } p ( x ) \ln ( q ( x ) )
86 | $$
87 |
88 | 問題是:為什麼在 Logistic Regression 不用 rms 當 loss function 了?
89 |
90 | 答:做微分後,某些項次會為 $0$,導致參數更新過慢。
91 |
92 | ### Step 3: Find the best function
93 |
94 | 決定完 loss function 後,我們要從一個 set 中,找出 best function,先對 $w_i$ 進行偏微分:
95 |
96 | $$
97 | \frac { - \ln L ( w , b ) } { \partial w _ { i } } = \sum _ { n } - \left[ \hat { y } ^ { n } \frac { \ln f _ { w , b } \left( x ^ { n } \right) } { \partial w _ { i } } + \left( 1 - \hat { y } ^ { n } \right) \frac { \ln \left( 1 - f _ { w , b } \left( x ^ { n } \right) \right) } { \partial w _ { i } } \right] \tag{*}
98 | $$
99 |
100 | 其中,
101 |
102 | - $f _ { w , b } ( x ) = \sigma ( z ) = 1 / (1 + e^{-z})$
103 | - $z = w \cdot x + b = \sum _ { i } w _ { i } x _ { i } + b$
104 |
105 | $$
106 | \begin{aligned}
107 | \frac { \partial \ln f _ { w , b } ( x ) } { \partial w _ { i } } & = \frac { \partial \ln f _ { w , b } ( x ) } { \partial z } \frac { \partial z } { \partial w _ { i } } \\\\
108 | & = \frac { \partial \ln \sigma ( z ) } { \partial z } \cdot x_i \\\\
109 | & = \frac { 1 } { \sigma ( z ) } \frac { \partial \sigma ( z ) } { \partial z } \cdot x_i \\\\
110 | & = \frac{1}{\sigma(z)} \sigma(z) (1 - \sigma(z)) \cdot x_i \\\\
111 | & = (1 - \sigma(z)) \cdot x_i \\\\
112 | & = \left( 1 - f _ { w , b } \left( x \right) \right) \cdot x_i
113 | \end{aligned}
114 | $$
115 |
116 | $$
117 | \begin{aligned}
118 | \frac { \partial \ln \left( 1 - f _ { w , b } ( x ) \right) } { \partial w _ { i } } & = \frac { \partial \ln \left( 1 - f _ { w , b } ( x ) \right) } { \partial z } \frac { \partial z } { \partial w _ { i } } \\\\
119 | & = \frac { \partial \ln ( 1 - \sigma ( z ) ) } { \partial z } \cdot x_i \\\\
120 | & = - \frac { 1 } { 1 - \sigma ( z ) } \frac { \partial \sigma ( z ) } { \partial z } \cdot x_i \\\\
121 | & = - \frac{1}{1 - \sigma(z)} \sigma(z) (1 - \sigma(z)) \cdot x_i \\\\
122 | & = -\sigma(z) \cdot x_i \\\\
123 | & = -f _ { w , b } \left( x \right) \cdot x_i
124 | \end{aligned}
125 | $$
126 |
127 | 透過上面計算出來的結果,我們可以對 $*$ 式進行代換:
128 |
129 | $$
130 | \begin{aligned}
131 | \frac { - \ln L ( w , b ) } { \partial w _ { i } } & = \sum _ { n } - \left[ \hat { y } ^ { n } \frac { \ln f _ { w , b } \left( x ^ { n } \right) } { \partial w _ { i } } + \left( 1 - \hat { y } ^ { n } \right) \frac { \ln \left( 1 - f _ { w , b } \left( x ^ { n } \right) \right) } { \partial w _ { i } } \right] \\\\
132 | & = \sum _ { n } - \left[ \hat { y } ^ { n } \left( 1 - f _ { w , b } \left( x ^ { n } \right) \right) x _ { i } ^ { n } - \left( 1 - \hat { y } ^ { n } \right) f _ { w , b } \left( x ^ { n } \right) x _ { i } ^ { n } \right] \\\\
133 | & = \sum _ { n } - \left[ \hat { y } ^ { n } - \hat { y } ^ { n } f _ { w , b } \left( x ^ { n } \right) - f _ { w , b } \left( x ^ { n } \right) + \hat { y } ^ { n } f _ { W , b } \left( x ^ { n } \right) \right] x _ { i } ^ { n } \\\\
134 | & = \sum _ { n } - \left( \hat { y } ^ { n } - f _ { w , b } \left( x ^ { n } \right) \right) x _ { i } ^ { n }
135 | \end{aligned}
136 | $$
137 |
138 | 參數更新方式如下:
139 |
140 | $$
141 | w _ { i } \leftarrow w _ { i } - \eta \sum _ { n } - \left( \hat { y } ^ { n } - f _ { w , b } \left( x ^ { n } \right) \right) x _ { i } ^ { n }
142 | $$
143 |
144 | ## Logistic v.s. Linear
145 |
146 | 下面對 Logistic Regression 和 Linear Regression 做比較:
147 |
148 | | | Logistic Regression | Linear Regression |
149 | | :-----------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------: |
150 | | $f_{w, b}(x)$ | $\sigma (\sum_i w_ix_i + b)$ | $\sum_i w_ix_i + b$ |
151 | | Output | between $0$ and $1$ | any value |
152 | | Training data | $(x^n, \hat y^n)$ | $(x^n, \hat y^n)$ |
153 | | $\hat y^n$ | $1$ for class 1, $0$ for class 2 | a real number |
154 | | $L(f)$ | $\sum_n C(f(x^n), \hat y^n) = \sum_n - \left[ \hat { y } ^ { n } \ln f \left( x ^ { n } \right) + \left( 1 - \hat { y } ^ { n } \right) \ln \left( 1 - f \left( x ^ { n } \right) \right) \right]$ | $\frac 1 2 \sum_n (f(x^n) - \hat y^n)^2$ |
155 | | update method | $w_i \leftarrow w_i - \eta \sum_n - (\hat y^n - f_{w, b}(x^n)) x_i^n$ |
156 |
157 | ## Why not Logistic Regression with Square Error?
158 |
159 | 若我們的 loss function 改寫成 square error 版本:
160 |
161 | $$
162 | L ( f ) = \frac { 1 } { 2 } \sum _ { n } \left( f _ { w , b } \left( x ^ { n } \right) - \hat { y } ^ { n } \right) ^ { 2 }
163 | $$
164 |
165 | 在 Step 3: Find the best function 對 $w_i$ 做微分時:
166 |
167 | $$
168 | \begin{aligned}
169 | \frac { \partial \left( f _ { w , b } ( x ) - \hat { y } \right) ^ { 2 } } { \partial w _ { i } } & = 2 \left( f _ { w , b } ( x ) - \hat { y } \right) \frac { \partial f _ { w , b } ( x ) } { \partial z } \frac { \partial z } { \partial w _ { i } } \\\\
170 | & = 2 \left( f _ { w , b } ( x ) - \hat { y } \right) f _ { w , b } ( x ) \left( 1 - f _ { w , b } ( x ) \right) x _ { i }
171 | \end{aligned}
172 | $$
173 |
174 | 不論 $\hat y^n = 1$ 或 $\hat y^n = 0$,都可能導致 $\partial L / \partial w _ { i } = 0$,無法有效更新參數。
175 |
176 | ## Generative v.s. Discriminative
177 |
178 | - Benefit of generative model
179 | - With the assumption of probability distribution,
180 | less training data is needed
181 | - With the assumption of probability distribution, more robust to the noise
182 | - Priors and class-dependent probabilities can be estimated from different sources.
183 |
184 | ## Multi-class Classification
185 |
186 | 我們用 3 個 classes 來做例子:
187 |
188 | 
189 |
190 | ## Limitation of Logistic Regression
191 |
192 | 
193 |
194 | 給定上述的 4 個 features,我們無法有效的分類,因為沒有任何線性的切法是可以完美將紅點和藍點分開,因此我們有以下兩種方法:
195 |
196 | - Feature Transformation: Not always easy to find a good transformation
197 | - Cascading logistic regression models
--------------------------------------------------------------------------------
/docs/PCP/1-5.md:
--------------------------------------------------------------------------------
1 | # Liveness
2 |
3 | ## Deadlock
4 |
5 | === "begin"
6 |
7 | ```cpp
8 | // Two philosophers, thinking and eating sushi
9 | #include
10 | #include
11 |
12 | int sushi_count = 5000;
13 |
14 | void philosopher(std::mutex& first_chopstick, std::mutex& second_chopstick) {
15 | while (sushi_count > 0) {
16 | first_chopstick.lock();
17 | second_chopstick.lock();
18 | if (sushi_count) {
19 | sushi_count--;
20 | }
21 | second_chopstick.unlock();
22 | first_chopstick.unlock();
23 | }
24 | }
25 |
26 | int main() {
27 | std::mutex chopstick_a, chopstick_b;
28 | std::thread barron(philosopher, std::ref(chopstick_a), std::ref(chopstick_b));
29 | std::thread olivia(philosopher, std::ref(chopstick_b), std::ref(chopstick_a));
30 | barron.join();
31 | olivia.join();
32 | printf("The philosophers are done eating.\n");
33 | }
34 | ```
35 |
36 | === "end"
37 |
38 | ```cpp hl_lines="22"
39 | // Two philosophers, thinking and eating sushi
40 | #include
41 | #include
42 |
43 | int sushi_count = 5000;
44 |
45 | void philosopher(std::mutex& first_chopstick, std::mutex& second_chopstick) {
46 | while (sushi_count > 0) {
47 | first_chopstick.lock();
48 | second_chopstick.lock();
49 | if (sushi_count) {
50 | sushi_count--;
51 | }
52 | second_chopstick.unlock();
53 | first_chopstick.unlock();
54 | }
55 | }
56 |
57 | int main() {
58 | std::mutex chopstick_a, chopstick_b;
59 | std::thread barron(philosopher, std::ref(chopstick_a), std::ref(chopstick_b));
60 | std::thread olivia(philosopher, std::ref(chopstick_a), std::ref(chopstick_b));
61 | barron.join();
62 | olivia.join();
63 | printf("The philosophers are done eating.\n");
64 | }
65 | ```
66 |
67 | === "scoped_lock"
68 |
69 | ```cpp hl_lines="9 19"
70 | // Two philosophers, thinking and eating sushi
71 | #include
72 | #include
73 |
74 | int sushi_count = 5000;
75 |
76 | void philosopher(std::mutex& first_chopstick, std::mutex& second_chopstick) {
77 | while (sushi_count > 0) {
78 | std::scoped_lock lock(first_chopstick, second_chopstick);
79 | if (sushi_count) {
80 | sushi_count--;
81 | }
82 | }
83 | }
84 |
85 | int main() {
86 | std::mutex chopstick_a, chopstick_b;
87 | std::thread barron(philosopher, std::ref(chopstick_a), std::ref(chopstick_b));
88 | std::thread olivia(philosopher, std::ref(chopstick_b), std::ref(chopstick_a));
89 | barron.join();
90 | olivia.join();
91 | printf("The philosophers are done eating.\n");
92 | }
93 | ```
94 |
95 | ## Abandoned lock
96 |
97 | === "begin"
98 |
99 | ```cpp
100 | // Two philosophers, thinking and eating sushi
101 | #include
102 | #include
103 |
104 | int sushi_count = 5000;
105 |
106 | void philosopher(std::mutex& chopsticks) {
107 | while (sushi_count > 0) {
108 | chopsticks.lock();
109 | if (sushi_count) {
110 | --sushi_count;
111 | }
112 | chopsticks.unlock();
113 | }
114 | }
115 |
116 | int main() {
117 | std::mutex chopsticks;
118 | std::thread barron(philosopher, std::ref(chopsticks));
119 | std::thread olivia(philosopher, std::ref(chopsticks));
120 | barron.join();
121 | olivia.join();
122 | printf("The philosophers are done eating.\n");
123 | }
124 | ```
125 |
126 | === "end"
127 |
128 | ```cpp hl_lines="8 14"
129 | // Two philosophers, thinking and eating sushi#include
130 | #include
131 |
132 | int sushi_count = 5000;
133 |
134 | void philosopher(std::mutex& chopsticks) {
135 | while (sushi_count > 0) {
136 | std::scoped_lock lock(chopsticks);
137 | if (sushi_count) {
138 | --sushi_count;
139 | }
140 | if (sushi_count == 10) {
141 | printf("This philosopher has had enough!\n");
142 | break;
143 | }
144 | }
145 | }
146 |
147 | int main() {
148 | std::mutex chopsticks;
149 | std::thread barron(philosopher, std::ref(chopsticks));
150 | std::thread olivia(philosopher, std::ref(chopsticks));
151 | barron.join();
152 | olivia.join();
153 | printf("The philosophers are done eating.\n");
154 | }
155 | ```
156 |
157 | ## Starvation
158 |
159 | === "begin"
160 |
161 | ```cpp
162 | // Too many philosophers, thinking and eating sushi
163 | #include
164 | #include
165 | #include
166 |
167 | int sushi_count = 5000;
168 |
169 | void philosopher(std::mutex& chopsticks) {
170 | int sushi_eaten = 0;
171 | while (sushi_count > 0) {
172 | std::scoped_lock lock(chopsticks);
173 | if (sushi_count) {
174 | --sushi_count;
175 | ++sushi_eaten;
176 | }
177 | }
178 | printf("Philosopher %d ate %d.\n", std::this_thread::get_id(), sushi_eaten);
179 | }
180 |
181 | int main() {
182 | std::mutex chopsticks;
183 | std::array philosophers;
184 | for (size_t i = 0; i < philosophers.size(); ++i) {
185 | philosophers[i] = std::thread(philosopher, std::ref(chopsticks));
186 | }
187 | for (size_t i = 0; i < philosophers.size(); ++i) {
188 | philosophers[i].join();
189 | }
190 | printf("The philosophers are done eating.\n");
191 | }
192 | ```
193 |
194 | === "end"
195 |
196 | ```cpp hl_lines="22"
197 | // Too many philosophers, thinking and eating sushi
198 | #include
199 | #include
200 | #include
201 |
202 | int sushi_count = 5000;
203 |
204 | void philosopher(std::mutex& chopsticks) {
205 | int sushi_eaten = 0;
206 | while (sushi_count > 0) {
207 | std::scoped_lock lock(chopsticks);
208 | if (sushi_count) {
209 | --sushi_count;
210 | ++sushi_eaten;
211 | }
212 | }
213 | printf("Philosopher %d ate %d.\n", std::this_thread::get_id(), sushi_eaten);
214 | }
215 |
216 | int main() {
217 | std::mutex chopsticks;
218 | std::array philosophers;
219 | for (size_t i = 0; i < philosophers.size(); ++i) {
220 | philosophers[i] = std::thread(philosopher, std::ref(chopsticks));
221 | }
222 | for (size_t i = 0; i < philosophers.size(); ++i) {
223 | philosophers[i].join();
224 | }
225 | printf("The philosophers are done eating.\n");
226 | }
227 | ```
228 |
229 | ## Livelock
230 |
231 | === "begin"
232 |
233 | ```cpp
234 | // Exceptionally polite philosophers, thinking and eating sushi
235 | #include
236 | #include
237 |
238 | int sushi_count = 5000;
239 |
240 | void philosopher(std::mutex& first_chopstick, std::mutex& second_chopstick) {
241 | while (sushi_count > 0) {
242 | first_chopstick.lock();
243 | second_chopstick.lock();
244 | if (sushi_count) {
245 | --sushi_count;
246 | }
247 | second_chopstick.unlock();
248 | first_chopstick.unlock();
249 | }
250 | }
251 |
252 | int main() {
253 | std::mutex chopstick_a, chopstick_b;
254 | std::thread barron(philosopher, std::ref(chopstick_a), std::ref(chopstick_b));
255 | std::thread olivia(philosopher, std::ref(chopstick_b), std::ref(chopstick_a));
256 | barron.join();
257 | olivia.join();
258 | printf("The philosophers are done eating.\n");
259 | }
260 | ```
261 |
262 | === "end"
263 |
264 | ```cpp hl_lines="10 11"
265 | // Exceptionally polite philosophers, thinking and eating sushi
266 | #include
267 | #include
268 |
269 | int sushi_count = 5000;
270 |
271 | void philosopher(std::mutex& first_chopstick, std::mutex& second_chopstick) {
272 | while (sushi_count > 0) {
273 | first_chopstick.lock();
274 | if (!second_chopstick.try_lock()) {
275 | first_chopstick.unlock();
276 | } else {
277 | if (sushi_count) {
278 | --sushi_count;
279 | }
280 | second_chopstick.unlock();
281 | first_chopstick.unlock();
282 | }
283 | }
284 | }
285 |
286 | int main() {
287 | std::mutex chopstick_a, chopstick_b;
288 | std::thread barron(philosopher, std::ref(chopstick_a), std::ref(chopstick_b));
289 | std::thread olivia(philosopher, std::ref(chopstick_b), std::ref(chopstick_a));
290 | std::thread steve(philosopher, std::ref(chopstick_a), std::ref(chopstick_b));
291 | std::thread nikki(philosopher, std::ref(chopstick_b), std::ref(chopstick_a));
292 | barron.join();
293 | olivia.join();
294 | steve.join();
295 | nikki.join();
296 | printf("The philosophers are done eating.\n");
297 | }
298 | ```
299 |
300 | === "yield"
301 |
302 | ```cpp hl_lines="12 13 14"
303 | // Exceptionally polite philosophers, thinking and eating sushi
304 | #include
305 | #include
306 |
307 | int sushi_count = 5000;
308 |
309 | void philosopher(std::mutex& first_chopstick, std::mutex& second_chopstick) {
310 | while (sushi_count > 0) {
311 | first_chopstick.lock();
312 | if (!second_chopstick.try_lock()) {
313 | first_chopstick.unlock();
314 | // allow current thread to wait a moment (don't pick the first_chopstick
315 | // so fast, so other threads can have chances to pick the first_chopstick)
316 | std::this_thread::yield();
317 | } else {
318 | if (sushi_count) {
319 | --sushi_count;
320 | }
321 | second_chopstick.unlock();
322 | first_chopstick.unlock();
323 | }
324 | }
325 | }
326 |
327 | int main() {
328 | std::mutex chopstick_a, chopstick_b;
329 | std::thread barron(philosopher, std::ref(chopstick_a), std::ref(chopstick_b));
330 | std::thread olivia(philosopher, std::ref(chopstick_b), std::ref(chopstick_a));
331 | std::thread steve(philosopher, std::ref(chopstick_a), std::ref(chopstick_b));
332 | std::thread nikki(philosopher, std::ref(chopstick_b), std::ref(chopstick_a));
333 | barron.join();
334 | olivia.join();
335 | steve.join();
336 | nikki.join();
337 | printf("The philosophers are done eating.\n");
338 | }
339 | ```
340 |
--------------------------------------------------------------------------------
/docs/PCP/2-1.md:
--------------------------------------------------------------------------------
1 | # Synchronization
2 |
3 | ## Condition variable
4 |
5 | === "busy waiting"
6 |
7 | ```cpp
8 | // Two hungry threads, anxiously waiting for their turn to take soup
9 | #include
10 | #include
11 |
12 | int soup_servings = 10;
13 | std::mutex slow_cooker_lid;
14 |
15 | void hungry_person(int id) {
16 | int put_lid_back = 0;
17 | while (soup_servings > 0) {
18 | std::unique_lock lid_lock(
19 | slow_cooker_lid); // pick up the slow cooker lid
20 | if ((id == soup_servings % 2) &&
21 | (soup_servings > 0)) { // is it your turn to take soup?
22 | --soup_servings; // it's your turn; take some soup!
23 | } else {
24 | ++put_lid_back; // it's not your turn; put the lid back...
25 | }
26 | }
27 | printf("Person %d put the lid back %u times.\n", id, put_lid_back);
28 | }
29 |
30 | int main() {
31 | std::thread hungry_threads[2];
32 | for (int i = 0; i < 2; ++i) {
33 | hungry_threads[i] = std::thread(hungry_person, i);
34 | }
35 | for (auto& ht : hungry_threads) {
36 | ht.join();
37 | }
38 | }
39 | ```
40 |
41 | === "notify_one"
42 |
43 | ```cpp hl_lines="4 8 18 22 23"
44 | // Two hungry threads, anxiously waiting for their turn to take soup
45 | #include
46 | #include
47 | #include
48 |
49 | int soup_servings = 10;
50 | std::mutex slow_cooker_lid;
51 | std::condition_variable soup_taken;
52 |
53 | void hungry_person(int id) {
54 | int put_lid_back = 0;
55 | while (soup_servings > 0) {
56 | std::unique_lock lid_lock(
57 | slow_cooker_lid); // pick up the slow cooker lid
58 | while ((id != soup_servings % 2) &&
59 | (soup_servings > 0)) { // is it your turn to take soup?
60 | ++put_lid_back; // it's not your turn; put the lid back...
61 | soup_taken.wait(lid_lock); // ...and wait...
62 | }
63 | if (soup_servings > 0) {
64 | --soup_servings; // it's your turn; take some soup!
65 | lid_lock.unlock(); // put back the lid
66 | soup_taken.notify_one(); // notify another thread to take their turn
67 | }
68 | }
69 | printf("Person %d put the lid back %u times.\n", id, put_lid_back);
70 | }
71 |
72 | int main() {
73 | std::thread hungry_threads[2];
74 | for (int i = 0; i < 2; ++i) {
75 | hungry_threads[i] = std::thread(hungry_person, i);
76 | }
77 | for (auto& ht : hungry_threads) {
78 | ht.join();
79 | }
80 | }
81 | ```
82 |
83 | === "notify_all"
84 |
85 | ```cpp hl_lines="15 23 30 31"
86 | // Two hungry threads, anxiously waiting for their turn to take soup
87 | #include
88 | #include
89 | #include
90 |
91 | int soup_servings = 10;
92 | std::mutex slow_cooker_lid;
93 | std::condition_variable soup_taken;
94 |
95 | void hungry_person(int id) {
96 | int put_lid_back = 0;
97 | while (soup_servings > 0) {
98 | std::unique_lock lid_lock(
99 | slow_cooker_lid); // pick up the slow cooker lid
100 | while ((id != soup_servings % 5) &&
101 | (soup_servings > 0)) { // is it your turn to take soup?
102 | ++put_lid_back; // it's not your turn; put the lid back...
103 | soup_taken.wait(lid_lock); // ...and wait...
104 | }
105 | if (soup_servings > 0) {
106 | --soup_servings; // it's your turn; take some soup!
107 | lid_lock.unlock(); // put back the lid
108 | soup_taken.notify_all(); // notify another threads to take their turn
109 | }
110 | }
111 | printf("Person %d put the lid back %u times.\n", id, put_lid_back);
112 | }
113 |
114 | int main() {
115 | std::thread hungry_threads[5];
116 | for (int i = 0; i < 5; ++i) {
117 | hungry_threads[i] = std::thread(hungry_person, i);
118 | }
119 | for (auto& ht : hungry_threads) {
120 | ht.join();
121 | }
122 | }
123 | ```
124 |
125 | ## Producer-consumer
126 |
127 | === "segmentation fault"
128 |
129 | ```cpp
130 | // Threads serving and eating soup
131 | #include
132 | #include
133 |
134 | class ServingLine {
135 | public:
136 | void serve_soup(int i) {
137 | soup_queue.push(i);
138 | }
139 |
140 | int take_soup() {
141 | int bowl = soup_queue.front();
142 | soup_queue.pop();
143 | return bowl;
144 | }
145 |
146 | private:
147 | std::queue soup_queue;
148 | };
149 |
150 | ServingLine serving_line = ServingLine();
151 |
152 | void soup_producer() {
153 | for (int i = 0; i < 1000000; ++i) { // serve a 10,000 bowls of soup
154 | serving_line.serve_soup(1);
155 | }
156 | serving_line.serve_soup(-1); // indicate no more soup
157 | printf("Producer is done serving soup!\n");
158 | }
159 |
160 | void soup_consumer() {
161 | int soup_eaten = 0;
162 | while (true) {
163 | int bowl = serving_line.take_soup();
164 | if (bowl == -1) { // check for last bowl of soup
165 | printf("Consumer ate %d bowls of soup.\n", soup_eaten);
166 | serving_line.serve_soup(-1); // put back last bowl for other consumers to take
167 | return;
168 | } else {
169 | soup_eaten += bowl; // eat the soup
170 | }
171 | }
172 | }
173 |
174 | int main() {
175 | std::thread olivia(soup_producer);
176 | std::thread barron(soup_consumer);
177 | std::thread steve(soup_consumer);
178 | olivia.join();
179 | barron.join();
180 | steve.join();
181 | }
182 | ```
183 |
184 | === "conditional_variable"
185 |
186 | ```cpp hl_lines="2 3 10 12 13 17 18 19 20 28 29"
187 | // Threads serving and eating soup
188 | #include
189 | #include
190 | #include
191 | #include
192 |
193 | class ServingLine {
194 | public:
195 | void serve_soup(int i) {
196 | std::unique_lock ladle_lock(ladle);
197 | soup_queue.push(i);
198 | ladle_lock.unlock();
199 | soup_served.notify_one();
200 | }
201 |
202 | int take_soup() {
203 | std::unique_lock ladle_lock(ladle);
204 | while (soup_queue.empty()) {
205 | soup_served.wait(ladle_lock);
206 | }
207 | int bowl = soup_queue.front();
208 | soup_queue.pop();
209 | return bowl;
210 | }
211 |
212 | private:
213 | std::queue soup_queue;
214 | std::mutex ladle;
215 | std::condition_variable soup_served;
216 | };
217 |
218 | ServingLine serving_line = ServingLine();
219 |
220 | void soup_producer() {
221 | for (int i = 0; i < 10000; ++i) { // serve a 10,000 bowls of soup
222 | serving_line.serve_soup(1);
223 | }
224 | serving_line.serve_soup(-1); // indicate no more soup
225 | printf("Producer is done serving soup!\n");
226 | }
227 |
228 | void soup_consumer() {
229 | int soup_eaten = 0;
230 | while (true) {
231 | int bowl = serving_line.take_soup();
232 | if (bowl == -1) { // check for last bowl of soup
233 | printf("Consumer ate %d bowls of soup.\n", soup_eaten);
234 | serving_line.serve_soup(-1); // put back last bowl for other consumers to take
235 | return;
236 | } else {
237 | soup_eaten += bowl; // eat the soup
238 | }
239 | }
240 | }
241 |
242 | int main() {
243 | std::thread olivia(soup_producer);
244 | std::thread barron(soup_consumer);
245 | std::thread steve(soup_consumer);
246 | olivia.join();
247 | barron.join();
248 | steve.join();
249 | }
250 | ```
251 |
252 | ## Semaphore
253 |
254 | === "begin"
255 |
256 | ```cpp
257 | // Connecting cell phones to a charger
258 | #include
259 | #include
260 | #include
261 | #include
262 |
263 | class Semaphore {
264 | public:
265 | Semaphore(unsigned long init_count) { count_ = init_count; }
266 |
267 | void acquire() { // decrement the internal counter
268 | std::unique_lock lck(m_);
269 | while (!count_) {
270 | cv_.wait(lck);
271 | }
272 | --count_;
273 | }
274 |
275 | void release() { // increment the internal counter
276 | std::unique_lock lck(m_);
277 | ++count_;
278 | lck.unlock();
279 | cv_.notify_one();
280 | }
281 |
282 | private:
283 | std::mutex m_;
284 | std::condition_variable cv_;
285 | unsigned long count_;
286 | };
287 |
288 | Semaphore charger(4);
289 |
290 | void cell_phone(int id) {
291 | charger.acquire();
292 | printf("Phone %d is charging...\n", id);
293 | srand(id); // charge for "random" amount between 1-3 seconds
294 | std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 2000 + 1000));
295 | printf("Phone %d is DONE charging!\n", id);
296 | charger.release();
297 | }
298 |
299 | int main() {
300 | std::thread phones[10];
301 | for (int i = 0; i < 10; ++i) {
302 | phones[i] = std::thread(cell_phone, i);
303 | }
304 | for (auto& p : phones) {
305 | p.join();
306 | }
307 | }
308 | ```
309 |
310 | === "end"
311 |
312 | ```cpp hl_lines="32"
313 | // Connecting cell phones to a charger
314 | #include
315 | #include
316 | #include
317 | #include
318 |
319 | class Semaphore {
320 | public:
321 | Semaphore(unsigned long init_count) { count_ = init_count; }
322 |
323 | void acquire() { // decrement the internal counter
324 | std::unique_lock lck(m_);
325 | while (!count_) {
326 | cv_.wait(lck);
327 | }
328 | --count_;
329 | }
330 |
331 | void release() { // increment the internal counter
332 | std::unique_lock lck(m_);
333 | ++count_;
334 | lck.unlock();
335 | cv_.notify_one();
336 | }
337 |
338 | private:
339 | std::mutex m_;
340 | std::condition_variable cv_;
341 | unsigned long count_;
342 | };
343 |
344 | Semaphore charger(1);
345 |
346 | void cell_phone(int id) {
347 | charger.acquire();
348 | printf("Phone %d is charging...\n", id);
349 | srand(id); // charge for "random" amount between 1-3 seconds
350 | std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 2000 + 1000));
351 | printf("Phone %d is DONE charging!\n", id);
352 | charger.release();
353 | }
354 |
355 | int main() {
356 | std::thread phones[10];
357 | for (int i = 0; i < 10; ++i) {
358 | phones[i] = std::thread(cell_phone, i);
359 | }
360 | for (auto& p : phones) {
361 | p.join();
362 | }
363 | }
364 | ```
--------------------------------------------------------------------------------
/docs/OS/Chap04.md:
--------------------------------------------------------------------------------
1 | # Chapter 4 Threads
2 |
3 | ## 4.1 Overview
4 |
5 | !!! note "Thread–Lightweight process (LWP)"
6 | A basit unit of CPU utilization.
7 |
8 | A thread shares
9 |
10 | - code section
11 | - data section
12 | - OS resources (e.g. open files and signals)
13 |
14 | A thread have its own
15 |
16 | - thread ID
17 | - program counter
18 | - register set
19 | - stack
20 |
21 | 
22 |
23 | ### 4.1.1 Motivation
24 |
25 | It is generally more efficient to use one process that contains multiple threads since process creation is time consuming and resource intensive.
26 |
27 | 
28 |
29 | ### 4.1.2 Benefits
30 |
31 | The benefits of multithreaded:
32 |
33 | 1. **Responsiveness**
34 | 2. **Resource sharing**
35 | 3. **Economy**
36 | 4. **Scalability/Utilization**
37 |
38 | ## 4.2 Multicore Programming
39 |
40 | A more recent, similar trend in system design is to place multiple computing cores on a single chip.
41 |
42 | !!! note "Multicore or Multiprocessor systems"
43 | The cores appear across CPU chips or within CPU chips.
44 |
45 | Consider an application with 4 threads.
46 |
47 | - With a single core
48 |
49 | 
50 |
51 | - With multiple cores
52 |
53 | 
54 |
55 | | Parallelism | Concurrency |
56 | | :--: | :--: |
57 | | Perform more than one task simultaneously. | Allow all the tasks to make progress. |
58 |
59 | !!! note "Amdahl's Law"
60 | If $S$ is the portion cannot be accelerated by $N$ cores (serially).
61 |
62 | $$speedup \le \frac{1}{S + \frac{(1 - S)}{N}}$$
63 |
64 | ### 4.2.1 Programming Challenges
65 |
66 | 1. Identifying tasks: Dividing Activities
67 | 2. Balance (Equal value)
68 | 3. Data splitting
69 | 4. Data dependency
70 | 5. Testing and debugging
71 |
72 | ### 4.2.2 Types of Parallelism
73 |
74 | !!! note "Data parallelism"
75 | Distribute subsets of the same data across multiple computing cores.
76 |
77 | Each core performs the same operation.
78 |
79 | e.g.
80 |
81 | $$\sum_{i = 0}^{N - 1} arr[i] = \sum_{i = 0}^{N / 2 - 1} arr[i] (\text{thread } A) + \sum_{i = N / 2}^{N - 1} arr[i] (\text{thread } B).$$
82 |
83 | !!! note "Task parallelism"
84 | Distribute tasks (threads) across multiple computing cores.
85 |
86 | Each thread performs a unique operation.
87 |
88 | ## 4.3 Multithreading Models
89 |
90 | ### 4.3.1 Many-to-One Model
91 |
92 | - pros:
93 | - Efficiency
94 |
95 | - cons:
96 | - One blocking syscall blocks all
97 | - No parallelism for multiple processors
98 |
99 | e.g. Green threads (Solaris)
100 |
101 | 
102 |
103 | ### 4.3.2 One-to-One Model
104 |
105 | - pros:
106 | - One syscall blocks one thread
107 |
108 | - cons:
109 | - Overheads in creating a kernel thread
110 |
111 | e.g. Windows NT/2000/XP, Linux, OS/2, Solaris 9
112 |
113 | 
114 |
115 | ### 4.3.3 Many-to-Many Model
116 |
117 | - pros:
118 | - A combination of parallelism and efficiency
119 |
120 | e.g. Solaris 2 & 9, IRIX, HP-UX, Tru64 UNIX
121 |
122 | 
123 | 
124 |
125 | ## 4.4 Thread Libraries
126 |
127 | - User level
128 | - Kernel level
129 |
130 | Three main thread libraries:
131 |
132 | - POSIX Pthreads: User or kernel level
133 | - Windows: Kernel level
134 | - Java: Level depending on the thread library on the host system.
135 |
136 | Two general strategie for creating threads:
137 |
138 | - Asynchronous threading: parent doesn't know children.
139 | - Synchronous threading: parent must wait for all of its children. (***fork-join***)
140 |
141 | All of the following examples use synchronous threading.
142 |
143 | ### 4.4.1 Pthreads
144 |
145 | !!! note "Pthreads"
146 | The POSIX standard (IEEE 1003.1c) defining an API for thread creation and synchronization. This is a ***specification*** for thread behavior, not and ***implementation***.
147 |
148 | ### 4.4.2 Windows Threads
149 |
150 | ### 4.4.3 Java Threads
151 |
152 | Creating a `Thread` object does not specifically create the new thread. $\to$ `start()` does!
153 |
154 | 1. It allocates memory and initializes a new thread in the JVM.
155 | 2. It calls the `run()` method, making the thread eligible to be run by the JVM.
156 | (Note again that we never call the `run()` method directly. Rather, we call the `start()` method, and it calls the `run()` method on our behalf)
157 |
158 | ## 4.5 Implicit Threading
159 |
160 | ### 4.5.1 Thread Pools
161 |
162 | The issue of multithreaded server:
163 |
164 | - Time to create the thread
165 | - Concurrency
166 |
167 | !!! note "Thread pool"
168 | Create a number of threads at process startup and place them into a pool, where they sit and wait for work.
169 |
170 | The benefits of thread pools:
171 |
172 | 1. Speed
173 | 2. Limited # of threads, which is good for OS.
174 | 3. Seperating the task of creating tasks allows us to use different strategies.
175 | 4. Dynamic or static thread pools
176 |
177 | e.g. `QueueUserWorkItem()`, `java.util.concurrent`.
178 |
179 | ### 4.5.2 OpenMP
180 |
181 | !!! note "OpenMP"
182 | A set of compiler directivese and APIs to support parallel programming in shared memory environment.
183 |
184 | Threads with divided workload are created automatically based on # of cores or a set bound.
185 |
186 | !!! note "Parallel regions"
187 | Blocks of code that may run in parallel.
188 |
189 | When OpenMP encounters
190 |
191 | ```c
192 | #pragma omp parallel
193 | ```
194 |
195 | it creates as many threads are there are processing cores in the system.
196 |
197 | e.g.
198 |
199 | ```c
200 | #pragma omp parallel for
201 | for (i = 0; i < N; ++i)
202 | c[i] = a[i] + b[i];
203 | ```
204 |
205 | ### 4.5.3 Grand Central Dispatch
206 |
207 | A ma
208 | sOS/iOS combination of extensions to the C.
209 |
210 | Like OpenMP, GCD manges most of the details of threading.
211 |
212 | ```c
213 | ^{ printf("I am a block."); }
214 | ```
215 |
216 | GCD schedules blocks for run-time execution by placing them on a **dispatch queue**.
217 |
218 | - Serial (FIFO)
219 | - Concurrent (FIFO)
220 | - low
221 | - default
222 | - high
223 |
224 | ```c
225 | dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
226 | dispatch_async(queue, ^{ printf("I am a block.") });
227 | ```
228 |
229 | ### 4.5.4 Other Approaches
230 |
231 | e.g. Intel's Threading Building Blocks (TBB), `java.util.concurrent`.
232 |
233 | ## 4.6 Threading Issues
234 |
235 | ### 4.6.1 The `fork()` and `exec()` System Calls
236 |
237 | !!! info "`fork()` issue"
238 |
239 | - Duplicate all threads?
240 | - Is the new process single-threaded?
241 |
242 |
243 | !!! info "`exec()` issue"
244 | If a thread invokese the `exec()`, the program specified in the parameter to `exec()` will replace the entire process—including all threads. Thus if `exec()` is called immediately after forking, then duplicating all threads is unnecessary.
245 |
246 | ### 4.6.2 Signal Handling
247 |
248 | All signals follows:
249 |
250 | 1. A signal is generated by the occurrence of a particular event.
251 | 2. The signal is delivered to a process.
252 | 3. Once delivered, the signal must be handled.
253 |
254 | Two types of signals:
255 |
256 | - Synchronous signal: delivered to the same process that performed the operation causing the signal.
257 | - illegal memory access
258 | - division by 0
259 |
260 | - Asynchronous signal
261 | - generated by an external process (e.g. ^C)
262 | - having a timer expire
263 |
264 | A signal may be handled by:
265 |
266 | 1. A default signal handler
267 | 2. A user-defined signal handler
268 |
269 | Signal delivering:
270 |
271 | 1. Deliver the signal to the thread to which the signal applies. (e.g. division by 0)
272 | 2. Deliver the signal to every thread in the process. (e.g. ^C)
273 | 3. Deliver the signal to certain threads in the process.
274 | 4. Assign a specific thread to receive all signals for the process.
275 |
276 | Functions/Methods for delivering a signal:
277 |
278 | - UNIX:
279 |
280 | ```c
281 | kill(pid_t pid, int signal)
282 | ```
283 |
284 | - POSIX:
285 |
286 | ```c
287 | pthread_kill(pthread_t tid, int signal)
288 | ```
289 |
290 | - Windows:
291 |
292 | - Asynchronous Procedure Calls (APCs)
293 |
294 | ### 4.6.3 Thread Cancellation
295 |
296 | !!! note "Target thread"
297 | A thread that is to be canceled.
298 |
299 | Cancellation of a target thread may occur in two different scenarios:
300 |
301 | 1. **Asynchronous cancellation**. One thread immediately terminates the target thread.
302 | 2. **Deferred cancellation**. The target thread periodically checks whether it should terminate, allowing it an opportunity to terminate itself in an orderly fashion.
303 |
304 | !!! info ""
305 | Canceling a thread asynchronously may not free a necessary system-wide resource.
306 |
307 | ```c
308 | pthread_tid;
309 |
310 | /* create the thread */
311 | pthread_create(&tid, 0, worker, NULL);
312 | ...
313 | /* cancel the thread */
314 | pthread_cancel(tid);
315 | ```
316 |
317 | Pthreads supports three cancellation modes:
318 |
319 | | Mode | State | Type |
320 | | :--: | :--: | :--: |
321 | | Off | Disabled | – |
322 | | Deferred | Enabled | Deferred |
323 | | Asynchronous | Enabled | Asynchronous |
324 |
325 | !!! note "Cancellation point"
326 | Cancellation occurs only when a thread reaches a cancellation point.
327 |
328 | !!! note "Cleanup handler"
329 | If a cancellation request is found to be pending, this function allows any resources a thread may have acquired to be released before the thread is terminated.
330 |
331 | e.g. deferred cancellation:
332 |
333 | ```c
334 | while (1) {
335 | /* do some work for awhile */
336 |
337 | /* check if there is a cancellation request */
338 | pthread_testcancel();
339 | }
340 | ```
341 |
342 | ### 4.6.4 Thread-Local Storage
343 |
344 | !!! note "Thread-Local Storage (TLS)"
345 | Each thread might need its own copy of certain data.
346 |
347 | TLS is similar to `static` data.
348 |
349 | | TLS | Local variables |
350 | | :--: | :--: |
351 | | visible across function invocations | visible only during a single function invocation |
352 |
353 | ### 4.6.5 Scheduler Activations
354 |
355 | !!! note "Lightweight process (LWP)"
356 | A virtual processor (kernel threads) on which the application can schedule a user thread to run. (many-to-many or two-level)
357 |
358 | 
359 |
360 | !!! note "Scheduler activation"
361 | The kernel provides an application with a set of virtual processors (LWPs), and the application can schedule user threads onto an available virtual processor.
362 |
363 | !!! note "Upcall"
364 | The kernel must inform an application about certain events.
365 |
366 | ## 4.7 Operating-System Examples
367 |
368 | ### 4.7.1 Windows Threads
369 |
370 | The general components of a thread include:
371 |
372 | - A thread ID uniquely identifying the thread
373 | - A register set representing the status of the processor
374 | - A user stack, employed when the thread is running in user mode
375 | - A kernel stack, employed when the thread is running in kernel mode
376 | - A private storage area used by various run-time libraries and dynamic link libraries (DLLs)
377 |
378 | **Context** (register set, stacks, and private sotrage area) of the thread:
379 |
380 | - Kernel space
381 | - ETHREAD—executive thread block:
382 | - a pointer to the process
383 | - the address of the routine
384 | - a pointer to the corresponding KTHREAD
385 |
386 | - KTHREAD—kernel thread block
387 | - scheduling/synchronization information
388 | - the kernel stack
389 | - a pointer to TEB
390 |
391 | - User space
392 | - TEB—thread environment block
393 | - the thread ID
394 | - a user-mode stack
395 | - an array for TLS
396 |
397 | 
398 |
399 | ### 4.7.2 Linux Threads
400 |
401 | `clone()` vs `fork()`
402 |
403 | - term ***task***—rather than ***process*** or ***thread***
404 | - Several per-process data structures
405 | - ***points*** to the same data structures for open files, signal handling, virtual memory, etc.
--------------------------------------------------------------------------------
/docs/OS/Chap06.md:
--------------------------------------------------------------------------------
1 | # Chapter 6 CPU Scheduling
2 |
3 | ## 6.1 Basic Concepts
4 |
5 | The objective of multiprogramming is to have some process running at all times, to maximize CPU utilization.
6 |
7 | A process is executed until it must wait, typically for the completion of some I/O request.
8 |
9 | ### 6.1.1 CPU–I/O Burst Cycle
10 |
11 | Process execution = cycle of CPU + I/O wait.
12 |
13 | 
14 |
15 | ### 6.1.2 CPU Scheduler
16 |
17 | **Short-term scheduler** (CPU scheduler): select process in the ready queue.
18 |
19 | ### 6.1.3 Preemptive Scheduling
20 |
21 | CPU-scheduling decisions when a process:
22 |
23 | 1. (nonpreemptive) Switches from the running state $\to$ the waiting state (e.g. I/O request, `wait()` for child)
24 | 2. (preemptive) Switches from the running state $\to$ the ready state (e.g. interrupt)
25 | 3. (preemptive) Switches from the waiting state $\to$ the ready state (e.g. completion of I/O)
26 | 4. (nonpreemptive) Terminates
27 |
28 | ### 6.1.4 Dispatcher
29 |
30 | !!! note "Dispatcher"
31 | The module that gives control of the CPU to *the process selected by the short-term scheduler*. It should be fast.
32 |
33 | - Switching context
34 | - Switching to user mode
35 | - Jumping to the proper location in the user program to restart that program
36 |
37 | !!! note "Dispatch latency"
38 | The time it takes for the dispatcher to stop one process and start another running.
39 |
40 | Stop a process $\leftrightarrow$ Start a process
41 |
42 | ## 6.2 Scheduling Criteria
43 |
44 | - **CPU utilization**
45 | - **Throughput**
46 | - **Turnaround time**: $\text{Completion Time} - \text{Start Time}$.
47 | - **Waiting time**: The sum of the periods spent waiting in the ready queue.
48 | - **Response time**
49 |
50 | ## 6.3 Scheduling Algorithms
51 |
52 | ### 6.3-1 First-Come, First-Served Scheduling
53 |
54 | - The process which requests the CPU first is allocated the CPU.
55 | - Properties:
56 | - Nonpreemptive FCFS.
57 | - CPU might be hold for an extended period.
58 |
59 | - Critical problem: Convoy effect!
60 |
61 | - Example:
62 |
63 | - Given processes:
64 |
65 | | Process | Busrt Time |
66 | | :-----: | :--------: |
67 | | $P_1$ | 24 |
68 | | $P_2$ | 3 |
69 | | $P_3$ | 3 |
70 |
71 | - Consider order: $P_1 \to P_2 \to P_3$:
72 |
73 | - Gantt chart:
74 |
75 | 
76 |
77 | - Average waiting time = (0 + 24 + 27) / 3 = 17 ms.
78 |
79 | - Consider order: $P_2 \to P_3 \to P_1$:
80 |
81 | - Gantt chart:
82 |
83 | 
84 |
85 | - Average waiting time = (0 + 3 + 6) / 3 = 9 ms.
86 |
87 | !!! note "Convoy effect"
88 | All the other processes wait for the one big process to get off the CPU.
89 |
90 | ### 6.3.2 Shortest-Job-First Scheduling
91 |
92 | - Properties:
93 | - Nonpreemptive SJF
94 | - ***Shortest-next-CPU-burst first***
95 |
96 | - Problem: Measure the future!
97 |
98 | - Example 1:
99 |
100 | - Given processes:
101 |
102 | | Process | Burst Time |
103 | | :-----: | :--------: |
104 | | $P_1$ | 6 |
105 | | $P_2$ | 8 |
106 | | $P_3$ | 7 |
107 | | $P_4$ | 3 |
108 |
109 | - By SJF scheduling:
110 |
111 | - Gantt chart:
112 |
113 | 
114 |
115 | - Average waiting time = (3 + 16 + 9 + 0) / 4 = 7 ms.
116 |
117 | !!! info ""
118 | SJF is used frequently in long-term (job) scheduling, but it cannot be implemented at the level of short-term CPU scheduling.
119 |
120 | !!! note "Exponential average"
121 | Let $t_n$ be time of $n$th CPU burst, and $\tau_{n + 1}$ be the next CPU burst.
122 |
123 | $$
124 | \begin{aligned}
125 | \tau_{n + 1} & = \alpha t_n + (1 - \alpha)\tau_n, \quad 0 \le \alpha \le 1. \\\\
126 | & = \alpha t_n + (1 - \alpha)\alpha t_{n - 1} + \cdots + (1 - \alpha)^j \alpha t_{n - j} + \cdots + (1 - \alpha)^{n + 1}\tau_0.
127 | \end{aligned}
128 | $$
129 |
130 | - Example 2:
131 |
132 | - Given processes:
133 |
134 | | Process | Arrival Time | Burst Time |
135 | | :-----: | :----------: | :--------: |
136 | | $P_1$ | 0 | 8 |
137 | | $P_2$ | 1 | 4 |
138 | | $P_3$ | 2 | 9 |
139 | | $P_4$ | 3 | 5 |
140 |
141 | By preemptive SJF scheduling:
142 |
143 | - Gantt chart:
144 |
145 | 
146 |
147 | - Average waiting time = [(10 - 1) + (1 - 1) + (17 - 2) + (5 - 3)] / 4 = 26 / 4 = 6.5 ms.
148 |
149 | ### 6.3.3 Priority Scheduling
150 |
151 | - Properties:
152 | - CPU is assigned to the process with the highest priority — A framework for various scheduling algorithms:
153 | - FCFS: Equal-priority with tie-breaking
154 | - SJF: Priority = 1 / next CPU burst length
155 |
156 | - Example:
157 |
158 | - Given processes:
159 |
160 | | Process | Burst Time | Priority |
161 | | :-----: | :--------: | :------: |
162 | | $P_1$ | 10 | 3 |
163 | | $P_2$ | 1 | 1 |
164 | | $P_3$ | 2 | 4 |
165 | | $P_4$ | 1 | 5 |
166 | | $P_5$ | 5 | 2 |
167 |
168 | - By preemptive SJF scheduling:
169 |
170 | - Gantt chart:
171 |
172 | 
173 |
174 | - Average waiting time = (6 + 0 + 16 + 18 + 1) / 5 = 8.2 ms.
175 |
176 | !!! info "Problem with priority scheduling"
177 | - indefinite blocking: low-priority processes could starve to death!
178 | - starvation
179 |
180 | !!! note "Aging"
181 | Aging gradually increase the priority of processes that wait in the system for a long time.
182 |
183 | ### 6.3.4 Round-Robin Scheduling
184 |
185 | - RR is similar to FCFS except that preemption is added to switch between processes.
186 | - Goal: fairness, time sharing.
187 |
188 | - Example:
189 |
190 | - Given processes with quantum = 4ms:
191 |
192 | | Process | Burst Time |
193 | | :-----: | :--------: |
194 | | $P_1$ | 24 |
195 | | $P_2$ | 3 |
196 | | $P_3$ | 3 |
197 |
198 | - Gantt chart:
199 |
200 | 
201 |
202 | - Average waiting time = [(10 - 4) + 4 + 7] / 3 = 5.66 ms.
203 |
204 | !!! info ""
205 | Although the time quantum should be large compared with the context switch time, it should not be too large.
206 |
207 | ### 6.3.5 Multilevel Queue Scheduling
208 |
209 | - Intra-queue scheduling
210 | - Independent choice of scheduling algorithms
211 |
212 | - Inter-queue scheduling
213 | - Fixed-priority preemptive scheduling
214 | - e.g., foreground queues always have absolute priority over the background queues.
215 | - Time slice between queues
216 | - e.g., 80% CPU is given to foreground processes, and 20% CPU is given to background processes.
217 |
218 | Each queue has absolute priority over lower-priority queues.
219 |
220 | If an interactive editing process entered the ready queue while a batch process was running, the batch process would be preempted.
221 |
222 | 
223 |
224 | ### 6.3.6 Multilevel Feedback Queue Scheduling
225 |
226 | !!! info ""
227 | Multilevel feedback queue allows a process to move between queues.
228 |
229 | A multilevel feedback queue is defined by:
230 |
231 | - \#queues
232 | - The scheduling algorithm for each queue
233 | - The method used to determine when to
234 | - upgrade a process to a higher priority queue
235 | - demote a process to a lower priority queue
236 |
237 | - The method used to determine which queue a process will enter when that process needs service
238 |
239 | ## 6.4 Thread Scheduling
240 |
241 | ### 6.4.1 Contention Scope
242 |
243 | !!! note "Process Contention Scope (PCS)"
244 | On systems implementing the [many-to-one](./Chap04/#431-many-to-one-model) and [many-to-many](./Chap04/#433-many-to-many-model) models, the thread library schedules user-level threads to run on an available LWP, since competition for the CPU takes place among threads belonging to the same process.
245 |
246 | It is important to note that PCS will typically preempt the thread currently running in favor of a higher-priority thread
247 |
248 | !!! note "System Contention Scope (SCS)"
249 | Competition for the CPU with SCS scheduling takes place among all threads in the system. Systems using the [one-to-one](./Chap04/#432-one-to-one-model) model.
250 |
251 | ### 6.4.2 Pthread Scheduling
252 |
253 | - PCS: `PTHREAD_SCOPE_PROCESS`
254 | - SCS: `PTHREAD_SCOPE_SYSTEM`
255 |
256 | 2 methods:
257 |
258 | - `pthread_attr_setscope(pthread attr_t *attr, int scope)`
259 | - `pthread_attr_getscope(pthread attr_t *attr, int *scope)`
260 |
261 | ## 6.5 Multiple-Processor Scheduling
262 |
263 | ### 6.5.1 Approaches to Multiple-Processor Scheduling
264 |
265 | - **Asymmetric multiprocessing**: only *the master server* process accesses the system data structures, reducing the need for data sharing.
266 | - **Symmetric multiprocessing (SMP)**: each processor is self-scheduling.
267 |
268 | ### 6.5.2 Processor Affinity
269 |
270 | !!! note "Processor Affinity"
271 | A process has an affinity for the processor on which it is currently running.
272 |
273 | - **Soft affinity**
274 | - **Hard affinity** (e.g. Linux: `sched_setaffinity()`)
275 |
276 | !!! note "Non-Uniform Memory Access (NUMA)"
277 | A CPU has faster access to some parts of main memory than to other parts.
278 |
279 | 
280 |
281 | ### 6.5.3 Load Balancing
282 |
283 | On systems with a common run queue, load balancing is often unnecessary, because once a processor becomes idle, it immediately extracts a runnable process from the common run queue.
284 |
285 | - **Push migration**: pushing processes from overloaded to less-busy processors.
286 | - **Pull migration**: pulling a waiting task from a busy processor.
287 |
288 | ### 6.5.4 Multicore Processors
289 |
290 | SMP systems that use multicore processors are faster and consume less power than systems in which each processor has its own physical chip.
291 |
292 | There are two ways to multithread a processing core:
293 |
294 | - **Coarse-grained**: a thread executes on a processor until a long-latency event such as a memory stall occurs.
295 | - **Fine-grained (interleaved)**: switches between threads at a much finer level of granularity
296 |
297 | ## 6.6 Real-Time CPU Scheduling
298 |
299 | - **Soft real-time systems**
300 | - **Hard real-time systems**
301 |
302 | ### 6.6.1 Minimizing Latency
303 |
304 | !!! note "Event latency"
305 | The amount of time that elapses from when an event occurs to when it is serviced.
306 |
307 | There are 2 types:
308 |
309 | 1. Interrupt latency
310 | 2. Dispatch latency
311 |
312 | !!! note "Interrupt latency"
313 | The period of time from the arrival of an interrupt at the CPU to the start of the interrupt service routine (ISR) that services the interrupt.
314 |
315 | !!! note "Dispatch latency"
316 | The amount of time required for the scheduling dispatcher to stop one process and start another.
317 |
318 | ### 6.6.2 Priority-Based Scheduling
319 |
320 | The processes are considered **periodic**. That is, they require the CPU at constant intervals (periods). ($t$: fixed processing time, $d$: deadline, and $p$: period.)
321 |
322 | $$0 \le t \le d \le p.$$
323 |
324 | $$rate = 1 / p.$$
325 |
326 | **Admission-control**:
327 |
328 | 1. Admits the process.
329 | 2. Rejects the request.
330 |
331 | ### 6.6.3 Rate-Monotonic Scheduling
332 |
333 | - Example 1:
334 |
335 | - Given processes: (the deadline for each process requires that it complete its CPU burst by the start of its next period.)
336 |
337 | | Process | Period | ProcTime |
338 | | :-----: | :---------: | :--------: |
339 | | $P_1$ | $p_1 = 50$ | $t_1 = 20$ |
340 | | $P_2$ | $p_2 = 100$ | $t_2 = 35$ |
341 |
342 | 
343 |
344 | - Example 2:
345 |
346 | - Given processes:
347 |
348 | | Process | Period | ProcTime |
349 | | :-----: | :--------: | :--------: |
350 | | $P_1$ | $p_1 = 50$ | $t_1 = 25$ |
351 | | $P_2$ | $p_2 = 80$ | $t_2 = 35$ |
352 |
353 | 
354 |
355 | ### 6.6.4 Earliest-Deadline-First Scheduling
356 |
357 | 
358 |
359 | ### 6.6.5 Proportional Share Scheduling
360 |
361 | Proportional share schedulers operate by allocating $T$ shares among all applications. An application can receive $N$ shares of time.
362 |
363 | ### 6.6.6 POSIX Real-Time Scheduling
364 |
365 | - POSIX.1b — Extensions for real-time computing
366 | - `SCHED_FIFO`
367 | - `SCHED_RR`
368 | - `SCHED_OTHER`
369 |
370 | - API
371 | - `pthread_attr_getsched_policy(pthread_attr_t *attr, int *policy)`
372 | - `pthread_attr_setsched_policy(pthread_attr_t *attr, int *policy)`
373 |
374 | ## 6.7 Operating-System Examples
375 |
376 | ### 6.7.1 Example: Linux Scheduling
377 |
378 | ### 6.7.2 Example: Windows Scheduling
379 |
380 | ### 6.7.3 Example: Solaris Scheduling
381 |
382 | ## 6.8 Algorithm Evaluation
383 |
384 | ### 6.8.1 Deterministic Modeling
385 |
386 | !!! note "Deterministic modeling"
387 | It is one type of analytic evaluation. This method takes a particular predetermined workload and defines the performance of each algorithm for that workload.
388 |
389 | ### 6.8.2 Queueing Models
390 |
391 | - Little's formula ($n$: # of processes in the queue, $\lambda$: arrival rate, $W$: average waiting time in the queue.)
392 |
393 | $$n = \lambda \times W.$$
394 |
395 | ### 6.8.3 Simulations
396 |
397 | - Properties:
398 | - Accurate but expensive
399 |
400 | - Procedures:
401 | - Program a model of the computer system
402 | - Drive the simulation with various data sets
403 |
404 | ### 6.8.4 Implementation
--------------------------------------------------------------------------------
/docs/OS/Chap08.md:
--------------------------------------------------------------------------------
1 | # Chapter 8 Main Memory
2 |
3 | ## 8.1 Background
4 |
5 | The CPU fetches instructions from memory according to the value of the program counter.
6 |
7 | Memory Management Motivation:
8 |
9 | - Keep several processes in memory to improve a system's performance
10 |
11 | ### 8.1.1 Basic Hardware
12 |
13 | !!! info ""
14 | **Main memory** and the **registers** built into the processor itself are the only general-purpose storage that the CPU can access directly.
15 |
16 | We need to make sure that each process has a separate memory space.
17 |
18 | We can provide this protection by using two registers, usually **a base** and **a limit**.
19 |
20 | 
21 | 
22 |
23 | ### 8.1.2 Address Binding
24 |
25 | The binding of instructions and data to memory addresses can be done at any step along the way:
26 |
27 | - **Compile time**: absolute code.
28 | - **Load time**: relocatable code.
29 | - **Execution time**
30 |
31 | 
32 |
33 | A major portion of this chapter is devoted to showing how these various bindings can be implemented effectively in a computer system and to discussing appropriate hardware support.
34 |
35 | ### 8.1.3 Logical Versus Physical Address Space
36 |
37 | !!! note "Logical address"
38 | An address generated by the CPU.
39 |
40 | !!! note "Physical address"
41 | An address seen by the memory unit and loaded into the memory-address register.
42 |
43 | - Generating identical logical and physical addresses:
44 | - Compile-time address-binding
45 | - Load-time address-binding
46 |
47 | - Generating different logical and physical addresses:
48 | - Execution-time address-binding
49 | - logical address $\to$ **virtual address**
50 |
51 | !!! note "Logical address space"
52 | The set of all logical addresses generated by a program.
53 |
54 | !!! note "Physical address space"
55 | The set of all physical addresses corresponding to these logical addresses.
56 |
57 | !!! note "Memory-management unit (MMU)"
58 | Run-time map from virtual to physical addresses.
59 |
60 | 
61 |
62 | The user program never sees the real physical addresses and deals with logical addresses.
63 |
64 | The memory-mapping hardware converts logical addresses into physical addresses
65 |
66 | ### 8.1.4 Dynamic Loading
67 |
68 | !!! note "Dynamic loading"
69 | A routine is not loaded until it is called.
70 |
71 | ### 8.1.5 Dynamic Linking and Shared Libraries
72 |
73 | !!! note "Dynamically linked libraries"
74 | System libraries that are linked to user programs when the programs are run.
75 |
76 | !!! note "Static linking"
77 | System libraries are treated like any other object module and are combined by the loader into the binary program image.
78 |
79 | !!! note "Dynamic linking"
80 | Linking is postponed until execution time. e.g. language subroutine libraries.
81 |
82 | With dynamic linking, a **stub** is included in the image for each library-routine reference.
83 |
84 | !!! note "Stub"
85 | A small piece of code that indicates how to locate the appropriate memory-resident library routine or how to load the library if the routine is not already present.
86 |
87 | !!! note "Shared libraries"
88 | Only programs that are compiled with the new library version are affected by any incompatible changes incorporated in it. Other programs linked before the new library was installed will continue using the older library.
89 |
90 | ## 8.2 Swapping
91 |
92 | A process must be in memory to be executed. A process, however, can be swapped temporarily out of memory to a **backing store** and then brought back into memory for continued execution.
93 |
94 | ### 8.2.1 Standard Swapping
95 |
96 | 
97 |
98 | The context-switch time in such a swapping system is fairly high.
99 |
100 | Let's assume that the user process is 100 MB in size and the backing store is a standard hard disk with a transfer rate of 50 MB per second. The actual transfer of the 100-MB process to or from main memory takes
101 |
102 | $$\frac{100\text{MB}}{50\text{MB}/s} = 2s.$$
103 |
104 | ### 8.2.2 Swapping on Mobile Systems
105 |
106 | Mobile systems do not support swapping in general but might have paging (iOS and Android)
107 |
108 | ## 8.3 Contiguous Memory Allocation
109 |
110 | The memory is usually divided into two partitions:
111 |
112 | - one for the resident operating system and
113 | - one for the user processes.
114 |
115 | !!! note "Contiguous memory allocation"
116 | Each process is contained in a single section of memory that is contiguous to the section containing the next process.
117 |
118 | ### 8.3.1 Memory Protection
119 |
120 | - The **relocation register** contains the value of the smallest *physical address*.
121 | - The **limit register** contains the range of *logical addresses*.
122 |
123 | 
124 |
125 | ### 8.3.2 Memory Allocation
126 |
127 | One of the simplest methods for allocating memory is to divide memory into several fixed-sized **partitions**.
128 |
129 | Thus, the degree of multiprogramming is bound by the number of partitions.
130 |
131 | - In this **multiple-partition method**, when a partition is free, a process is selected from the input queue and is loaded into the free partition.
132 |
133 | - In the **variable-partition** scheme, the operating system keeps a table indicating which parts of memory are available and which are occupied.
134 |
135 | **Dynamic storage-allocation problem** concerns how to satisfy a request of size $n$ from a list of free holes. There are many solutions to this problem:
136 |
137 | - **First fit**
138 | - **Best fit**
139 | - **Worst fit**
140 |
141 | Simulations have shown that both first fit and best fit are better than worst fit in terms of decreasing time and storage utilization. Neither first fit nor best fit is clearly better than the other in terms of storage utilization, but first fit is generally faster.
142 |
143 | ### 8.3.3 Fragmentation
144 |
145 | Both the first-fit and best-fit strategies for memory allocation suffer from **external fragmentation**.
146 |
147 | !!! note "External fragmentation"
148 | There is enough total memory space to satisfy a request but the available spaces are not contiguous
149 |
150 | !!! note "50-percent rule"
151 | Even with some optimization, given $N$ allocated blocks, another $0.5 N$ blocks will be lost to fragmentation. That is, one-third of memory may be unusable!
152 |
153 | !!! note "Internal fragmentation"
154 | The memory allocated to a process may be slightly larger than the requested memory. The difference between these two numbers is internal fragmentation.
155 |
156 | !!! note "Compaction"
157 | The goal is to shuffle the memory contents so as to place all free memory together in one large block.
158 |
159 | Compaction is possible only if
160 |
161 | - relocation is dynamic and
162 | - is done at execution time.
163 |
164 | Another possible solution to the external-fragmentation problem is to permit the logical address space of the processes to be noncontiguous, thus allowing a process to be allocated physical memory wherever such memory is available:
165 |
166 | - Segmentation
167 | - Paging
168 |
169 | ## 8.4 Segmentation
170 |
171 | !!! note "Segmentation"
172 | A memory-management scheme that supports this programmer view of memory.
173 |
174 | ### 8.4.1 Basic Method
175 |
176 | segments are numbered and are referred to by a segment number, rather than by a segment name. Thus, a logical address consists of a *two tuple*:
177 |
178 |
179 | <*segment-number, offset*>
180 |
181 |
182 | ### 8.4.2 Segmentation Hardware
183 |
184 | A logical address consists of two parts:
185 |
186 | - a segment number: $s$
187 | - an offset into that segment: $d$
188 |
189 | **Segment table** consists of
190 |
191 | - a segment base: contains the starting physical address where the segment resides in memory.
192 | - a segment limit: specifies the length of the segment.
193 |
194 | 
195 |
196 | ## 8.5 Paging
197 |
198 | Paging avoids external fragmentation and the need for compaction, whereas segmentation does not.
199 |
200 | - breaking physical memory into fixed-sized blocks called **frames**
201 | - breaking logical memory into blocks of the same size called **pages**
202 |
203 | Every address generated by the CPU is divided into two parts:
204 |
205 | - a **page number (p)**
206 | - a **page offset (d)**
207 |
208 | 
209 |
210 | 
211 |
212 | If the size of the logical address space is $2^m$, and a page size is $2^n$ bytes. The logical address is as follows:
213 |
214 | 
215 |
216 | On my MacBook Pro (15-inch, 2017), I obtain the page size of 4096 bytes = 4 KB.
217 | 
218 |
219 | In the worst case, a process would need $n$ pages plus $1$ byte. It would be allocated $n + 1$ frames, resulting in internal fragmentation of almost an entire frame.
220 |
221 | !!! note "Frame table"
222 | It has one entry for each physical page frame, indicating whether the latter is free or allocated and, if it is allocated, to which page of which process or processes.
223 |
224 | ### 8.5.2 Hardware Support
225 |
226 | - The page table is implemented as a set of dedicated **registers**.
227 | - pros: fast
228 | - cons: entries could be small
229 |
230 | - The page table is kept in main memory, and a **page-table base register** (**PTBR**) points to the page table. Changing page tables requires changing only this one register, substantially reducing context-switch time.
231 | - pros: entries could be large
232 | - cons: slow (the time required to access a user memory location)
233 | - With this scheme, ***two*** memory accesses are needed to access a byte (one for the page-table entry, one for the byte)
234 |
235 | !!! note "Translation look-aside buffer (TLB)"
236 | The TLB is associative, high-speed memory. Each entry in the TLB consists of two parts:
237 |
238 | - a key (or tag)
239 | - a value
240 |
241 | The TLB contains only a few of the page-table entries (typically between 32 and 1024 entries). When a logical address is generated by the CPU, its page number is presented to the TLB. If the page number is found, its frame number is immediately available and is used to access memory. As just mentioned, *these steps are executed as part of the instruction pipeline within the CPU, adding no performance penalty* compared with a system that does not implement paging.
242 |
243 | !!! note "TLB miss"
244 | The page number is not in the TLB.
245 |
246 | 
247 |
248 | !!! info "TLB replacement policies"
249 | If the TLB is already full of entries, an existing entry must be selected for replacement. Replacement policies range from **least recently used (LRU)** through round-robin to random.
250 |
251 | !!! info "Wire down"
252 | Some TLBs allow certain entries to be **wired down**, meaning that they cannot be removed from the TLB. Typically, TLB entries for key kernel code are wired down.
253 |
254 | Some TLBs store **address-space identifiers** (**ASIDs**) in each TLB entry.
255 |
256 | !!! note "ASID"
257 | An ASID uniquely identifies each process and is used to provide address-space protection for that process.
258 |
259 | !!! note "Hit ratio"
260 | The percentage of times that the page number of interest is found in the TLB.
261 |
262 | ### 8.5.3 Protection
263 |
264 | We can create hardware to provide read-only, read-write, or execute-only protection.
265 |
266 | !!! note "Valid–invalid bit"
267 | When this bit is set to valid, the associated page is in the process's logical address space and is thus a legal page.
268 |
269 | !!! note "Page-table length register (PTLR)"
270 | To indicate the size of the page table.
271 |
272 | ### 8.5.4 Shared Pages
273 |
274 | To be sharable, the code must be reentrant. The read-only nature of shared code should not be left to the correctness of the code; the operating system should enforce this property.
275 |
276 | ## 8.6 Structure of the Page Table
277 |
278 | ### 8.6.1 Hierarchical Paging
279 |
280 | Hierarchical paging is also known as **forward-mapped page table**.
281 |
282 | 
283 |
284 | 
285 |
286 | The VAX minicomputer from Digital Equipment Corporation (DEC):
287 |
288 | 
289 |
290 | ### 8.6.2 Hashed Page Tables
291 |
292 | !!! note "Clustered page tables"
293 | Each entry in the hash table refers to several pages (such as 16) rather than a single page, which are particularly useful for address spaces.
294 |
295 | 
296 |
297 | ### 8.6.3 Inverted Page Tables
298 |
299 | !!! note "Inverted page table"
300 | An inverted page table has one entry for each real page (or frame) of memory. Each entry consists of the virtual address of the page stored in that real memory location, with information about the process that owns the page.
301 |
302 | 
303 |
304 | For the ***IBM RT***, each virtual address in the system consists of a triple:
305 |
306 |
307 | <*process-id, page-number, offset*>
308 |
309 |
310 | !!! info "Shared memory & Inverted page tables"
311 | Shared memory cannot be used with inverted page tables; because there is only one virtual page entry for every physical page, one physical page cannot have two (or more) shared virtual addresses.
312 |
313 | ### 8.6.4 Oracle SPARC Solaris
314 |
315 | !!! note "TLB walk"
316 | - If a match is found in the TSB, the CPU copies the TSB entry into the TLB, and the memory translation completes.
317 | - If no match is found in the TSB, the kernel is interrupted to search the hash table.
318 |
319 | ## 8.7 Example: Intel 32 and 64-bit Architectures
320 |
321 | ### 8.7.1 IA-32 Architecture
322 |
323 | 
324 |
325 | segmentation unit + paging unit = memory-management unit (MMU)
326 |
327 | #### 8.7.1.1 IA-32 Segmentation
328 |
329 | The logical address is a pair (selector, offset), where the selector is a 16-bit number:
330 |
331 | 
332 |
333 | - $s$: the segment number
334 | - $g$: GDT or LDT
335 | - $p$: protection.
336 |
337 | 
338 |
339 | #### 8.7.1.2 IA-32 Paging
340 |
341 | 
342 |
343 | !!! note "Page address extension (PAE)"
344 | It allows 32-bit processors to access a physical address space larger than 4 GB.
345 |
346 | 
347 |
348 | ### 8.7.2 x86-64
349 |
350 | ## 8.8 Example: ARM Architecture
351 |
352 | ## 8.9 Summary
353 |
354 | - Hardware support
355 | - Performance
356 | - Fragmentation
357 | - Relocation
358 | - Swapping
359 | - Sharing
360 | - Protection
--------------------------------------------------------------------------------