Есть ли акаузальное поведение с циклами зависимости в расслабленной модели памяти C ++?

Предположим, что x и y являются атомарными целыми числами, инициализированными 0.

Теперь поток A выполняет следующий код:

if (x.load(memory_order_relaxed) == 1) {
    y.store(1, memory_order_relaxed);
}

и поток B запускает этот код:

if (y.load(memory_order_relaxed) == 1) {
    x.store(1, memory_order_relaxed);
}

Возможно ли в C ++ достичь ситуации, когда (x == 1 and y == 1)? Если это возможно, то почему?

Я видел это утверждение в https://people.mpi-sws.org/~viktor/slides/2014-07-ec2.pdf (раздел цикла зависимостей).


person 최범석    schedule 23.03.2017    source источник
comment
Вы спрашиваете только потому, что вам любопытно? Или это вопрос домашнего задания / экзамена / собеседования? Или есть какая-то другая проблема, которая заставляет вас задать этот вопрос? Если это какая-то другая проблема, то лучше спросить об этом напрямую.   -  person Some programmer dude    schedule 23.03.2017
comment
Интересно, действительно ли слайды предназначены для сравнения нагрузок с 0. Это может быть более интересный случай. … Ах, нет, они, кажется, приводят аргумент, что расслабленный порядок памяти C11 нарушает причинность (монотонность?), Потому что здесь вообще не задана синхронизация…   -  person Jonas Schäfer    schedule 23.03.2017
comment
@JonasWielicki: Стандарт накладывает ограничения на реализации. Спецификация ослабленного порядка памяти не заставляет реализации нарушать причинно-следственную связь. Реализации, конечно, могут нарушать причинно-следственную связь, если они не ограничены стандартом и реальностью.   -  person MSalters    schedule 23.03.2017
comment
Лучше бы выложить компилируемый пример.   -  person Daniel Daranas    schedule 23.03.2017


Ответы (2)


Хороший вопрос!

Они известны как значения «из воздуха», поскольку для значения 1 не существует источника. В C ++ 11 они были упущены из виду, о чем говорится в статье N3710 и заблокирован в C ++ 14.

Как отмечает N3710,

На самом деле ни одна из известных реализаций не дает таких результатов.

person MSalters    schedule 23.03.2017
comment
@ 최범석: Да, согласно N3710. И C ++ 14 гарантирует, что это также невозможно в будущих реализациях. - person MSalters; 23.03.2017
comment
я думаю, что я почти у цели .. и, кроме того, нет известных реализаций, которые дают результат x == 1 и y == 1 в c ++ 11? - person 최범석; 23.03.2017
comment
@ 최범석: Ну, не совсем. Проблема в том, что C ++ имеет несколько расслабленное представление о причинно-следственных связях. C ++ требует только, чтобы реализации вели себя так, как если бы они подчинялись требованиям стандарта, но по соображениям производительности это может отличаться. На практике инструкции могут быть переупорядочены по скорости и / или выполняться параллельно, если программы на C ++ не могут обнаружить это с помощью чистого C ++. А поскольку стандарт C ++ не полностью определяет причинность, реализации могут воспользоваться этим. Существует много причинно-следственных связей в результате отношений последовательность-до, но не с memory_order_relaxed - person MSalters; 23.03.2017

Часто, задавая эти вопросы, можно не только понять, что такое атомарные переменные, но и представить все возможные сценарии.

Что такое атомарная операция? Это операция, которую нельзя разделить. Это либо сделано, либо не сделано.

Учитывая это, рассмотрите все возможные сценарии.

  • Может ли любой из случаев входить в условие if? Нет. Потому что обе переменные 0, и ничто не превратит их в 1.

Звучит банально, но это все ваши возможности. Более важный вопрос: почему x или y вообще должны стать 1? На основе того, что вы предоставили. Нет никаких причин.


РЕДАКТИРОВАТЬ:

Мой единственный комментарий к той презентации, которую вы связали, заключается в том, что она просто неверна. Чтобы доказать это, я использовал эту программу, и кейсы никогда не входили в условия if. Любой, кто читает это, подтвердите, что я говорю, потому что я могу ошибаться. Я запустил эту программу несколько минут, и ничего не произошло (gcc (Debian 6.2.1-5) 6.2.1 20161124).

#include <iostream>
#include <atomic>
#include <thread>

std::atomic_int x,y;

void call1()
{
    while(true)
    {
        if(x.load(std::memory_order_relaxed) == 1)
        {
            std::cout<<"I'm in!"<<std::endl;
            y.store(1, std::memory_order_relaxed);
        }
    }
}

void call2()
{
    while(true)
    {
        if(y.load(std::memory_order_relaxed) == 1)
        {
            std::cout<<"I'm also in!"<<std::endl;
            x.store(1, std::memory_order_relaxed);
        }
    }
}

int main()
{
    x.store(0);
    y.store(0);

    std::thread t1(call1);
    std::thread t2(call2);

    t1.join();
    t2.join();

    return 0;
}
person The Quantum Physicist    schedule 23.03.2017
comment
Спасибо за ваш совет. отредактировал мой вопрос. раздел цикла зависимостей на добавленной странице ссылок указывает, что это возможно (x == 1, y == 1), и я не знаю, почему. - person 최범석; 23.03.2017
comment
@ 최범석 Как насчет сейчас? - person The Quantum Physicist; 23.03.2017
comment
мой компьютер использует процессор Intel, поэтому я не могу его протестировать, потому что упрощенное упорядочение памяти не работает. - person 최범석; 23.03.2017
comment
@ 최범석 Я тоже использую интеллект, но я действительно думаю, что эта информация совершенно неверна. Запрещение синхронизации означает, что порядок не является детерминированным, но в этом примере нет такого порядка, который позволил бы вам войти в цикл. Обычно в таких простых случаях можно указать путь, ведущий к условиям гонки, но здесь его нет. - person The Quantum Physicist; 23.03.2017
comment
Я думаю, что презентация содержит аргументы на математическом уровне. Возможно, они не ошибаются, но, по крайней мере, они не очень полезны в реальном оборудовании. Потому что реальное оборудование подчиняется причинно-следственной связи, которая должна быть нарушена, чтобы программа действительно вошла в случай x == 1 && y == 1. (Хотя мне интересно, может ли случиться так, что причинно-следственная связь нарушится, если в пьесе будет спекулятивное исполнение.) - person Jonas Schäfer; 23.03.2017
comment
@JonasWielicki Причинность? Как следствие раньше причины? хмммм ... Если мы не используем квантовые компьютеры, где важен принцип неопределенности Гейзенберга, я не понимаю, почему это возможно. - person The Quantum Physicist; 23.03.2017
comment
@TheQuantumPhysicist For x == 1 || y == 1 (что является предварительным условием для x == 1 && y == 1), требуется, чтобы была введена любая из веток if, верно? Однако это само по себе требует, чтобы соответствующая другая переменная была 1. Я не могу понять, как это может произойти, когда наблюдаемая причинность сохраняется, а переменные инициализируются значением 0, но я могу что-то упустить. Если у нас нет видимых побочных эффектов спекулятивного выполнения, когда ядро ​​ЦП решает оценить ветвь if и только после этого проверить условие. В этом случае другое ядро ​​могло видеть 1, и мы получаем x == 1 && y == 1. - person Jonas Schäfer; 23.03.2017
comment
Может быть, причинно-следственная связь - неправильный термин. Мне кажется, что слайды называют это понятие монотонностью. Из быстрого ознакомления с концепцией мне кажется, что этого недостаточно (согласно Википедии). Таненбаум определяет монотонность как то, что любая последующая операция чтения на x этим процессом всегда будет возвращать то же самое значение или более новое значение. ценить. Например, чтобы x стал 1, y должен читаться как 1. Однако y может быть только 1, если x уже есть. Я не понимаю, как это может произойти, если причинно-следственная связь сохраняется (и, конечно, x и y инициализируются равными 0). - person Jonas Schäfer; 23.03.2017
comment
@JonasWielicki Я согласен с вами по большей части. Хотя я никогда раньше не слышал о том, что процессоры сначала оценивают условие if. Еще одна вещь, которую нужно изучить. - person The Quantum Physicist; 23.03.2017
comment
Я знаю, что на этот вопрос сложно ответить правильно, но все же -1, неверно. Вы не можете доказать это экспериментально, это довольно ясно. Что еще более важно, ваш первоначальный анализ основан на (невысказанном) предположении, что существует (неуказанный) порядок, в котором происходят утверждения. Это не относится к расслабленному порядку памяти. - person MSalters; 23.03.2017
comment
@MSalters Что еще более важно, ваш первоначальный анализ основан на (невысказанном) предположении, что существует (неуказанный) порядок, в котором происходят утверждения. Это не относится к расслабленному порядку памяти. Не могли бы вы объяснить, что именно не верно для расслабленного порядка памяти? Я читал много о модели памяти C ++ 11, но не считаю себя экспертом в этой области. Так что объясните, пожалуйста. - person The Quantum Physicist; 23.03.2017
comment
При ослабленном порядке памяти (как правило, без упорядочивания) два потока могут иметь разные представления о том, какие инструкции и в каком порядке выполняются. Ваш анализ сценария Может ли любой из случаев входить в условие if? Нет. Поскольку обе переменные равны 0, и ничто не превратит их в 1. не удается проанализировать возможность того, что хранилище в одном потоке переупорядочено с точки зрения другого потока. - person MSalters; 23.03.2017
comment
@MSalters Но другой поток смотрит на другой поток через память, а не через инструкции, выполняемые в другом процессоре. Почему другой поток увидит, что значение изменилось на 1, если первый поток никогда этого не сделает? - person The Quantum Physicist; 23.03.2017
comment
Это звучит вполне разумно, но Стандарт описывает синхронизацию потоков с точки зрения упорядоченных операций с инструкциями, не с точки зрения общей памяти. - person MSalters; 23.03.2017
comment
@MSalters Мне сложно это понять. Мне нужно кое-что почитать. - person The Quantum Physicist; 23.03.2017
comment
@ 최범석 Это то, что я здесь узнал. Я думаю, ты прав, иначе я все понял неправильно. - person The Quantum Physicist; 23.03.2017