Почему 4-мерный вектор лучше, чем 4-мерный std :: array - PullRequest
0 голосов
/ 22 февраля 2019
#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";
};

Итак, я создал 4D-вектор и 4D-массив объекта biggish (128B) и дважды попытался пройти через них ... Чтобы обнулить эффекты разогрева кэша ... Я последовательно нашел версию массива длябыть в 2 раза медленнее ...

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

Добавляя оптимизацию -O3, я получаю несколько всплывающих окон .. Но я ожидал существенной разницы

С оптимизацией:

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

1 Ответ

0 голосов
/ 22 февраля 2019

Использовал Godbolt, как предложил Bob_, и обнаружил, что есть оптимизация цикла с включенной оптимизацией.С включенной печатью и работающей для значительного увеличения скорости пилы в 2 раза.

Elapsed vec 15.7311 
Elapsed arr 7.78011 
Elapsed vec 14.7511 
Elapsed arr 7.24151 
Sum 2486663010270848384
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...