SHARED RESOURCE
• Race condition:
T1: RW
T2: RW
T1+T2: RRWW
• Use lock → Thread-safe:
T1+T2: (RW) (RW)
• But lock causes worse performance and deadlock.
9
Slide 28
Slide 28 text
SHARED RESOURCE
• Race condition:
T1: RW
T2: RW
T1+T2: RRWW
• Use lock → Thread-safe:
T1+T2: (RW) (RW)
• But lock causes worse performance and deadlock.
• Which is the hard part.
9
Slide 29
Slide 29 text
DIAGNOSE PROBLEM
10
Slide 30
Slide 30 text
DIAGNOSE PROBLEM
• Where is the bottleneck?
10
Slide 31
Slide 31 text
DIAGNOSE PROBLEM
• Where is the bottleneck?
• Divide your problem.
10
Slide 32
Slide 32 text
PRODUCER-CONSUMER
PATTERN
11
Slide 33
Slide 33 text
PRODUCER-CONSUMER
PATTERN
12
Slide 34
Slide 34 text
PRODUCER-CONSUMER
PATTERN
• A queue
12
Slide 35
Slide 35 text
PRODUCER-CONSUMER
PATTERN
• A queue
• Producers → A queue
12
Slide 36
Slide 36 text
PRODUCER-CONSUMER
PATTERN
• A queue
• Producers → A queue
• A queue → Consumers
12
Slide 37
Slide 37 text
PRODUCER-CONSUMER
PATTERN
• A queue
• Producers → A queue
• A queue → Consumers
• Python has built-in Queue module for it.
12
WHY .TASK_DONE?
• It’s for .join.
• When the counter goes zero,
it will notify the threads which are waiting.
14
Slide 42
Slide 42 text
WHY .TASK_DONE?
• It’s for .join.
• When the counter goes zero,
it will notify the threads which are waiting.
• It’s implemented by threading.Condition.
14
19
• It’s not that “daemon”.
• Just will be killed when Python shutting down.
DAEMONIC THREAD
Slide 60
Slide 60 text
19
• It’s not that “daemon”.
• Just will be killed when Python shutting down.
• Immediately.
DAEMONIC THREAD
Slide 61
Slide 61 text
19
• It’s not that “daemon”.
• Just will be killed when Python shutting down.
• Immediately.
• Others keep running until return.
DAEMONIC THREAD
Slide 62
Slide 62 text
SO, HOW TO STOP?
20
Slide 63
Slide 63 text
SO, HOW TO STOP?
• Set demon and let Python clean it up.
20
Slide 64
Slide 64 text
SO, HOW TO STOP?
• Set demon and let Python clean it up.
• Let it return.
20
Slide 65
Slide 65 text
BUT, THE THREAD IS BLOCKING
21
Slide 66
Slide 66 text
BUT, THE THREAD IS BLOCKING
• Set timeout.
21
Slide 67
Slide 67 text
HOW ABOUT CTRL+C?
22
Slide 68
Slide 68 text
HOW ABOUT CTRL+C?
• Only main thread can receive that.
22
Slide 69
Slide 69 text
HOW ABOUT CTRL+C?
• Only main thread can receive that.
• BSD-style.
22
Slide 70
Slide 70 text
BROADCAST SIGNAL
TO SUB-THREAD
23
Slide 71
Slide 71 text
BROADCAST SIGNAL
TO SUB-THREAD
• Set a global flag when get signal.
23
Slide 72
Slide 72 text
BROADCAST SIGNAL
TO SUB-THREAD
• Set a global flag when get signal.
• Let thread read it before each task.
23
Slide 73
Slide 73 text
BROADCAST SIGNAL
TO SUB-THREAD
• Set a global flag when get signal.
• Let thread read it before each task.
• No, you can’t kill non-daemonic thread.
23
Slide 74
Slide 74 text
BROADCAST SIGNAL
TO SUB-THREAD
• Set a global flag when get signal.
• Let thread read it before each task.
• No, you can’t kill non-daemonic thread.
• Just can’t do so.
23
Slide 75
Slide 75 text
BROADCAST SIGNAL
TO SUB-THREAD
• Set a global flag when get signal.
• Let thread read it before each task.
• No, you can’t kill non-daemonic thread.
• Just can’t do so.
• It’s Python.
23
Slide 76
Slide 76 text
BROADCAST SIGNAL
TO SUB-PROCESS
24
Slide 77
Slide 77 text
BROADCAST SIGNAL
TO SUB-PROCESS
• Just broadcast the signal to sub-processes.
24
Slide 78
Slide 78 text
BROADCAST SIGNAL
TO SUB-PROCESS
• Just broadcast the signal to sub-processes.
• Start with register signal handler:
signal(SIGINT, _handle_to_term_signal)
24
Slide 79
Slide 79 text
25
Slide 80
Slide 80 text
• Realize process context if need:
pid = getpid()
pgid = getpgid(0)
proc_is_parent = (pid == pgid)
25
Slide 81
Slide 81 text
• Realize process context if need:
pid = getpid()
pgid = getpgid(0)
proc_is_parent = (pid == pgid)
• Off the handler:
signal(signum, SIG_IGN)
25
Slide 82
Slide 82 text
• Realize process context if need:
pid = getpid()
pgid = getpgid(0)
proc_is_parent = (pid == pgid)
• Off the handler:
signal(signum, SIG_IGN)
• Broadcast:
killpg(pgid, signum)
25
Slide 83
Slide 83 text
MISC. TECHIQUES
26
Slide 84
Slide 84 text
JUST THREAD IT OUT
27
Slide 85
Slide 85 text
JUST THREAD IT OUT
• Or process it out.
27
Slide 86
Slide 86 text
JUST THREAD IT OUT
• Or process it out.
• Let main thread exit earlier. (Looks faster!)
27
Slide 87
Slide 87 text
JUST THREAD IT OUT
• Or process it out.
• Let main thread exit earlier. (Looks faster!)
• Let main thread keep dispatching tasks.
27
Slide 88
Slide 88 text
JUST THREAD IT OUT
• Or process it out.
• Let main thread exit earlier. (Looks faster!)
• Let main thread keep dispatching tasks.
• “Async”
27
Slide 89
Slide 89 text
JUST THREAD IT OUT
• Or process it out.
• Let main thread exit earlier. (Looks faster!)
• Let main thread keep dispatching tasks.
• “Async”
• And fix some stupid behavior.
(I meant atexit with multiprocessing.Pool.)
27
Slide 90
Slide 90 text
COLLECT RESULT SMARTER
28
Slide 91
Slide 91 text
COLLECT RESULT SMARTER
• Put into a safe queue.
28
Slide 92
Slide 92 text
COLLECT RESULT SMARTER
• Put into a safe queue.
• Use a thread per instance.
28
Slide 93
Slide 93 text
COLLECT RESULT SMARTER
• Put into a safe queue.
• Use a thread per instance.
• Learn “let it go”.
28
MONITOR THEM
• No one is a master at first.
• Don’t guess.
30
Slide 98
Slide 98 text
MONITOR THEM
• No one is a master at first.
• Don’t guess.
• Just use a function to print log.
30
Slide 99
Slide 99 text
BENCHMARK THEM
31
Slide 100
Slide 100 text
BENCHMARK THEM
• No one is a master at first.
31
Slide 101
Slide 101 text
BENCHMARK THEM
• No one is a master at first.
• Don’t guess.
31
Slide 102
Slide 102 text
BENCHMARK THEM
• No one is a master at first.
• Don’t guess.
• Just prove it.
31
Slide 103
Slide 103 text
CONCLUSION
32
Slide 104
Slide 104 text
CONCLUSION
• Avoid shared resource
— or just use producer-consumer pattern.
32
Slide 105
Slide 105 text
CONCLUSION
• Avoid shared resource
— or just use producer-consumer pattern.
• Signals only go main thread.
32
Slide 106
Slide 106 text
CONCLUSION
• Avoid shared resource
— or just use producer-consumer pattern.
• Signals only go main thread.
• Just thread it out.
32
Slide 107
Slide 107 text
CONCLUSION
• Avoid shared resource
— or just use producer-consumer pattern.
• Signals only go main thread.
• Just thread it out.
• Collect your result smarter.
32
Slide 108
Slide 108 text
CONCLUSION
• Avoid shared resource
— or just use producer-consumer pattern.
• Signals only go main thread.
• Just thread it out.
• Collect your result smarter.
• Monitor and benchmark your code.
32