Optimization 访问for循环中的向量元素,比较几种方法

Optimization 访问for循环中的向量元素,比较几种方法,optimization,c++11,vector,benchmarking,Optimization,C++11,Vector,Benchmarking,我编写了一个小的基准测试程序来检查访问向量中存储的数据的一些方法。 我使用tww嵌套for循环来对抗 A) 为第一个循环的每次迭代创建对向量对象的引用,并在第二个for循环中使用该引用 B) 创建一个指针,在该指针中为第一个循环的每次迭代存储对向量对象的引用,并在第二个for循环中使用该指针 C) 使用[]运算符直接访问向量对象 D) 在第一个循环中使用auto&命令 这对嵌套for循环本身与一个计时函数一起嵌套在另一个循环中。 运行测试几次,for循环从0到100,对于所有这些方法,我得到了相

我编写了一个小的基准测试程序来检查访问向量中存储的数据的一些方法。 我使用tww嵌套for循环来对抗 A) 为第一个循环的每次迭代创建对向量对象的引用,并在第二个for循环中使用该引用 B) 创建一个指针,在该指针中为第一个循环的每次迭代存储对向量对象的引用,并在第二个for循环中使用该指针 C) 使用[]运算符直接访问向量对象 D) 在第一个循环中使用auto&命令

这对嵌套for循环本身与一个计时函数一起嵌套在另一个循环中。 运行测试几次,for循环从0到100,对于所有这些方法,我得到了相同的计时结果,总是在0.150秒左右,波动为0.02%

我的问题是:

1) 我的测试正确吗

2) 是否有一些优化/不同的方法我错过了,哪种可能更快

这是我的密码

#include <iostream>
#include <chrono>
#include <ratio>
#include <ctime>
#include <vector>
using namespace std;
using namespace std::chrono;


struct my_struct{

    vector<float> data;

    my_struct(int N, float x){

        for(int i=0;i<N;i++){
            data.push_back(cos(x+i));
        }
    }

    void work(){
        for(int i=0;i<data.size();i++){
            data[i]=data[i]*data[i];
         }
    }

};

int main(){
int N=100;
vector<my_struct> stuff;
for(int k=0; k<N; ++k){
    stuff.push_back( my_struct(100,sin(k)) );
}

vector<duration<double>> results_t1,results_t2,results_t3,results_t4;
high_resolution_clock::time_point t1 = high_resolution_clock::now();
for(int k=0; k<N; ++k){
    int which=0; //this is used to choose what method of access will be used
    switch(which){
        case 0:{ //pointer
            my_struct * thing=NULL;
            for( int i=0; i<N;++i){
                high_resolution_clock::time_point t2 = high_resolution_clock::now();
                for( int j=0; j<N;++j){
                    thing =&stuff[j];
                    for( int jj=0; jj<N;++jj)
                        thing->work();
                }
                duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
                results_t1.push_back(time_span);
                t1=t2;
            }
            break;
        }

        case 1:{    //direct access
            for( int i=0; i<N;++i){
                high_resolution_clock::time_point t2 = high_resolution_clock::now();
                for( int j=0; j<N;++j){
                    for( int jj=0; jj<N;++jj)
                        stuff[j].work();
                }
                duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
                results_t2.push_back(time_span);
                t1=t2;
            }
            break;
        }

        case 2:{    //auto reference
            for( int i=0; i<N;++i){
                high_resolution_clock::time_point t2 = high_resolution_clock::now();
                for( auto& temp : stuff){
                    for( int jj=0; jj<N;++jj)
                        temp.work();
                }
                duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
                results_t3.push_back(time_span);
                t1=t2;
            }
            break;
        }
        case 3:{    //reference
            for( int i=0; i<N;++i){
                high_resolution_clock::time_point t2 = high_resolution_clock::now();
                for( int j=0; j<N;++j){
                    my_struct & temp =stuff[j];
                    for( int jj=0; jj<N;++jj)
                        temp.work();
                }
                duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
                results_t4.push_back(time_span);
                t1=t2;
            }
            break;
        }

    }
}
double temp=0;
for(auto& t : results_t1){
temp+=t.count();
}
temp=temp/N;
std::cout << "pointer " << temp << " seconds.";
std::cout << std::endl;

temp=0.0;
for(auto& t : results_t2){
temp+=t.count();
}
temp=temp/N;
std::cout << "direct " << temp << " seconds.";
std::cout << std::endl;

temp=0.0;
for(auto& t : results_t3){
temp+=t.count();
}
temp=temp/N;
std::cout << "auto reference " << temp << " seconds.";
std::cout << std::endl;

    temp=0.0;
for(auto& t : results_t4){
temp+=t.count();
}
temp=temp/N;
std::cout << "reference " << temp << " seconds.";
std::cout << std::endl;

cin.get();

return 0;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间std::chrono;
结构我的结构{
矢量数据;
我的结构(整数N,浮点x){

对于(int i=0;i我希望每种方法都能得到类似的结果。时间不会花在循环上,而是花在数学函数
sin
cos
上。诸如循环不变量之类的编译器优化将使
case 1
与其他循环一样快,并且在每个循环上没有任何选择表演


对于风格,更喜欢保持简单,这将有助于维护性,并从长远来看减少错误。在此基础上,我会选择案例1。引入临时工具来帮助编译器实际上不会帮助编译器。

标签用于
优化
,如果你需要好的答案,也可以使用。@UchiaItachi你的评论似乎很有用暗示只有优化问题才能得到好的答案;)@Borgleader:如果你想得到关于优化的好答案,用标记似乎是显而易见的事情。你能更好地格式化你的代码吗?Markdown不喜欢标记。@Rapptz我更正了结构的格式。main中的代码似乎还可以。谢谢,“引入临时变量来帮助编译器实际上不会帮助编译器”这是一个非常好的范例。