QtConcurrentの簡単な例
QtConcurrentはQtの並列処理を行うモジュールです。
プロジェクトファイルの設定
QtConcurrentを使用するには、.proファイルにconcurrentを追加します。
QT += concurrent
サンプルプログラム
QtConcurrentを使用した単純なサンプルプログラムです。
まず、処理を行うデータのクラスを作成します。 単純にint値を保持するだけです…(^_^;)
/**
* @brief The Params class
*/
class Params {
public:
/**
* @brief Params
* コンストラクタ
* @param[in] val 初期値
*/
Params(const int val) : _value{val} {
}
/**
* @brief setValue
* 値設定
* @param[in] val 設定値
*/
void setValue(const int val) {
_value = val;
}
/**
* @brief value
* 設定値取得
* @return
*/
int value() const {
return _value;
}
private:
int _value; //!< 設定値
};
次に処理結果を示すクラスを作成します。 これも単にint値を保持するだけです。
/**
* @brief The Result class
*/
class Result {
public:
/**
* @brief Result
* コンストラクタ
* @param[in] val 設定するリザルト値
*/
Result(const int val) : _value{val} {
}
/**
* @brief Result
* デフォルトコンストラクタ
*/
Result() : _value{0} {
}
/**
* @brief value
* リザルト値取得
* @return リザルト値
*/
int value() const {
return _value;
}
private:
int _value; //!< リザルト値
};
次に、順次処理と並列処理を行うクラスを作成します。
/**
* @brief The TestClass class
*/
class TestClass {
public:
/**
* @brief TestClass
* コンストラクタ
*/
TestClass();
void execute1();
void execute2();
private:
QList<Params> generateParamsSet();
static Result someReallyTimeConsumingFunction(const Params ¶ms);
static Result calculateStats(const Params ¶ms);
};
/**
* @brief TestClass
* コンストラクタ
*/
TestClass::TestClass() {
}
/**
* @brief execute1
* シーケンシャル処理テスト関数
*/
void TestClass::execute1() {
QList<Params> params = generateParamsSet();
QList<Result> results;
for (int i = 0; i < params.size(); ++i)
results.append(someReallyTimeConsumingFunction(params[i]));
foreach (Result r, results)
std::cout << r.value() << " ";
std::cout << std::endl << std::flush;
}
/**
* @brief TestClass::execute2
* 並列処理テスト関数
*/
void TestClass::execute2() {
QList<Params> params = generateParamsSet();
QList<Result> results = QtConcurrent::blockingMapped(params, &calculateStats);
foreach (Result r, results)
std::cout << r.value() << " ";
std::cout << std::endl << std::flush;
}
/**
* @brief generateParamsSet
* 初期値設定処理
* @return 設定された初期値リスト
*/
QList<Params> TestClass::generateParamsSet() {
QList<Params> params;
for (int i = 0; i < COUNT_MAX; ++i)
params.append(Params(i));
return params;
}
/**
* @brief someReallyTimeConsumingFunction
* 各要素に対する処理(時間のかかる処理本体)
* @param[in] params 処理するパラメータリスト
* @return リザルト値オブジェクト
*/
Result TestClass::someReallyTimeConsumingFunction(const Params ¶ms) {
qApp->thread()->msleep(10);
int r = 0;
r = std::pow(params.value(), 2);
return Result(r);
}
/**
* @brief calculateStats
* 並行処理実行関数
* @param[in] params パラメータリスト
* @return リザルトオブジェクト
*/
Result TestClass::calculateStats(const Params ¶ms) {
return someReallyTimeConsumingFunction(params);
}
最後に、テストを実行するメイン処理を実装します。
/**
* @brief main
* プログラムメイン
* @param argc
* @param argv
* @return
*/
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QElapsedTimer et;
TestClass t;
// シーケンシャル処理
et.start();
t.execute1();
std::cout << "elapsed time:" << et.elapsed() << std::endl << std::flush;
// 並列処理
et.restart();
t.execute2();
std::cout << "elapsed time:" << et.elapsed() << std::endl << std::flush;
return 0;
}
実行結果
上記のプログラムの実行結果を示します。
※これはWindows10上のQt 5.12.8を使用した結果です。(CPUはi9-9900K) 並列処理を行った場合の処理時間の短さがわかりますね(^_^;)
QtConcurrent非対応の場合を加味する
QtConcurrentが使用できない環境のへの対応が必要な場合は、QT_NO_CONCURRENTを使用して処理を振り分けます。
#if defined(QT_NO_CONCURRENT)
// シーケンシャル処理
et.start();
t.execute1();
std::cout << "elapsed time:" << et.elapsed() << std::endl << std::flush;
#else
// 並列処理
et.restart();
t.execute2();
std::cout << "elapsed time:" << et.elapsed() << std::endl << std::flush;
#endif
プログラム全体
最後に、プログラム全体を示します。
#include <iostream>
#include <QObject>
#include <QCoreApplication>
#include <QElapsedTimer>
#include <QThread>
#include <QtConcurrent>
constexpr int COUNT_MAX = 500;
/**
* @brief The Params class
*/
class Params {
public:
/**
* @brief Params
* コンストラクタ
* @param[in] val 初期値
*/
Params(const int val) : _value{val} {
}
/**
* @brief setValue
* 値設定
* @param[in] val 設定値
*/
void setValue(const int val) {
_value = val;
}
/**
* @brief value
* 設定値取得
* @return
*/
int value() const {
return _value;
}
private:
int _value; //!< 設定値
};
/**
* @brief The Result class
*/
class Result {
public:
/**
* @brief Result
* コンストラクタ
* @param[in] val 設定するリザルト値
*/
Result(const int val) : _value{val} {
}
/**
* @brief Result
* デフォルトコンストラクタ
*/
Result() : _value{0} {
}
/**
* @brief value
* リザルト値取得
* @return リザルト値
*/
int value() const {
return _value;
}
private:
int _value; //!< リザルト値
};
/**
* @brief The TestClass class
*/
class TestClass {
public:
/**
* @brief TestClass
* コンストラクタ
*/
TestClass();
void execute1();
void execute2();
private:
QList<Params> generateParamsSet();
static Result someReallyTimeConsumingFunction(const Params ¶ms);
static Result calculateStats(const Params ¶ms);
};
/**
* @brief TestClass
* コンストラクタ
*/
TestClass::TestClass() {
}
/**
* @brief execute1
* シーケンシャル処理テスト関数
*/
void TestClass::execute1() {
QList<Params> params = generateParamsSet();
QList<Result> results;
for (int i = 0; i < params.size(); ++i)
results.append(someReallyTimeConsumingFunction(params[i]));
foreach (Result r, results)
std::cout << r.value() << " ";
std::cout << std::endl << std::flush;
}
/**
* @brief TestClass::execute2
* 並列処理テスト関数
*/
void TestClass::execute2() {
QList<Params> params = generateParamsSet();
QList<Result> results = QtConcurrent::blockingMapped(params, &calculateStats);
foreach (Result r, results)
std::cout << r.value() << " ";
std::cout << std::endl << std::flush;
}
/**
* @brief generateParamsSet
* 初期値設定処理
* @return 設定された初期値リスト
*/
QList<Params> TestClass::generateParamsSet() {
QList<Params> params;
for (int i = 0; i < COUNT_MAX; ++i)
params.append(Params(i));
return params;
}
/**
* @brief someReallyTimeConsumingFunction
* 各要素に対する処理(時間のかかる処理本体)
* @param[in] params 処理するパラメータリスト
* @return リザルト値オブジェクト
*/
Result TestClass::someReallyTimeConsumingFunction(const Params ¶ms) {
qApp->thread()->msleep(10);
int r = 0;
r = std::pow(params.value(), 2);
return Result(r);
}
/**
* @brief calculateStats
* 並行処理実行関数
* @param[in] params パラメータリスト
* @return リザルトオブジェクト
*/
Result TestClass::calculateStats(const Params ¶ms) {
return someReallyTimeConsumingFunction(params);
}
/**
* @brief main
* プログラムメイン
* @param argc
* @param argv
* @return
*/
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QElapsedTimer et;
TestClass t;
// シーケンシャル処理
et.start();
t.execute1();
std::cout << "elapsed time:" << et.elapsed() << std::endl << std::flush;
// 並列処理
et.restart();
t.execute2();
std::cout << "elapsed time:" << et.elapsed() << std::endl << std::flush;
return 0;
}