SIMD指令

时间:2015-08-18 15:00:09

标签: c++ templates openmp standards vectorization

我正在开发一些并行的C ++模拟代码,我想尽可能有效地进行矢量化。这就是我使用模板参数和OpenMP SIMD指令的原因:

  • 模板参数用于解决在最关键的循环中可能发生的一些条件,通过在编译时解析它们并完全删除相应的分支。
  • OpenMP SIMD指令强制编译器生成矢量化代码。

我的意思的一个(愚蠢的)例子如下:

template< bool checkNeeded >
int ratio( double *res, double *num, double *denom, int n ) {
    #pragma omp simd
    for ( int i = 0; i < n; i++ ) {
        if ( checkNeeded ) { // dead code removed by the compiler when template is false
            if ( denom == 0 ) {
                std::cout << "Houston, we've got a problem\n";
                return i;
            }
        }
        res[i] = num[i] / denom[i];
    }
    return n;
}

在全球范围内,它运行良好,但我遇到的麻烦是在(非常罕见的)我希望使用代码的ratio<true>()版本的情况下,这个由编译器进行了矢量化,因为#pragma omp simd指令,由于测试,打印和循环的早期退出,比非矢量化版本慢... 所以我需要的是在我的if指令中添加simd子句,指示编译器何时服从指令。这会是这样的:

#pragma omp simd if( checkNeeded == false )

不幸的是,尽管许多OpenMP指令支持这样的if条款,但它不适用于simd ...我不认为我的请求是完全愚蠢的,所以我想知道为什么是这样的,以及它是否有可能在未来得到支持。 有人知道吗?

3 个答案:

答案 0 :(得分:2)

  

我不认为我的请求是完全愚蠢的,所以我想知道为什么   所以,以及它是否有可能在未来得到支持。任何人   我知道吗?

SIMD指令在编译时影响代码生成,而&#34; if&#34;其他OpenMP构造的子句实现了运行时测试。 (&#34; if&#34;条件不是编译时常量)。实施&#34; if&#34;因此,在SIMD子句中,需要编译器克隆循环体并生成两个不同的版本,然后选择在运行时动态执行的版本。

这对于一个非常罕见的情况似乎付出了很多努力,所以我怀疑它是否会成为标准。 (而且,无论如何,在这一点上,你可以看到它的第一个标准是赢了几年,所以你可能需要更实用的修复: - )

答案 1 :(得分:1)

扩展user3528438的注释,这可能是将您的功能分成两个不同功能的最合理的地方之一。一个处理false的情况,并按照您的方式编写,另一个处理true情况并且没有simd命令。

或者,如果你坚持使用一个功能,你可以很容易地写

template< bool checkNeeded >
int ratio( double *res, double *num, double *denom, int n ) {
    if (!checkNeeded) {
        #pragma omp simd
        for ( int i = 0; i < n; i++ ) {
            res[i] = num[i] / denom[i];
        }
        return n;
    } else {
        for ( int i = 0; i < n; i++ ) {
            if ( denom == 0 ) {
                std::cout << "Houston, we've got a problem\n";
                return i;
            }
            res[i] = num[i] / denom[i];
        }
        return n;
    }
}

这会比false案例中的初始函数稍慢,因为有一个if语句要评估(假设n很大,则不是一个很重要的因素[甚至大于10且你不应该'注意减速])。此外,true情况会更快,因为您不必每次迭代都要评估第一个if语句。

答案 2 :(得分:0)

template< bool checkNeeded >
int ratio( double *res, double *num, double *denom, int n );// c++ declaration

template<>int ratio<true>( double *res, double *num, double *denom, int n ) 
{

    for ( int i = 0; i < n; i++ ) {
        res[i] = num[i] / denom[i];
    }
    return n;
}

template<>int ratio<false>( double *res, double *num, double *denom, int n ) {
    for ( int i = 0; i < n; i++ ) {
        if ( denom == 0 ) {
            std::cout << "Houston, we've got a problem\n";
            return i;
        }
        res[i] = num[i] / denom[i];
        }
    return n;
}

How do I explicitly instantiate a template function?