Здравствуйте, 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 ?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Mr.Delphist, Вы писали:
MD>>2) работа с non-aligned адресами может быть либо хуже с точки зрения перфоманса, либо просто невозможна на данной машинной архитектуре
PD>О каком align может идти речь при работе с байтами ? Для них alignment вроде как всегда 1 ?
Мы все уже привыкли к тому, что байт является минимальной аппаратно адресуемой единицей на всех распространённых CPU, но если говорить о кросс-платформе "по гамбургскому счёту", то я бы не стал упускать из вида всякие хитровывернутые микроконтроллеры, у которых минимально адресуемым может быть WORD или DWORD (проще блок доступа к памяти, меньше заморочек с кешем и т.п.).
IRO>и
IRO>когда идет каст на uint8_t * а не через юнион
Это бессмысленно — лучше оптимизировать это компилятор не сможет, а вот хуже — запросто. Вариант с rol будет либо такой же, либо чуть лучше. Так что используйте либо битфилд, либо только требуемые битовые операции .
IRO>>и
IRO>>когда идет каст на uint8_t * а не через юнион
AS>Это бессмысленно — лучше оптимизировать это компилятор не сможет, а вот хуже — запросто. Вариант с rol будет либо такой же, либо чуть лучше. Так что используйте либо битфилд, либо только требуемые битовые операции .
Мы как всегда отошли от темы топика, если честно изначально меня не интересовало "самое быстрое".
А факт того что по указателю будет медленней чем арифметически. Или даже могут быть проблемы с align или еще какими прелестями. Вот основной посыл который я услышал из всего топика — только то что есть проблемы endian и что компилятор — не будет оптимизировать. с endian понятно, но мой оппонент говорит что в его жизни нету и не будет других кроме как little. А вот "отказ оптимизатора" это весомый аргумент.
Здравствуйте, Pavel Dvorkin, Вы писали:
MD>>2) работа с non-aligned адресами может быть либо хуже с точки зрения перфоманса, либо просто невозможна на данной машинной архитектуре PD>О каком align может идти речь при работе с байтами ? Для них alignment вроде как всегда 1 ?
Не всякая аппаратура умеет адресовать части слов...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Andrew S, Вы писали:
AS>Это бессмысленно — лучше оптимизировать это компилятор не сможет, а вот хуже — запросто. Вариант с rol будет либо такой же, либо чуть лучше. Так что используйте либо битфилд, либо только требуемые битовые операции .
Битфилд тоже стрёмно, так как переносимых гарантий раскладки полей по битам нет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, IROV.., Вы писали:
IRO>Мы как всегда отошли от темы топика, если честно изначально меня не интересовало "самое быстрое".
А какое интересовало? В чём критерий хорошести решений?
И если самое быстрое не интересовало, то почему отказ от оптимизации -- аргумент?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, VladFein, Вы писали:
VF>Какие FF? VF>0xFFFF00AA ? VF>0xFFFF00AA ?
А какая разница?
Меня смутило ещё и то, что не ясно что делать, если там не AA, а что-то другое, 66, например...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
IRO>>как правильней делать? IRO>>преобразовать к uint8_t * и свапнуть 0 и 2 элемент. IRO>>либо делать
F>явный union и выглядит наиболее "канонично": F>
AS>>Это бессмысленно — лучше оптимизировать это компилятор не сможет, а вот хуже — запросто. Вариант с rol будет либо такой же, либо чуть лучше. Так что используйте либо битфилд, либо только требуемые битовые операции .
E>Битфилд тоже стрёмно, так как переносимых гарантий раскладки полей по битам нет...
Скажем так, по опыту это не менее переносимо, чем битовые операции. И как минимум ровно так же эффективно.
Здравствуйте, VladFein, Вы писали:
VF>Здравствуйте, IROV.., Вы писали:
IRO>>есть
IRO>>
IRO>>uint32_t color = 0xFFFF00AA;
IRO>>
IRO>>нужно поменять FF и AA местами
VF>Похоже, меня одного смутила неопределённость вопроса: VF>Какие FF? VF>0xFFFF00AA ? VF>0xFFFF00AA ? VF>0xFFFF00AA ?
согласен, не корректно.
Но если прочитать вопрос целиком, а не частями то станет ясно что не важно что с чем. А важно как!? и точнее даже не как, а с намеком на то "а не будет ли плохо делать это через указатели" я специально не хотел точную формулировку. Хотел услышать более расширенное мнение людей по данному поводу.
Узнал что бест-практик все таки битовые операции.
VF>Из разговора о uint8_t как бы понятно, что НЕ средний вариант.
не уловил замечание по поводу uint8_t