Является ли аннулирование кэша обещанным в этой реализации - PullRequest
0 голосов
/ 13 декабря 2018

Рассмотрим следующий код:

volatile uint32_t word;
for (i=0; i<10; i++)
{
    word = *(uint32_t *)(ADDRESS_IN_MEMORY);
    printf("%"PRIu32, word);
    some_function_compiled_in_other_object();  /* this function may or may not change memory content at adress ADDRESS_IN_MEMORY */
}

Итак, поскольку word является энергозависимым, мы знаем, что word = *(uint32_t *)(ADDRESS_IN_MEMORY) действительно будет выполнено 10 раз.Но есть ли обещание относительно системного кэша здесь?Я ожидаю, что скомпилированный код будет недействительным ADDRESS_IN_MEMORY до \ после каждого чтения с этого адреса, так что word будет загружаться со значением из системной памяти, а не из кэша.Это обещано?

Зависит ли ответ от того, знает ли компилятор об some_function_compiled_in_other_object изменении значения в адресе памяти ADDRESS_IN_MEMORY?

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Стандарт C ничего не знает о кеш-памяти.Они относятся к конкретному приложению и выходят за рамки языка C.

Ключевое слово volatile относится только к оптимизации, выполняемой компилятором.Компилятор должен убедиться, что операции с volatile -квалифицированными переменными упорядочены в определенном порядке и не оптимизированы.

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

Так что если в вашем примере ADDRESS_IN_MEMORY - это число, соответствующее адресу, у вас есть ошибка, поскольку вы читаете его как *(uint32_t *)(ADDRESS_IN_MEMORY);.Эта ошибка не имеет ни малейшего отношения к кеш-памяти.

Обработка кеш-памяти обрабатывается предсказанием ЦП / ветвления, а не компилятором и языком Си.И поэтому вы не можете влиять на него непосредственно из кода приложения, если вы не обращаетесь к регистрам MMU, где вы можете указать поведение.Это, конечно, очень специфично для системы.Настройка звуковой системы не загружает доступ к отображаемому в памяти аппаратному регистру доступа в кэш данных.

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

0 голосов
/ 13 декабря 2018

Итак, поскольку слово является изменчивым, мы знаем, что слово = * (uint32_t *) (ADDRESS_IN_MEMORY) действительно будет выполнено 10 раз.

Нет.

Предположим, что ЦПУ имеет несколько регистров (и позволяет передавать значения только в регистры и из них и не позволяет передавать данные непосредственно из одного места в памяти в другое место в памяти), а скомпилированный код фактически выполняет нечто подобное:

    for (i=0; i<10; i++)
    {
        CPU_register_1 = *(uint32_t *)(ADDRESS_IN_MEMORY);
        word = CPU_register_1

Теперь давайте также предположим, что компилятор оптимизирует код.Он знает, что *(uint32_t *)(ADDRESS_IN_MEMORY); НЕ является летучим, поэтому может преобразовать его в нечто подобное;

    CPU_register_1 = *(uint32_t *)(ADDRESS_IN_MEMORY);
    for (i=0; i<10; i++)
    {
        word = CPU_register_1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...