Почему std :: allocator работает намного лучше, чем пользовательский распределитель в Linux в некоторых сценариях? - PullRequest
1 голос
/ 15 июня 2019

Работая над пользовательским распределителем для использования с STL, я обнаружил, что есть некоторые сценарии, в которых std :: allocator значительно превосходит любой пользовательский распределитель, который я пробовал на некоторых платформах Linux.

В Windows, используя обаVC ++ 2019 и clang, я не вижу заметных различий в скорости.

Я не могу понять, почему я вижу эти совершенно разные результаты на платформах Linux (я пробовал и Fedora, и Ubuntu.) Я создал этопрограмма, которая демонстрирует то, что я вижу (заимствование SampleAllocator, представленного в отдельном вопросе, указанном в коде.)

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

// SimpleAllocator code from:
// https://stackoverflow.com/questions/22487267/unable-to-use-custom-allocator-with-allocate-shared-make-shared
template <class Tp>
struct SimpleAllocator
{
  typedef Tp value_type;
  SimpleAllocator() {}
  template <class T> SimpleAllocator(const SimpleAllocator<T>& other) {}
  Tp* allocate(std::size_t n) { return static_cast<Tp*>(::operator new(n * sizeof(Tp))); }
  void deallocate(Tp* p, std::size_t n) { ::operator delete(p); }
};
template <class T, class U>
bool operator==(const SimpleAllocator<T>&, const SimpleAllocator<U>&) { return true; }
template <class T, class U>
bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&) { return false; }

template <typename T> void TimeInsertions(T &vec, const std::string &alloc_name)
{
    auto start_time = std::chrono::steady_clock::now();
    for (int i = 0 ; i<=100000000; i++)
    {
        vec.push_back(i);
    }
    auto end_time = std::chrono::steady_clock::now();

    std::cout << "Time using " << alloc_name << ": "
              << std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count()
              << "ms" << std::endl;
}

int main()
{
    {
        std::vector<int, SimpleAllocator<int>> vec;
        TimeInsertions(vec, "SampleAllocator");
    }

    {
        std::vector<int> vec;
        TimeInsertions(vec, "std::allocator");
    }
}

Учитывая этот базовый пример, я ожидал, что ссылочный SimpleAllocator будет работать примерно так же, как std:: allocator, но на самом деле я вижу такие результаты:

$ ./sample
Time using SampleAllocator: 5283ms
Time using std::allococator: 1485ms

Конечно, эти результаты различаются в зависимости от машины, но я получаю одинаково очень разные результаты на разных машинах Linux.Это наводит меня на мысль, что в g ++ или Linux есть какая-то магия, которую я не до конца понимаю.Может ли кто-нибудь помочь мне понять, что я вижу?

РЕДАКТИРОВАТЬ

Возвращаясь к этому сегодня, возможно, это может быть связано с оптимизацией компилятора,Я перекомпилировал код в Linux, используя флаг -O3 в gcc, и получил очень разные (и более близкие) результаты:

$ ./sample
Time using SampleAllocator: 341ms
Time using std::allocator: 479ms

Итак, возможно, это просто связано с тем, как код STL компилируется ине имеет ничего общего с оптимизацией конкретной платформы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...