Сообщение Re[5]: Memory barrier не могу понять что это от 08.04.2023 14:45
Изменено 08.04.2023 18:38 Pzz
Re[5]: Memory barrier не могу понять что это
Здравствуйте, okman, Вы писали:
O>sfence/lfence/mfence — это малость для другого. В машинный код для x86/x64 практически всегда вставляется инструкция типа xchg, xadd или что-то подобное.
Это разные вещи.
Представь, два потока на разных ядрах CPU у тебя одновременно инкрементируют одну переменную. Пусть даже с помощью одной инструкции процессора, а не трех (прочитать, проинкрементировать, сохранить).
Величина, на которую увеличится переменная, будет меньше, чем суммарное количество операций по ее увеличению, сделанных обеими потоками. Вот смотри, что делает инструкция INC, если ее аргумент — адрес в памяти, с учетом кеширования:
1. Загрузить значение в ALU. Значение само по себе, скорее всего, в кеше
2. Прибавить 1
3. Сохранить значение в кеш.
Поскольку потоков два, а переменная одна, на 3-м шаге возникает синхронизация кешей. На 3-м, заметь, а не на 1-м. Поэтому запросто может быть, что на первом шаге оба потока прочтут в ALU одно и то же значение (кеш в этот момент синхронен и процессору не о чем беспокоиться), прибавят к нему 1 и сохранят на место. Т.е., в итоге, переменная увеличится на 1, хотя оба потока ее увеличивали.
Чтобы этого избежать, существует префикс LOCK. Он делает всю цепочку 1-2-3 атомарной в том смысле, что с того момента, пока один поток сделал шаг и и до того, как он сделал 3, второму потоку просто не дадут туда войти.
У некоторых команд, типа XCHG, префикс LOCK встроенный, некоторым другим приходится приделывать его явно.
Это совсем не то же самое, что reordering инструкций, от которого "защищают" барьеры памяти.
O>sfence/lfence/mfence — это малость для другого. В машинный код для x86/x64 практически всегда вставляется инструкция типа xchg, xadd или что-то подобное.
Это разные вещи.
Представь, два потока на разных ядрах CPU у тебя одновременно инкрементируют одну переменную. Пусть даже с помощью одной инструкции процессора, а не трех (прочитать, проинкрементировать, сохранить).
Величина, на которую увеличится переменная, будет меньше, чем суммарное количество операций по ее увеличению, сделанных обеими потоками. Вот смотри, что делает инструкция INC, если ее аргумент — адрес в памяти, с учетом кеширования:
1. Загрузить значение в ALU. Значение само по себе, скорее всего, в кеше
2. Прибавить 1
3. Сохранить значение в кеш.
Поскольку потоков два, а переменная одна, на 3-м шаге возникает синхронизация кешей. На 3-м, заметь, а не на 1-м. Поэтому запросто может быть, что на первом шаге оба потока прочтут в ALU одно и то же значение (кеш в этот момент синхронен и процессору не о чем беспокоиться), прибавят к нему 1 и сохранят на место. Т.е., в итоге, переменная увеличится на 1, хотя оба потока ее увеличивали.
Чтобы этого избежать, существует префикс LOCK. Он делает всю цепочку 1-2-3 атомарной в том смысле, что с того момента, пока один поток сделал шаг и и до того, как он сделал 3, второму потоку просто не дадут туда войти.
У некоторых команд, типа XCHG, префикс LOCK встроенный, некоторым другим приходится приделывать его явно.
Это совсем не то же самое, что reordering инструкций, от которого "защищают" барьеры памяти.
Re[5]: Memory barrier не могу понять что это
Здравствуйте, okman, Вы писали:
O>sfence/lfence/mfence — это малость для другого. В машинный код для x86/x64 практически всегда вставляется инструкция типа xchg, xadd или что-то подобное.
Это разные вещи.
Представь, два потока на разных ядрах CPU у тебя одновременно инкрементируют одну переменную. Пусть даже с помощью одной инструкции процессора, а не трех (прочитать, проинкрементировать, сохранить).
Величина, на которую увеличится переменная, будет меньше, чем суммарное количество операций по ее увеличению, сделанных обеими потоками. Вот смотри, что делает инструкция INC, если ее аргумент — адрес в памяти, с учетом кеширования:
1. Загрузить значение в ALU. Значение само по себе, скорее всего, в кеше
2. Прибавить 1
3. Сохранить значение в кеш.
Поскольку потоков два, а переменная одна, на 3-м шаге возникает синхронизация кешей. На 3-м, заметь, а не на 1-м. Поэтому запросто может быть, что на первом шаге оба потока прочтут в ALU одно и то же значение (кеш в этот момент синхронен и процессору не о чем беспокоиться), прибавят к нему 1 и сохранят на место. Т.е., в итоге, переменная увеличится на 1, хотя оба потока ее увеличивали.
Чтобы этого избежать, существует префикс LOCK. Он делает всю цепочку 1-2-3 атомарной в том смысле, что с того момента, пока один поток сделал шаг 1 и до того, как он сделал 3, второму потоку просто не дадут туда войти.
У некоторых команд, типа XCHG, префикс LOCK встроенный, некоторым другим приходится приделывать его явно.
Это совсем не то же самое, что reordering инструкций, от которого "защищают" барьеры памяти.
O>sfence/lfence/mfence — это малость для другого. В машинный код для x86/x64 практически всегда вставляется инструкция типа xchg, xadd или что-то подобное.
Это разные вещи.
Представь, два потока на разных ядрах CPU у тебя одновременно инкрементируют одну переменную. Пусть даже с помощью одной инструкции процессора, а не трех (прочитать, проинкрементировать, сохранить).
Величина, на которую увеличится переменная, будет меньше, чем суммарное количество операций по ее увеличению, сделанных обеими потоками. Вот смотри, что делает инструкция INC, если ее аргумент — адрес в памяти, с учетом кеширования:
1. Загрузить значение в ALU. Значение само по себе, скорее всего, в кеше
2. Прибавить 1
3. Сохранить значение в кеш.
Поскольку потоков два, а переменная одна, на 3-м шаге возникает синхронизация кешей. На 3-м, заметь, а не на 1-м. Поэтому запросто может быть, что на первом шаге оба потока прочтут в ALU одно и то же значение (кеш в этот момент синхронен и процессору не о чем беспокоиться), прибавят к нему 1 и сохранят на место. Т.е., в итоге, переменная увеличится на 1, хотя оба потока ее увеличивали.
Чтобы этого избежать, существует префикс LOCK. Он делает всю цепочку 1-2-3 атомарной в том смысле, что с того момента, пока один поток сделал шаг 1 и до того, как он сделал 3, второму потоку просто не дадут туда войти.
У некоторых команд, типа XCHG, префикс LOCK встроенный, некоторым другим приходится приделывать его явно.
Это совсем не то же самое, что reordering инструкций, от которого "защищают" барьеры памяти.