|
Target Audience [ Advanced ]
This course is for more experienced Python programmers who like a
challenge and who want to take their Python skills to a whole new
level. Attendees are expected to already be familiar with the core
Python language and common library modules such
as pickle, os, sys, etc. Having some basic
knowledge of network and systems programming is advised.
Price: $595 (Regular), $125 (Student)
[Register | More Information | FAQ]
|
|
Python Concurrency Workshop
January 17, 2010. Update! The January, 2010 workshop was a success.
Look for another offering in the Summer.
This one-of-kind workshop, designed for more experienced
Python programmers, provides an in-depth examination of concurrent
programming idioms and standard library modules. The aim of this
workshop is to go far beyond the information found in the manual and
to gain a deeper understanding of how different approaches work, their
performance characteristics, limitations, and types of real-world
problems for which they are suited. Course topics include, but are not
limited to the following:
- Interpreter execution model
- Thread programming
- The global interpreter lock
- Subprocesses
- Multiprocessing
- Interprocess communication
- Message queues and message passing
- Coroutines
- Asynchronous and non-blocking I/O
- Distributed computing
Workshop Agenda
Here is a outline for the workshop.
- Thread Programming. Everything you wanted to know about
Python threads, but were afraid to ask. Includes the absolute basics
of using the threading module and different techniques for
using threads to carry out work. Includes detailed coverage of using
different synchronization primitives, queues, and thread pools. Also
provided detailed information on the Global Interpreter Lock (GIL),
tuning parameters, and the interaction between threads and C/C++
extension modules.
- Message Passing and Data Serialization. Message
passing is a core component of distributed computation. This
section provides an in-depth look at different interprocess
communication mechanisms, their performance characteristics,
and tuning options. In addition, different approaches for
serializing Python data structures are explored. Topics include
the subprocess module, named pipes, network sockets, memory mapped regions,
pickle, marshal, structure packing, and binary I/O.
- Multiprocessing. A tour of features provided by the
multiprocessing library added in Python 2.6. Covers processes,
queues, pipes, process pools, and shared memory regions. Examples
will illustrate how multiprocessing can be used to achieve higher
performance when working on multiple CPU cores.
- Distributed Programming. An in-depth tour of different distributed
programming techniques. Topics include programming with actors, client-server
computing, REST, remote procedure call, and distributed objects. Also
includes material on XML-RPC and WSGI.
- Advanced I/O handling. A look at different I/O handling
techniques including blocking, non-blocking, asynchronous, and event-driven
I/O. The primary goal of this section is to better understand the
I/O handling using by different libraries and frameworks such as asyncore, Twisted, etc.
- Generators and Coroutines. An overview of concurrent
programming using generators and coroutines. The major focus of
this section is on using generators to implement user-level task switching
and to better understand libraries based on microthreads, tasklets, green-threads,
and similarly named entities.
Format
The workshop consists of highly detailed presentation slides and
nearly 50 hands on exercises where you will get to
experiment--approximately half the time will be spent working on
programs. For a sample of presentation materials, see my talk on
the Python GIL. If
you are familiar with some of my
past PyCON tutorials,
you should know that the concurrency workshop has almost no overlap.
With the exception of the GIL talk, almost all of the material has not
been presented in any other venue.
Visit Chicago in January? Are you kidding?
January is a great time to visit Chicago when airfares and hotels are
cheap and available. Besides, we're going to spend the whole time
inside hacking code. I will just mention that the workshop venue is
just steps away from about about a dozen bakeries and coffee shops,
not to mention Chicago's most famous pub for getting strong Belgian
ales. Staying warm will be the least of your concerns. That said, you should
still bring a good coat though :-).
Slide Topic Index
The following table, generated automatically from the workshop presentation slides,
gives much more detail about the material to be covered. This outline is still subject to
minor changes as the workshop nears.
1. Introduction
| Python Concurrency Workshop | 1-1 |
| Welcome! | 1-2 |
| Requirements | 1-3 |
| Concurrency | 1-4 |
| A Warning | 1-6 |
| Basic Concurrency Concepts | 1-7 |
| Concurrent Programming | 1-8 |
| Multitasking | 1-9 |
| Parallel Processing | 1-10 |
| Task Execution | 1-11 |
| CPU Bound Tasks | 1-12 |
| I/O Bound Tasks | 1-13 |
| Shared Memory | 1-14 |
| Processes | 1-15 |
| Distributed Computing | 1-16 |
| Why Python? | 1-17 |
| Some Issues | 1-18 |
| Why Use Python at All? | 1-19 |
| Python as a Framework | 1-20 |
| Programming Productivity | 1-21 |
| Performance is Irrelevant | 1-22 |
| You Can Go Faster | 1-23 |
| Commentary | 1-24 |
| Let's Get Started | 1-25 |
2. Thread Programming
| Python Multithreading | 2-1 |
| Overview | 2-2 |
| Background : Threads | 2-3 |
| Usage : Threads | 2-4 |
| Concept: Threads | 2-5 |
| Thread Basics | 2-6 |
| threading Module | 2-11 |
| Thread Objects | 2-12 |
| Launching Thread Objects | 2-13 |
| Thread Execution | 2-14 |
| Joining a Thread | 2-15 |
| Thread Status | 2-16 |
| Interpreter Execution | 2-17 |
| Daemonic Threads | 2-18 |
| Keyboard Interrupt | 2-19 |
| Killing Threads | 2-20 |
| Thread Termination | 2-21 |
| Returning Results | 2-23 |
| The Problem | 2-24 |
| Returning Results | 2-25 |
| Result Objects | 2-26 |
| Returning Results | 2-27 |
| Returning Exceptions | 2-28 |
| Results w/ Exceptions | 2-29 |
| Returning Exceptions | 2-30 |
| An Exception Wart | 2-31 |
| Commentary | 2-34 |
| Threads and Memory | 2-36 |
| Shared Memory | 2-37 |
| Shared Objects | 2-38 |
| Thread Local Data | 2-39 |
| Interlude | 2-42 |
| Debugging with Threads | 2-43 |
| Setting the Thread Name | 2-44 |
| Thread Logging | 2-45 |
| Logging Information | 2-46 |
| Nondeterminism | 2-48 |
| Accessing Shared Data | 2-49 |
| Race Conditions | 2-53 |
| Thread Synchronization | 2-54 |
| Synchronization Options | 2-55 |
| Mutex Locks | 2-57 |
| Use of Mutex Locks | 2-59 |
| Using a Mutex Lock | 2-60 |
| Locking Perils | 2-63 |
| Lock Management | 2-64 |
| Locks and Deadlock | 2-66 |
| Special Topic: | 2-68 |
| with Statement | 2-69 |
| Context Management | 2-70 |
| Context Mgr: Locking | 2-72 |
| Exception Handling | 2-73 |
| Context Setup | 2-74 |
| A Simple Example | 2-75 |
| Where to Put Locks? | 2-77 |
| Fine-Grained Locking | 2-78 |
| Locking Costs | 2-79 |
| Contested Locking | 2-80 |
| Course-Grained Locking | 2-81 |
| RLock | 2-82 |
| RLock Example | 2-83 |
| Commentary | 2-84 |
| Special Topic: | 2-85 |
| Background | 2-86 |
| Decorators | 2-87 |
| A Decorator for Locking | 2-88 |
| Discussion | 2-89 |
| An Example | 2-90 |
| Decorators with Arguments | 2-91 |
| Semaphores | 2-94 |
| Semaphore Uses | 2-95 |
| Resource Control | 2-96 |
| Thread Signaling | 2-97 |
| Events | 2-100 |
| Barrier Synchronization | 2-101 |
| Event Waiting | 2-102 |
| Condition Variables | 2-104 |
| Interlude | 2-109 |
| Threads and Queues | 2-110 |
| Queue Library Module | 2-111 |
| Queue Usage | 2-112 |
| Queue Completion | 2-113 |
| Queue Programming | 2-114 |
| Example: Thread Pools | 2-115 |
| An Inconvenient Truth | 2-117 |
| A Performance Test | 2-118 |
| Bizarre Results | 2-119 |
| Interlude | 2-121 |
| What is a Thread? | 2-122 |
| Thread Creation | 2-123 |
| Behind the Scenes | 2-124 |
| Thread-Specific State | 2-125 |
| PyThreadState Structure | 2-126 |
| Threads and sys module | 2-127 |
| Thread Execution | 2-128 |
| The Infamous GIL | 2-129 |
| GIL Behavior | 2-130 |
| CPU Bound Processing | 2-131 |
| The Check Interval | 2-132 |
| The Periodic Check | 2-133 |
| What is a "Tick?" | 2-134 |
| Tick Execution | 2-135 |
| Interlude : Signals | 2-136 |
| Signal Handling | 2-137 |
| Thread Scheduling | 2-138 |
| Frozen Signals | 2-139 |
| A Useful Tip | 2-140 |
| GIL Implementation | 2-142 |
| Thread Scheduling | 2-143 |
| CPU-Bound Threads | 2-144 |
| Signaling Overhead | 2-145 |
| A Rough Measurement | 2-146 |
| Multiple CPU Cores | 2-147 |
| Multicore GIL Contention | 2-148 |
| The GIL and C Code | 2-150 |
| The GIL and C Extensions | 2-151 |
| How to Release the GIL | 2-152 |
| The GIL and C Extensions | 2-153 |
| Why is the GIL there? | 2-157 |
| GIL Future | 2-158 |
| A Note on Locks | 2-159 |
| Some Lessons Learned | 2-160 |
| Using Threads | 2-161 |
| I/O Bound Processing | 2-162 |
| Thread Limits | 2-164 |
| Check Interval Tuning | 2-165 |
| Cooperative Multitasking | 2-166 |
| Thread Memory Use | 2-167 |
| Thread Stack Space | 2-168 |
| Final Comments | 2-169 |
3. Messaging and Data Serialization
| Message Passing | 3-1 |
| Concept: Message Passing | 3-2 |
| Commentary | 3-3 |
| Message Passing | 3-4 |
| Problem Decomposition | 3-5 |
| Example : Dataflow | 3-6 |
| Example : Worker Pool | 3-8 |
| Example : Map-Reduce | 3-10 |
| Example : Decomposed Data | 3-11 |
| Comments | 3-13 |
| Sending Messages | 3-14 |
| A Problem | 3-15 |
| Section Focus | 3-16 |
| Some Tricky Bits | 3-17 |
| Preview | 3-18 |
| Messaging Basics | 3-19 |
| What is a Message? | 3-20 |
| Message Transport | 3-21 |
| Pipes | 3-22 |
| An Example | 3-23 |
| Named Pipes/FIFOs | 3-24 |
| Pipe Performance | 3-25 |
| Sockets | 3-26 |
| Using Sockets | 3-27 |
| Socket Families | 3-28 |
| Datagrams | 3-29 |
| Datagram Example | 3-30 |
| Memory Mapped Regions | 3-32 |
| Using mmap | 3-34 |
| Data Overlay | 3-35 |
| mmap Commentary | 3-36 |
| Message Encoding | 3-38 |
| Some Philosophy | 3-39 |
| Object Serialization | 3-40 |
| The Problem | 3-41 |
| pickle Module | 3-42 |
| Some Pickle Issues | 3-45 |
| cPickle vs. Pickle | 3-46 |
| Pickle Encodings | 3-48 |
| Selecting a Protocol | 3-49 |
| Pickling to Strings | 3-52 |
| Pickling Instances | 3-53 |
| Python and References | 3-55 |
| Reference Example | 3-56 |
| Pickle and References | 3-57 |
| Preserving References | 3-59 |
| Pickler Objects | 3-60 |
| Pickler Caution | 3-61 |
| Pickle and Large Objects | 3-62 |
| Classes and Functions | 3-63 |
| Miscellaneous Comments | 3-64 |
| marshal Module | 3-66 |
| Foreign Objects | 3-69 |
| struct module | 3-70 |
| Structure Alignment | 3-74 |
| Packing Binary Records | 3-75 |
| Unpacking Records | 3-76 |
| Performance Tip | 3-77 |
| struct Comments | 3-78 |
| struct Cautions | 3-79 |
| Binary Arrays | 3-81 |
| ByteArray Objects | 3-82 |
| Direct Array Output | 3-83 |
| Direct Array Input | 3-84 |
| Direct Array Overwriting | 3-86 |
| ctypes module | 3-88 |
| ctypes Types | 3-89 |
| ctypes module | 3-90 |
| ctypes arrays | 3-91 |
| ctypes module | 3-92 |
| ctypes Caution | 3-94 |
| buffer() function | 3-96 |
| buffer() Function | 3-97 |
| Using buffer() | 3-98 |
| Recognizing Buffers | 3-101 |
| Messaging Wrap up | 3-103 |
4. Multiprocessing
| Multiprocessing | 4-1 |
| multiprocessing Module | 4-2 |
| Multiprocessing Tour | 4-4 |
| Processes | 4-5 |
| Functions as Processes | 4-6 |
| multiprocessing Example | 4-7 |
| Launching Processes | 4-8 |
| Does it Work? | 4-9 |
| Other Process Features | 4-10 |
| Process Creation | 4-11 |
| A Caution | 4-12 |
| Distributed Memory | 4-15 |
| Synchronization Primitives | 4-16 |
| Message Queues | 4-17 |
| Joinable Queues | 4-18 |
| Queue Example | 4-19 |
| Commentary | 4-21 |
| Pipes | 4-23 |
| Using Pipes | 4-24 |
| Pipe Setup | 4-25 |
| Advice | 4-26 |
| Pipe Example | 4-27 |
| Pipes vs. Queues | 4-29 |
| Process Pools | 4-31 |
| Async Results | 4-35 |
| Process Pools | 4-36 |
| Using Process Pools | 4-38 |
| Shared Data | 4-40 |
| Shared Example | 4-41 |
| Shared Arrays | 4-42 |
| Locking Performance | 4-43 |
| Lock-Free Sharing | 4-44 |
| Wrap Up | 4-45 |
5. Distributed Programming
| Distributed Programming | 5-1 |
| Introduction | 5-2 |
| A Problem | 5-3 |
| Commentary | 5-4 |
| Silver Bullets | 5-5 |
| Overview | 5-6 |
| Major Topics | 5-7 |
| Actor Programming | 5-8 |
| Actors | 5-9 |
| Features of Actors | 5-10 |
| Actor History | 5-11 |
| Disclosure | 5-12 |
| Actor Implementation | 5-13 |
| An Example | 5-14 |
| Another Example | 5-15 |
| Using Actors | 5-16 |
| A Problem | 5-18 |
| Actor Runtime | 5-19 |
| Async Messaging | 5-20 |
| Concurrency | 5-21 |
| Implementing the Runtime | 5-22 |
| Example: Threaded Actor | 5-23 |
| Actors and Processes | 5-29 |
| Process Issues | 5-30 |
| Actor Addressing | 5-32 |
| Actor Naming | 5-33 |
| Names and Wrappers | 5-36 |
| Name Registry | 5-38 |
| Message Addressing | 5-40 |
| Implementing send() | 5-41 |
| Examples | 5-42 |
| Distributed Actors | 5-44 |
| Connection Objects | 5-45 |
| Distributed Send | 5-49 |
| Proxy Actors | 5-50 |
| Proxy Implementation | 5-51 |
| Using a Proxy | 5-52 |
| Message Dispatching | 5-53 |
| Message Dispatcher | 5-54 |
| Using the Dispatcher | 5-59 |
| Putting it All Together | 5-60 |
| Big Picture | 5-61 |
| Tricky Bits With Actors | 5-63 |
| What's in a Message? | 5-64 |
| Instances and Messages | 5-65 |
| Don't Do It! | 5-69 |
| Actor Naming | 5-70 |
| Name Registry | 5-71 |
| Registry Details | 5-72 |
| Concurrency Alternatives | 5-73 |
| Optional Concurrency | 5-74 |
| Concurrency Alternatives | 5-76 |
| Hard Problems | 5-77 |
| Actor Commentary | 5-79 |
| A Caution | 5-80 |
| Client/Server Computing | 5-81 |
| Client/Server Comments | 5-83 |
| RESTful Services | 5-84 |
| REST Resources | 5-85 |
| Resource Representation | 5-86 |
| REST Actions | 5-87 |
| REST Examples | 5-88 |
| Stateless Implementation | 5-90 |
| Reuse of HTTP | 5-91 |
| Implementing REST | 5-92 |
| Example with WSGI | 5-93 |
| Running an WSGI App | 5-98 |
| RESTful WSGI | 5-100 |
| REST Example | 5-101 |
| Running the Server | 5-105 |
| REST Clients | 5-106 |
| REST Commentary | 5-109 |
| Remote Procedure Call | 5-112 |
| XML-RPC | 5-115 |
| Simple XML-RPC | 5-116 |
| XML-RPC Commentary | 5-118 |
| XML-RPC and Binary | 5-119 |
| XML-RPC and Instances | 5-120 |
| Some Issues | 5-121 |
| More Commentary | 5-122 |
| RPC Libraries | 5-123 |
| Problems with Objects | 5-125 |
| Distributed Objects | 5-126 |
| Server Instances | 5-128 |
| Server Dispatching | 5-129 |
| Client Proxies | 5-130 |
| Object Registry | 5-131 |
| Proxy Creation/Lookup | 5-132 |
| Various Problems | 5-134 |
| Object Managers | 5-135 |
| Managers | 5-136 |
| Using a Manager | 5-137 |
| Manager Example | 5-138 |
| Commentary | 5-143 |
| Hard Problems | 5-144 |
| Some Resources | 5-145 |
| Resources | 5-146 |
| Final Comments | 5-147 |
6. Advanced I/O
| Advanced I/O Handling | 6-1 |
| Introduction | 6-2 |
| Disclaimers | 6-3 |
| Goal | 6-4 |
| I/O Basics | 6-5 |
| Blocking I/O | 6-6 |
| Blocking I/O Rules | 6-9 |
| Caution : Partial Sends | 6-10 |
| Socket Tuning Parameters | 6-11 |
| Non-blocking I/O | 6-13 |
| Non-blocking Sockets | 6-14 |
| Using Non-blocking I/O | 6-15 |
| Overlapped I/O | 6-16 |
| Overlapped I/O Example | 6-17 |
| Commentary | 6-18 |
| Asynchronous I/O | 6-20 |
| Signal Driven I/O | 6-22 |
| Commentary | 6-24 |
| I/O Polling/Multiplexing | 6-25 |
| select module | 6-26 |
| select() function | 6-27 |
| select() performance | 6-30 |
| A select() limitation | 6-32 |
| Event Driven I/O | 6-34 |
| Event Driven "Tasks" | 6-37 |
| Multitasking | 6-40 |
| Example : Time Server | 6-41 |
| A Complication | 6-44 |
| Solution | 6-45 |
| Example : Echo Server | 6-46 |
| Commentary | 6-51 |
| Events and Asyncore | 6-52 |
| Using Asyncore | 6-53 |
| Twisted | 6-54 |
| Twisted Example | 6-55 |
| Event Driven Problems | 6-56 |
| Scaling Problems | 6-57 |
| Some Solutions | 6-59 |
| A Scaling Benefit | 6-60 |
| Long-Running Calculations | 6-61 |
| Blocking Operations | 6-62 |
| The Blocking Problem | 6-63 |
| Incremental Feeding | 6-65 |
| Events and Threads | 6-66 |
| Interoperability Problems | 6-68 |
| Personal Bias | 6-69 |
| Commentary | 6-70 |
7. Generators and Coroutines
| Generators and Coroutines | 7-1 |
| Introduction | 7-2 |
| Reference Material | 7-3 |
| Background Material | 7-4 |
| Generators | 7-5 |
| Generator Functions | 7-7 |
| A Practical Example | 7-9 |
| Generators as Pipelines | 7-10 |
| A Pipeline Example | 7-11 |
| Yield as an Expression | 7-12 |
| Coroutines | 7-13 |
| Coroutine Execution | 7-14 |
| Coroutine Priming | 7-15 |
| Using a Decorator | 7-16 |
| Processing Pipelines | 7-17 |
| An Example | 7-18 |
| Generators as Tasks | 7-21 |
| Program Execution | 7-22 |
| Task Switching | 7-23 |
| An Insight | 7-24 |
| Multitasking Example | 7-25 |
| Scheduling Example | 7-26 |
| Yielding For I/O | 7-29 |
| More About Yield | 7-30 |
| Talking to the Scheduler | 7-31 |
| An Example Task | 7-32 |
| Signaling an I/O Request | 7-33 |
| Implementing I/O Waits | 7-35 |
| Building a Scheduler | 7-36 |
| Example : Time Server | 7-44 |
| Example : Echo Server | 7-45 |
| Comments | 7-48 |
| Problems | 7-50 |
| Some Links | 7-52 |
| More Information | 7-53 |
|