使用带有 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[]
.
一样快
我正在尝试使用 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[]
.