реклама на сайте
подробности

 
 
> Барьер компилятора asm volatile ("" ::: «memory»)
koluna
сообщение Aug 27 2014, 20:07
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Всем привет!

Цитата
Конструкция не содержит никаких инструкций и является барьером, говорящим компилятору: “сбрось все регистры в RAM до барьера и перечитай после”.


Расскажите, пожалуйста, поконкретнее, что же делает на самом деле этот барьер помимо действий, описываемых фразой, приведенной выше.

Цитата
Барьеры обеспечивают надлежащий порядок доступа к volatile переменным и не обеспечивают надлежащий порядок доступа к не volatile переменным (может происходить перебрасывание через барьер).


Почему? Что это значит?

Код
volatile x, y, z;
x = 1;
y = 2;
z = 3;

Может ли компилятор поменять порядок обращения к volatile переменным x, y, z?
Т. е., влияет ли как-нибудь volatile на порядок обращения к переменным или нет?
Насколько далеко может зайти компилятор, переставляя инструкции?

Есть ли какая-либо взаимосвязь между барьером компилятора и точками следования?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 11)
koluna
сообщение Aug 30 2014, 07:47
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Ребят, кто-нибудь поделится знаниями? sm.gif


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 30 2014, 08:24
Сообщение #3


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Откуда у вас такие цитаты?
Насколько я знаю, обращение к volatile переменным компилятор менять не имеет права.
А барьер этот используется для обеспечения порядка доступа к не-volatile переменным.
Приведу пример.
Код
void test(){
    enable_interrupts = 0;
    some_stuff();
    enable_interrupts = 1;
}

enable_interrupts = volatile-регистр, отвечающий за разрешение прерываний.
Без барьра компилятор делал так:
Код
void test(){
    enable_interrupts = 0;
    enable_interrupts = 1;
    some_stuff();
}

То есть, some_stuff() выполнялась при включенных прерываниях, что противоречит задумке.
Введение барьера:
Код
void test(){
    enable_interrupts = 0;
    some_stuff();
    __asm__ __volatile__ ( :::"memory");
    enable_interrupts = 1;
}

Решило проблему.
Наверное такой барьер можно считать принудительной точкой следования, но я не берусь давать чётких определений на этот счёт.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Aug 30 2014, 11:34
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Aug 30 2014, 12:24) *
Откуда у вас такие цитаты?


С форума.

Цитата
Насколько я знаю, обращение к volatile переменным компилятор менять не имеет права.


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

http://blog.regehr.org/archives/28
Цитата
and also accesses to volatiles should not be reordered (with some exceptions).


http://www.nongnu.org/avr-libc/user-manual/optimization.html
Цитата
memory barriers don't ensure statements with no volatile accesses to be reordered across the barrier




--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 30 2014, 11:57
Сообщение #5


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(koluna @ Aug 30 2014, 17:34) *
Я тоже так думал, но, судя по всему бывают исключения...

Нет, менять местами обращение к volatile-переменным компилятор не имеет. Собственно, про это и написано в ссылке.
То, что сделал avr-gcc в примере с cli()/sei() - может быть просто багом avr-gcc.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Aug 30 2014, 12:59
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Aug 30 2014, 15:57) *
Нет, менять местами обращение к volatile-переменным компилятор не имеет. Собственно, про это и написано в ссылке.
То, что сделал avr-gcc в примере с cli()/sei() - может быть просто багом avr-gcc.


Там еще про некоторые исключения написано sm.gif

А между цитатами из первой и второй статьи вижу противоречие:

Цитата
Moreover, code motion is not permitted around the barrier in either direction


Цитата
memory barriers don't ensure statements with no volatile accesses to be reordered across the barrier


Интересно, какой оверхед дает использование барьера?

Сообщение отредактировал koluna - Aug 30 2014, 13:02


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 30 2014, 14:02
Сообщение #7


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(koluna @ Aug 30 2014, 18:59) *
Там еще про некоторые исключения написано sm.gif

Про исключения из правила не менять порядок доступа к volatile-переменным? Не увидел. Где?
Цитата(koluna @ Aug 30 2014, 18:59) *
А между цитатами из первой и второй статьи вижу противоречие:

Я согласен с первой цитатой. Хотя пример из avr-gcc не согласуется с нейsm.gif
Цитата(koluna @ Aug 30 2014, 18:59) *
Интересно, какой оверхед дает использование барьера?

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


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
CrimsonPig
сообщение Aug 30 2014, 22:30
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502



Цитата(koluna @ Aug 27 2014, 21:07) *
Расскажите, пожалуйста, поконкретнее, что же делает на самом деле этот барьер помимо действий, описываемых фразой, приведенной выше.


Тут все просто sm.gif Надо немножко погуглить на предмет "memory barrier", "out of order execution", "cache coherency" На хабре был цикл очень хороших статей по этому поводу..
Где-то в этом районе:
http://habrahabr.ru/company/ifree/blog/196548/

Цитата
Код
volatile x, y, z;
x = 1;
y = 2;
z = 3;

Может ли компилятор поменять порядок обращения к volatile переменным x, y, z?
Т. е., влияет ли как-нибудь volatile на порядок обращения к переменным или нет?


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

Go to the top of the page
 
+Quote Post
yes
сообщение Sep 1 2014, 12:10
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 198
Регистрация: 23-12-04
Пользователь №: 1 640



если отвлечься от армовской (?) архитектуры, то это _compiler_barrier, а бывают еще _machine_barrier (в спарке v8 он например вставляет flush), то есть можно почитать для SPARC-а про формализацию моделей памяти TSO, PSO и т.д.
у современных х86 тоже должно быть интересно, но я не в теме
Go to the top of the page
 
+Quote Post
koluna
сообщение Sep 1 2014, 17:50
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(CrimsonPig @ Aug 31 2014, 02:30) *
Самое забавное, не в том, что компилятор может нагенерить, а то, процессор может выполнять инструкции не в том порядке, в котором они лежат в памяти..


Это я знаю, но в данный момент меня интересуют более простые ситуации sm.gif

В данный момент обсуждаем именно барьер компилятора.


Сообщение отредактировал koluna - Sep 1 2014, 17:52


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
koluna
сообщение Sep 1 2014, 20:09
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(CrimsonPig @ Aug 31 2014, 02:30) *


Спасибо за ссылки.
Вот в этой статье вижу противоречие с этой статьей (в ней есть ссылка на официальную документацию GCC):

Цитата
Надо отметить, что ассемблерные вставки __asm__ __volatile__ ( … ) также являются в некотором роде барьером для GCC/Clang: компилятор не имеет права ни выкидывать, ни перемещать их вверх/вниз по коду (об этом говорит модификатор __volatile__).


Цитата
Note that even a volatile asm instruction can be moved relative to other code, including across jump instructions. [...] Similarly, you can't expect a sequence of volatile asm instructions to remain perfectly consecutive.


Видимо, в этой ситуации лучше доверять официальной документации GCC, т. е., asm volatile вставки компилятор не может выбрасывать, но может "перетаскивать" и немного оптимизировать согласно стратегии своей работы.


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Sep 2 2014, 04:21
Сообщение #12


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(koluna @ Sep 2 2014, 02:09) *
Видимо, в этой ситуации лучше доверять официальной документации GCC, т. е., asm volatile вставки компилятор не может выбрасывать, но может "перетаскивать" и немного оптимизировать согласно стратегии своей работы.

Там дальше (в официальной документации) есть разъяснение, как этого избежать. (Добавить искусственную зависимость от переменной, относительно операции с которой мы не хотим, чтобы компилятор двигал asm volatile вставку.
А поскольку зависимость "memory" - самая сильная (она означает зависимость от всех переменных), то, вероятно, барьер типа asm volatile (::: "memory") компилятор передвинуть никак не может.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th July 2025 - 14:56
Рейтинг@Mail.ru


Страница сгенерированна за 0.01487 секунд с 7
ELECTRONIX ©2004-2016