Скорость получения байта по указателю
От: WinterMute Россия http://yarrr.ru
Дата: 06.09.04 16:49
Оценка:
Допустим, у меня есть указатель на 32-х битное целое, нужно получить в нём второй байт, какой код будет быстрее:

int* pInt = ....;

BYTE second = ((byte*)pInt)[1];
или 
BYTE second = (*pInt & 0x00ff0000) >> 16;

// И что быстрее, если мне нужно разложить по байтам всё целое число?

BYTE first  = ((byte*)pInt)[0];
BYTE second = ((byte*)pInt)[1];
BYTE third  = ((byte*)pInt)[2];
BYTE fourth = ((byte*)pInt)[3];

или 

BYTE first  = (*pInt & 0xff000000) >> 24;
BYTE second = (*pInt & 0x00ff0000) >> 16;
BYTE third  = (*pInt & 0x0000ff00) >> 8;
BYTE fourth = (*pInt & 0x000000ff);
... << RSDN@Home 1.1.4 @@subversion >>
Re: Скорость получения байта по указателю
От: JakeS  
Дата: 06.09.04 17:26
Оценка:
46:       BYTE second1 = ((byte*)pInt)[1];
00402A08   mov         eax,dword ptr [ebp-14h]
00402A0B   mov         cl,byte ptr [eax+1]
00402A0E   mov         byte ptr [ebp-18h],cl
47:       BYTE second2 = (*pInt & 0x00ff0000) >> 16;
00402A11   mov         edx,dword ptr [ebp-14h]
00402A14   mov         eax,dword ptr [edx]
00402A16   and         eax,0FF0000h
00402A1B   shr         eax,10h
00402A1E   mov         byte ptr [ebp-1Ch],al


думаю ясно без слов.
Re[2]: Скорость получения байта по указателю
От: WinterMute Россия http://yarrr.ru
Дата: 06.09.04 17:52
Оценка:
JS>
JS>46:       BYTE second1 = ((byte*)pInt)[1];
JS>00402A08   mov         eax,dword ptr [ebp-14h]
JS>00402A0B   mov         cl,byte ptr [eax+1]
JS>00402A0E   mov         byte ptr [ebp-18h],cl
JS>47:       BYTE second2 = (*pInt & 0x00ff0000) >> 16;
JS>00402A11   mov         edx,dword ptr [ebp-14h]
JS>00402A14   mov         eax,dword ptr [edx]
JS>00402A16   and         eax,0FF0000h
JS>00402A1B   shr         eax,10h
JS>00402A1E   mov         byte ptr [ebp-1Ch],al
JS>


JS>думаю ясно без слов.


Вроде ведь mov mov'у рознь, т.е. в зависимости от аргументов будут выполняться разные команды. Тут я вижу только что в первом случае код на ассемблере короче, что не гарантирует более быстрого выполнения.

Или нет? Я ассемблер почти не знаю.
... << RSDN@Home 1.1.4 @@subversion >>
Re: Скорость получения байта по указателю
От: _nn_ www.nemerleweb.com
Дата: 06.09.04 18:02
Оценка:
Здравствуйте, WinterMute, Вы писали:

Может сделать так :
union int_char
{
 int i;
 char c[4];
};

int_char* ic = pInt;
// Доступ
ic.c[0]
ic.c[1]
ic.c[2]
ic.c[3]


P.S.
Под Windows будет работать, но корректная работа не гарантированна стандартом.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Скорость получения байта по указателю
От: WinterMute Россия http://yarrr.ru
Дата: 06.09.04 18:16
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Может сделать так :

__>
__>union int_char
__>{
__> int i;
__> char c[4];
__>};

__>int_char* ic = pInt;
__>// Доступ
__>ic.c[0]
__>ic.c[1]
__>ic.c[2]
__>ic.c[3]
__>


Но сначала-то у меня указатель на int, т.е., придётся или копировать содержимое в эту структуру, или приводить указатели, что в общем я и делал, только с байтами. В итоге выйгрыш будет только в удобстве, но не в скорости.
... << RSDN@Home 1.1.4 @@subversion >>
Re[3]: Скорость получения байта по указателю
От: _nn_ www.nemerleweb.com
Дата: 06.09.04 18:22
Оценка:
Здравствуйте, WinterMute, Вы писали:

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


__>>Может сделать так :

__>>
__>>union int_char
__>>{
__>> int i;
__>> char c[4];
__>>};

__>>int_char* ic = pInt;
__>>// Доступ
__>>ic.c[0]
__>>ic.c[1]
__>>ic.c[2]
__>>ic.c[3]
__>>


WM>Но сначала-то у меня указатель на int, т.е., придётся или копировать содержимое в эту структуру, или приводить указатели, что в общем я и делал, только с байтами. В итоге выйгрыш будет только в удобстве, но не в скорости.


А в чем проблема :
void x(int* p)
{
 ((int_char*)p)->c[0];
 // или
 int_char* pic = (int_char*)p;
 pic->c[0];
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: Скорость получения байта по указателю
От: WinterMute Россия http://yarrr.ru
Дата: 06.09.04 18:28
Оценка:
__>А в чем проблема :
__>
__>void x(int* p)
__>{
__> ((int_char*)p)->c[0];
__> // или
__> int_char* pic = (int_char*)p;
 pic->>c[0];
__>}
__>


Проблемы нет, просто где тут выйгрыш в скорости по сравнению с:
>void x(int* p)
>{
> BYTE b = ((byte*)p)[0];
>}
... << RSDN@Home 1.1.4 @@subversion >>
Re: Скорость получения байта по указателю
От: Шахтер Интернет  
Дата: 06.09.04 18:56
Оценка:
Здравствуйте, WinterMute, Вы писали:

WM>Допустим, у меня есть указатель на 32-х битное целое, нужно получить в нём второй байт, какой код будет быстрее:


WM>
WM>int* pInt = ....;

WM>BYTE second = ((byte*)pInt)[1];
WM>или 
WM>BYTE second = (*pInt & 0x00ff0000) >> 16;

WM>// И что быстрее, если мне нужно разложить по байтам всё целое число?

WM>BYTE first  = ((byte*)pInt)[0];
WM>BYTE second = ((byte*)pInt)[1];
WM>BYTE third  = ((byte*)pInt)[2];
WM>BYTE fourth = ((byte*)pInt)[3];

WM>или 

WM>BYTE first  = (*pInt & 0xff000000) >> 24;
WM>BYTE second = (*pInt & 0x00ff0000) >> 16;
WM>BYTE third  = (*pInt & 0x0000ff00) >> 8;
WM>BYTE fourth = (*pInt & 0x000000ff);
WM>


Второй вариант правильный. Первый будет работать только на некоторых платформах. Насчет скорости сказать ничего нельзя. Хотя при большом регистровом пространстве второй вариант может оказаться быстрее.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Скорость получения байта по указателю
От: JakeS  
Дата: 07.09.04 05:07
Оценка:
господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.
Re[3]: Скорость получения байта по указателю
От: WinterMute Россия http://yarrr.ru
Дата: 07.09.04 06:36
Оценка:
JS>господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.

Но я не знаю ассемблера
... << RSDN@Home 1.1.4 @@subversion >>
Re[2]: Скорость получения байта по указателю
От: Sir Wiz Россия  
Дата: 07.09.04 07:32
Оценка:
Здравствуйте, Шахтер, Вы писали:


WM>>
WM>>int* pInt = ....;

// Кусь

WM>>BYTE first  = (*pInt & 0xff000000) >> 24;
WM>>BYTE second = (*pInt & 0x00ff0000) >> 16;
WM>>BYTE third  = (*pInt & 0x0000ff00) >> 8;
WM>>BYTE fourth = (*pInt & 0x000000ff);
WM>>


Ш>Второй вариант правильный. Первый будет работать только на некоторых платформах.


Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.
Кроме того не гарантируется, что размер типа int будет равен 4-м байтам.
... << RSDN@Home 1.1.4 @@subversion >>
Re[3]: Скорость получения байта по указателю
От: Sir Wiz Россия  
Дата: 07.09.04 07:33
Оценка:
Здравствуйте, JakeS, Вы писали:

JS>господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.


Как правило интеловский, например, компилятор генерирует более качественный код. Так как учитывает особенности работы процессора.
... << RSDN@Home 1.1.4 @@subversion >>
Re[4]: Скорость получения байта по указателю
От: JakeS  
Дата: 07.09.04 08:36
Оценка:
Здравствуйте, Sir Wiz, Вы писали:

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


JS>>господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.


SW>Как правило интеловский, например, компилятор генерирует более качественный код. Так как учитывает особенности работы процессора.


В данном случае никакие особенности процессора ни при чем. речь идет всего лишь о доступе к участкам памяти. Очевидно что быстрее всего единственная операция mov регистр, адрес и в дальнейшем работа только с регистрами. Причем совершенно без разницы какой процессор.
mov eax, addr
mov ebx
а затем получение и сразу же использование байтиков, типа:
mov eax, ebx
shr eax, 16
and eax, FFh
но ни один компиллятор такого не сделает, ибо все зависит от конкретного случая, а компиллятору это до фонаря. Поэтому повторяю, если это действительно критично — inline asm. Иначе не стоит парится о таких мелочах а оптимизировать чтонибудь другое.
Re[3]: Скорость получения байта по указателю
От: elcste  
Дата: 07.09.04 09:18
Оценка:
Здравствуйте, Sir Wiz, Вы писали:

WM>>>int* pInt = ....;

SW>// Кусь

WM>>>BYTE first  = (*pInt & 0xff000000) >> 24;
WM>>>BYTE second = (*pInt & 0x00ff0000) >> 16;
WM>>>BYTE third  = (*pInt & 0x0000ff00) >> 8;
WM>>>BYTE fourth = (*pInt & 0x000000ff);

Ш>>Второй вариант правильный. Первый будет работать только на некоторых платформах.

А почему, кстати?

SW>Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.


В приведенном выше коде — surprise! — никогда не будет правого сдвига отрицательных чисел.

SW>Кроме того не гарантируется, что размер типа int будет равен 4-м байтам.


Это да. Но тогда и задача разложить int на черыре байта выглядит как-то...
Re[3]: Скорость получения байта по указателю
От: WinterMute Россия http://yarrr.ru
Дата: 07.09.04 09:26
Оценка:
WM>>>BYTE first = (*pInt & 0xff000000) >> 24;
WM>>>BYTE second = (*pInt & 0x00ff0000) >> 16;
WM>>>BYTE third = (*pInt & 0x0000ff00) >> 8;
WM>>>BYTE fourth = (*pInt & 0x000000ff);
WM>>>[/ccode]

Ш>>Второй вариант правильный. Первый будет работать только на некоторых платформах.


SW>Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.


int я привёл для примера, у меня, конечно, unsigned int

SW>Кроме того не гарантируется, что размер типа int будет равен 4-м байтам.


Меня интересовало как будет быстрее, все попутные проблемы в общем не суть.
... << RSDN@Home 1.1.4 @@subversion >>
Re[4]: Скорость получения байта по указателю
От: Sir Wiz Россия  
Дата: 07.09.04 09:29
Оценка:
Здравствуйте, elcste, Вы писали:

SW>>Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.


E>В приведенном выше коде — surprise! — никогда не будет правого сдвига отрицательных чисел.


(*pInt & 0xff000000) >> 24;


Не будет, говорите? Это для x86. Borland и VC сделают тут две разные вещи.

А ещё есть вариации с low/big endian... Я не нашел в стандарте ни слова о требованиях к побитному расположению в памяти интегральных типов.
... << RSDN@Home 1.1.4 @@subversion >>
Re[5]: Скорость получения байта по указателю
От: Sir Wiz Россия  
Дата: 07.09.04 09:31
Оценка:
Здравствуйте, JakeS, Вы писали:

JS>>>господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.


SW>>Как правило интеловский, например, компилятор генерирует более качественный код. Так как учитывает особенности работы процессора.


JS>В данном случае никакие особенности процессора ни при чем. речь идет всего лишь о доступе к участкам памяти. Очевидно что быстрее всего единственная операция mov регистр, адрес и в дальнейшем работа только с регистрами. Причем совершенно без разницы какой процессор.


Не претендую на профессианлизм в этом вопросе, но как же конвейерная оптимизация?
... << RSDN@Home 1.1.4 @@subversion >>
Re[4]: Скорость получения байта по указателю
От: Sir Wiz Россия  
Дата: 07.09.04 09:35
Оценка:
Здравствуйте, WinterMute, Вы писали:

WM>Меня интересовало как будет быстрее, все попутные проблемы в общем не суть.


Правильно
Автор: JakeS
Дата: 06.09.04
, ИМХО.
... << RSDN@Home 1.1.4 @@subversion >>
Re[4]: Скорость получения байта по указателю
От: Sir Wiz Россия  
Дата: 07.09.04 09:39
Оценка:
Здравствуйте, elcste, Вы писали:

Ш>>>Второй вариант правильный. Первый будет работать только на некоторых платформах.

E>А почему, кстати?

Например, отсутствие физической возможности обратиться к адресу не кратному 2^n, где n > 0.
... << RSDN@Home 1.1.4 @@subversion >>
Кстати да
От: WinterMute Россия http://yarrr.ru
Дата: 07.09.04 09:43
Оценка:
WM>>Меня интересовало как будет быстрее, все попутные проблемы в общем не суть.

SW>Правильно
Автор: JakeS
Дата: 06.09.04
, ИМХО.


Опыт показал что способ с преобразованием к указателю на байт вроде как быстрее (примерно на 20-30%%). Хотя подозреваю что результат может измениться при использовании разных компиляторов и оптимизаций под отдельные процессоры. (Я компилировал на штатном VC с включением оптимизации по скорости).
... << RSDN@Home 1.1.4 @@subversion >>
Re[5]: Скорость получения байта по указателю
От: elcste  
Дата: 07.09.04 09:48
Оценка:
Здравствуйте, Sir Wiz, Вы писали:

SW>>>Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.


E>>В приведенном выше коде — surprise! — никогда не будет правого сдвига отрицательных чисел.

SW>(*pInt & 0xff000000) >> 24;


SW>Не будет, говорите? Это для x86.


Никогда — это значит никогда. В том числе для x86, конечно.

SW>Borland и VC сделают тут две разные вещи.


Что ж, если какой-то компилятор работает неправильно (что, правда, еще надо показать), стоит отправить bug report.

SW>А ещё есть вариации с low/big endian... Я не нашел в стандарте ни слова о требованиях к побитному расположению в памяти интегральных типов.


Стандарт, по большей части, внутреннее представление типов не регламентирует. А при чем тут это?
Re[5]: Скорость получения байта по указателю
От: elcste  
Дата: 07.09.04 09:54
Оценка:
Здравствуйте, Sir Wiz, Вы писали:

Ш>>>>Второй вариант правильный. Первый будет работать только на некоторых платформах.

E>>А почему, кстати?

SW>Например, отсутствие физической возможности обратиться к адресу не кратному 2^n, где n > 0.


Гм-гм... Вы, как и я, предполагаете, что типы BYTE и byte в примерах WinterMute — это синонимы unsigned char?
Re[6]: Скорость получения байта по указателю
От: Sir Wiz Россия  
Дата: 07.09.04 09:57
Оценка:
Здравствуйте, elcste, Вы писали:

SW>>>>Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.


E>>>В приведенном выше коде — surprise! — никогда не будет правого сдвига отрицательных чисел.

E>

SW>>(*pInt & 0xff000000) >> 24;


SW>>Не будет, говорите? Это для x86.


E>Никогда — это значит никогда. В том числе для x86, конечно.


Извольте, вот пояснение с картинками

int * pInt = new int;
*pInt = -1;
*pInt = *pInt & 0xFF000000; // *pInt == -16777216
*pInt >> 24; // Правый сдвиг отрицательного числа.


SW>>Borland и VC сделают тут две разные вещи.

E>Что ж, если какой-то компилятор работает неправильно (что, правда, еще надо показать), стоит отправить bug report.

Правильно работает. В соответствии со стандартом делает что хочет. В частности, VC сохраняет знак, Borland — нет.

SW>>А ещё есть вариации с low/big endian... Я не нашел в стандарте ни слова о требованиях к побитному расположению в памяти интегральных типов.


E>Стандарт, по большей части, внутреннее представление типов не регламентирует. А при чем тут это?


К тому, что побитные операции в принципе не переносимы. Поправьте, если это не так.
... << RSDN@Home 1.1.4 @@subversion >>
Re[6]: Скорость получения байта по указателю
От: Sir Wiz Россия  
Дата: 07.09.04 09:59
Оценка:
Здравствуйте, elcste, Вы писали:

E>Гм-гм... Вы, как и я, предполагаете, что типы BYTE и byte в примерах WinterMute — это синонимы unsigned char?


Да, точно подмечено. Не знаю, честно говоря. Но, видимо, да.
... << RSDN@Home 1.1.4 @@subversion >>
Re[7]: Скорость получения байта по указателю
От: elcste  
Дата: 07.09.04 10:22
Оценка: 23 (2) +2
Здравствуйте, Sir Wiz, Вы писали:

E>>>>В приведенном выше коде — surprise! — никогда не будет правого сдвига отрицательных чисел.

SW>>>(*pInt & 0xff000000) >> 24;

SW>*pInt = *pInt & 0xFF000000; // *pInt == -16777216
SW>*pInt >> 24; // Правый сдвиг отрицательного числа.

Найдите в картинках одно отличие.

Отгадка: Подвыражение *pInt имеет тип int, тогда как подвыражение *pInt & 0xff000000 в 32-разрядных компиляторах под x86 имеет тип unsigned int.

Литература: Читать про integer literals, integral promotions и usual arithmetic conversions.

SW>К тому, что побитные операции в принципе не переносимы. Поправьте, если это не так.


Побитовые операции над беззнаковыми типами в принципе переносимы. Побитовые операции над знаковыми типами имеют ряд опасных особенностей (которые, кстати, лучше описаны в стандарте C99, нежели C++).
Re[7]: Скорость получения байта по указателю
От: elcste  
Дата: 07.09.04 10:27
Оценка:
Здравствуйте, Sir Wiz, Вы писали:

E>>Гм-гм... Вы, как и я, предполагаете, что типы BYTE и byte в примерах WinterMute — это синонимы unsigned char?


SW> Да, точно подмечено. Не знаю, честно говоря. Но, видимо, да.


То есть вопрос о выравнивании исчерпан. Правильно я понимаю?
Re[8]: Скорость получения байта по указателю
От: Sir Wiz Россия  
Дата: 07.09.04 11:16
Оценка:
Здравствуйте, elcste, Вы писали:

E>Отгадка: Подвыражение *pInt имеет тип int, тогда как подвыражение *pInt & 0xff000000 в 32-разрядных компиляторах под x86 имеет тип unsigned int.


Сдаюсь. Правильно.
... << RSDN@Home 1.1.4 @@subversion >>
Re[6]: Скорость получения байта по указателю
От: JakeS  
Дата: 07.09.04 12:35
Оценка:
Здравствуйте, Sir Wiz, Вы писали:

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


JS>>>>господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.


SW>>>Как правило интеловский, например, компилятор генерирует более качественный код. Так как учитывает особенности работы процессора.


JS>>В данном случае никакие особенности процессора ни при чем. речь идет всего лишь о доступе к участкам памяти. Очевидно что быстрее всего единственная операция mov регистр, адрес и в дальнейшем работа только с регистрами. Причем совершенно без разницы какой процессор.


SW>Не претендую на профессианлизм в этом вопросе, но как же конвейерная оптимизация?


Конвейерная оптимизация — это то, поведение чего никто не гарантирует и, кроме создателей, предсказать не может. Короче как морская свинка и не свинка, и не морская, но работает быстрее.
Re[3]: Скорость получения байта по указателю
От: Шахтер Интернет  
Дата: 07.09.04 16:32
Оценка: 8 (1)
Здравствуйте, Sir Wiz, Вы писали:

SW>Здравствуйте, Шахтер, Вы писали:



WM>>>
WM>>>int* pInt = ....;

SW>// Кусь

WM>>>BYTE first  = (*pInt & 0xff000000) >> 24;
WM>>>BYTE second = (*pInt & 0x00ff0000) >> 16;
WM>>>BYTE third  = (*pInt & 0x0000ff00) >> 8;
WM>>>BYTE fourth = (*pInt & 0x000000ff);
WM>>>


Ш>>Второй вариант правильный. Первый будет работать только на некоторых платформах.


SW>Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.

SW>Кроме того не гарантируется, что размер типа int будет равен 4-м байтам.

Как сказал автор, int 32 разрядный. Сколько он при этом занимает на самом деле байт -- не имеет значения.
Сдвигов отрицательных чисел в этом примере не будет. Потому что константе 0xFF000000, например, на машине, где int 32 разрядный, будет назначен тип unsigned int.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[7]: Скорость получения байта по указателю
От: Sir Wiz Россия  
Дата: 08.09.04 06:25
Оценка:
Здравствуйте, JakeS, Вы писали:

SW>>Не претендую на профессианлизм в этом вопросе, но как же конвейерная оптимизация?


JS>Конвейерная оптимизация — это то, поведение чего никто не гарантирует и, кроме создателей, предсказать не может. Короче как морская свинка и не свинка, и не морская, но работает быстрее.


AFAIK, поведение конвейеров описано в интеловской документации.

И в компиляторе Intel реализована оптимизация именно под их процессоры, учитывающая работу конвейеров, HT, и времени выполнения команд.

Пожалуй единственное, известное мне место, где приходится писать на ассемблере — MMX/SSE/SSE2/SSE3. Например при умножении матриц компилятор не всегда может сам векторизовать.
... << RSDN@Home 1.1.4 @@subversion >>
Re: Скорость получения байта по указателю
От: K13 http://akvis.com
Дата: 31.08.09 10:41
Оценка:
WM>Допустим, у меня есть указатель на 32-х битное целое, нужно получить в нём второй байт, какой код будет быстрее:

А нужен именно второй байт или все четыре распихать в разные стороны?
На входе указатель или само целое?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.