2 つの画像 (配列) の乗算に Intel IPP を使用しています。
Intel Composer 2015 Update 6 に付属する Intel IPP 8.2 を使用しています。
大きすぎる画像を乗算する簡単な関数を作成しました (プロジェクト全体が添付されています。以下を参照してください)。
インテル® IPP マルチスレッド・ライブラリーを使用した場合の利点を確認したかったのです。
簡単なプロジェクトを次に示します (Visual Studio から完全なプロジェクトも添付しました)。
#include "ippi.h"
#include "ippcore.h"
#include "ipps.h"
#include "ippcv.h"
#include "ippcc.h"
#include "ippvm.h"
#include <ctime>
#include <iostream>
using namespace std;
const int height = 6000;
const int width = 6000;
Ipp32f mInput_image [1 * width * height];
Ipp32f mOutput_image[1 * width * height] = {0};
int main()
{
IppiSize size = {width, height};
double start = clock();
for (int i = 0; i < 200; i++)
ippiMul_32f_C1R(mInput_image, 6000 * 4, mInput_image, 6000 * 4, mOutput_image, 6000 * 4, size);
double end = clock();
double douration = (end - start) / static_cast<double>(CLOCKS_PER_SEC);
cout << douration << endl;
cin.get();
return 0;
}
このプロジェクトは、インテル IPP シングルスレッドを使用して 1 回、インテル IPP マルチスレッドを使用して 1 回コンパイルしました。
さまざまなサイズの配列を試してみましたが、そのすべてにおいて、マルチスレッド バージョンでは効果がありません (さらに遅い場合もあります)。
マルチスレッドでこのタスクに利益がないのはなぜですか?
Intel IPP が AVX を使用していることは知っていますが、タスクがメモリ制限になるのではないかと思いました。
OpenMP を手動で使用して別のアプローチを試み、Intel IPP シングル スレッド実装を使用したマルチスレッド アプローチを採用しました。
これはコードです:
#include "ippi.h"
#include "ippcore.h"
#include "ipps.h"
#include "ippcv.h"
#include "ippcc.h"
#include "ippvm.h"
#include <ctime>
#include <iostream>
using namespace std;
#include <omp.h>
const int height = 5000;
const int width = 5000;
Ipp32f mInput_image [1 * width * height];
Ipp32f mOutput_image[1 * width * height] = {0};
int main()
{
IppiSize size = {width, height};
double start = clock();
IppiSize blockSize = {width, height / 4};
const int NUM_BLOCK = 4;
omp_set_num_threads(NUM_BLOCK);
Ipp32f* in;
Ipp32f* out;
// ippiMul_32f_C1R(mInput_image, width * 4, mInput_image, width * 4, mOutput_image, width * 4, size);
#pragma omp parallel \
shared(mInput_image, mOutput_image, blockSize) \
private(in, out)
{
int id = omp_get_thread_num();
int step = blockSize.width * blockSize.height * id;
in = mInput_image + step;
out = mOutput_image + step;
ippiMul_32f_C1R(in, width * 4, in, width * 4, out, width * 4, blockSize);
}
double end = clock();
double douration = (end - start) / static_cast<double>(CLOCKS_PER_SEC);
cout << douration << endl;
cin.get();
return 0;
}
結果は同じで、パフォーマンスの向上はありませんでした。
この種のタスクでマルチスレッドを活用する方法はありますか?
タスクがメモリ制限になり、並列化してもメリットがないかどうかを検証するにはどうすればよいですか? CPU で 2 つの配列を乗算するタスクを AVX で並列化する利点はありますか?
私が試したコンピュータは、Core i7 4770k (Haswell) ベースです。
Visual Studio 2013のプロジェクトへのリンクは次のとおりです。
ありがとうございました。