C# all writes are volatile
От: Ellin Россия www.rsdn.ru
Дата: 24.03.10 11:42
Оценка: 4 (1)
Правда что в C# все записи volatile? Вне зависимости помечана переменная как volatile или нет.здесь

However, in C# all writes are volatile (unlike say in Java), regardless of whether you write to a volatile or a non-volatile field. So, the above situation actually never happens in C#.

Re: C# all writes are volatile
От: Pavel_Agurov Россия  
Дата: 24.03.10 13:01
Оценка: 1 (1)
Здравствуйте, Ellin, Вы писали:

E>Правда что в C# все записи volatile? Вне зависимости помечана переменная как volatile или нет.здесь


E>

E>However, in C# all writes are volatile (unlike say in Java), regardless of whether you write to a volatile or a non-volatile field. So, the above situation actually never happens in C#.


Однако тут MS говорит: "Also, the variable is declared to be volatile to ensure that assignment to the instance variable completes before the instance variable can be accessed."
Re[2]: C# all writes are volatile
От: Pavel_Agurov Россия  
Дата: 24.03.10 13:29
Оценка:
P_A>Однако тут MS говорит: "Also, the variable is declared to be volatile to ensure that assignment to the instance variable completes before the instance variable can be accessed."

Ссылку забыл здесь
Re: C# all writes are volatile
От: Sinix  
Дата: 25.03.10 01:56
Оценка:
Здравствуйте, Ellin, Вы писали:

E>Правда что в C# все записи volatile?

Читаем источник:

The mainstream x86 and x64 processors implement a strong memory model where memory access is effectively volatile. So, a volatile field forces the compiler to avoid some high-level optimizations like hoisting a read out of a loop, but otherwise results in the same assembly code as a non-volatile read.

с оговоркой про чтение:

The x86/x64 instruction set actually does contains three fence instructions: LFENCE, SFENCE, and MFENCE. .. MFENCE is useful to go around one particular issue: if a core reads a memory location it previously wrote, the read may be served from the store buffer, even though the write has not yet been written to memory. I don’t actually know whether the CLR JIT ever inserts MFENCE instructions.


С итаниумами разруливается (в теории) JITом.

В общем помечайте переменные, к которым вы явно или неявно обращаетесь из нескольких потоков без lock { } и будет вам щастье.
Re[2]: C# all writes are volatile
От: Ellin Россия www.rsdn.ru
Дата: 25.03.10 08:34
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Ellin, Вы писали:


E>>Правда что в C# все записи volatile?

S>Читаем источник:

S>

S>The mainstream x86 and x64 processors implement a strong memory model where memory access is effectively volatile. So, a volatile field forces the compiler to avoid some high-level optimizations like hoisting a read out of a loop, but otherwise results in the same assembly code as a non-volatile read.

S>с оговоркой про чтение:
S>

S>The x86/x64 instruction set actually does contains three fence instructions: LFENCE, SFENCE, and MFENCE. .. MFENCE is useful to go around one particular issue: if a core reads a memory location it previously wrote, the read may be served from the store buffer, even though the write has not yet been written to memory. I don’t actually know whether the CLR JIT ever inserts MFENCE instructions.


S>С итаниумами разруливается (в теории) JITом.


S>В общем помечайте переменные, к которым вы явно или неявно обращаетесь из нескольких потоков без lock { } и будет вам щастье.


При volatile записи кеш процессора сбрасывается (анулируется). Если каждая запись volatile, то кеш практически вообще не используется. В чем тогда смысл lowlock?
Re[3]: C# all writes are volatile
От: Jolly Roger  
Дата: 25.03.10 08:44
Оценка: 4 (1) +1
Здравствуйте, Ellin, Вы писали:

E>При volatile записи кеш процессора сбрасывается (анулируется). Если каждая запись volatile, то кеш практически вообще не используется. В чем тогда смысл lowlock?


Ну что Вы, volatile к кэшу не имеет никакого отношения. Оно запрещает перемещать инструкции, обращающиеся к данной переменной, относительно остальных. Кроме того, оно запрещает компилятору кэшировать значения таких переменных, например в регистрах процессора, и каждое такое обращение будет обращением к ячейке памяти. А вот будет-ли при этом сброшен кэш (точнее, конкретная линейка кэша), зависит вовсе не от volatile, а от состояния этой самой линейки.

Это, кстати, несколько раз за последнее время сдесь обсуждалось
"Нормальные герои всегда идут в обход!"
Re[3]: C# all writes are volatile
От: Sinix  
Дата: 25.03.10 08:46
Оценка:
Здравствуйте, Ellin, Вы писали:

E>При volatile записи кеш процессора сбрасывается (анулируется). Если каждая запись volatile, то кеш практически вообще не используется.


И снова читаем источник, практически те же два абзаца:

The processors may not bother to keep those caches coherent by default, and special instructions may be needed to flush and refresh the caches.

The mainstream x86 and x64 processors implement a strong memory model where memory access is effectively volatile.

Как оно на самом деле — к вендорам.

Даже для итаниумов речь о "сбрось кэш" (точнее, о рефреше) идёт только для volatile read:

Instruction LD.ACQ effectively says, “refresh my cache and then read a value” and ST.REL says, “write a value to my cache and then flush the cache to main memory”


А как оно по-вашему должно быть-то?
Re[4]: C# all writes are volatile
От: Jolly Roger  
Дата: 25.03.10 08:57
Оценка: 10 (1)
Здравствуйте, Sinix, Вы писали:

S>Даже для итаниумов речь о "сбрось кэш" (точнее, о рефреше) идёт только для volatile read:

S>[q]
S>Instruction LD.ACQ effectively says, “refresh my cache and then read a value” and ST.REL says, “write a value to my cache and then flush the cache to main memory”

Это довольно вольная интерпретация документации автором блога Вот здесь более строго изложено.
"Нормальные герои всегда идут в обход!"
Re[3]: C# all writes are volatile
От: Jolly Roger  
Дата: 25.03.10 09:22
Оценка:
Здравствуйте, Ellin, Вы писали:

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

Что он подразумевает под кэшем, когда пишет

you can imagine each thread as having its own cache


не очень понятно. Можно понять как некоторое локальное хранилище, связанное с конкретным потоком, но речь явно идёт не о кэше процессора.
"Нормальные герои всегда идут в обход!"
Re[4]: C# all writes are volatile
От: Ellin Россия www.rsdn.ru
Дата: 25.03.10 09:45
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, Ellin, Вы писали:


JR>Боюсь, несколько вольное использование автором блога терминологии, без уточнения используемых терминов, запутывает ситуацию.


JR>Что он подразумевает под кэшем, когда пишет


JR>

JR>you can imagine each thread as having its own cache


JR>не очень понятно. Можно понять как некоторое локальное хранилище, связанное с конкретным потоком, но речь явно идёт не о кэше процессора.

Тогда у меня возникает вопрос. Допустим есть ПК с двумя процессорами. Может ли один поток выполняться на одно процессоре а чере секунду возобнавить свое выполнение на другом процессоре. Соответсвенно кеш процессора на одном процессоре один, а через секунду это уже кеш второго процессора, где совсем другие значения.
Re[4]: C# all writes are volatile
От: Ellin Россия www.rsdn.ru
Дата: 25.03.10 09:49
Оценка:
Там есть таблица в разделе "Memory model and .NET operations"
Volatile write / Flushes thread cache after?/ Yes.
Вот я и подумал что скидывает кеш. Но это оказывается некий кеш потока...
Re[5]: C# all writes are volatile
От: Jolly Roger  
Дата: 25.03.10 10:05
Оценка: 6 (1) +1
Здравствуйте, Ellin, Вы писали:


E>Допустим есть ПК с двумя процессорами. Может ли один поток выполняться на одно процессоре а чере секунду возобнавить свое выполнение на другом процессоре. Соответсвенно кеш процессора на одном процессоре один, а через секунду это уже кеш второго процессора, где совсем другие значения.


Да, это вполне реальная ситуация, и для её разруливания существует специальный механизм — cache coherency.

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

Когда процессор(1) изменяет данные в одной из линеек кэша, то извещения об этом рассылается остальным процессорам. Если у другого процессора(2) есть линейка с данными, загруженными из того-же адреса, то эта линейка помечается как недействительная. Если теперь этот процессор(2) попытается прочитать данные из этой линейки, то процессор(1) получит требование "сбросить" данную линейку в ОЗУ, а процессор(2) произведёт обновление своей линейки из ОЗУ, и только после этого произведёт операцию чтения из кэша.

Таким образом, как только поток, переключившийся на другой процессор, попытается прочитать какие-то данные, эти данные будут загружены в кэш этого процессора.
"Нормальные герои всегда идут в обход!"
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.