Здравствуйте, IROV.., Вы писали:
IRO>как правильней делать? IRO>преобразовать к uint8_t * и свапнуть 0 и 2 элемент.
Это вряд ли хорошо, будут какие-нибудь пенальти за смены разрядности и работу с памятью...
Я бы по маске вырезал "неподвижную и "подвижную" части, и подвижной сделал бы rotl какой-нибудь интрисик-функцией...
А если компиллер интрисики не умеет эффективно, то что-то вроде
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, IROV.., Вы писали:
E>Это вряд ли хорошо, будут какие-нибудь пенальти за смены разрядности и работу с памятью...
А вот тут по подробней?
E>Я бы по маске вырезал "неподвижную и "подвижную" части, и подвижной сделал бы rotl какой-нибудь интрисик-функцией... E>А если компиллер интрисики не умеет эффективно, то что-то вроде
Здравствуйте, IROV.., Вы писали:
IRO>для x84 и для ARM и вообще для мобильных и тд
Ну, если хочется портобабельно, то сдвигами и масками. В надежде, что компилятор поймет, что вы пытаетесь сказать, и подберет более-менее подходящий ассемблерный вариант (например, gcc догадывается циклический сдвиг, расписанный сдвигами и масками, в команду ror/rol превратить).
А так, на любой платформе что-нибудь да есть, что превращается в нормальный ассемблер. Например, htonl/ntohl, если речь идет о преобразовании между нативным форматом и big endian. Нп универсального портабельного варианта нет, к сожалению.
Здравствуйте, IROV.., Вы писали:
IRO>как правильней делать? IRO>для x84 и для ARM и вообще для мобильных и тд
Для дебажной версии — без разницы, лишь бы работало; для релизной — сделать платформо-зависимый код, наиболее эффективно решающий эту задачу (надо читать документацию на процессор и компилятор, затем профилировать).
Компилятору удобнее будет, если арифметика останется арифметикой — меньше шансов на пессимизацию, чем при манёврах с битфилдами и байтовой адресацией.
aik>компилятор такое переваривает хорошо. с типами, "UL" и "|" вместо "+".
ок, я тоже вижу везде примерно такой код.
Но некоторые люди говорят что это "перевымудренно" и давай свапать байты по uint8_t *
у меня сразу "стоп-сигнал" из разряда работа с памятью, могут быть траблы.
На IOS и Android вроде есть выравнивание по 4 байта для указателя. Наловил этих дров.
Думал отсюда ноги ростут.
IRO>>для x84 и для ARM и вообще для мобильных и тд aik>они ж все little-endian, нет разве? ну, если "x84" на самом деле "x86"
уже вроде нет) little-endian можно в реальной жизни найти на старых маках там где еще Power проц был, и да спасибо чтото уже x64 в голову въелся что 4 тащу везде))
IRO>>З.Ы. кроме big endian проблемы aik>это что за проблема конкретно?
big-endian VS little-endian
IRO>нужно поменять FF и AA местами
IRO>как правильней делать?
Так как порядок байтов нам не известен, то перед преобразованиями его надо привести к чему нибудь известному.
Я использую для этого htonl(..) и ntohl(..). Другой переносимый способ мне не известен. Дело в том, что (чисто теоретически) порядок может быть не только обратным, но и смешанным.
IRO>преобразовать к uint8_t * и свапнуть 0 и 2 элемент.
Я бы преобразовал, таки, к unsigned char*, а не к uint8_t*. В стандарте нет гарантии, что sizeof(uint8_t) == sizeof(char)
Кстати, нет гарантии, что и sizeof(uint32_t) == 4, так что вариант со сдвигами предпочтительнее, если интересует переносимость.
IRO>либо делать
Можно и так, но сначала htonl IRO>
Здравствуйте, IROV.., Вы писали:
IRO>>>для x84 и для ARM и вообще для мобильных и тд aik>>они ж все little-endian, нет разве? ну, если "x84" на самом деле "x86" IRO>уже вроде нет) little-endian можно в реальной жизни найти на старых маках там где еще Power проц был, и да спасибо чтото уже x64 в голову въелся что 4 тащу везде))
Все ровно наоборот — x86 всегда был (и будет) little-endian, и последние дистрибутивы линукса (типа fedora21, ubuntu14) для powerpc64 тоже собираются под little-endian. Я знаю что arm умеет и так, и эдак, но что у них по дефолту — не знаю.
Здравствуйте, aik, Вы писали:
aik>Здравствуйте, IROV.., Вы писали:
IRO>>>>для x84 и для ARM и вообще для мобильных и тд aik>>>они ж все little-endian, нет разве? ну, если "x84" на самом деле "x86" IRO>>уже вроде нет) little-endian можно в реальной жизни найти на старых маках там где еще Power проц был, и да спасибо чтото уже x64 в голову въелся что 4 тащу везде))
aik>Все ровно наоборот — x86 всегда был (и будет) little-endian, и последние дистрибутивы линукса (типа fedora21, ubuntu14) для powerpc64 тоже собираются под little-endian. Я знаю что arm умеет и так, и эдак, но что у них по дефолту — не знаю.
ну да) это я уже в названиях перепутал. Просто опять же смысл в том что сейчас все привели к одному, пусть будет "little-endian")))
IRO>нужно поменять FF и AA местами
IRO>как правильней делать?
Всё уже придумано до нас, с учётом endianness и прочее. Взять в интернете/Линуксе/etc реализацию htonl/ntohl, убрать лишние байт-манипуляции Получаете свой макрос (или функцию, смотрите что удобнее).
Здравствуйте, Mr.Delphist, Вы писали:
MD>Здравствуйте, IROV.., Вы писали:
IRO>>есть
IRO>>
IRO>>uint32_t color = 0xFFFF00AA;
IRO>>
IRO>>нужно поменять FF и AA местами
IRO>>как правильней делать?
MD>Всё уже придумано до нас, с учётом endianness и прочее. Взять в интернете/Линуксе/etc реализацию htonl/ntohl, убрать лишние байт-манипуляции Получаете свой макрос (или функцию, смотрите что удобнее).
А что против свап двух байт по указателю? Чем это хуже если не брать во внимание endianness
Здравствуйте, IROV.., Вы писали:
IRO>А что против свап двух байт по указателю? Чем это хуже если не брать во внимание endianness
Ну, уже упоминалось, что
1) нужно знать смещения этих байтов относительно исходного адреса (зависит от endianness)
2) работа с non-aligned адресами может быть либо хуже с точки зрения перфоманса, либо просто невозможна на данной машинной архитектуре
Здравствуйте, Erop, Вы писали:
E>Я бы по маске вырезал "неподвижную и "подвижную" части, и подвижной сделал бы rotl какой-нибудь интрисик-функцией... E>А если компиллер интрисики не умеет эффективно, то что-то вроде
[GLS1] suggests that the following sort of generalization of bit reversal, which he calls "flip," is a good candidate to consider for a computer's instruction set:
if (k & 1) x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
if (k & 2) x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
if (k & 4) x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
if (k & 8) x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
if (k & 16) x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
(The last two and operations can be omitted.) For k = 31, this operation reverses the bits in a word. For k = 24, it reverses the bytes in a word. For k = 7, it reverses the bits in each byte, without changing the positions of the bytes. For k = 16, it swaps the left and right halfwords of a word, and so on. In general, it moves the bit at position m to position m xor k. It can be implemented in hardware very similarly to the way a rotate shifter is usually implemented (five stages of MUX's, with each stage controlled by a bit of the shift amount k).
E>>Это вряд ли хорошо, будут какие-нибудь пенальти за смены разрядности и работу с памятью... IRO>А вот тут по подробней?
Это зависит от конкретной архитектуры и от того где данные лежат до обмена байт и где должны оказаться после.
Если, например, работа с памятью медленная, то выгружать регистр в память, что бы потом переслать ещё байт туда/байт сюда, а потом загрузить данные из памяти обратно -- это тормоза, хотя есть надежда на кэш...
Если архитектура допускает параллельность, то опять же все эти выгрузки в память и загрузки обратно, а так же перходы между разной битностью, процу трудно параллелить, а вычисление формулы вроде (x&~mask)|__rotl(x&mask, 16) параллелится идеально... И результат сразу в процессоре имеем.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
IRO>для x84 и для ARM и вообще для мобильных
Если всё же отвлечься от С, а просто рассмотреть задачу по перетасовки байт на x86 и на ARM, то можно ещё вспомнить, что, например, у первого встречается SSE, а у второго — Neon. А в них есть есть инструкции, делающие именно нужные преобразования сразу над массивами байт. Тебе ведь порядок байт нужно не в одном пикселе единоразово поменять, а в целом массиве, не так ли?
Ну то есть, если нужно сделать чтобы работало быстро, то придётся учитывать возможности платформы (или, что лучше, взять готовую библиотеку, где нужные функции уже написаны и оптимизированы под все распространённые версии процессоров). А если использовать С, то, как уже сказали, используй побитовые сдвиги и маски, и надейся что компилятор сможет это более-менее векторизовать.
IRO>преобразовать к uint8_t * и свапнуть 0 и 2 элемент.
В контексте векторизации, кстати говоря, такая операция может смутить компилятор и векторизовать он может отказаться. Ну то есть помимо того, что на многих архитектурах сама манипуляция байтами выйдет дороже свапа внутри 32-битного регистра, так ещё и компилятор такой код будет хуже оптимизировать.
IRO>>нужно поменять FF и AA местами
IRO>>как правильней делать? IRO>>преобразовать к uint8_t * и свапнуть 0 и 2 элемент.
AS>Да, так. Можно еще попробовать битфилды запользовать — но тут надо смотреть реально генерируемый код.
IRO>>>есть
IRO>>>
IRO>>>uint32_t color = 0xFFFF00AA;
IRO>>>
IRO>>>нужно поменять FF и AA местами
IRO>>>как правильней делать?
MD>>Всё уже придумано до нас, с учётом endianness и прочее. Взять в интернете/Линуксе/etc реализацию htonl/ntohl, убрать лишние байт-манипуляции Получаете свой макрос (или функцию, смотрите что удобнее).
IRO>А что против свап двух байт по указателю? Чем это хуже если не брать во внимание endianness
Вариант с кастом к массиву компилятор не может корректно оптимизировать в случае использования в качестве источника данных массива uin32_t — получается лишнее перекладывание на стек. В результае на моем железе вариант с битовыми операциями примерно в 8 раз быстрее и примерно равен по стоимости обвязке (вычитыванию значения из памяти + организация цикла). Получается, в данном случае надо использовать либо битовые операции в любом из вариантов выше, либо rol, если он есть.
Здравствуйте, Mr.Delphist, Вы писали:
MD>2) работа с non-aligned адресами может быть либо хуже с точки зрения перфоманса, либо просто невозможна на данной машинной архитектуре
О каком align может идти речь при работе с байтами ? Для них alignment вроде как всегда 1 ?