128-битный int написан или загружен в две инструкции в C / C ++? - PullRequest
0 голосов
/ 25 мая 2018

Я знаю, что существует тип int128_t в C и C ++.

Если у меня есть два потока, один из которых читает из области памяти, содержащей это 128-битное целое число, а другой записывает в нее.

Есть ли вероятность, что это значение будет записано в виде двух 64-разрядных целочисленных записей или это будет одна 128-разрядная целочисленная запись?

Ответы [ 3 ]

0 голосов
/ 25 мая 2018

Во-первых, в C ++ есть тип no int128_t.Самый большой стандартный тип - int64_t.

Во-вторых, некоторые платформы предоставляют в качестве расширения 128-битный целочисленный тип.Например, gcc / clang / icc поддерживает тип __int128.

Чтобы правильно использовать этот тип в сценариях с многопоточностью, нужно (как и с любым другим типом!) Либо защитить доступ с помощью соответствующих конструкций синхронизации, либо использоватьstd::atomic<__int128>.Платформы, поддерживающие __int128, обычно также поддерживают его атомарную версию.

И просто чтобы удовлетворить ваше любопытство, я не знаю ни одного распространенного в настоящее время оборудования, которое могло бы изначально поддерживать 128-битные целые числа.

0 голосов
/ 25 мая 2018

Поддержка обсуждается в других ответах.Я буду обсуждать вопросы реализации.

Обычно при чтении из памяти компилятор выдает инструкции процессора для извлечения данных из памяти в регистр.Это может быть атомарным в зависимости от того, как установлена ​​база данных между процессором и памятью.

Если ваш процессор поддерживает 128-битную передачу, а память поддерживает 128-битную шину данных, это может быть одна выборка (или запись).

Если ваш процессор поддерживает 128-битную передачу {регистр}, но шина данных меньше, процессор выполнит достаточно выборок для передачи данных из памяти.Это может быть или не быть атомарным, в зависимости от вашего определения атомарного (это одна инструкция процессора, но может потребоваться более одной выборки).

Для процессоров, которые не поддерживают передачу 128-битных регистров, компилятор выдаст достаточно инструкций для считывания памяти в регистр (ы).Это для регистрации в памяти или памяти для регистрации передач.

Для передачи из памяти в память (например, назначение переменных) компилятор может выбрать использование чтения и записи блоков (если ваш процессор поддерживает чтение и запись блоков).Некоторые процессоры поддерживают SIMD, другие могут иметь инструкции по передаче блоков.Например, ARM имеет инструкции LDM (загрузить несколько) и STM (хранить несколько) для загрузки многих регистров из памяти и хранения многих регистров в памяти.Другой метод чтения и записи блоков состоит в использовании устройства DMA (если имеется).DMA может передавать данные, пока процессор выполняет другие инструкции.Тем не менее, накладные расходы на использование DMA могут потребовать больше инструкций, чем использование 16 8-байтовых (байтовых) передач.

Таким образом, компиляторы не обязаны поддерживать int128_t.Если они это поддерживают, существуют различные способы передачи данных в зависимости от аппаратной поддержки процессора и платформы.Просмотрите язык ассемблера, чтобы увидеть инструкции, выданные компилятором для поддержки int128_t.

0 голосов
/ 25 мая 2018

Ни C, ни C ++ не обязательно должны иметь тип int128_t, хотя, если компилятор поддерживает этот тип, тогда должен быть 128-битным целочисленным типом дополнения signed 2.Но атомарность не является обязательным.

Поведение при чтении и записи одновременно любого типа, не являющегося атомарным, равно undefined .

В C ++, если бы вы могли использовать std::atomic<int128_t> и, если ваша платформа имеет , имеет атомный int128_t, то это будет немногим больше, чем typedef.

В противном случае и в C,ваш компилятор может иметь атомарный 128-битный целочисленный тип.Если нет, то вы можете свернуть свою собственную версию, используя встроенную сборку.

...