Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> циклический буфер/очередь, что можно еще выкрасть? 
:(
    Опции темы
bel_nikita
Дата 20.11.2004, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

Репутация: 21
Всего: 47



Понадобилась, давече, очередь, но непростая, а скоростная. И на ум пришло только: организовать циклический буфер. Т.к. мне кажется, что быстрее и проще ничего на свете не бывает.
Хотел бы, чтобы покритиковали и нашли узкие места: как еще оптимизировать и выкрасть асмовские инструкции smile
Код

#define __INLINE  FORCEINLINE  // нужно ли это?
#define __FAST    __fastcall         // нужно ли это?


 template<typename T>
 class cCyclicBuffer
 {
   typedef T   TYPE;
   typedef T*  PTYPE;
 public:
   cCyclicBuffer(size_t count): m_Head(0),m_Tail(0)
   {
     m_LenBuffer = count;
     m_pBuffer = (PTYPE)malloc(m_LenBuffer * sizeof(TYPE));
     if ( m_pBuffer == NULL ) throw ("not enough memory");
  }
   ~cCyclicBuffer()
   {
     free(m_pBuffer);
   }

   // получение свободного места в буфере
   __INLINE  size_t __FAST GetSpace()
   {
     return m_LenBuffer - GetLength();
   }
   
   // получение данных в буфере
   __INLINE  size_t __FAST GetLength()
   {
     size_t  len = m_Head - m_Tail;
     if ( len & (1 << (sizeof( size_t )*8 - 1))  )         // Buffer: Begin...m_Head...m_Tail...End
       len = m_LenBuffer - ( -len );                       // здесь зараза варнинг C4146 кидает
     return len;
   }

   // кладем в буфер
   __INLINE  size_t __FAST PutData(PTYPE pData, size_t count )
   {
     if ( GetSpace() < count ) return 0;                   // Not enough memory

     if ( m_Head + count < m_LenBuffer )                   // Buffer: Begin...m_Tail...m_Head...End
     {
       memcpy(m_pBuffer + m_Head,pData,sizeof(TYPE)*count);
     }
     else                                                  // Buffer: Begin...m_Head...m_Tail...End
     {
       size_t part1 = m_LenBuffer - m_Head;
       size_t part2 = count - part1;
       memcpy(m_pBuffer + m_Head,pData,sizeof(TYPE)*part1);
       memcpy(m_pBuffer,pData,sizeof(TYPE)*part2);
     }
     m_Head = (m_Head + count) % m_LenBuffer;
     return count;
   }

   // тяним из буфера
   __INLINE  size_t __FAST GetData(const PTYPE pData, size_t count )
   {
     size_t read = GetLength();                    // All Data from buffer
     if ( !Read ) return 0;
     if ( read >= count ) read = count;            // Length of Data from buffer
     if ( m_Tail + read < m_LenBuffer )            // Buffer: Begin...m_Tail...m_Head...End
     {
       memcpy(pData,m_pBuffer + m_Tail,read);
     }
     else                                          // Buffer: Begin...m_Head...m_Tail...End
     {
       size_t part1,part2;
       part1 = m_LenBuffer - m_Tail;               // Length from m_Tail to end buffer
       part2 = read - part1;                       // Last read
       memcpy(pData,m_pBuffer + m_Tail,part1);
       memcpy(pData + part1,m_pBuffer,part2);
     }
      m_Tail = ( m_Tail + read) % m_LenBuffer;
     return read;
   };  

 protected:
   size_t  m_Head;
   size_t  m_Tail;
   size_t  m_LenBuffer;
   PTYPE   m_pBuffer;
 };


Может стоит, заменить len = - len; на
Код
__asm {
             mov         eax,dword ptr [len];
             neg         eax;
             mov         dword ptr [len],eax ;
       }
Чтобы варнинг не генерила. Или отрубить варниг через прагму?

З.Ы.: Может в ФАКю кинуть? Пригодится ведь когда-то... smile



--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
Adil'
Дата 20.11.2004, 17:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 311
Регистрация: 26.8.2004
Где: Питер

Репутация: 6
Всего: 15



1. Cтранная функция GetLength, даже не стал вникать, что в if происходит... м.б. так проще:
Код
// получение данных в буфере
  __INLINE  size_t __FAST GetLength()
  {
    size_t  len = m_Head - m_Tail;
    if(len<=0)
      return m_LenBuffer+len;
    return len;
  }

2. Если торопимся, то для больших по размеру типов м.б. лучше использовать буфер, в котором хранятся адреса объектов - меньше времени будет уходить на копирование объектов из памяти в память.


З.Ы. Классы, шаблоны и malloc, free - как-то не гармонично? smile


--------------------
Удачи
PM MAIL WWW   Вверх
bel_nikita
Дата 20.11.2004, 18:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

Репутация: 21
Всего: 47



Adil'
Цитата
Cтранная функция GetLength, даже не стал вникать, что в if происходит... м.б. так проще

Да, будет проще. Если вместо size_t был бы int, то я бы так и сделал, но size_t - беззнаковый тип, поэтому
Код
// получение данных в буфере
 __INLINE  size_t __FAST GetLength()
 {
   size_t  len = m_Head - m_Tail;
   if(len<=0)
     return m_LenBuffer+len;
   return len;
 }
не подходит. Пришлось извратиться smile Кстати, данный вариант функции проигрывает по компактности из-за if(len<=0)

if ( len & (1 << (sizeof( size_t )*8 - 1)) ) - нахождение, является ли, полученный len отрицательным или нет, т.е. проверяется самый старший бит.
len = m_LenBuffer - ( -len ); - инвертируем len в представление положительного числа и отнимаем от m_LenBuffer.

Цитата
2. Если торопимся, то для больших по размеру типов м.б. лучше использовать буфер, в котором хранятся адреса объектов - меньше времени будет уходить на копирование объектов из памяти в память.

Дело в том, что в конечном итоге, это будет буффер для разных физических устройств, которые будут обмениваться между собой через два таких буфера. Т.е. один только пишит, второй только читает. Второй буфер, наоборот, второй пишет, первый читает.

Цитата
З.Ы. Классы, шаблоны и malloc, free - как-то не гармонично?
Есть предложения smile


--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
Adil'
Дата 21.11.2004, 11:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 311
Регистрация: 26.8.2004
Где: Питер

Репутация: 6
Всего: 15



Цитата(bel_nikita @ 20.11.2004, 18:59)
Да, будет проще. Если вместо size_t был бы int, то я бы так и сделал
Да, в самом деле, сорри, не обратил внимание. Правда тут же возникает вопрос (с учетом 2). - неужели физические устройства будут обмениваться данными размером больше, чем 2 ГигаОбъекта?
В погоне за универсальностью можно проиграть в той же скорости для некоего конкретного случая.

Цитата(bel_nikita @ 20.11.2004, 18:59)
Есть предложения
Код

m_pBuffer = new TYPE[m_LenBuffer];
delete[] m_pBuffer;





--------------------
Удачи
PM MAIL WWW   Вверх
bel_nikita
Дата 22.11.2004, 00:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

Репутация: 21
Всего: 47



Adil'
Цитата
Код
m_pBuffer = new TYPE[m_LenBuffer];
delete[] m_pBuffer;

Ага, точно smile

Цитата
м.б. лучше использовать буфер, в котором хранятся адреса объектов - меньше времени будет уходить на копирование объектов из памяти в память.
Это именно буффер для обмена пакетами между, грубо говоря, двумя объектами. И в конечной реализации не будет никакого выделения памяти и memcpy, а будет WriteDevice, ReadDevice.

З.Ы.: а данную циклическую очередь хочу отладить от и до. а то с периодичностью, раз в год приходится копаться в старых исходниках и искать циклический буфер или писать заново, как сейчас smile


--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
cardinal
Дата 22.11.2004, 01:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Инженер
****


Профиль
Группа: Экс. модератор
Сообщений: 6003
Регистрация: 26.3.2002
Где: Германия

Репутация: 2
Всего: 99



Цитата(bel_nikita @ 20.11.2004, 14:25)
sizeof( size_t )*8

можно заменить на
Код

sizeof( size_t )<<3

Цитата(bel_nikita @ 20.11.2004, 14:25)
if ( !Read ) return 0;

Цитата(bel_nikita @ 20.11.2004, 14:25)
size_t part1

А кто такие Read и size_t?


--------------------
Немецкая оппозиция потребовала упростить натурализацию иммигрантов
В моем блоге: Разные истории из жизни в Германии

"Познание бесконечности требует бесконечного времени, а потому работай не работай - все едино".  А. и Б. Стругацкие
PM   Вверх
bel_nikita
Дата 22.11.2004, 02:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

Репутация: 21
Всего: 47



cardinal
Цитата
sizeof( size_t )*8 можно заменить на sizeof( size_t )<<3
Ага, уже сделано. Просто засорять эфир неохота было еще одним листингом smile
Цитата
А кто такие Read и size_t?
smile
Read - это read;
size_t - беззнаковый тип, обычно unsigned int.




--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
cardinal
Дата 22.11.2004, 03:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Инженер
****


Профиль
Группа: Экс. модератор
Сообщений: 6003
Регистрация: 26.3.2002
Где: Германия

Репутация: 2
Всего: 99



Цитата(bel_nikita @ 20.11.2004, 14:25)
#define __INLINE  FORCEINLINE  // нужно ли это?
#define __FAST    __fastcall        // нужно ли это?

Хуже от этого не будет.
Цитата(bel_nikita @ 20.11.2004, 14:25)
Чтобы варнинг не генерила. Или отрубить варниг через прагму? ...

Может, а может просто стоит заменить на
Код

len = m_LenBuffer - ( -(int)len );
smile


--------------------
Немецкая оппозиция потребовала упростить натурализацию иммигрантов
В моем блоге: Разные истории из жизни в Германии

"Познание бесконечности требует бесконечного времени, а потому работай не работай - все едино".  А. и Б. Стругацкие
PM   Вверх
bel_nikita
Дата 22.11.2004, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

Репутация: 21
Всего: 47



cardinal
Код
len = m_LenBuffer - ( -(int)len );

Как то не очень смотриться smile Тогда уж лучше не size_t, а int использовать.
Хотя... асмовская вставка, которая у меня сейчас стоит, тоже не смотриться...



--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0988 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.