Ada_Ru форум

Обсуждение языка Ада

Re: Атомарные примитивы

Оставить новое сообщение

Сообщения

Иван Левашев
Re: Атомарные примитивы
2009-10-06 08:27:17

Dmitry A. Kazakov writes:

 

 

On Thu, 5 Nov 2009 11:26:37 +0000 (UTC), you wrote:

 

Начну с того, что, как я выяснил, pragma Atomic () не

работает.

 

Вы неверно интерпретировали стандарт, см. ниже, а так

же другие посты.

 

Видимо, я пытался искать то, чего нет там, где ему

следует быть. А таким вещам, я думаю, в стандарте Ады

следует быть. gatomic.c датируется девяностыми годами.

 

 

Легко, если соответствующая инструкция атомарна.

 

Как написано в Platform SDK, чтение и запись по выровненным

адресам атомарны.

 

Например, GNAT будет

ругаться на Atomic для Unsigned_64, но не на

Unsigned_32, на 32 разрядной

машине. Если инструкция mov на одно слово атомарна, но

на два слова - mov и

mov - нет.

 

64битные значения на x86 можно атомарно гонять с помощью

lock cmpxchg8b. CAS здесь ни к чему, зато он

атомарен и для восьми байт.

 

На pragma Atomic для new Unsigned_n GNAT, кстати, ругается в

любом случае, потому что примитивные операции уже объявлены.

 

 

Я развлекался задачкой реализации X := X + 1 используя

только pragma Atomic.

 

Одна из причин, почему это не получится — нужен барьер памяти.

Без lock, mfence или т. п. не будет гарантирован порядок.

 

Atomic там используется только для разделяемых

переменных, для которых

"update" достаточно. Т.е. для тех, где изменение значения

не зависит от

прежнего значения, или, иначе, такие изменения

происходят на контексте

protected action, тогда как чтение может происходить

асинхронно.

 

А нет ли такого места, где переупорядочивание

записи/чтения могло бы всё испортить? Может быть,

на x86 окно не большое, а вот на каком–нибудь убойном

Itanium запись и чтение могут перескочить на расстояние,

достаточное для создания проблем. protected, несомненно,

создаёт полные барьеры, а вот без него?

 

 

Нет. Именно для этого и были введены protected object-ы. На них

Вы можете

реализовать все примитивы низкого уровня БЕЗ

использования атомарных

ИНСТРУКЦИЙ. Разница в значении в том, что атомарные

инструкции используют

неявную блокировку встроенную в процессор.

 

Ну почему же неявную. lock очень даже явно фигурирует. Встречал

упоминание, что xchgl, incl и им подобные неявно устанавливают

LOCK#, но мне как–то спокойнее написать префикс. А присваивания

по адресам, выравненным на границе 4х байт, я так понимаю, за

счёт архитектуры атомарны, даже без всяких блокировок. Тут, правда, нужно различать атомарность и последовательность. Атомарность

применительно к 386+ подразумевает, что при чтении 32битного

выровненного значения мы не получим пол–старого, пол–нового

значения. Но это только полбеды. Порядок записи/чтения тоже важен.

Обычный movl работает атомарно, но не создаёт барьер.

 

 

Да даже, если бы pragma Atomic работала, как на Аде

выразить атомарный CAS? Без if не обойтись, а на if

неделимость чтения–записи уже не должна распространяться.

В стандартной библиотеке CAS пока нет.

 

protected type Low_Level is

...

 

Я имел в виду что–нибудь такое же короткое, как X := X + 1;

 

Наверное, какой–нибудь Intel Ada Compiler мог бы соптимизировать

этот крендель в 32битное целое. Нету атомарности в стандарте,

понял уже.

 

 

Строки без счётчика ссылок — это несерьёзно. protected в

роли счётчика ссылок — это тоже несерьёзно. Только для

fallback implementation.

 

Не уверен. Во всяком случае, simple components использует

protected object

для работы со счетчиками. Хотя я не сравнивал

эффективность с Windows

InterlockedExchangeAdd на x86. Я не ожидаю особо "УЖАСНОЙ" разницы, но можно было бы померить.

 

Вадим что–то писал насчёт разницы в три раза для Qt строк в

C++ и в Аде. Не привлекательно. На стационарных пофиг, но

сейчас всё более распространены ноуты, и трёхкратное увеличение

производительности автоматически значит повышение времени

работы примерно в три раза. В самолётах и на спутниках это,

может быть, не очень важно. Я рад за спутники, но меня

больше волнует Ада на desktop. И на ноутах.

 

Интересно, если соптимизировать так:

 

type Fast_Reference_Counter is record

Common_Counter : Integer_32 := 0;

pragma Atomic (Common_Counter);

Origin_Thread_Id : Unsigned_32 := Current_Thread_Id;

Origin_Counter : Integer_32 := 0;

end record;

 

... это будет быстрее, чем обычный счётчик ссылок? Я сейчас

программированием занимаюсь в Windows XP, запущенной в VMWare

на Mac OS X. Для программирования нормально, но для

замеров не подходит.

Новое сообщение:
Страницы: 1

Чтобы оставить новое сообщение необходимо Зарегистрироваться и Войти