О производительности структур данных
От: Abyx Россия  
Дата: 19.10.12 20:25
Оценка: -1 :)
#include <cstdlib>
#include <algorithm>
#include <chrono>
#include <iostream>
#include <iomanip>
#include <numeric>
#include <string>
#include <thread>
#include <vector>

struct Obj
{
    Obj* next;
    unsigned x;

    Obj() : x(::rand()) {}
    void update()
    {
        ++x; // как-то меняем данные объекта
    }
};

template<typename F>
void test(const char* name, F f)
{
    std::vector<unsigned> times(100);

    for (auto& dt : times)
    {
        std::this_thread::yield();

        auto t1 = std::chrono::high_resolution_clock::now();
        f();
        auto t2 = std::chrono::high_resolution_clock::now();

        dt = (unsigned)std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
    }

    std::cout << name << ": " << std::accumulate(times.begin(), times.end(), 0) / times.size() << " ms" << std::endl;
}

int main()
{
    std::srand((unsigned)std::time(nullptr));

    std::vector<Obj> vObj(1 * 1000 * 1000);

    std::vector<Obj*> vPtr;
    for (auto& o : vObj)
        vPtr.push_back(&o);

    std::random_shuffle(vPtr.begin(), vPtr.end()); // убиваем memory locality при последовательном доступе

    Obj* lst = nullptr;
    for (auto p : vPtr)
    {
        p->next = lst;
        lst = p;
    }

    test("vector<Obj>", [&]{ for (auto& o : vObj) o.update(); });
    test("vector<Obj*>", [&]{ for (auto& o : vPtr) o->update(); });
    test("intrusive list", [&]{ for (auto o = lst; o; o = o->next) o->update(); });
}


Типичный результат на моей машине
vector<Obj>: 0 ms
vector<Obj*>: 10 ms
intrusive list: 76 ms


Почему так?
В случае с vector<Obj> объект лежат друг за другом, и эффективно читаются в кеш процессора
У vector<Obj*> перемешаны указатели, по этому кешировать доступ к данным объектов не получается.
Однако, сам vector<Obj*> прекрасно кешируется, а вот для связанного списка кеширование не работает вообще.
In Zen We Trust
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.