vendredi 22 février 2019

Why is 4 dimensional vector better per formant than 4 dimensional std::array here

#include <iostream>
#include <vector>
#include <array>
#include <chrono>


#define D1  8
#define D2 16
#define D3 12
#define D4 16

struct my_big_Struct {
    uint64_t data[16] = {0};
};


struct my_vector_class {
    std::vector<std::vector<std::vector<std::vector<struct my_big_Struct>>>> myobj;
    my_vector_class() {
        myobj.resize(D1);
        for (auto i = 0; i < D1; i++) {
            myobj[i].resize(D2);
            for (auto j = 0; j < D2; j++) {
                myobj[i][j].resize(D3);
                for (auto k = 0; k < D3; k++) {
                    myobj[i][j][k].resize(D4);
                }
            }
        }
        for (auto i = 0; i < D1; i++) {
            for (auto j = 0; j < D2; j++) {
                for (auto k = 0; k < D3; k++) {
                    for (auto l = 0; l < D4; l++) {
                        myobj[i][j][k][l].data[0] = rand();
                    }
                }
            }
        }
    }
};

struct my_array_class {
    std::array< std::array < std::array < std::array<struct my_big_Struct, D1>, D2>, D3>, D4> arr;
    my_array_class() {
        for (auto i = 0; i < D1; i++) {
            for (auto j = 0; j < D2; j++) {
                for (auto k = 0; k < D3; k++) {
                    for (auto l = 0; l < D4; l++) {
                        arr[i][j][k][l].data[0] = rand();
                    }
                }
            }
        }
    }
};

#define LOOP_COUNT 1



int main() {
    struct my_vector_class vec;
    struct my_array_class arr;
    uint64_t sum = 0;
    auto start = std::chrono::high_resolution_clock::now();

    for (auto lc = 0; lc < LOOP_COUNT; ++lc) {
        for (auto i = 0; i < D1; i++) {
            for (auto j = 0; j < D2; j++) {
                for (auto k = 0; k < D3; k++) {
                    for (auto l = 0; l < D4; l++) {
                        sum +=vec.myobj[i][j][k][l].data[0];
                    }
                }
            }
        }
    }
    auto stop  = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> diff = stop-start;
    std::cout << "Elapsed vec " << diff.count() << "\n";
    auto start2 = std::chrono::high_resolution_clock::now();
    for (auto lc = 0; lc < LOOP_COUNT; ++lc) {
        for (auto i = 0; i < D1; i++) {
            for (auto j = 0; j < D2; j++) {
                for (auto k = 0; k < D3; k++) {
                    for (auto l = 0; l < D4; l++) {
                        sum +=arr.arr[i][j][k][l].data[0];
                    }
                }
            }
        }
    }
    auto stop2  = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> diff2 = stop2-start2;
    std::cout << "Elapsed arr " << diff2.count() << "\n";
    auto start3 = std::chrono::high_resolution_clock::now();
    for (auto lc = 0; lc < LOOP_COUNT; ++lc) {
        for (auto i = 0; i < D1; i++) {
                for (auto j = 0; j < D2; j++) {
                    for (auto k = 0; k < D3; k++) {
                        for (auto l = 0; l < D4; l++) {
                            sum +=vec.myobj[i][j][k][l].data[0];
                        }
                }
            }
        }
    }
    auto stop3  = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> diff3 = stop3-start3;
    std::cout << "Elapsed vec " << diff3.count() << "\n";
    auto start4 = std::chrono::high_resolution_clock::now();
    for (auto lc = 0; lc < LOOP_COUNT; ++lc) {
        for (auto i = 0; i < D1; i++) {
            for (auto j = 0; j < D2; j++) {
                for (auto k = 0; k < D3; k++) {
                    for (auto l = 0; l < D4; l++) {
                        sum +=arr.arr[i][j][k][l].data[0];
                    }
                }
            }
        }
    }
    auto stop4  = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> diff4 = stop4-start4;
    std::cout << "Elapsed arr " << diff4.count() << "\n";
};

So, I have created a 4D - vector and 4D array of a biggish object (128B) and tried to loop through them twice...To zero out cache warming effects... I consistently found array version to be 2x slower...

gcc-5.2.0/bin/g++

g++ -std=c++11 main.cpp -o vecvsarr ./vecvsarr

Elapsed vec 0.475446
Elapsed arr 0.846845
Elapsed vec 0.441586
Elapsed arr 0.829504

By adding the optimization -O3 I get some sppedups.. But I expected significant difference

With optimizations:

Elapsed vec 2.58e-07
Elapsed arr 1.52e-07
Elapsed vec 1.21e-07
Elapsed arr 1.15e-07

Aucun commentaire:

Enregistrer un commentaire