Polynomial Time as a Definition of Efficiency
Objectives
We would like to :- Discuss why polynomial time is equated with efficiency
- Discuss what we measure for performance
- Formally define O(f(n)).
Notes
- This continues chapter 2 of Kleinberg and Tardos.
- When we analyze an algorithm, what is it we would like to count?
- In architecture we learned
- time = instruction count × cycles per instruction × seconds per cycle.
- The time per instruction is fixed by the machine and changes as the machine changes
- IE gets faster as new machines are introduced.
- But does the instruction count change?
- Actually we know this does vary by machine
- Consider the c/c++ code
a = b + c;- In intel assembly:
-
mov eax,[b] add eax,[c] move [a], eax - but in mips assembly
lw $t1, b lw $t2, c add $t2, $t2, $t1 sw $t22, a - A difference of one instruction, but over time ...
- And some higher level operations are much worse.
- In architecture we learned
- Let's discuss the number of instructions for
-
const int SIZE{some number} int a[SIZE],b[SIZE],c[SIZE]; for(i = 0; i < SIZE; ++i) { a[i] = b[i] + c[i] } - In intel assembly:
(Courtesy of chatGPT)mov ecx, 1 ; i = 1 mov ebx, SIZE ; loop bound loop: cmp ecx, ebx jge done ; if i >= SIZE, exit loop mov eax, [b + ecx*4] ; eax = b[i] add eax, [c + ecx*4] ; eax = b[i] + c[i] mov [a + ecx*4], eax ; a[i] = eax inc ecx ; i++ jmp loop done: - The loop takes 7 instructions.
- And there are two instructions for setup
- The performance is 7*SIZE + 2
-
- The loop in mips assembly
-
(Again, thanks to chatGPT)li $t0, 1 # i = 1 li $t1, SIZE # loop bound loop: bge $t0, $t1, done # if i >= SIZE, exit loop sll $t2, $t0, 2 # offset = i * 4 (since word = 4 bytes) lw $t3, b($t2) # load b[i] lw $t4, c($t2) # load c[i] add $t5, $t3, $t4 # t5 = b[i] + c[i] sw $t5, a($t2) # store into a[i] addi $t0, $t0, 1 # i++ j loop done: - takes 8 instructions.
- There are also two instructions for setup.
- The performance is 8*SIZE + 2
-
-
add mem, mem, mem.
- My loop might be something like:
(My own brain!)li $t0, 1 # i = 1 li $t1, SIZE # loop bound loop: bge $t0, $t1, done # if i >= SIZE, exit loop sll $t2, $t0, 2 # offset = i * 4 (since word = 4 bytes) add a($t2), b($t2), c($t2) addi $t0, $t0, 1 # i++ j loop - My time would be 5*SIZE + 2
- Clearly the "algorithm" is better on the DAN computer?
- Traditionally code falls into
- Log based: or c×log2(n)
- In this case, c must be constant
- Polynomial: aini + ai-1ni-1 + ... + a1n + a0.
- ai and i are constant.
- Combination of log and polynomial: c×ndlog2n
- c and d are constant.
- Constant to n: cn, we shall see this is a different beast.
- Factorial: n!, again this is a different beast.
- Log based: or c×log2(n)
- The book on page 34 has a comparison chart.
-
- Looking at the first four columns...
- Do the non leading degree of the polynomial terms matter?
- Look at for example n3, n3+ n2
- n = 10,000 : 12 days vs 12 days and 2 minutes
- Compare this to 2n or n!: very long
- How about if we have a leading coefficient?
- n = 10,000: 12 days vs 24, 36, 48 days
- Compare this to 2n or n! : vary long
- How about n log2n?
- Is this radically different from n or n2?
- Use desmos to explore these.
-
- How important is the ai term?
- Isn't it mostly just an indication of the number of instructions in the loop in a particular assembly language?
- Isn't it really not a major contributor to time (ni dominates).
- How important are ai-1ni-1 + ... + a1n + a0?
- We will see these represent setup and completion of the main "loop".
- But from above, they contribute, but not as much as the leading term.
- So in the end, we only look at the degree of the polynomial, or ...
-
SELECTION-SORT(A) Input: A an array of items with the comparison operator Output: the array A ordered by the comparison operator
- current ← 0
- while current < A.size
- small ← current
- for next ← current +1 to A.size
- if A[next] < A[small]
- small ← next
- if small ≠ current
- swap(A[small], A[current])
- current ← current + 1
- What does this algorithm do?
- How does it do it?
- Will it work?
- What is the performance of this algorithm?
- How many times will the loop in line 2 execute?
- How many times will the loop in line 4 execute?
- Are all of the instructions basic?
- Can you come up with the exact polynomial for this algorithm? (ie true instruction count?)
- On linux you can run
perfto determine the number of instructions executed. - I implemented the sort in ssort.cpp.
- I ran it ten times for 1,000 elements to 10,000 elements, by 1,000.
-
- On linux you can run