使用带有 TBB 的函数指针的性能下降

Performance degradation using function pointers with TBB

我正在尝试使用 TBB 在结构内执行函数。

#include<tbb/tbb.h>
#include<iostream>
#include<vector>
#include<time.h>

const int size = 10000000;

struct add{
    float operator()(const float &x, const float& y)const {
        return x + y;
    }
};

std::vector<float>A(size);
std::vector<float>B(size);

template<typename Function, typename First, typename Second, typename Last>
struct Make{
    Function function;
    First first;
    Second second;
    Last last;
    Make(Function _function) :function(_function){}
    void operator()(int i) const {
        clock_t start = clock();
        for (int j = 0; j < size / 10; j++){
            last[j + i*size / 10] = function(first[j + i*size / 10], second[j + i*size / 10]);
        }
        clock_t end = clock();
        std::cout << (float)(end - start) / CLOCKS_PER_SEC << std::endl;
    }
};


template<typename FirstVector, typename SecondVector, typename Func>
void execute_tbb(place p, FirstVector First, SecondVector Second, Func func){
    struct Make<Func, FirstVector, SecondVector, SecondVector> make(func);
    make.first = First;
    make.second = Second;
    make.last = Second;
    clock_t start = clock();
    tbb::parallel_for(0, 10, 1, make);
    clock_t end = clock();
    std::cout << (float)(end - start) / CLOCKS_PER_SEC << std::endl;
}

void foo(int i){
    clock_t start = clock();
    for (int j = 0; j < size / 10; j++){
        B[j + i*size / 10] = A[j + i*size / 10] + B[j + i*size / 10];
    }
    clock_t end = clock();
    std::cout << (float)(end - start) / CLOCKS_PER_SEC << std::endl;
}

int main(){
    std::fill(A.begin(), A.end(), 1);
    std::fill(B.begin(), B.end(), 2);
    execute_tbb(A.begin(), B.begin(), add());

    clock_t start = clock();
    tbb::parallel_for(0, 10, 1, foo);
    clock_t end = clock();
    std::cout << (float)(end - start) / CLOCKS_PER_SEC << std::endl;

    return 0;
}

代码引用自example under complexity

问题:foo

相比,结构 add 的性能非常差 0.0002

Working:主函数向execute_tbb()传递数据和函数。然后它使用 struct Make 设置数据和函数,以 tbb::parallel_for 可运行的格式执行。 struct Make中的function存放可执行函数add,由execute_tbb中的tbb::parallel_for执行。

$ g++ add.cpp -ltbb -o add

您的问题是在默认优化下,您的 vector<?>::iterator::operator[]vector<?>::operator[] 慢得多。

正确的解决方法是使用 -O2-O3 进行编译——在分析之前先优化它们。未经优化编译的代码仅用于调试非性能问题。

一个简单的解决方法是将对 A.begin() 的调用替换为 A.data(),对 B.begin() 的调用也类似,将迭代器访问替换为原始指针访问。然后在没有优化的情况下,我猜测指针上的 [] 至少与 vector::operator[].

一样快