Переквалификация c#-> ??

User avatar
M. Ridcully
Уже с Приветом
Posts: 11999
Joined: 08 Sep 2006 20:07
Location: Силиконка

Re: Переквалификация c#-> ??

Post by M. Ridcully »

crypto5 wrote:Давайте ваш тест, я есго запрограммирую на джава, вы на с++.
Давайте ваш.
Опишите чего на входе, чего на выходе ожидается.
Задание типа "давайте наплодим туеву хучу маленьких объектов в динамической памяти" не канает - это детали реализации.
Мир Украине. Свободу России.
User avatar
crypto5
Уже с Приветом
Posts: 4637
Joined: 24 Oct 2009 01:38
Location: Chicago ;-) -> SFBA!

Re: Переквалификация c#-> ??

Post by crypto5 »

M. Ridcully wrote:
crypto5 wrote:Давайте ваш тест, я есго запрограммирую на джава, вы на с++.
Давайте ваш.
Опишите чего на входе, чего на выходе ожидается.
Задание типа "давайте наплодим туеву хучу маленьких объектов в динамической памяти" не канает - это детали реализации.
Ну вот я сейчас буду пыжиться, стараться, а там опять что-то будет "не канать".
In vino Veritas!
User avatar
Мальчик-Одуванчик
Уже с Приветом
Posts: 15475
Joined: 27 Sep 2007 22:53

Re: Переквалификация c#-> ??

Post by Мальчик-Одуванчик »

Интеррапт wrote:
Мальчик-Одуванчик wrote:осталось только переопределить функции operator new и operator delete для самого класса и не брать памяит из кучи
Но все-равно все это в конце концов упрется в то, что shared_ptr все-таки медленоват.
Да похоже в него и уперлось. Даже несколько обескуражен - сочетание счетчика ссылок с наколенным аллокатором дало незначительный прирост производительности. В примере, приведенном ниже ( к сожалению на другом компьютере по отношению с примером tbb) исходный тест занял 25 сек, а с встроенным аллокатром - 14 сек.


class Data {
public:
int payload;
Data(int bb) : payload(bb) {}
void *operator new(size_t);
void operator delete(void *);
};

struct memslot {
enum { max = COUNT+2};
static memslot *free;
static int used;
union {
char store[sizeof(Data)];
memslot *next;
};
};
static memslot storage[memslot::max];

typedef std::shared_ptr<Data > DataPtr;
int main() {
DataPtr data[COUNT];
for(int i = 0; i < COUNT; i ++) data = DataPtr(new Data(i));
auto curr = data[0];
for(long i = 0; i < 100000000; i ++) {
int next_index = (curr->payload + 1) % COUNT;
auto next_node = data[next_index];
data[next_index] = DataPtr(new Data((curr->payload + next_node->payload + 1) % COUNT));
curr = next_node;
}
}

memslot* memslot::free;
int memslot::used;
void * Data::operator new(size_t ) {
if(memslot::free) {
memslot *ptr = memslot::free;
memslot::free = memslot::free->next;
return ptr;
}
else if(memslot::used < memslot::max) {
return &storage[memslot::used++];
} else {
throw std::bad_alloc();
}
}
void Data::operator delete(void *ptr ) {
static_cast<memslot *>(ptr)->next = memslot::free;
memslot::free = static_cast<memslot *>(ptr);
}
User avatar
crypto5
Уже с Приветом
Posts: 4637
Joined: 24 Oct 2009 01:38
Location: Chicago ;-) -> SFBA!

Re: Переквалификация c#-> ??

Post by crypto5 »

Используйте тег code что бы ваш код было легче читать пожалуйста.
Еще используйте вариант Интеррапта а не мой как основу, он быстрее.
In vino Veritas!
User avatar
Мальчик-Одуванчик
Уже с Приветом
Posts: 15475
Joined: 27 Sep 2007 22:53

Re: Переквалификация c#-> ??

Post by Мальчик-Одуванчик »

Кстати Placement new мне тоже ничего не дал в этом плане - результат практически тот же что и выше.
User avatar
Интеррапт
Уже с Приветом
Posts: 17281
Joined: 07 Sep 2011 10:05
Location: Seattle, WA

Re: Переквалификация c#-> ??

Post by Интеррапт »

Мальчик-Одуванчик wrote:Кстати Placement new мне тоже ничего не дал в этом плане - результат практически тот же что и выше.
Да, ваш вариант, который вы выше опубликовали - медленноват.

Эта конструкция

data[next_index] = DataPtr(...)

медленная. т.к. при таком создании shared_ptr - происходит двойна аллокация (для счетчика и для обьекта), а если использовать std::make_shared - то только одна аллокация. Ну или нужно использовать std::allocate_shared, если есть кастом аллокатор.
User avatar
Medium-rare
Уже с Приветом
Posts: 9194
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: Переквалификация c#-> ??

Post by Medium-rare »

Это здесь.

Code: Select all

      myallocator<Data> MyAllocator( COUNT );
      ////
      data[nextIndex] = std::allocate_shared<Data, myallocator<Data>>(MyAllocator, ((*current)->payload + (*newNode)->payload + 1) % COUNT);
Аллокатор примерно такой:

Code: Select all

template <typename T>
class myallocator: public std::allocator<T>
{
public:
    //    typedefs
    typedef T value_type;
    typedef value_type* pointer;
    typedef const value_type* const_pointer;
    typedef value_type& reference;
    typedef const value_type& const_reference;
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;

public:
   // template <typename U> struct rebind { typedef myallocator<U> other; }; // WILL THIS COMPILE FOR GCC?

   pointer allocate(size_type n, const void *hint=0)
   {
      pointer p = nullptr;
      if (m_nLastFreed != -1)
         p = &m_pool[ m_nLastFreed ];
      else if (m_nAllocated < m_nItems)
         p = &m_pool[ m_nAllocated ++ ];
      return p;
   }

   inline pointer address(reference r) { return &r; }
   inline const_pointer address(const_reference r) { return &r; }


   void deallocate(pointer p, size_type n)
   {
      m_nLastFreed = n;
      return; // std::allocator<T>::deallocate(p, n);
   }

   //    construction/destruction
   void construct(pointer p, const T& t) { new(p) T(t); }
   void destroy(pointer p) { p->~T(); }

   inline bool operator==(myallocator const&) { return true; }
   inline bool operator!=(myallocator const& a) { return !operator==(a); }

   myallocator(size_t nItems) throw(): std::allocator<T>(), m_nItems( nItems ), m_nLastFreed( -1 ) { m_pool = new T[m_nItems]; }
   myallocator() throw(): std::allocator<T>(), m_nItems( 0 ), m_nLastFreed( -1 ) { }
   explicit myallocator(const myallocator &a) throw(): std::allocator<T>(a) { }
   template<typename U>
   explicit myallocator(myallocator<U> const&) : m_nItems( 0 ), m_nLastFreed( -1 ) {}

   ~myallocator() throw() { delete[] m_pool; }

private:
   T* m_pool;
   size_t m_nItems;
   size_t m_nAllocated;
   size_t m_nLastFreed;
};
Меня задрал глюк в компайлере. allocate и deallocate "соптимизированы" в ноль. Когда-то до C++ 11 делал rebind, без него не проходило. Теперь Лававей чего-то напорол в майкрософтовской STL, и уже по блогам всем спасибо за найденные баги именно в том месте говорит. Всё ему определил, чего надо для template, вроде. До GCC сегодня не добрался.
... and even then it's rare that you'll be going there...
User avatar
Интеррапт
Уже с Приветом
Posts: 17281
Joined: 07 Sep 2011 10:05
Location: Seattle, WA

Re: Переквалификация c#-> ??

Post by Интеррапт »

Это здесь.

Code: Select all

      myallocator<Data> MyAllocator( COUNT );
      ////
      data[nextIndex] = std::allocate_shared<Data, myallocator<Data>>(MyAllocator, ((*current)->payload + (*newNode)->payload + 1) % COUNT);
А конкретней код есть? А то судя по (*current) и по (*newNode) - используются там поинтеры. С поинтерами я уже код написал, который меньше секунды отрабатывает. Тут интересней именно с shared_ptr во всех случаях.
User avatar
Medium-rare
Уже с Приветом
Posts: 9194
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: Переквалификация c#-> ??

Post by Medium-rare »

Code: Select all

// SchedulerMain.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>

#include <iostream>
#include <iomanip>
#include <ctime>
#include <chrono>

#include "Scheduler.h"


using namespace ppi_sch;

void print_local_date(std::chrono::time_point<std::chrono::system_clock>& tmpt)
{
	std::time_t t = std::chrono::system_clock::to_time_t(tmpt);
	std::tm* lt = std::localtime(&t);
	std::cout << "Now: " <<
		1 + lt->tm_mon << "/" << lt->tm_mday << "/" << 1900 + lt->tm_year << " " <<
		std::setfill('0') << std::setw(2) <<
		lt->tm_hour << ":" <<
		std::setfill('0') << std::setw(2) <<
		lt->tm_min << ":" <<
		std::setfill('0') << std::setw(2) <<
		lt->tm_sec << "\n";
}

int main(int argc, const char* argv[])
{
	std::chrono::time_point<std::chrono::system_clock> now =
		std::chrono::system_clock::now();

	std::chrono::time_point<std::chrono::system_clock> in5secs =
		now + std::chrono::seconds::duration(5);
	std::chrono::time_point<std::chrono::system_clock> in10secs =
		now + std::chrono::seconds::duration(10);
	std::chrono::time_point<std::chrono::system_clock> in15secs =
		now + std::chrono::seconds::duration(15);

	print_local_date(now);
	print_local_date(in5secs);
	print_local_date(in10secs);
	print_local_date(in15secs);

	auto beepFunc = [](SI){::Beep(1000, 200);};
	auto killerBeepFunc = [](SI ctrl){::Beep(1000, 200); ctrl->stop();};

	std::vector<ScheduleItem> vctTasks2Execute;

	vctTasks2Execute.emplace_back(in10secs, new Action("Beep in 10 seconds", killerBeepFunc));
	vctTasks2Execute.emplace_back(in15secs, new Action("Beep in 15 seconds", beepFunc));
	vctTasks2Execute.emplace_back(in5secs,  new Action("Beep in 5 seconds", beepFunc));

    Scheduler scheduler;
    scheduler.consumeSchedule(vctTasks2Execute);

	std::future<Result> futureR = scheduler.start();
	Result R = futureR.get();

	std::cout << R.getInfo() << "\n";

	return 0;
}
Крипто, скажи Гуглу, чтобы компенсировали за труды. :crazy:
... and even then it's rare that you'll be going there...
User avatar
Medium-rare
Уже с Приветом
Posts: 9194
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: Переквалификация c#-> ??

Post by Medium-rare »

Крипто, скажи Гуглу, чтобы нам компенсировали. :crazy:

Code: Select all

#include <memory>
#include <chrono>
#include <ctime>
#include <iostream>

template <typename T>
class myallocator: public std::allocator<T>
{
public:
    //    typedefs
    typedef T value_type;
    typedef value_type* pointer;
    typedef const value_type* const_pointer;
    typedef value_type& reference;
    typedef const value_type& const_reference;
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;

public:
   // template <typename U> struct rebind { typedef myallocator<U> other; }; // WILL THIS COMILE FOR GCC?

   pointer allocate(size_type n, const void *hint=0)
   {
      pointer p = nullptr;
      if (m_nLastFreed != -1)
         p = &m_pool[ m_nLastFreed ];
      else if (m_nAllocated < m_nItems)
         p = &m_pool[ m_nAllocated ++ ];
      return p;
   }

   inline pointer address(reference r) { return &r; }
   inline const_pointer address(const_reference r) { return &r; }


   void deallocate(pointer p, size_type n)
   {
      m_nLastFreed = n;
      return; // std::allocator<T>::deallocate(p, n);
   }

   //    construction/destruction
   void construct(pointer p, const T& t) { new(p) T(t); }
   void destroy(pointer p) { p->~T(); }

   inline bool operator==(myallocator const&) { return true; }
   inline bool operator!=(myallocator const& a) { return !operator==(a); }

   myallocator(size_t nItems) throw(): std::allocator<T>(), m_nItems( nItems ), m_nLastFreed( -1 ) { m_pool = new T[m_nItems]; }
   myallocator() throw(): std::allocator<T>(), m_nItems( 0 ), m_nLastFreed( -1 ) { }
   explicit myallocator(const myallocator &a) throw(): std::allocator<T>(a) { }
   template<typename U>
   explicit myallocator(myallocator<U> const&) : m_nItems( 0 ), m_nLastFreed( -1 ) {}

   ~myallocator() throw() { delete[] m_pool; }

private:
   T* m_pool;
   size_t m_nItems;
   size_t m_nAllocated;
   size_t m_nLastFreed;
};

class Data
{
public:
    int payload;
    Data() : payload(0) {
    }
    Data(int value) : payload(value) {
    }
};

typedef std::shared_ptr<const Data> data_ptr;

const int COUNT = 100;


int main(int argc, const char * argv[])
{
	auto start = std::chrono::system_clock::now();

   myallocator<Data> MyAllocator( COUNT );

    
   data_ptr data[COUNT];
   for (int i = 0; i < COUNT; i++) {
   data[i] = std::make_shared<Data>(i);
   }

   data_ptr* current = &data[0];
   for(long iter = 0; iter < 100000000; iter ++) {
      int nextIndex = ((*current)->payload + 1) % COUNT;
      data_ptr* newNode = &data[nextIndex];
      data[nextIndex] = std::allocate_shared<Data, myallocator<Data>>(MyAllocator, ((*current)->payload + (*newNode)->payload + 1) % COUNT);
      current = newNode;
   }

	auto finish = std::chrono::system_clock::now();
   
   int64_t elapsed_seconds = std::chrono::duration_cast<std::chrono::milliseconds>( finish - start ).count();   
   std::cout << "\n" << elapsed_seconds << "ms elapsed";
   return 0;
}
... and even then it's rare that you'll be going there...
User avatar
crypto5
Уже с Приветом
Posts: 4637
Joined: 24 Oct 2009 01:38
Location: Chicago ;-) -> SFBA!

Re: Переквалификация c#-> ??

Post by crypto5 »

Medium-rare wrote: Крипто, скажи Гуглу, чтобы компенсировали за труды. :crazy:
А что это такое было?..
In vino Veritas!
User avatar
crypto5
Уже с Приветом
Posts: 4637
Joined: 24 Oct 2009 01:38
Location: Chicago ;-) -> SFBA!

Re: Переквалификация c#-> ??

Post by crypto5 »

Похоже какой то секретный кусок кода скайнета, который быстро убрал :D
In vino Veritas!
User avatar
Интеррапт
Уже с Приветом
Posts: 17281
Joined: 07 Sep 2011 10:05
Location: Seattle, WA

Re: Переквалификация c#-> ??

Post by Интеррапт »

Medium-rare wrote:Крипто, скажи Гуглу, чтобы нам компенсировали.
Под GCC не скомпилировался, к сожалению. А что за цифры по производительности выдает? Желательно в сравнении с другими приведенными здесь тестами.
User avatar
Интеррапт
Уже с Приветом
Posts: 17281
Joined: 07 Sep 2011 10:05
Location: Seattle, WA

Re: Переквалификация c#-> ??

Post by Интеррапт »

Не, тест где используются указатели

Code: Select all

data_ptr* current = &data[0];
   for(long iter = 0; iter < 100000000; iter ++) {
      int nextIndex = ((*current)->payload + 1) % COUNT;
      data_ptr* newNode = &data[nextIndex];
      data[nextIndex] = std::allocate_shared<Data, myallocator<Data>>(MyAllocator, ((*current)->payload + (*newNode)->payload + 1) % COUNT);
      current = newNode;
   }
не принимается. Это я уже писал пару страниц назад и ес-но все работало очень быстро. Тут речь идет именно о присваивании shared_ptr. А с указателями так я уже показал код, который отрабатывает за меньше чем за секунду, при джавиных 14 секунд :)
User avatar
Medium-rare
Уже с Приветом
Posts: 9194
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: Переквалификация c#-> ??

Post by Medium-rare »

Интеррапт wrote: Под GCC не скомпилировался, к сожалению. А что за цифры по производительности выдает? Желательно в сравнении с другими приведенными здесь тестами.
Компиллируется под Visual C++. Но allocate и deallocate компиллятор решает исключить, как невызываемые. Я думал, то из-за rebind, который должен быть определён, но если я его определяю, как до C++ 11, то далее случается ошибка компилляции. Надо много читать.
... and even then it's rare that you'll be going there...
User avatar
Medium-rare
Уже с Приветом
Posts: 9194
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: Переквалификация c#-> ??

Post by Medium-rare »

Интеррапт wrote: не принимается. Это я уже писал пару страниц назад и ес-но все работало очень быстро. Тут речь идет именно о присваивании shared_ptr. А с указателями так я уже показал код, который отрабатывает за меньше чем за секунду, при джавиных 14 секунд :)
shared_ptr там и есть.
... and even then it's rare that you'll be going there...
User avatar
Интеррапт
Уже с Приветом
Posts: 17281
Joined: 07 Sep 2011 10:05
Location: Seattle, WA

Re: Переквалификация c#-> ??

Post by Интеррапт »

Medium-rare wrote:
Интеррапт wrote: Под GCC не скомпилировался, к сожалению. А что за цифры по производительности выдает? Желательно в сравнении с другими приведенными здесь тестами.
Компиллируется под Visual C++. Но allocate и deallocate компиллятор решает исключить, как невызываемые. Я думал, то из-за rebind, который должен быть определён, но если я его определяю, как до C++ 11, то далее случается ошибка компилляции. Надо много читать.
Ну так какие там цифры? Особенно в сравнении с
viewtopic.php?p=5479042#p5479042

но в любом случае, тут используются указатели, а не только shared_ptr
User avatar
Интеррапт
Уже с Приветом
Posts: 17281
Joined: 07 Sep 2011 10:05
Location: Seattle, WA

Re: Переквалификация c#-> ??

Post by Интеррапт »

Medium-rare wrote:
Интеррапт wrote: не принимается. Это я уже писал пару страниц назад и ес-но все работало очень быстро. Тут речь идет именно о присваивании shared_ptr. А с указателями так я уже показал код, который отрабатывает за меньше чем за секунду, при джавиных 14 секунд :)
shared_ptr там и есть.
Там shared_ptr только в одном случае. А в остальном используются указатели. А похоже основная медленность выходит именно при манипулировании shared_ptr. Попробуйте вместо указателей использовать shared_ptr и посмотрите сами на разницу.
User avatar
Medium-rare
Уже с Приветом
Posts: 9194
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: Переквалификация c#-> ??

Post by Medium-rare »

За прообраз был взят вариант, который работал 6 секунд, там есть shared_ptr присвоение. Оптимизация скорости не работает из-за исключения кода из тимплейта. Без неё у меня 8 секунд. Почитаем завтра про... надеялся, что под GCC скомпиллится.
... and even then it's rare that you'll be going there...
User avatar
Интеррапт
Уже с Приветом
Posts: 17281
Joined: 07 Sep 2011 10:05
Location: Seattle, WA

Re: Переквалификация c#-> ??

Post by Интеррапт »

Medium-rare wrote:За прообраз был взят вариант, который работал 6 секунд, там есть shared_ptr присвоение.
Да, но потом на следующей странице мы решили от указателей избавиться. Скорость замедлилась на полторы секунды (или что-то вроде).
User avatar
crypto5
Уже с Приветом
Posts: 4637
Joined: 24 Oct 2009 01:38
Location: Chicago ;-) -> SFBA!

Re: Переквалификация c#-> ??

Post by crypto5 »

Интеррапт wrote: не принимается. Это я уже писал пару страниц назад и ес-но все работало очень быстро. Тут речь идет именно о присваивании shared_ptr. А с указателями так я уже показал код, который отрабатывает за меньше чем за секунду, при джавиных 14 секунд :)
Правда и итераций джава успела обработать в 10 раз больше
In vino Veritas!
User avatar
Интеррапт
Уже с Приветом
Posts: 17281
Joined: 07 Sep 2011 10:05
Location: Seattle, WA

Re: Переквалификация c#-> ??

Post by Интеррапт »

crypto5 wrote:
Интеррапт wrote: не принимается. Это я уже писал пару страниц назад и ес-но все работало очень быстро. Тут речь идет именно о присваивании shared_ptr. А с указателями так я уже показал код, который отрабатывает за меньше чем за секунду, при джавиных 14 секунд :)
Правда и итераций джава успела обработать в 10 раз больше
Точно. Спутал два теста. При равных кол-вах итераций у меня было меньше одной секунды на том тесте для С++ и 3 секунды на Джава тесте.
User avatar
Medium-rare
Уже с Приветом
Posts: 9194
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: Переквалификация c#-> ??

Post by Medium-rare »

Code: Select all

   myallocator<Data> MyAllocator( COUNT ); // TODO: create myallocator::operator[]
   data_ptr data[COUNT];                          // TODO: exclude and use MyAllocator object instead
Вот из-за присвоения к data[index] компиллятор видит, что смысла в аллокаторе 0 и просто оптимизирует его в 0. В этом массиве просто shared_ptr, создаваемые, как обычно. Эффекта потому и нет. Не в чем обвинять компиллятор, и GCC тут не улучшит. Другая проблема в том, что myallocator::m_pool показывает просто на оригинальный тип, а там тип + shared_ptr должен быть. Вот чем и займусь, когда работа отстанет.
... and even then it's rare that you'll be going there...
User avatar
Medium-rare
Уже с Приветом
Posts: 9194
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: Переквалификация c#-> ??

Post by Medium-rare »

Фухъ, добрался. 3587ms elapsed. shared_point работает, не игнорируется. Кривыми руками кое-как прикрутил кастомный аллокатор. Зачем там создаётся instance аллокатора, при том, что все переменные аллокатора static, уже забыл, но надо было правильно имплементировать не stateless аллокатор, а с нестатическими переменными классами почему-то творится дикая дичь. Хочу повторить, что постановка задачи изначально абсурдная, но интересовали детали имплементации. С момента последних ковыряний в аллокаторе утекло много воды, в тот раз как-то легче для вектора получилось. Сейчас за такой код меня на код-ревью расстреляет взвод по утру. Но тут же дружественно настроенные коллеги, а не работа. :twisted:

Code: Select all

#include <memory>
#include <chrono>
#include <ctime>
#include <iostream>

static  void* s_pool      = nullptr;
static  int s_nItems      = 0;
static  int s_nAllocated  = 0;
static  int s_nLastFreed = -1;


template <typename T>
class myallocator: public std::allocator<T>
{
public:
   // typedefs
   typedef T value_type;
   typedef std::size_t size_type;
   typedef std::ptrdiff_t difference_type;
   typedef value_type* pointer;
   typedef const value_type* const_pointer;
   typedef value_type& reference;
   typedef const value_type& const_reference;

   pointer address(reference r) { return &r; }
   const_pointer address(const_reference r) { return &r; }

   template< class U >
   struct rebind { typedef myallocator< U > other; };

   template< class U >
   myallocator( const myallocator< U >& other ) throw()
      : m_pool( reinterpret_cast<T*&>(s_pool) ) {}

   explicit myallocator(int nItems) throw() : m_pool( reinterpret_cast<T*&>(s_pool) )
   {
      if (s_pool == nullptr)
      {
         s_nItems = nItems;
         s_pool = new T[s_nItems];
      }
   }
   myallocator() throw(): m_pool( s_pool ) { }
   explicit myallocator(const myallocator &a) throw(): m_pool( reinterpret_cast<T*&>(s_pool) ) { }
   // ~myallocator() throw() { delete[] s_pool; }

   bool operator==(myallocator const&) { return true; }
   bool operator!=(myallocator const& a) { return !operator==(a); }
   T& operator[](int idx) { return m_pool[idx]; }

   pointer allocate(size_type n, const void *hint=0)
   {
      pointer p = nullptr;
      if (s_nLastFreed != -1)
         p = &m_pool[ s_nLastFreed ];
      else if (s_nAllocated < s_nItems)
         p = &m_pool[ s_nAllocated ++ ];
      return p;
   }
   void deallocate(pointer p, size_type n)
   {
      s_nLastFreed = n;
      return; // std::allocator<T>::deallocate(p, n);
   }

   size_type max_size() const { 
       return static_cast<size_type>(-1) / sizeof(value_type);
   }

   void construct(pointer p, const T& t) { new(p) T(t); }
   void destroy(pointer p) { p->~T(); }

private:
    T*& m_pool;
    /// disallow assignment
    void operator=( const myallocator& );
};



struct Data
{
   int payload;
   Data() : payload(0) {
   }
   Data(int value) : payload(value) {
   }
};

typedef std::shared_ptr<const Data> data_ptr;
typedef data_ptr* data_pptr;

const int COUNT = 100;


int main(int argc, const char* argv[])
{
   auto start = std::chrono::system_clock::now();

   myallocator<data_ptr> MyAllocator( COUNT );
   data_pptr data[COUNT];

   for (int i = 0; i < COUNT; i++) {
      data[i] = reinterpret_cast<data_pptr>( &std::allocate_shared<Data, myallocator<data_ptr>>( MyAllocator, i ) );
   }

   data_ptr* current = data[0];
   for(long iter = 0; iter < 100000000; iter ++) {
      int nextIndex = ((*current)->payload + 1) % COUNT;
      data_ptr* newNode = data[nextIndex];

      // Yes, here we have shared_ptr working *data[nextIndex] is shared_ptr  by val
      *data[nextIndex] = std::allocate_shared<Data, myallocator<data_ptr>>(MyAllocator, ((*current)->payload + (*newNode)->payload + 1) % COUNT);
      current = newNode;
   }

   auto finish = std::chrono::system_clock::now();
   
   int64_t elapsed_seconds = std::chrono::duration_cast<std::chrono::milliseconds>( finish - start ).count();   
   std::cout << "\n" << elapsed_seconds << "ms elapsed";
   return 0;
}
... and even then it's rare that you'll be going there...
User avatar
Интеррапт
Уже с Приветом
Posts: 17281
Joined: 07 Sep 2011 10:05
Location: Seattle, WA

Re: Переквалификация c#-> ??

Post by Интеррапт »

Medium-rare wrote:Фухъ, добрался. 3587ms elapsed. shared_point работает, не игнорируется.
На GCC выдает ошибку (КМК вполне правильную) на этой строчке
data = reinterpret_cast<data_pptr>( &std::allocate_shared<Data, myallocator<data_ptr>>( MyAllocator, i ) );

Taking the address of a temporary object of type 'typename enable_if<!is_array<Data>::value, shared_ptr<Data> >::type' (aka 'std::__1::shared_ptr<Data>')

Правда я уже приводил код, который использует boost и меньше 1-й секунды отрабатывает.

Code: Select all

    boost::object_pool<Data> pool(sizeof(Data) * COUNT);
    Data* data[COUNT];
    for (int i = 0; i < COUNT; i++) {
        data[i] = pool.construct(i);
    }

    Data* current = data[0];
    Data nodeMem;
    for(long iter = 0; iter < 100000000; iter ++) {
        const int nextIndex = (current->payload + 1) % COUNT;
        nodeMem = *data[nextIndex];
        pool.destroy(data[nextIndex]);
        data[nextIndex] = pool.construct((current->payload + nodeMem.payload + 1) % COUNT);
        current = &nodeMem;
    }

Return to “Работа и Карьера в IT”