Перші спроби багатопотокового програмування Qt5
Існує задача обробки зображень, по пікселям обробляється у циклі.
Наприклад:
for (int i = 0; i < numPixels; i++, data += pixelSize) {
if (output->colors == 3) {
pixels[i * 4] = data[2 * colorSize];
pixels[i * 4 + 1] = data[1 * colorSize];
pixels[i * 4 + 2] = data[0];
}
else {
pixels[i * 4] = data[0];
pixels[i * 4 + 1] = data[0];
pixels[i * 4 + 2] = data[0];
}
}
З метою оптимізації розрахунку, спробую використати можливості багатопроцесорного комп’ютера.
Використовуючи фрейморк Qt 5.4.0. Створив новий клас IncTask. Вхідні дані до потоку можливо передати тільки під час ініціалізації класу. А надалі використовувати приватні змінні.
#include <QRunnable>
#include <QThreadPool>
class IncTask : public QRunnable {
public:
IncTask(int sstart, int scolorSize, int scolors, int spixelSize,
int snumPixels, uchar *sdata, uchar *spixels) :
start(sstart),
colorSize(scolorSize),
colors(scolors),
pixelSize(spixelSize),
numPixels(snumPixels),
cdata(sdata),
pixels(spixels)
{
}
virtual void run()
{
qDebug() << "from thread start" << start << "end" << numPixels;
uchar *data = cdata;
data += (pixelSize*start);
for (int i = start; i < numPixels; i++, data += pixelSize) {
if (colors == 3) {
pixels[i * 4] = data[2 * colorSize];
pixels[i * 4 + 1] = data[1 * colorSize];
pixels[i * 4 + 2] = data[0];
}
else {
pixels[i * 4] = data[0];
pixels[i * 4 + 1] = data[0];
pixels[i * 4 + 2] = data[0];
}
}
}
virtual bool autoDelete(){
return true;
}
private:
int start, colorSize, colors, pixelSize, numPixels;
uchar *cdata;
uchar *pixels;
};
Надалі у тілі програми, створюємо екземпляри класу IncTask у кількості рівної максимальної кількості потоків у системі. У моєму випадку це 8.
qDebug() << "converting LIBRAW_IMAGE_RAW";
int numPixels = output->width * output->height;
int colorSize = output->bits / 8;
int pixelSize = output->colors * colorSize;
pixels = new uchar[numPixels * 4];
uchar *data = output->data;
timer.restart();
//split calculation to threads
int maximumThreadCount = QThreadPool::globalInstance()->maxThreadCount();
qDebug() << "maximumThreadCount" << maximumThreadCount;
int threadCount = maximumThreadCount; int perThread = numPixels / threadCount;
for (int threadId = 0; threadId<threadCount; threadId++){
int start = perThread*threadId;
int end = (perThread*(threadId + 1));
QThreadPool::globalInstance()->start(new IncTask(start, colorSize, output->colors, pixelSize, end, data, pixels));
}
QThreadPool::globalInstance()->waitForDone();
qDebug() << "converting loop elapsed" << timer.elapsed() / 1000. << "sec.";
Таким чином на потоки розбито частини обробки всього зображення на потоки.
converting LIBRAW_IMAGE_RAW
maximumThreadCount 8
from thread start 0 end 2263744
from thread start 2263744 end 4527488
from thread start 4527488 end 6791232
from thread start 6791232 end 9054976
from thread start 9054976 end 11318720
from thread start 11318720 end 13582464
from thread start 13582464 end 15846208
from thread start 15846208 end 18109952
converting loop elapsed 0.034 sec.
| Дяка: QThreadPool - BlackBerry Native, code of QtRaw, [Qt Multi Threaded Programming | Ynon Perek](http://ynonperek.com/course/qt/threads.html) |
