Beruflich Dokumente
Kultur Dokumente
Morten Sørvig
Pronounced like "more–ten sir–wig"
Software developer at Trolltech since 2004
Responsibilities:
Threading
Qt/Mac
Agenda
Introduction
API in detail
Demo
3
Note!
4
Introduction
5
Multi-Core Hardware
6
Multi-Core Software
Think parallel!
First step: Identify tasks that can be parallelized
7
qt3to4
AST
Parse source files in parallel
cpp
cpp AST
cpp AST
8
Assistant
9
Image Viewer
10
What's next?
11
I'll use threads!"
12
Threads Considered Harmful
Non-deterministic
Requires synchronization
Dead-locks & race conditions
How many threads should I use?
13
Threads Considered Useful After All
14
Structured Threaded Programming
15
API in Detail
16
Overview
QtConcurrent namespace
run()
map(), mapped(), mappedReduced()
Synchronization objects
QFuture
QFutureWatcher
17
Two Aspects
18
Asynchronous Behavior - run()
void hello()
{
qDebug() << "Hello World";
}
QtConcurrent::run(hello);
19
Behind the Scenes
20
Synchronizing
...
greeting.waitForFinished();
21
Future?
22
QFuture<T>
23
Return values
QImage loadImage()
{
Qimage image;
image.load("foo.jpg");
return image;
}
24
Return values
QImage loadImage()
{
Qimage image;
image.load("foo.jpg");
return image;
}
25
Function Arguments
run(loadImage, QLatin1String("foo.jpg"));
26
Member Functions
class Greeter
{
void sayHello()
{
qDebug() << "Hello World";
}
};
Greeter greeter;
run(&Greeter::sayHello, &greeter);
run(&Greeter::sayHello, greeter);
27
Non-blocking Synchronization
28
QFutureWatcher<T>
QObject
Non-blocking synchronization
Callbacks using signals and slots
29
QFutureWatcher
class Greeter : public QObject
{
Q_OBJECT
private:
void sayHello();
private slots:
void greetingCompleted();
};
30
QFutureWatcher
// In the class constructor:
QFutureWatcher<void> *greeting = new
QFutureWatcher<void>(this);
connect(greeting, SIGNAL(finished()),
SLOT(greetingCompleted()));
...
// In a member function:
greeting->setFuture(run(&Greeter::sayHello, this));
31
QFutureWatcher
// In the class constructor:
QFutureWatcher<void> *greeting = new
QFutureWatcher<void>(this);
connect(greeting, SIGNAL(finished()),
SLOT(greetingCompleted()));
...
// In a member function:
greeting->setFuture(run(&Greeter::sayHello, this));
32
QFutureWatcher
// In the class constructor:
QFutureWatcher<void> *greeting = new
QFutureWatcher<void>(this);
connect(greeting, SIGNAL(finished()),
SLOT(greetingCompleted()));
...
// In a member function:
greeting->setFuture(run(&Greeter::sayHello, this));
33
Summary – Asynchronous behavior
34
Scaling for Multi-Core
35
map
...
QList<QImage> images;
map(images, scale);
36
mapped
...
37
mappedReduced
...
38
mappedReduced
...
39
Filter – filtered - filteredReduced
...
QList<QImage> colorImages =
filtered(images, isColorImage);
40
Member functions
void QImage::invertPixels();
...
QList<QImage> images;
map(images, &QImage::invertPixels);
41
Iterators
QList<QImage> images;
map(images.begin(), image.end(),
&QImage::invertPixels);
42
Summary – scaling for multicore
43
Recap
Concurrent
Parallel
Can they be combined?
44
Two Versions of mapped()
Synchronous:
QList<T> QtConcurrent::blocking::mapped(...)
Asynchronous:
QFuture<T> QtConcurrent::mapped(...)
45
QFutureWatcher supports:
Result notifications
Progress notifications
Canceling
46
Result Notifications
47
Result Notifications
class ImageHandler public: QObject
{
QFutureWatcher<QImage> *watcher;
public:
ImageHandler()
{
watcher = new ...
connect(watcher, SIGNAL(resultReadyAt(int)),
SLOT(imageReadyAt(int)))
}
private slots:
void imageReady(int index)
{
QImage image = watcher->resultAt(index);
}
};
48
Result Notifications
class ImageHandler public: QObject
{
QFutureWatcher<QImage> *watcher;
public:
ImageHandler()
{
watcher = new ...
connect(watcher, SIGNAL(resultReadyAt(int)),
SLOT(imageReadyAt(int)));
}
private slots:
void imageReady(int index)
{
QImage image = watcher->resultAt(index);
}
};
49
Result Notifications
class ImageHandler public: QObject
{
QFutureWatcher<QImage> *watcher;
public:
ImageHandler()
{
watcher = new ...
connect(watcher, SIGNAL(resultReadyAt(int)),
SLOT(imageReadyAt(int)))
}
private slots:
void imageReady(int index)
{
QImage image = watcher->resultAt(index);
}
};
50
Too Many results?
51
Progress Notification and Canceling
Progress updates:
progressRangeChanged(minimum, maximum)
progressValueChanged(value)
Canceling:
cancel()
52
Connecting a QProgressDialog
53
Connecting a QProgressDialog
QProgressDialog *dialog = ...
QFutureWatcher<void> *fw = ...
connect(fw, SIGNAL(progressValueChanged(int)),
dialog, SLOT(setValue(int)));
54
Connecting a QProgressDialog
QProgressDialog *dialog = ...
QFutureWatcher<void> *fw = ...
connect(fw, SIGNAL(progressValueChanged(int)),
dialog, SLOT(setValue(int)));
55
Connecting a QProgressDialog
QProgressDialog *dialog = ...
QFutureWatcher<void> *fw = ...
connect(fw, SIGNAL(progressValueChanged(int)),
dialog, SLOT(setValue(int)));
56
Connecting a QProgressDialog
connect(fw, SIGNAL(finished()),
dialog, SLOT(reset()));
connect(dialog, SIGNAL(canceled()),
fw, SLOT(cancel()));
fw->setFuture(map(list, function));
dialog->exec();
57
Connecting a QProgressDialog
connect(fw, SIGNAL(finished()),
dialog, SLOT(reset()));
connect(dialog, SIGNAL(canceled()),
fw, SLOT(cancel()));
fw->setFuture(map(list, function));
dialog->exec();
58
Demo
Load images
Scale down
Display thumbnails
QThread
QtConcurrent
59
End
Questions?
60
Emergency Slides
61
Jambi support
62
Custom Worker Threads
63
QThreadPool
64
QThreadManager
65
QFutureInterface
66
Safety
67
Example – creating a Task
void run(foo);
68
Task Example
void primes(QFutureInteface<int> &interface,
int begin, int end)
{
setProgressRange(begin, end);
int current = begin;
while (isCanceled() == false && current < end) {
if (isPrime(current))
reportResult(current);
setProgressValue(current);
++current;
}
}
69
Exceptions
try {
map(images, foo);
} catch (Exception e) {
...
}
70
Exceptions – the catch:
71
Producer / Consumer
bool Result::isValid()
int Result::index()
72
Efficient Producer / Consumer
QFutureWatcher::resultsReady();
73
Argument binding
Use boost::bind
Will also be a part of C++09
QList<QImage> image;
map(image, bind(image, 100));
74
STL containers
vector<int> vector;
vector<int> result =
mapped(vec.begin(), vec.end(), foo):
75
QFutureSynchronizer
void foo()
{
QFuture<void> future = ...
QFutureSynchronizer<void> sync(future);
if (...)
return;
}
76
Qt Concurrent vs OpenMP
QtConcurrent::map(list, foo);
//--------------
omp_set_num_threads(QThread::idealThreadCount());
77
Qt Concurrent vs TBB
QtConcurrent::map(list, foo);
//--------------
class ApplyFoo
{
List list;
public:
void operator()(const BLockedRange<size_t> &r) const {
for (size_t i = r.begin(); i != r.end() ++i)
foo(list[i]);
}
ApplyFoo(List &list)
: list(list) { }
};
ParallelFor(BlockedRange<size_t>(0, list.count()),
ApplyFoo(list), auto_partitioner());
78