Presentation is loading. Please wait.

Presentation is loading. Please wait.

מבוא מורחב למדעי המחשב תרגול 14. Serial Programming Expressions are evaluated in a well-known order One expression at a time Life are easy (though slow)

Similar presentations


Presentation on theme: "מבוא מורחב למדעי המחשב תרגול 14. Serial Programming Expressions are evaluated in a well-known order One expression at a time Life are easy (though slow)"— Presentation transcript:

1 מבוא מורחב למדעי המחשב תרגול 14

2 Serial Programming Expressions are evaluated in a well-known order One expression at a time Life are easy (though slow)

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

4 Why parallel programming?

5 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))

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

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

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

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

10 But reading minds takes time… (define (MindReader) (display “Enter your name”) (let ((name (read))) (begin (display “Thinking…”) (ReadMind name))) (MindReader) )

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) )

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?

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?

14 Queue Helper Procedures Hidden 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 cdba front-ptr rear-ptr

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))))

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 cdba front-ptr rear-ptr

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

18 Application Workflow

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) )

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) )

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

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 ))))

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

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

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

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) )

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) )

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

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))))

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

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) )))

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))))

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!

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?

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

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))))

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)) )))

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?

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


Download ppt "מבוא מורחב למדעי המחשב תרגול 14. Serial Programming Expressions are evaluated in a well-known order One expression at a time Life are easy (though slow)"

Similar presentations


Ads by Google