Допустим, у меня есть указатель на 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);
Вроде ведь mov mov'у рознь, т.е. в зависимости от аргументов будут выполняться разные команды. Тут я вижу только что в первом случае код на ассемблере короче, что не гарантирует более быстрого выполнения.
Здравствуйте, _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, т.е., придётся или копировать содержимое в эту структуру, или приводить указатели, что в общем я и делал, только с байтами. В итоге выйгрыш будет только в удобстве, но не в скорости.
Здравствуйте, 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, т.е., придётся или копировать содержимое в эту структуру, или приводить указатели, что в общем я и делал, только с байтами. В итоге выйгрыш будет только в удобстве, но не в скорости.
Здравствуйте, 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>
Второй вариант правильный. Первый будет работать только на некоторых платформах. Насчет скорости сказать ничего нельзя. Хотя при большом регистровом пространстве второй вариант может оказаться быстрее.
господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.
JS>господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.
Ш>Второй вариант правильный. Первый будет работать только на некоторых платформах.
Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.
Кроме того не гарантируется, что размер типа int будет равен 4-м байтам.
Здравствуйте, JakeS, Вы писали:
JS>господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.
Как правило интеловский, например, компилятор генерирует более качественный код. Так как учитывает особенности работы процессора.
Здравствуйте, Sir Wiz, Вы писали:
SW>Здравствуйте, JakeS, Вы писали:
JS>>господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.
SW>Как правило интеловский, например, компилятор генерирует более качественный код. Так как учитывает особенности работы процессора.
В данном случае никакие особенности процессора ни при чем. речь идет всего лишь о доступе к участкам памяти. Очевидно что быстрее всего единственная операция mov регистр, адрес и в дальнейшем работа только с регистрами. Причем совершенно без разницы какой процессор.
mov eax, addr
mov ebx
а затем получение и сразу же использование байтиков, типа:
mov eax, ebx
shr eax, 16
and eax, FFh
но ни один компиллятор такого не сделает, ибо все зависит от конкретного случая, а компиллятору это до фонаря. Поэтому повторяю, если это действительно критично — inline asm. Иначе не стоит парится о таких мелочах а оптимизировать чтонибудь другое.
Ш>>Второй вариант правильный. Первый будет работать только на некоторых платформах.
А почему, кстати?
SW>Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.
В приведенном выше коде — surprise! — никогда не будет правого сдвига отрицательных чисел.
SW>Кроме того не гарантируется, что размер типа int будет равен 4-м байтам.
Это да. Но тогда и задача разложить int на черыре байта выглядит как-то...
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-м байтам.
Меня интересовало как будет быстрее, все попутные проблемы в общем не суть.
Здравствуйте, elcste, Вы писали:
SW>>Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.
E>В приведенном выше коде — surprise! — никогда не будет правого сдвига отрицательных чисел.
(*pInt & 0xff000000) >> 24;
Не будет, говорите? Это для x86. Borland и VC сделают тут две разные вещи.
А ещё есть вариации с low/big endian... Я не нашел в стандарте ни слова о требованиях к побитному расположению в памяти интегральных типов.
Здравствуйте, JakeS, Вы писали:
JS>>>господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.
SW>>Как правило интеловский, например, компилятор генерирует более качественный код. Так как учитывает особенности работы процессора.
JS>В данном случае никакие особенности процессора ни при чем. речь идет всего лишь о доступе к участкам памяти. Очевидно что быстрее всего единственная операция mov регистр, адрес и в дальнейшем работа только с регистрами. Причем совершенно без разницы какой процессор.
Не претендую на профессианлизм в этом вопросе, но как же конвейерная оптимизация?
Опыт показал что способ с преобразованием к указателю на байт вроде как быстрее (примерно на 20-30%%). Хотя подозреваю что результат может измениться при использовании разных компиляторов и оптимизаций под отдельные процессоры. (Я компилировал на штатном VC с включением оптимизации по скорости).