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

Performance degradation using function pointers with TBB

本文关键字:指针 性能 函数 TBB      更新时间:2023-10-16

我试图使用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;
}

代码在复杂度下从示例中引用。

问题:结构add的性能比foo差0.0002倍

Working: main函数传递数据和函数给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[] s比vector<?>::operator[]慢得多。

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

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