Concurrency and PythonConcurrency and Python
PyCon MY 2015PyCon MY 2015
Kuala LumpurKuala Lumpur
August 21-23, 2015August 21-23, 2015
Boey Pak CheongBoey Pak Cheong
Pytech ResourcesPytech Resources
http://pytechresources.comhttp://pytechresources.com
pcboey@pytech.com.mypcboey@pytech.com.my
Overview of ConcurrencyOverview of Concurrency
●
Emergence of multicore CPUsEmergence of multicore CPUs
●
Challenging but we need to deal with itChallenging but we need to deal with it
●
Every language has its own concurrency storyEvery language has its own concurrency story
●
Understand the Python Concurrency StoryUnderstand the Python Concurrency Story
Processes and ThreadsProcesses and Threads
●
OS provides 2 ways of organizing a thread ofOS provides 2 ways of organizing a thread of
executionexecution
●
A processA process
– An instance of a running programAn instance of a running program
●
A threadA thread
– A path of execution within a processA path of execution within a process
●
A process can contain multiple threads orA process can contain multiple threads or
multiple processesmultiple processes
●
Processes and threads are quite similarProcesses and threads are quite similar
●
Example – On Linux both threads andExample – On Linux both threads and
processes are created with clone()processes are created with clone()
●
Major difference is what they share or don'tMajor difference is what they share or don't
Key DifferencesKey Differences
PROCESS THREAD
Memory Not shared Shared
File Descriptors Mostly not shared Shared
Filesystem
context
Not shared Shared
Signal handlers Not shared Shared
Some benefits of threadsSome benefits of threads
●
Threads are more efficientThreads are more efficient
●
Example – a daemon spawning 10 child processesExample – a daemon spawning 10 child processes
needs a much larger memory footprint than 10needs a much larger memory footprint than 10
threadsthreads
●
Shared memory makes it trivial to share dataShared memory makes it trivial to share data
amongst threadsamongst threads
●
Processes need IPC call to communicateProcesses need IPC call to communicate
Downside of threadsDownside of threads
●
Threads lets you write higher performance appsThreads lets you write higher performance apps
●
…… That's the theoryThat's the theory
●
Writing bug-free multithreaded code is hardWriting bug-free multithreaded code is hard
●
Subtle and baffling bugs – sometimes hard toSubtle and baffling bugs – sometimes hard to
reproducereproduce
●
Race conditions, deadlocks, livelocksRace conditions, deadlocks, livelocks
●
It will cost you development timeIt will cost you development time
●
Requires skillful use of synchronizationRequires skillful use of synchronization
primitives (locks, mutexes)primitives (locks, mutexes)
Python thread vs OS threadPython thread vs OS thread
●
OS thread – created in C codeOS thread – created in C code
●
thread_createthread_create (OS X, Linux)(OS X, Linux)
●
CreateThreadCreateThread (Windows)(Windows)
●
Python threadPython thread
●
Start thread by invokingStart thread by invoking start()start() method on anmethod on an
instance ofinstance of threading.Threadthreading.Thread
●
What's the difference?What's the difference?
●
OS threads can run at the same timeOS threads can run at the same time
●
Python threads generally cannot do thatPython threads generally cannot do that
●
Global Interpreter Lock (GIL)Global Interpreter Lock (GIL)
●
You can bypass GIL limitations with PythonYou can bypass GIL limitations with Python
processesprocesses
Two ApproachesTwo Approaches
●
Two kinds of real-world problems :Two kinds of real-world problems :
●
CPU-bound tasksCPU-bound tasks
●
I/O-bound tasksI/O-bound tasks
●
Two approaches to implementing concurrentTwo approaches to implementing concurrent
programmingprogramming
1.1. Shared memoryShared memory
2.2. Message passingMessage passing
Multicore PythonMulticore Python
●
Use multiple processes with message passingUse multiple processes with message passing
●
multiprocessingmultiprocessing modulemodule
Example – using multiprocessingExample – using multiprocessing
●
Thumper - fast mass image thumbnailThumper - fast mass image thumbnail
generatorgenerator
●
Generating a thumbnail is CPU-boundGenerating a thumbnail is CPU-bound
●
Ideal use case for multiple CPUsIdeal use case for multiple CPUs
●
Calculation is independent for each imageCalculation is independent for each image
●
https://github.com/migrateup/thumperhttps://github.com/migrateup/thumper
●
Results of running thumper repeatedly on aResults of running thumper repeatedly on a
huge data set of NASA TIFF images, on anhuge data set of NASA TIFF images, on an
AWS c3.2xlarge instanceAWS c3.2xlarge instance
●
The worker function that creates the thumbnailsThe worker function that creates the thumbnails
from PIL import Image
def create_thumbnail(src_path,
dest_path,
thumbnail_width,
thumbnail_height):
image = Image.open(src_path)
image.thumbnail((thumbnail_width,thumbnail_height))
os.makedirs(os.path.dirname(dest_path),
exist_ok=True)
image.save(dest_path)
Worker ProcessesWorker Processes
●
Some considerationsSome considerations
●
How many processes?How many processes?
●
Too few or too many?Too few or too many?
multiprocessingmultiprocessing modulemodule
●
The pool methods available :The pool methods available :
●
apply and apply_asyncapply and apply_async
●
map and map_asyncmap and map_async
●
imap and imap_asyncimap and imap_async
●
starmap and starmap_asyncstarmap and starmap_async
import multiprocessing
pool = multiprocessing.Pool(num_processes)
●
Thumper uses starmap_asyncThumper uses starmap_async
def gen_child_args():
for (dirpath, dirnames, filenames) in os.walk(src_dir):
for filename in filenames:
src_path = os.path.join(dirpath, filename)
dest_path = find_dest_path(src_dir, dest_dir,
src_path)
yield (src_path, dest_path, thumbnail_width,
thumbnail_height)
pool.starmap_async(create_thumbnail, gen_child_args())
Performance ConsiderationsPerformance Considerations
●
Example, for a 8 core machineExample, for a 8 core machine
●
How many cores should Thumper use?How many cores should Thumper use?
●
Can fewer processes than the number of cores giveCan fewer processes than the number of cores give
same performance?same performance?
●
Only way to know is to testOnly way to know is to test
●
Y-axis – total elapsed time to thumbnail allY-axis – total elapsed time to thumbnail all
imagesimages
●
Decreases till 6 worker processesDecreases till 6 worker processes
CreditsCredits
●
This presentation is largly based on two articles onThis presentation is largly based on two articles on
the Python Concurrency Story by Aaron Maxwellthe Python Concurrency Story by Aaron Maxwell
●
http://migrateup.com/python-concurrency-story-pt1/http://migrateup.com/python-concurrency-story-pt1/
●
http://migrateup.com/python-concurrency-story-pt2/http://migrateup.com/python-concurrency-story-pt2/
●
Thank you Aaron for agreeing to the use of theThank you Aaron for agreeing to the use of the
content and for sharing of your knowledge andcontent and for sharing of your knowledge and
expertise on this topic and other Python subjectsexpertise on this topic and other Python subjects

Concurrency and Python - PyCon MY 2015

  • 1.
    Concurrency and PythonConcurrencyand Python PyCon MY 2015PyCon MY 2015 Kuala LumpurKuala Lumpur August 21-23, 2015August 21-23, 2015 Boey Pak CheongBoey Pak Cheong Pytech ResourcesPytech Resources http://pytechresources.comhttp://pytechresources.com pcboey@pytech.com.mypcboey@pytech.com.my
  • 2.
    Overview of ConcurrencyOverviewof Concurrency ● Emergence of multicore CPUsEmergence of multicore CPUs ● Challenging but we need to deal with itChallenging but we need to deal with it ● Every language has its own concurrency storyEvery language has its own concurrency story ● Understand the Python Concurrency StoryUnderstand the Python Concurrency Story
  • 3.
    Processes and ThreadsProcessesand Threads ● OS provides 2 ways of organizing a thread ofOS provides 2 ways of organizing a thread of executionexecution ● A processA process – An instance of a running programAn instance of a running program ● A threadA thread – A path of execution within a processA path of execution within a process ● A process can contain multiple threads orA process can contain multiple threads or multiple processesmultiple processes
  • 4.
    ● Processes and threadsare quite similarProcesses and threads are quite similar ● Example – On Linux both threads andExample – On Linux both threads and processes are created with clone()processes are created with clone() ● Major difference is what they share or don'tMajor difference is what they share or don't
  • 5.
    Key DifferencesKey Differences PROCESSTHREAD Memory Not shared Shared File Descriptors Mostly not shared Shared Filesystem context Not shared Shared Signal handlers Not shared Shared
  • 6.
    Some benefits ofthreadsSome benefits of threads ● Threads are more efficientThreads are more efficient ● Example – a daemon spawning 10 child processesExample – a daemon spawning 10 child processes needs a much larger memory footprint than 10needs a much larger memory footprint than 10 threadsthreads ● Shared memory makes it trivial to share dataShared memory makes it trivial to share data amongst threadsamongst threads ● Processes need IPC call to communicateProcesses need IPC call to communicate
  • 7.
    Downside of threadsDownsideof threads ● Threads lets you write higher performance appsThreads lets you write higher performance apps ● …… That's the theoryThat's the theory ● Writing bug-free multithreaded code is hardWriting bug-free multithreaded code is hard ● Subtle and baffling bugs – sometimes hard toSubtle and baffling bugs – sometimes hard to reproducereproduce ● Race conditions, deadlocks, livelocksRace conditions, deadlocks, livelocks ● It will cost you development timeIt will cost you development time ● Requires skillful use of synchronizationRequires skillful use of synchronization primitives (locks, mutexes)primitives (locks, mutexes)
  • 8.
    Python thread vsOS threadPython thread vs OS thread ● OS thread – created in C codeOS thread – created in C code ● thread_createthread_create (OS X, Linux)(OS X, Linux) ● CreateThreadCreateThread (Windows)(Windows) ● Python threadPython thread ● Start thread by invokingStart thread by invoking start()start() method on anmethod on an instance ofinstance of threading.Threadthreading.Thread ● What's the difference?What's the difference?
  • 9.
    ● OS threads canrun at the same timeOS threads can run at the same time ● Python threads generally cannot do thatPython threads generally cannot do that ● Global Interpreter Lock (GIL)Global Interpreter Lock (GIL) ● You can bypass GIL limitations with PythonYou can bypass GIL limitations with Python processesprocesses
  • 10.
    Two ApproachesTwo Approaches ● Twokinds of real-world problems :Two kinds of real-world problems : ● CPU-bound tasksCPU-bound tasks ● I/O-bound tasksI/O-bound tasks ● Two approaches to implementing concurrentTwo approaches to implementing concurrent programmingprogramming 1.1. Shared memoryShared memory 2.2. Message passingMessage passing
  • 11.
    Multicore PythonMulticore Python ● Usemultiple processes with message passingUse multiple processes with message passing ● multiprocessingmultiprocessing modulemodule
  • 12.
    Example – usingmultiprocessingExample – using multiprocessing ● Thumper - fast mass image thumbnailThumper - fast mass image thumbnail generatorgenerator ● Generating a thumbnail is CPU-boundGenerating a thumbnail is CPU-bound ● Ideal use case for multiple CPUsIdeal use case for multiple CPUs ● Calculation is independent for each imageCalculation is independent for each image ● https://github.com/migrateup/thumperhttps://github.com/migrateup/thumper
  • 13.
    ● Results of runningthumper repeatedly on aResults of running thumper repeatedly on a huge data set of NASA TIFF images, on anhuge data set of NASA TIFF images, on an AWS c3.2xlarge instanceAWS c3.2xlarge instance
  • 14.
    ● The worker functionthat creates the thumbnailsThe worker function that creates the thumbnails from PIL import Image def create_thumbnail(src_path, dest_path, thumbnail_width, thumbnail_height): image = Image.open(src_path) image.thumbnail((thumbnail_width,thumbnail_height)) os.makedirs(os.path.dirname(dest_path), exist_ok=True) image.save(dest_path)
  • 15.
    Worker ProcessesWorker Processes ● SomeconsiderationsSome considerations ● How many processes?How many processes? ● Too few or too many?Too few or too many?
  • 16.
    multiprocessingmultiprocessing modulemodule ● The poolmethods available :The pool methods available : ● apply and apply_asyncapply and apply_async ● map and map_asyncmap and map_async ● imap and imap_asyncimap and imap_async ● starmap and starmap_asyncstarmap and starmap_async import multiprocessing pool = multiprocessing.Pool(num_processes)
  • 17.
    ● Thumper uses starmap_asyncThumperuses starmap_async def gen_child_args(): for (dirpath, dirnames, filenames) in os.walk(src_dir): for filename in filenames: src_path = os.path.join(dirpath, filename) dest_path = find_dest_path(src_dir, dest_dir, src_path) yield (src_path, dest_path, thumbnail_width, thumbnail_height) pool.starmap_async(create_thumbnail, gen_child_args())
  • 18.
    Performance ConsiderationsPerformance Considerations ● Example,for a 8 core machineExample, for a 8 core machine ● How many cores should Thumper use?How many cores should Thumper use? ● Can fewer processes than the number of cores giveCan fewer processes than the number of cores give same performance?same performance? ● Only way to know is to testOnly way to know is to test
  • 19.
    ● Y-axis – totalelapsed time to thumbnail allY-axis – total elapsed time to thumbnail all imagesimages ● Decreases till 6 worker processesDecreases till 6 worker processes
  • 20.
    CreditsCredits ● This presentation islargly based on two articles onThis presentation is largly based on two articles on the Python Concurrency Story by Aaron Maxwellthe Python Concurrency Story by Aaron Maxwell ● http://migrateup.com/python-concurrency-story-pt1/http://migrateup.com/python-concurrency-story-pt1/ ● http://migrateup.com/python-concurrency-story-pt2/http://migrateup.com/python-concurrency-story-pt2/ ● Thank you Aaron for agreeing to the use of theThank you Aaron for agreeing to the use of the content and for sharing of your knowledge andcontent and for sharing of your knowledge and expertise on this topic and other Python subjectsexpertise on this topic and other Python subjects