优化C++模板执行

nos*_*bor 3 c++ algorithm optimization templates

我正在开展性能至关重要的项目.该应用程序正在处理大量数据.代码是用C++编写的,我需要做一些更改.

给出了以下代码(这不是我的代码,我把它简化为最小):

void process<int PARAM1, int PARAM2>() {
    // processing the data
}

void processTheData (int param1, int param2) { // wrapper

    if (param1 == 1 && param2 == 1) { // Ugly looking block of if's
        process<1, 1>();
    else if(param1 == 1 && param2 == 2) {
        process<1, 2>();
    else if(param1 == 1 && param2 == 3) {
        process<1, 3>();
    else if(param1 == 1 && param2 == 4) {
        process<1, 4>();
    else if(param1 == 2 && param2 == 1) {
        process<2, 1>();
    else if(param1 == 2 && param2 == 2) {
        process<2, 2>();
    else if(param1 == 2 && param2 == 3) {
        process<2, 3>();
    else if(param1 == 2 && param2 == 4) {
        process<2, 4>();
    }   // and so on....

}
Run Code Online (Sandbox Code Playgroud)

主要功能:

int main(int argc, char *argv[]) {

    factor1 = atoi(argv[1]);
    factor2 = atoi(argv[2]);

    // choose some optimal param1 and param2
    param1 = choseTheOptimal(factor1, factor2);
    param2 = choseTheOptimal(factor1, factor2);

    processTheData(param1, param2); //start processing

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

希望代码看起来很清楚.

功能:

  • process是处理数据的核心功能,
  • processTheData是流程函数的包装器.

params(param1param2)所采用的值有限(假设大约10 x 10).

执行前不知道param1param2的值.

如果我只是重写过程函数,那么它使用函数参数而不是模板常量(表示process(int PARAM1,int PARAM2)),那么处理速度大约慢10倍.

由于上述原因,PARAM1PARAM2必须是过程函数的常数.

有没有什么聪明的方法可以摆脱这个丑陋的if块位于processTheData函数中?

Ric*_*ges 8

像这样.

#include <array>
#include <utility>

template<int PARAM1, int PARAM2>
void process() {
    // processing the data
}

// make a jump table to call process<X, Y> where X is known and Y varies    
template<std::size_t P1, std::size_t...P2s>
constexpr auto make_table_over_p2(std::index_sequence<P2s...>)
{
    return std::array<void (*)(), sizeof...(P2s)>
    {
        &process<int(P1), int(P2s)>...
    };
}

// make a table of jump tables to call process<X, Y> where X and Y both vary    
template<std::size_t...P1s, std::size_t...P2s>
constexpr auto make_table_over_p1_p2(std::index_sequence<P1s...>, std::index_sequence<P2s...> p2s)
{
    using element_type = decltype(make_table_over_p2<0>(p2s));
    return std::array<element_type, sizeof...(P1s)>
    {
        make_table_over_p2<P1s>(p2s)...
    };
}


void processTheData (int param1, int param2) { // wrapper

    // make a 10x10 jump table
    static const auto table = make_table_over_p1_p2(
        std::make_index_sequence<10>(), 
        std::make_index_sequence<10>()
    ) ;

    // todo - put some limit checks here

    // dispatch
    table[param1][param2]();
}
Run Code Online (Sandbox Code Playgroud)