Re[8]: inline memset
От: Кодт Россия  
Дата: 13.02.04 14:44
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Оба на!!!


Долго втыкал, но когда воткнул... a*=a абзац.
Щас народу в конторе расскажу.
Перекуём баги на фичи!
Re[8]: inline memset
От: Анатолий Широков СССР  
Дата: 13.02.04 15:05
Оценка: +1
Это не сюрприз, это ошибка. Ведь с умножением матриц Вы бы так не поступили?
Re[8]: inline memset
От: Andrew S Россия http://alchemy-lab.com
Дата: 13.02.04 16:25
Оценка:
CS>>и 7.1 хороший компайлер. правильно разбирает ситуацию на stosd и stosb.
CS>>Интересно, а что будет с невыровненными данными?

Ш>Это надо эксперементировать. Но вообще, у современных Pentium-ов внутренняя шина данных (процессор -- кэш) 128-битная, по идее, это должно скомпенсировать блочные операции с невыровненными данными.


Однако невыравненности это никак не компенсирует. Отнюдь, увеличение конвейера требует большой осторожности при выравнивании, поскольку производительность подсистемы памяти тут крайне важна. В некоторых краевых случаях можно в разы поднять быстродейстиве только за счет выравнивания.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: inline memset
От: lextasy Украина www.mira-tech.com.ua
Дата: 13.02.04 19:34
Оценка:
Здравствуйте, MShura, Вы писали:

MS>Есть подзадача:

MS> написать эквивалент
MS>
MS>memset( mem, 0, size );
MS>

MS>но без вызова функции memset.

MS>Ограничение в том, чтобы при использовании любого компилятора, с любыми ключами, не было вызова внешней функции "memset", потому как в некоторых случаях этой функции нет в подключаемых библиотеках.

MS>Очень хочется, чтобы любой компилятор встраивал эту функцию всегда.

MS>Варианты типа:

MS>- самому написать memset с помощью циклов — не интересны
MS>- написать вставку на asm не подходят, т.к. на разных компиляторах разные синтаксисы.




MS>P.S.

MS>memcpy(dst, src, size) легко заменяется примерно таким кодом:

MS>*(A*)dst = *(A*)src, где A — произвольная структура размера size.


MS>Для memset хочется примерно такой же вариант, поскольку если написать


MS>
MS>A a = {0};
MS>


MS>то сгенерится почти нужный код.



Я уже давно пользуюсь такой конструкцией:

template<int N> class dword_fill_t{
public:
    static inline void fill(int* buf, const int& value)
    {
        *buf = value;
        dword_fill_t<N-1>::fill(buf + 1, value);
    }
};

template<> class dword_fill_t<0>{
public:
    static inline void fill(int* buf, const int& value){}
};

template<int N> class byte_fill_t{
public:
    static inline void fill(char* buf, const char& value)
    {
        *buf = value;
        byte_fill_t<N-1>::fill(buf + 1, value);
    }
};

template<> class byte_fill_t<0>{
public:
    static inline void fill(char* buf, const char& value){}
};

template<class X> void zero_fill(X& x)
{
    dword_fill_t<sizeof(x)/sizeof(int)>::fill((int*)&x, 0);
    byte_fill_t<sizeof(x)%sizeof(int)>::fill(((char*)&x) + sizeof(x) - sizeof(x)%sizeof(int), 0);
}


Например,

inline void clear_guid(GUID& x)
{
    zero_fill(x);
}



вызов функции clear_guid в релизе транслируется в 4 ассемблерных инструкции mov
Re[9]: inline memset
От: Шахтер Интернет  
Дата: 14.02.04 02:06
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Это не сюрприз, это ошибка.


Ну да. По-моему, я так и написал -- bug.

АШ>Ведь с умножением матриц Вы бы так не поступили?


Честно говоря, не понял про матрицы. Как, так?
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: inline memset
От: folk Россия  
Дата: 14.02.04 04:32
Оценка:
Здравствуйте, lextasy, Вы писали:

L>Я уже давно пользуюсь такой конструкцией:


L>
L>template<int N> class dword_fill_t{
L>public:
L>    static inline void fill(int* buf, const int& value)
L>    {
L>        *buf = value;
L>        dword_fill_t<N-1>::fill(buf + 1, value);
L>    }
L>};

L>template<> class dword_fill_t<0>{
L>public:
L>    static inline void fill(int* buf, const int& value){}
L>};

L>template<int N> class byte_fill_t{
L>public:
L>    static inline void fill(char* buf, const char& value)
L>    {
L>        *buf = value;
L>        byte_fill_t<N-1>::fill(buf + 1, value);
L>    }
L>};

L>template<> class byte_fill_t<0>{
L>public:
L>    static inline void fill(char* buf, const char& value){}
L>};

L>template<class X> void zero_fill(X& x)
L>{
L>    dword_fill_t<sizeof(x)/sizeof(int)>::fill((int*)&x, 0);
L>    byte_fill_t<sizeof(x)%sizeof(int)>::fill(((char*)&x) + sizeof(x) - sizeof(x)%sizeof(int), 0);
L>}

L>


L>Например,


L>
L>inline void clear_guid(GUID& x)
L>{
L>    zero_fill(x);
L>}
L>



L>вызов функции clear_guid в релизе транслируется в 4 ассемблерных инструкции mov


Для типов, размер которых >= sizeof(int), но требования к выравниванию менее строгие чем у int, это может привести к alignment fault.

Например:

char array[4];
zero_fill(array);

// будет эквивалентно
char array[4];
*reinterpret_cast<int*>(&array) = 0; // здесь возможен fault, т.к. array не обязательно будет выровнен на 4
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[3]: inline memset
От: zrs  
Дата: 14.02.04 09:05
Оценка:
Здравствуйте, folk, Вы писали:

L>>вызов функции clear_guid в релизе транслируется в 4 ассемблерных инструкции mov


F>Для типов, размер которых >= sizeof(int), но требования к выравниванию менее строгие чем у int, это может привести к alignment fault.


F>Например:


F>
F>char array[4];
F>zero_fill(array);

F>// будет эквивалентно
F>char array[4];
F>*reinterpret_cast<int*>(&array) = 0; // здесь возможен fault, т.к. array не обязательно будет выровнен на 4
F>


Это можно решить, заполняя начало блока байтами, а потом уже интами с выравниванием, но дело в том, что данная конструкция не эквивалентна memset и предназначена для более других вещей.
... << RSDN@Home 1.1.3 beta 1 >>
Re[10]: inline memset
От: Кодт Россия  
Дата: 14.02.04 09:32
Оценка:
Здравствуйте, Шахтер, Вы писали:

АШ>>Ведь с умножением матриц Вы бы так не поступили?


Ш>Честно говоря, не понял про матрицы. Как, так?


Вот как раз с матрицами я бы
1) передавал по ссылке, и только по ссылке (слишком велик оригинал). Внутри функции заводил бы локальные переменные и как-то учитывал, что на вход может придти *this.

2) В матричной алгебре нет оператора *= произведение имеет другую размерность. Хотя если матрицы с динамическим размером, то пуркуа бы и не па...
... << RSDN@Home 1.1.2 stable >>
Перекуём баги на фичи!
Re[10]: inline memset
От: Анатолий Широков СССР  
Дата: 14.02.04 10:10
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, Анатолий Широков, Вы писали:


АШ>>Это не сюрприз, это ошибка.


Ш>Ну да. По-моему, я так и написал -- bug.


АШ>>Ведь с умножением матриц Вы бы так не поступили?


Ш>Честно говоря, не понял про матрицы. Как, так?


Я имел ввиду это:

...
    //    композиция преобразований
    matrix& operator*= (const matrix &rht)
    {
        matrix temp = {0};

                matrix &lft = (*this);

        for(size_t i = 0; i<4; i++)
        for(size_t j = 0; j<4; j++)
        for(size_t k = 0; k<4; k++)    
            temp[i][j] +=  lft[i][k] * rht[k][j];
                
                lft = temp;

                return (*this);
    } // operator *=..


И умножение комплексных чисел я бы реализовывал схожим манером, поэтому

m*=m;

не приводил бы к "удивительному" результату.
Re[11]: inline memset
От: Павел Кузнецов  
Дата: 14.02.04 11:33
Оценка: +1
Здравствуйте, Кодт, Вы писали:

К> 2) В матричной алгебре нет оператора *= произведение имеет другую

К> размерность.

Это если матрицы не квадратные...
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: inline memset
От: lextasy Украина www.mira-tech.com.ua
Дата: 14.02.04 19:27
Оценка:
Здравствуйте, folk, Вы писали:

F>Для типов, размер которых >= sizeof(int), но требования к выравниванию менее строгие чем у int, это может привести к alignment fault.


F>Например:


F>
F>char array[4];
F>zero_fill(array);

F>// будет эквивалентно
F>char array[4];
F>*reinterpret_cast<int*>(&array) = 0; // здесь возможен fault, т.к. array не обязательно будет выровнен на 4
F>


В общем случае — так оно и есть...
Интересно только, для x86 это замечание актуально? Если да, то насколько?
Re[4]: inline memset
От: lextasy Украина www.mira-tech.com.ua
Дата: 14.02.04 19:30
Оценка:
Здравствуйте, zrs, Вы писали:

zrs> дело в том, что данная конструкция не эквивалентна memset и предназначена для более других вещей.


Для более каких вещей?
Re[4]: inline memset
От: folk Россия  
Дата: 15.02.04 02:38
Оценка: 4 (1)
Здравствуйте, lextasy, Вы писали:

L>Здравствуйте, folk, Вы писали:


F>>Для типов, размер которых >= sizeof(int), но требования к выравниванию менее строгие чем у int, это может привести к alignment fault.


F>>Например:


F>>
F>>char array[4];
F>>zero_fill(array);

F>>// будет эквивалентно
F>>char array[4];
F>>*reinterpret_cast<int*>(&array) = 0; // здесь возможен fault, т.к. array не обязательно будет выровнен на 4
F>>


L>В общем случае — так оно и есть...

L>Интересно только, для x86 это замечание актуально? Если да, то насколько?

Во сколько точно обойдется копирование на невыровненный адрес в x86 я не знаю, но здравый смысл подсказывает что падение производительности будет не менее чем в 2-3 раза.
Простейшее решение — вставить компайл-тайм проверку __alignof(X) >= __alignof(int), чтобы шаблон работал только с допустимыми типами.
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[5]: inline memset
От: lextasy Украина www.mira-tech.com.ua
Дата: 15.02.04 15:53
Оценка:
Здравствуйте, folk, Вы писали:

F>Простейшее решение — вставить компайл-тайм проверку __alignof(X) >= __alignof(int), чтобы шаблон работал только с допустимыми типами.


Большое спасибо за действительно ценный совет!

Удалено избыточное цитирование. -- ПК.
Re[8]: inline memset
От: e-Xecutor Россия  
Дата: 16.02.04 08:06
Оценка:
Здравствуйте, Шахтер, Вы писали:

А вот так:
const Complex & Complex::operator *= (const Complex &x)
 {
  const Complex& tmp=this==&x?Complex(x):x;
  double re_=re;

  re = re*tmp.re - im*tmp.im ;
  im = re_*tmp.im + im*tmp.re ;

  return *this;
 }



Re[5]: inline memset
От: zrs  
Дата: 16.02.04 08:18
Оценка:
Здравствуйте, lextasy, Вы писали:

L>Здравствуйте, zrs, Вы писали:


zrs>> дело в том, что данная конструкция не эквивалентна memset и предназначена для более других вещей.


L>Для более каких вещей?


Для вещей, размер которых известен в compile time и не слишком большой. Оговорюсь, сам ничего против такого подхода не имею и даже использую что то подобное.
... << RSDN@Home 1.1.3 beta 1 >>
Re[9]: inline memset
От: e-Xecutor Россия  
Дата: 16.02.04 08:40
Оценка:
Здравствуйте, e-Xecutor, Вы писали:

Мнда.
В точности как задумывалось этот код работает только
будучи откомпилённым борландом 5.5
Вообще работает под cl 6,7.1, g++ 3.2.3 и CC: Sun C++ 5.5 2003/03/12.
Под icl 7.1 не работает. Темпорал убивается сразу же...
Re[10]: inline memset
От: Шахтер Интернет  
Дата: 16.02.04 23:32
Оценка:
Здравствуйте, e-Xecutor, Вы писали:

EX>Здравствуйте, e-Xecutor, Вы писали:


EX>Мнда.

EX>В точности как задумывалось этот код работает только
EX>будучи откомпилённым борландом 5.5
EX>Вообще работает под cl 6,7.1, g++ 3.2.3 и CC: Sun C++ 5.5 2003/03/12.
EX>Под icl 7.1 не работает. Темпорал убивается сразу же...

const Complex & Complex::operator *= (const Complex &x)
 {
  double re_ = re*x.re - im*x.im ;
  double im_ = re*x.im + im*x.re ;
  
  re=re_;
  im=im_;
  
  return *this;
 }
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[11]: inline memset
От: e-Xecutor Россия  
Дата: 17.02.04 07:31
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, e-Xecutor, Вы писали:


EX>>Здравствуйте, e-Xecutor, Вы писали:


EX>>Мнда.

EX>>В точности как задумывалось этот код работает только
EX>>будучи откомпилённым борландом 5.5
EX>>Вообще работает под cl 6,7.1, g++ 3.2.3 и CC: Sun C++ 5.5 2003/03/12.
EX>>Под icl 7.1 не работает. Темпорал убивается сразу же...

В данном конкретном случае всё понятно
Я ж про общий.
Жаль, такая фитча пропала...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.