Show Lecture.Threads as a slide show.
CS253 Threads
pthreads
- pthreads
- A POSIX standard, not a C++ standard.
- They’re great.
- They still work, and will continue to do so forever.
- If your existing code uses pthreads, leave it alone.
- C++ threads
- I prefer them for new work.
- They became standard with C++ 2011, so they’re fairly well
established, now.
- I’ll bet that they’re implemented using pthreads.
Simple task
This small program counts the numbers under a billion that are
divisible by seventeen, and shows how long that took to run.
int count = 0;
for (int i=1; i<=1e9; i++)
count += (i % 17 == 0);
cout << count << '\n';
58823529
Real time: 726 ms
Of course it’s a stupid program.
The result is ⌊10⁹ ÷ 17⌋ = 58823529.
Threading
- This task lends itself to parallel processing, with each sub-task
(or thread) executing on a separate CPU.
- One thread could scan 1–100M,
the next thread would scan 100M–200M, the next 200M–300M, etc.
- After all threads are done, add up the results.
// How many CPUs?
cout << thread::hardware_concurrency();
12
How it Usually Works
- With traditional threading facilities (e.g., pthreads), you have to:
- create a new thread for each sub-task
- wait for the threads to finish
- obtain the results for each thread
- You can still operate that way with C++ threads, but you can
also do it a lot easier using the
future<
type>
templated class.
- It contains a value that will be computed asynchronously.
- When you ask for the value, it’ll wait for the value to be computed.
Threaded
int count_them(int start, int count) {
int found = 0;
for (int i=start; i<start+count; i++)
found += (i % 17 == 0);
return found;
}
int main() {
vector<future<int>> counts;
const auto block = 1e9 / thread::hardware_concurrency();
for (int b=1; b<=1e9; b+=block)
counts.emplace_back(async(count_them, b, block));
int total = 0;
for (auto &w : counts)
total += w.get();
cout << total << '\n';
}
63725489
Real time: 172 ms
Details
Remember to:
#include <future>
for std::future
and std::async
.
- Compile & link with
g++ -O3 -pthread
to get
optimization and the thread library.
Other
We’ve just scratched the surface. Other cool stuff:
-
<atomic>
-
integral types which can be safely incremented in threads without
problems from a race condition
-
<mutex>
-
mutexes, for mutual exclusion, which guard critical sections of
code that musn’t run in several threads simutaneously
-
<condition>
-
blocking and resuming threads until it’s ok for them to run
-
<thread>
-
general thread control: creation, status, killing, joining, etc.