インテル® C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス

例 4

例 4 は、プリミティブに対して組込みオフセットと呼び出しメソッドを使用して、2D ステンシルを線形形式に変換します。

#include <sdlt/sdlt.h>

// 画像のピクセルを表す一般的な C++ オブジェクト
struct RGBs
{
    float red;
    float green;
    float blue;

    RGBs() {}
    RGBs(const RGBs &iOther)
        : red(iOther.red)
        , green(iOther.green)
        , blue(iOther.blue)
    {
    }

    RGBs & operator =(const RGBs &iOther)
    {
        red = iOther.red;
        green = iOther.green;
        blue = iOther.blue;
        return *this;
    }

    RGBs operator + (const RGBs &iOther) const
    {
        RGBs sum;
        sum.red = red + iOther.red;
        sum.green = green + iOther.green;
        sum.blue = blue + iOther.blue;
        return sum;
    }

    RGBs operator * (float iScalar) const
    {
        RGBs scaledColor;
        scaledColor.red = red * iScalar;
        scaledColor.green = green * iScalar;
        scaledColor.blue = blue * iScalar;
        return scaledColor;
    }
};

SDLT_PRIMITIVE(RGBs, red, green, blue)

const int StencilHaloSize = 1;
const int width = 1920;
const int height = 1080;

template<typename AccessorT> void loadImageStub(AccessorT) {}
template<typename AccessorT> void saveImageStub(AccessorT) {}


// 上下左右の隣接するピクセルと平均色フィルターを実行
void main(void)
{
    // 境界条件を回避するため +-1 のパディングを追加
    const int paddedWidth = width + 2 * StencilHaloSize;
    const int paddedHeight = height + 2 * StencilHaloSize;
    int elementCount = paddedWidth*paddedHeight;
    sdlt::soa1d_container<RGBs> inputImage(elementCount);
    sdlt::soa1d_container<RGBs> outputImage(elementCount);

    loadImageStub(inputImage.access());

    SDLT_INLINE_BLOCK
    {
        const int endOfY = StencilHaloSize + height;
        const int endOfX = StencilHaloSize + width;
        for (int y = StencilHaloSize; y < endOfY; ++y)
        {
            // 正しい行を取得するためアクセサーにオフセットを組込む
            auto prevRow = inputImage.const_access((y - 1)*paddedWidth);
            auto curRow = inputImage.const_access(y*paddedWidth);
            auto nextRow = inputImage.const_access((y + 1)*paddedWidth);

            auto outputRow = outputImage.access(y*paddedWidth);

            #pragma omp simd
            for (int ix = StencilHaloSize; ix < endOfX; ++ix)
            {
                sdlt::linear_index x(ix);

                const RGBs color1 = curRow[x - 1];
                const RGBs color2 = curRow[x];
                const RGBs color3 = curRow[x + 1];
                const RGBs color4 = prevRow[x];
                const RGBs color5 = nextRow[x];
                // AOS コードのように見えるが、コンパイラーはオブジェクトの
                // private インスタンスを作成し、インライン展開可能なメソッドを呼び出す
                // アルゴリズムを高レベルに保つ
                const RGBs sumOfColors = color1 + color2 + color3 + color4 + color5;
                const RGBs averageColor = sumOfColors*(1.0f / 5.0f);
                outputRow[x] = averageColor;
            }
        }
    }
    saveImageStub(outputImage.access());
}