![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Endian LibraryBoost , ,
|
Endian Home Конверсионные функции Арифметические типы Буферные типы Подход к выбору |
Повышаю. Endian предоставляет возможности для манипулирования endianness целых чисел и определяемых пользователем типов.
Рассмотрим следующий код:
int16_t i = 0x0102; FILE * file = fopen("test.bin", "wb"); // binary file! fwrite(&i, sizeof(int16_t), 1, file); fclose(file);
На OS X, Linux или системах Windows с процессором Intel, шестнадцатеричный сброс "теста. bin" выходной файл производит:
0201
На системах OS X с процессором PowerPC, или системах Solaris с процессором SPARC, шестнадцатеричный сброс "теста. bin" выходной файл производит:
0102
Здесь происходит то, что процессоры Intel сначала заказывают байты целого числа с наименее значимым байтом, в то время как процессоры SPARC сначала размещают самый значимый байт. Некоторые процессоры, такие как PowerPC, позволяют операционной системе выбирать, какой заказ применяется.
Самый значимый байт-первый порядок традиционно называется "большой эндиан" заказ и наименее значимый байт-первый традиционно называется "маленький эндиан" заказ. Название происходит от сатирического романа Джонатана Свифта Путешествия Гулливера , где конкурирующие королевства открывали свои яйца в мягком варе на разных концах.
См. статью Википедии Endianness для широкого обсуждения эндианности.
Программисты обычно могут игнорировать эндианность, за исключением случаев, когда они читают свалку ядра на малоэндианных системах. Но программистам приходится иметь дело с эндианностью при обмене двоичными целыми числами и двоичными значениями плавающей точки между компьютерными системами с различной эндианностью, будь то физическая передача файлов или по сети. Программисты также могут использовать библиотеку при минимизации внутренних или внешних размеров данных.
Повышаю. Эндиан предлагает три различных подхода к борьбе с эндианностью. Все три подхода поддерживают целые числа и типы пользовательских определений (UDT).
Каждый подход имеет долгую историю успешного использования, и каждый подход имеет случаи использования, когда он предпочтительнее других подходов.
Функции преобразования Endian - Приложение использует встроенные целочисленные типы для удержания значений и вызывает предоставленные функции преобразования для преобразования байтового порядка по мере необходимости. Поставляются как мутирующие, так и немутирующие конверсии, и каждый из них поставляется в безусловных и условных вариантах.
Типы индийских буферов - Приложение использует предоставленные эндианные типы буферов для удержания значений и явно преобразует в встроенные целые типы и из них. Предусмотрены буферные размеры 8, 16, 24, 32, 40, 48, 56 и 64 бит (т.е. 1, 2, 3, 4, 5, 6, 7 и 8 байт). Неупорядоченные целочисленные типы буферов предусмотрены для всех размеров, а выровненные типы буферов предусмотрены для 16, 32 и 64-разрядных размеров. Предоставленные конкретные типы представляют собой типографские теги для шаблона общего класса, которые могут использоваться непосредственно для менее распространенных вариантов использования.
Endian арифметические типы - В приложении используются предоставленные эндиановые арифметические типы, которые обеспечивают те же операции, что и встроенные арифметические типы C++. Все преобразования являются неявными. Предоставляются арифметические размеры 8, 16, 24, 32, 40, 48, 56 и 64 бит (т.е. 1, 2, 3, 4, 5, 6, 7 и 8 байт). Невыровненные целые типы предусмотрены для всех размеров, а выровненные арифметические типы предусмотрены для 16, 32 и 64-битных размеров. Предоставляемые конкретные типы представляют собой типографские теги для шаблона общего класса, которые могут использоваться непосредственно в общем коде для менее распространенных случаев использования.
Boost Endian - это библиотека только для заголовков. Функции C++11, влияющие на интерфейсы, такие как , за исключением
, используются только при наличии. См. C++03 поддержка функций C++11 для деталей.
Этот раздел был перенесен на свой Выберите подход .
Большинство компиляторов, включая GCC, Clang и Visual C++, предоставляют встроенную поддержку для байт-своппинга. Библиотека Endian использует эти внутренние элементы, поскольку они могут привести к меньшему и более быстрому генерируемому коду, особенно для оптимизированных сборок.
Определение макро BOOST_ENDIAN_NO_INTRINSICS
будет подавлять использование внутренних элементов. Это полезно, когда компилятор не имеет внутренней поддержки или не может найти соответствующий заголовок, возможно, потому, что он является более старым релизом или имеет очень ограниченные библиотеки поддержки.
Макро BOOST_ENDIAN_INTRINSIC_MSG
определяется либо как "no byte swap intrinsics"
, либо как строка, описывающая конкретный набор используемых внутренних элементов. Это полезно для устранения недостающих свойств как источника проблем с производительностью.
Рассмотрим эту проблему:
Add 100 to a big endian value in a file, then write the result to a file | |
Подход индийского арифметического типа | Подход к функции преобразования в Индии |
big_int32_at x; ... read into x from a file ... x += 100; ... write x to a file ... |
int32_t x; ... читать в x из файла ... big_to_native_inplace(x); x += 100; native_to_big_inplace(x); ... записывать x в файл ... |
В оптимизированных сборках не будет разницы в производительности между двумя подходами, независимо от нативной эндианности машины. Это связано с тем, что оптимизация компиляторов будет генерировать один и тот же код для каждого. Этот вывод был подтвержден изучением сгенерированного кода сборки для GCC и Visual C++. Кроме того, время, затрачиваемое на выполнение ввода/вывода, определяет скорость этого приложения.
Теперь рассмотрим немного другую проблему:
Add a million values to a big endian value in a file, then write the result to a file | |
Подход индийского арифметического типа | Подход к функции преобразования в Индии |
big_int32_at x; ... read into x from a file ... for (int32_t i = 0; i < 1000000; ++i) x += i; ... write x to a file ... |
int32_t x; ... читать в x из файла ... big_to_native_inplace(x); для (int32_t i = 0; i < 1000000; ++i) x += i; native_to_big_inplace(x); ... писать x в файл ... |
С эндианским арифметическим подходом на маленьких эндианских платформах происходит неявное преобразование из и обратно в большой эндиан. При подходе к функции конверсии Endian пользователь гарантирует, что конверсии выполняются вне цикла, поэтому код может работать быстрее на небольших эндиан-платформах.
Эти тесты были запущены против сборок релиза примерно в 2012 году 4-ядерного маленького эндиана X64 Intel Core i5-3570K CPU @ 3,40 ГГц под Windows 7.
Пещерный пылесос: Таймер Windows CPU имеет очень высокую гранулярность. Повторные пробежки одних и тех же тестов часто дают значительно разные результаты.
См. test/loop_time_test.cpp для фактического кода и benchmark/Jamfile.v2 для настройки сборки.
GNU C++ version 4.8.2 on Linux virtual machine | |||||
Iterations: 10'000'000'000, Intrinsics: __builtin_bswap16, etc. | |||||
Тестовый случай | Endian arithmetic type |
Endian conversion function |
|||
16-битный выровненный большой эндиан | 8.46 s | 5.28 s | |||
16-битный маленький эндиан | 5.28 s | 5.22 s | |||
32-битный выровненный большой эндиан | 8.40 s | 2.11 s | |||
32-битный маленький эндиан | 2.11 s | 2.10 s | |||
64-битный выровненный большой эндиан | 14.02 s | 3.10 s | |||
64-битный маленький эндиан | 3.00 s | 3.03 s |
Microsoft Visual C++ version 14.0 | |||||
Iterations: 10'000'000'000, Intrinsics: cstdlib _byteswap_ushort, etc. | |||||
Тестовый случай | Endian arithmetic type |
Endian conversion function |
|||
16-битный выровненный большой эндиан | 8.27 s | 5.26 s | |||
16-битный маленький эндиан | 5.29 s | 5.32 s | |||
32-битный выровненный большой эндиан | 8.36 s | 5.24 s | |||
32-битный маленький эндиан | 5.24 s | 5.24 s | |||
64-битный выровненный большой эндиан | 13.65 s | 3.34 s | |||
64-битный маленький эндиан | 3.35 s | 2.73 s |
Только ли заголовок реализации?
Да.
Поддерживаются ли компиляторы C++03?
Да.
Используется ли в реализации компилятор встроенного байт-своппинга?
Да, если есть. См. Внутренняя встроенная поддержка .
Зачем беспокоиться об эндианности?
Переносимость двоичных данных является основным вариантом использования.
Имеет ли эндианность какое-либо использование за пределами портативных двоичных файлов или сетевых форматов ввода/вывода?
Использование невыровненных целых типов с размером, адаптированным к потребностям приложения & # 39, является второстепенным использованием, которое сохраняет внутреннее или внешнее пространство памяти. Например, использование
big_int40_buf_t
илиbig_int40_t
в большом массиве экономит много места по сравнению с одним из 64-битных типов.
Зачем беспокоиться о бинарных вводах/выводах? Почему стоит использовать C++ Стандартные библиотечные вставки и экстракторы?
Форматы обмена данными часто определяют двоичные целочисленные данные.
Бинарные целочисленные данные меньше, поэтому I/O быстрее, а размеры файлов меньше. Передача между системами обходится дешевле.
Furthermore, binary integer data is of fixed size, and so fixed-size disk records are possible without padding, easing sorting and allowing random access.
Disadvantages, such as the inability to use text utilities on the resulting files, limit usefulness to applications where the binary I/O advantages are paramount.
Что лучше, большой или маленький?
Big-endian, как правило, предпочтительнее в сетевой среде и немного больше отраслевого стандарта, но Little-endian может быть предпочтительнее для приложений, которые работают в основном на x86, x86-64 и других процессорах Little-endian. Статья Wikipedia дает больше плюсов и минусов.
Почему поддерживается только большая и маленькая родная эндианность?
Это единственные эндианские схемы, которые сегодня имеют какую-либо практическую ценность. PDP-11 и другие подходы среднего эндиана интересны, но не имеют отношения к сегодняшним разработчикам C++. То же самое относится и к архитектурам, которые позволяют переключать эндианность во время выполнения. Спецификация для нативного заказа была тщательно разработана, чтобы обеспечить поддержку таких заказов в будущем, если возникнет необходимость. Спасибо Говарду Хиннанту за предложение.
Почему существуют буферные и арифметические типы?
Конверсии в буферных типах являются явными. Преобразования в арифметических типах неявны. Это фундаментальное различие является преднамеренной особенностью дизайна, которая была бы потеряна, если бы иерархия наследования была разрушена.
Оригинальный дизайн предусматривал только арифметические типы. Типы буферов были запрошены во время официального рассмотрения теми, кто желает получить полный контроль над конверсией. Они также полагали, что буферные типы с меньшей вероятностью будут неправильно использоваться программистами технического обслуживания, не знакомыми с последствиями выполнения множества целочисленных операций на эндиановых арифметических целочисленных типах.
Что получается при использовании буферных типов, а не только при использовании арифметических типов?
Гарантия того, что скрытые преобразования не выполняются. Это имеет первостепенное значение для пользователей, заинтересованных в достижении максимальной скорости.
Всегда простое использование типов арифметики отлично подходит для других пользователей. Когда необходимо обеспечить максимальную скорость, арифметические типы могут использоваться в тех же шаблонах проектирования или идиомах, которые будут использоваться для буферных типов, в результате чего один и тот же код генерируется для обоих типов.
Каковы ограничения целочисленной поддержки?
Испытания проводились только на машинах, которые используют арифметику комплемента. Функции преобразования Endian поддерживают только 16, 32 и 64-разрядные целые числа. Эндиановые типы поддерживают только 8, 16, 24, 32, 40, 48, 56 и 64-битные невыровненные целые числа, а 8, 16, 32 и 64-битные выровненные целые числа.
Почему нет поддержки плавающей точки?
Была предпринята попытка поддержки четырехбайтного
float
s и восьмибайтногоdouble
s, ограниченного IEEE 754 (также известный как ISO/IEC/IEEE 60559) плавающая точка и далее ограниченный системами, где плавающая точка эндианности не отличается от целочисленной эндианности.Даже с этими ограничениями поддержка типов с плавающей запятой не была надежной и была удалена. Например, простое изменение эндианности числа с плавающей точкой может привести к сигнализации-NAN. Для всех практических целей двоичная сериализация и эндианность для целых чисел являются одной и той же проблемой. Это не относится к числам с плавающей запятой, поэтому интерфейсы и форматы двоичной сериализации для с плавающей запятой плохо вписываются в библиотеку на основе эндиана.
Библиотека была переработана сверху донизу, чтобы учесть изменения, запрошенные во время официального обзора. См. страницу Mini-Review для подробностей.
boost/endian/endian.hpp
был переименован в
boost/endian/arithmetic.hpp
. Добавлены заголовкиboost/endian/conversion.hpp
иboost/endian/buffers.hpp
. Соответственно были изменены имена файлов инфраструктуры._t
, но имена псевдонимов выровненного типа теперь имеют суффикс_at
.endian_reverse()
перегрузкиint8_t
и
uint8_t
были добавлены для улучшенной общности. (Пьер Тэлбот)endian_reverse_inplace()
на
endian_reverse_inplace()
endian_reverse_inplace()
. (Пьер Тэлбот)noexcept
. Компиляторы C++03 все еще поддерживаются.До официального выпуска Boost, шаблон класса endian_arithmetic
используется в течение десятилетия или более с той же функциональностью, но под названием endian
. Другие названия также изменились в официальном релизе. Если макро BOOST_ENDIAN_DEPRECATED_NAMES
определено, старые, теперь устаревшие имена все еще поддерживаются. Тем не менее, имя шаблона класса endian
предоставляется только для компиляторов, поддерживающих псевдонимы шаблона C++11. Для компиляторов C++03 имя должно быть изменено на endian_arithmetic
.
Для поддержки обратной совместимости заголовка прежний заголовок boost/endian/endian.hpp
перенаправляется на boost/endian/arithmetic.hpp
. Для этого необходимо определить BOOST_ENDIAN_DEPRECATED_NAMES
. Он должен использоваться только при переходе к официальному выпуску библиотеки, поскольку он будет удален в будущем выпуске.
C++11 Функция | Работа с компиляторами C++03 |
Охваченные числа | Использует заголовок boost/core/scoped_enum.hpp для эмуляции C++11 scoped enums. |
за исключением |
Использует макрос BOOST_NOEXCEPT, который определяется как нуль для компиляторов, не поддерживающих эту функцию C++11. |
C++11 PODs (N2342) | Использует компиляторы C++03, которые расслабляют правила POD C++03, но см. Ограничения здесь и здесь . Также см. макросы для явного POD-контроля here и here. |
Стандартизация. План состоит в том, чтобы представить Boost. Эндиан в комитет по стандартам C++ для возможного включения в Техническую спецификацию или сам стандарт C++.
Специализации для численные_лимиты
. Роджер Ли попросил, чтобы все типы boost::endian
предоставляли специализации numeric_limits
. Видишь? Выпуск GitHub 4.
Поддержка буфера символов. В ходе мини-обзора Питер Димов отметил, что получение и настройка основных типов арифметики (или эквивалентов
) из / в смещение в массив неподписанного угля является общей необходимостью. См. Boost.Endian mini-review posting.
Вне диапазона обнаружения. Петр Димов указал, что в ходе мини-обзора было бы желательно сделать исключение из буферных значений. См. конец этой публикации и последующие ответы.
Комментарии и предложения были получены от Аддера, Бенаки Мурти, Кристофера Колхоффа, Клиффа Грина, Даниэля Джеймса, Дэйва Хандли, Дженнаро Прото, Гордона Деретта, Гордона Вудхула, головокружения, Хартмута Кайзера, Говарда Хиннана, Джейсона Ньютона, Джеффа Флинна, Джереми Майтина-Шепарда, Джона Фило, Джона Мэддока, Кима Барретта, Марша Рэя, Мартина Боннера, Матиаса Капелетто, Матиаса Капелетто, Нейла Мэйхью, Невина Либера, Олафа ван дер Спека, Пола Бристоу, Питера Димова, Пьера Эндекота, Фила Беннефолла, Пири Джахколы, Рене Риверы, Роберта Стюарта, Роланда Ли, Роланда Шварца, Себастьяна Редла, Тима Блехмана, Тима Прошу прощения, если кого-то пропустили.
Последняя редакция: 05 Апрель 201605 April, 2016[ORIG_END] -->
© Copyright Beman Dawes, 2011, 2013
Распространяется под лицензией Boost Software License, версия 1.0. См. www.boost.org/ LICENSE_1_0.txt
Статья Endian Library раздела может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: ::
реклама |