Атомарность? boost::detail::atomic_count
От: Аноним  
Дата: 26.08.09 19:54
Оценка:
Доброго времени суток. Читаю исходники буста, нахожу там этот класс. Класс реализован для нескольких платформ (boost/smart_ptr/detail/atomic_count_*). Есть пара непонятных моментов. Смотрю реализацию для Windows, компилятор MSVC:
operator long() const
{
    return static_cast<long const volatile &>( value_ );
}

Как понимаю, здесь это делается для избежания нежелательной оптимизации? Так-ли это?

Смотрю дальше. Вариант для gcc 4 (с использованием встроенных __sync*), и для gcc3:
operator long() const
{
    return __sync_fetch_and_add( &value_, 0 );
}

using __gnu_cxx::__exchange_and_add;
...
operator long() const
{
    return __exchange_and_add( &value_, 0 );
}

Почему здесь так делается? И почему нельзя использовать вариант, реализованный для msvc?

Еще вопрос — насколько корректно присваивание значения разделяемой для нескольких потоков переменной типа long? Т.е. если для указанного atomic_count добавить:
atomic_count& operator=(long value)
{
    m_value = value;
}

Это корректно? Спасибо.
Re: Атомарность? boost::detail::atomic_count
От: Аноним  
Дата: 27.08.09 14:59
Оценка:
Неужели никто не может разъяснить нубу эту тему?
Re[2]: Атомарность? boost::detail::atomic_count
От: Аноним  
Дата: 27.08.09 20:33
Оценка: 30 (1)
Здравствуйте, Аноним, Вы писали:

А>Неужели никто не может разъяснить нубу эту тему?


Тема не нубовая

насколько я это понимаю, под Windows чтения long и так атомарны

Simple reads and writes to properly-aligned 32-bit variables are atomic operations.

http://msdn.microsoft.com/en-us/library/ms684122(VS.85).aspx

Каст на volatile требуется для того, чтобы другие нити видели такие атомарные операции в правильном порядке относительно других операций.

A read of a volatile object (volatile read) has Acquire semantics; a reference to a global or static object that occurs after a read of volatile memory in the instruction sequence will occur after that volatile read in the compiled binary.


Although the processor will not reorder un-cacheable memory accesses, un-cacheable variables must be volatile to guarantee that the compiler will not change memory order.

http://msdn.microsoft.com/en-us/library/12a04hfd.aspx

А>И почему нельзя использовать вариант, реализованный для msvc?

В первой ссылке указано про все 32 и 64 разрядные версии Windows.
Во второй — указано, что такой смысл volatile — Microsoft Specific.

А>насколько корректно присваивание значения разделяемой для нескольких потоков переменной типа long?

Некорректно по тем же причинам, что и некорректно простое чтение. Под Windows гарантирована атомарность, но не порядок, под сферической платформой в вакууме не гарантирована и атомарность.
Re[3]: Атомарность? boost::detail::atomic_count
От: Аноним  
Дата: 27.08.09 21:22
Оценка:
А>Каст на volatile требуется для того, чтобы другие нити видели такие атомарные операции в правильном порядке относительно других операций.
А>

A read of a volatile object (volatile read) has Acquire semantics; a reference to a global or static object that occurs after a read of volatile memory in the instruction sequence will occur after that volatile read in the compiled binary.

А>

Although the processor will not reorder un-cacheable memory accesses, un-cacheable variables must be volatile to guarantee that the compiler will not change memory order.

А>http://msdn.microsoft.com/en-us/library/12a04hfd.aspx

Переменная value_ объявлена без volatile, и то что её кастуют к ссылке на const volatile, не делает её volatile объектом.
Re: Атомарность? boost::detail::atomic_count
От: remark Россия http://www.1024cores.net/
Дата: 30.08.09 15:03
Оценка: 2 (1)
Здравствуйте, Аноним, Вы писали:

А>Доброго времени суток. Читаю исходники буста, нахожу там этот класс. Класс реализован для нескольких платформ (boost/smart_ptr/detail/atomic_count_*). Есть пара непонятных моментов. Смотрю реализацию для Windows, компилятор MSVC:

А>
А>operator long() const
А>{
А>    return static_cast<long const volatile &>( value_ );
А>}
А>

А>Как понимаю, здесь это делается для избежания нежелательной оптимизации? Так-ли это?


Во-первых, дело не только в атомарности, атомарность — это верхушка айсберга. Обычно вместе с ней идут упорядочивание и видимость.
Голая атомарность обычно никому не нужна. Смотри:
http://www.rsdn.ru/forum/philosophy/3181311.1.aspx
Автор: remark
Дата: 20.11.08


В данном случае volatile:
— гарантирует, что не будет использоваться кэшированное в регистре значение
— подавляет переупорядочивания компилятором
— подавляет переупорядочивания процессором


А>Смотрю дальше. Вариант для gcc 4 (с использованием встроенных __sync*), и для gcc3:

А>
А>operator long() const
А>{
А>    return __sync_fetch_and_add( &value_, 0 );
А>}
А>

А>
А>using __gnu_cxx::__exchange_and_add;
А>...
А>operator long() const
А>{
А>    return __exchange_and_add( &value_, 0 );
А>}
А>

А>Почему здеь так делается? И почему нельзя использовать вариант, реализованный для msvc?

В MSVC volatile наделён значительно большими полномочиями, чем в gcc. Фактически в MSVC volatile является примитивом многопоточной синхронизации.
Почему в gcc версии используются встроенные атомарные RMW операции... видимо просто автору было лень переходить на ассемблер. В gcc того же эффекта можно добиться с помощью __asm volatile ("..." ::: "memory") блока. Того же в смысле, что ран-тайм стоимость на x86 будет равна одной обычной MOV инструкции. Стоимость __sync_fetch_and_add() в 20-200 раз выше.



А>Еще вопрос — насколько корректно присваивание значения разделяемой для нескольких потоков переменной типа long? Т.е. если для указанного atomic_count добавить:

А>
А>atomic_count& operator=(long value)
А>{
А>    m_value = value;
А>}
А>

А>Это корректно? Спасибо.

Насколько это корректно зависит от того, что тебе надо. Синтаксически это корректно и будет скомпилировано компилятором.
Если m_value объявлена как volatile, то для многих нужно (но не для всех) это будет достаточно. Опять же на MSVC, на других компиляторах придётся использовать ассемблер или интринсики компилятора. Плюс зависимость от аппаратной платформы, которая будет определять какие доступы к памяти атомарны, а какие нет, где нужны дополнительные барьеры памяти, а где нет и т.д.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.