מבוא מורחב למדעי המחשב

39
בבבב בבבבב בבבבב בבבבב בבבבב14

description

מבוא מורחב למדעי המחשב. תרגול 14. Serial Programming. Expressions are evaluated in a well-known order One expression at a time Life are easy (though slow). Concurrent (Parallel) Computation. Some code parts are “parallel” to each other Order of evaluation is not well-defined - PowerPoint PPT Presentation

Transcript of מבוא מורחב למדעי המחשב

Page 1: מבוא מורחב למדעי המחשב

מבוא מורחב למדעי המחשב

14תרגול

Page 2: מבוא מורחב למדעי המחשב

Serial Programming

• Expressions are evaluated in a well-known order

• One expression at a time

• Life are easy (though slow)

Page 3: מבוא מורחב למדעי המחשב

Concurrent (Parallel) Computation

• Some code parts are “parallel” to each other

• Order of evaluation is not well-defined

• Typically depends on an internal OS mechanism which we can assume (almost) nothing about

Page 4: מבוא מורחב למדעי המחשב

Why parallel programming?

Page 5: מבוא מורחב למדעי המחשב

Why parallel programming?

Because it can be faster!(define (P i) (let ((counter (+ 1 (* (- i 1) (power 10 9)))) (upto (* i (power 10 9)))) (define (iter) (if (< counter upto) (begin (if (prime? counter) (display counter) #f) (increment-counter) (iter)) 'done)) (iter)))

(parallel-execute (P 1) (P 2) ... (P 10))

Page 6: מבוא מורחב למדעי המחשב

faster• Can be faster even on a single computer (dual-

core)

• Even on a single-core, things can happen in parallel

• Mainly CPU vs. I\O (disk access, communication…)

• But we need to parallelize wisely

Page 7: מבוא מורחב למדעי המחשב

Always parallelize?

• No• Parallel programs are harder to write and

are more error prone• Also, if designed badly, can be even

slower than sequential• Parallelize when you can gain something,

or when you have to

Page 8: מבוא מורחב למדעי המחשב

Why Parallelize?

• Because life are parallel!

• Say that you’ve built a desktop application

• Receives a query from the user, processes it and returns an answer

Page 9: מבוא מורחב למדעי המחשב

MindReader

(define (MindReader) (display “Enter your name”) (let ((name (read))) (ReadMind name)) (MindReader))

Page 10: מבוא מורחב למדעי המחשב

But reading minds takes time…

(define (MindReader) (display “Enter your name”) (let ((name (read))) (begin (display “Thinking…”) (ReadMind name))) (MindReader))

Page 11: מבוא מורחב למדעי המחשב

Put it on the web!(define (MindReader) (display “Enter your name”) (let (name (readMessage)) (begin (display “Thinking…”)

(let ((result (ReadMind name)))(display result))))

(MindReader))

Page 12: מבוא מורחב למדעי המחשב

Won’t work

• Say that reading minds takes only 5 seconds

• If only 20 people asked for it before I did, I should wait almost 2 minutes

• And I don’t even get a message• And probably my message is thrown away• Parallel Programming to the rescue!• But how?

Page 13: מבוא מורחב למדעי המחשב

Tactics• MindReader is a black-box, can’t change it

• But can separate web-interface from reading minds

• One process will receive messages, the other will read minds, and a third will print results

• How to communicate?

Page 14: מבוא מורחב למדעי המחשב

Queue Helper ProceduresHidden inside the abstraction(define (front-ptr q) (cadr q))(define (rear-ptr q) (cddr q))

(define (set-front-ptr! q item) (set-car! (cdr q) item))(define (set-rear-ptr! q item) (set-cdr! (cdr q) item))

queue

c dba

front-ptr

rear-ptr

Page 15: מבוא מורחב למדעי המחשב

Queue implementation (define (make-queue) (cons 'queue (cons null null)))(define (queue? q) (and (pair? q) (eq? 'queue (car q))))

(define (empty-queue? q) (if (not (queue? q)) (error "object not a queue:" q) (null? (front-ptr q))))

(define (front-queue q) (if (empty-queue? q) (error "front of empty queue:" q) (car (front-ptr q))))

Page 16: מבוא מורחב למדעי המחשב

Queue implementation – Insert(define (insert-queue! q elt) (let ((new-pair (cons elt nil))) (cond ((empty-queue? q) (set-front-ptr! q new-pair) (set-rear-ptr! q new-pair) ‘ok) (else (set-cdr! (rear-ptr q) new-pair) (set-rear-ptr! q new-pair) ‘ok))))

e

new-pair

queue

c dba

front-ptr

rear-ptrrear-ptr

Page 17: מבוא מורחב למדעי המחשב

pop-queue!

(define (pop-queue! q) (let ((result (front-queue q))) (begin (delete-queue! q) result))))

Page 18: מבוא מורחב למדעי המחשב

Application Workflow

ReadAndSave ExtractAndProcess ExtractAndPrint

requests results

Page 19: מבוא מורחב למדעי המחשב

New interface function

(define (ReadAndSave q) (display “Enter your name”) (let ((name (readMessage))) (begin (display “Your message was received”)

(insert-queue! q name))) (ReadAndSave q)

)

Page 20: מבוא מורחב למדעי המחשב

Processing message

(define (ExtractAndProcess q-in q-out) (let ((name (pop-queue! q-in)) (let ((result (ReadMind name))) (insert-queue! q-out result))) (ExtractAndProcess q-in q-out))

Page 21: מבוא מורחב למדעי המחשב

Printing the result

(define (ExtractAndPrint q) (let ((result (pop-queue! q))) (display result)) (ExtractAndPrint q))

Page 22: מבוא מורחב למדעי המחשב

Putting it all together(define (myWebApplication) (let ((q-requests (make-queue)) (q-results (make-queue)))

(parallel-execute (ReadAndSave q-requests)

(ExtractAndProcess q-requests q-results)

(ExtractAndPrint q-results))))

Page 23: מבוא מורחב למדעי המחשב

A Problem

• One process might try to access the queue while the other is inserting

• A message might get lost

• We need Mutual Exclusion

Page 24: מבוא מורחב למדעי המחשב

Mutual Exclusion

• The problem rises in case of a shared object

• We can’t have two processes writing to it in the same time

• In the vast majority of cases, read+write is forbidden as well

• read+read is sometimes ok, depends on the case

Page 25: מבוא מורחב למדעי המחשב

Mutex• A synchronization object

• A process can request for access

• It will be granted access only if no one is holding the mutex

• Otherwise wait

Page 26: מבוא מורחב למדעי המחשב

New interface function(define (ReadAndSave q m) (display “Enter your name”) (let ((name (readMessage))) (begin (display “Your message was received”) (m 'begin) (insert-queue! q name) (m 'end)) (ReadAndSave q m))

Page 27: מבוא מורחב למדעי המחשב

New processing message(define (ExtractAndProcess q-in m-in q-out m-out) (m-in ‘begin) (let ((name (pop-queue! q-in)) (m-in ‘end) (let ((result (ReadMind name))) (begin (m-out ‘begin) (insert-queue! q-out result) (m-out ‘end)))) (ExtractAndProcess q-in m-in q-out m-out))

Page 28: מבוא מורחב למדעי המחשב

Printing the result(define (ExtractAndPrint q m) (m ‘begin) (let ((result (pop-queue! q))) (begin (m ‘end) (display result))) (ExtractAndPrint q m))

Page 29: מבוא מורחב למדעי המחשב

Putting it all together (new)(define (myWebApplication) (let ((q-requests (make-queue)) (m-requests (make-mutex)) (q-results (make-queue))) (m-results (make-mutex))) (parallel-execute (ReadAndSave q-requests m-requests)

(ExtractAndProcess q-requests m-requests q-results m-results)

(ExtractAndPrint q-results m-results))))

Page 30: מבוא מורחב למדעי המחשב

A better solution

• Put a mutex within the queue object

• We’ll create a new object: secure-mutex

• Don’t throw away the old queue, though

Page 31: מבוא מורחב למדעי המחשב

Secure-Queue implementation (define (make-secure-queue)

( cons (make-mutex) (cons ‘secure-queue (cons null null))

(define (mutex q) (car q)

(define (secure-queue? q) (and (pair? q) (pair? (cdr q)) (eq? ‘secure-queue

(cadr q))))

(define (empty-secure-queue? q) (if (not (secure-queue? q)) (error "object not a secure queue:" q) (begin ((mutex q) ‘begin) (let ((res (null? (front-ptr q)))) ((mutex q) ‘end) res) )))

Page 32: מבוא מורחב למדעי המחשב

front-secure-queue

(define (front-secure-queue q) (if (empty-secure-queue? q) (error "front of empty queue:" q) (begin ((mutex q) ‘begin) (car (front-ptr q) ((mutex q) ‘end))))

Page 33: מבוא מורחב למדעי המחשב

front-secure-queue

(define (front-secure-queue q) (if (empty-secure-queue? q) (error "front of empty queue:" q) (begin ((mutex q) ‘begin) (car (front-ptr q) ((mutex q) ‘end))))

Mind the gap!

Page 34: מבוא מורחב למדעי המחשב

front-secure-queue

(define (front-secure-queue q) (if (empty-secure-queue? q) (error "front of empty queue:" q) (begin ((mutex q) ‘begin) (car (front-ptr q) ((mutex q) ‘end))))

Mind the gap!

What about the return value?

Page 35: מבוא מורחב למדעי המחשב

front-secure-queue

(define (front-secure-queue q) ((mutex q) ‘begin) (if (empty-secure-queue? q) (begin ((mutex q) ‘end) (error "front of empty queue:" q)) (begin (car (front-ptr q)) ((mutex q) ‘end)))))

Not all mutex implementations support multiple

acquisition

Page 36: מבוא מורחב למדעי המחשב

front-secure-queue

(define (front-secure-queue q) ((mutex q) ‘begin) (if (empty-queue? q) (begin ((mutex q) ‘end) (error "front of empty queue:" q)) (begin (let ((ret (car (front-ptr q))) ((mutex q) ‘end) ret))))

Page 37: מבוא מורחב למדעי המחשב

Insert-secure-queue!(define (insert-secure-queue! q elt) (let ((new-pair (cons elt nil))) (cond ((empty-queue? q) (begin ((mutex q) ‘begin) (set-front-ptr! q new-pair) (set-rear-ptr! q new-pair) ((mutex q) ‘end) ‘ok) (else (begin ((mutex q) ‘begin) (set-cdr! (rear-ptr q) new-pair) (set-rear-ptr! q new-pair) ((mutex q) ‘end) ‘ok)) )))

Page 38: מבוא מורחב למדעי המחשב

Insert-secure-queue!(define (insert-secure-queue! q elt) (let ((new-pair (cons elt nil))) (cond ((empty-queue? q) (begin ((mutex q) ‘begin) (set-front-ptr! q new-pair) (set-rear-ptr! q new-pair) ((mutex q) ‘end) ‘ok) (else (begin ((mutex q) ‘begin) (set-cdr! (rear-ptr q) new-pair) (set-rear-ptr! q new-pair) ((mutex q) ‘end) ‘ok)) )))

Need to lock before calling

queue-empty?

Page 39: מבוא מורחב למדעי המחשב

Where to put the mutex?

• Sometimes difficult to decide

• Thumb rule – lock as lower as possible, and as little as possible

• But note that accessing the locks in real life is costly as well