イメージ/イメージの領域を操作するために Intel IPP によって定義された関数があります。
画像への入力は、画像へのポインター、処理するサイズを定義するパラメーター、およびフィルターのパラメーターです。
IPP 関数はシングルスレッドです。
これで、サイズ M x N の画像が
できました。フィルターを並列に適用したいと思います。
主なアイデアは単純で、画像を互いに独立した 4 つのサブ画像に分割します。
フィルターを各サブ画像に適用し、結果を空の画像のサブ ブロックに書き込みます。各スレッドは、個別のピクセル セットに書き込みます。
それは、それぞれ独自のコアで 4 つの画像を処理するようなものです。
これは私がそれをやっているプログラムです:
void OpenMpTest()
{
const int width = 1920;
const int height = 1080;
Ipp32f input_image[width * height];
Ipp32f output_image[width * height];
IppiSize size = { width, height };
int step = width * sizeof(Ipp32f);
/* Splitting the image */
IppiSize section_size = { width / 2, height / 2};
Ipp32f* input_upper_left = input_image;
Ipp32f* input_upper_right = input_image + width / 2;
Ipp32f* input_lower_left = input_image + (height / 2) * width;
Ipp32f* input_lower_right = input_image + (height / 2) * width + width / 2;
Ipp32f* output_upper_left = input_image;
Ipp32f* output_upper_right = input_image + width / 2;
Ipp32f* output_lower_left = input_image + (height / 2) * width;
Ipp32f* output_lower_right = input_image + (height / 2) * width + width / 2;
Ipp32f* input_sections[4] = { input_upper_left, input_upper_right, input_lower_left, input_lower_right };
Ipp32f* output_sections[4] = { output_upper_left, output_upper_right, output_lower_left, output_lower_right };
/* Filter Params */
Ipp32f pKernel[7] = { 1, 2, 3, 4, 3, 2, 1 };
omp_set_num_threads(4);
#pragma omp parallel for
for (int i = 0; i < 4; i++)
ippiFilterRow_32f_C1R(
input_sections[i], step,
output_sections[i], step,
section_size, pKernel, 7, 3);
}
ここでの問題は、すべてのイメージでシングル スレッド モードを使用する場合と比較して、利益が見られないことです。
画像サイズまたはフィルターサイズを変更しようとしましたが、画像は何も変わりません。
私が得ることができた最大のものは、重要なものではありませんでした (10-20%)。
受け取ったゾーンが「読み取り専用」である各スレッドを「約束」できないことに関係があるのではないかと思いました。
さらに、書き込み先のメモリの場所も自分だけのものであることを知らせます。
変数をプライベートおよび共有として定義することについて読みましたが、配列とポインターを処理するためのガイドが見つかりませんでした。
OpenMP でポインターとサブ配列を処理する適切な方法は何でしょうか?