2015-04-26 8 views
1

Я наблюдал Mike Acton's talk on Data-oriented design in C++ в CppCon 2014, и он дает этот пример:Могу ли я «__restrict__ это» каким-то образом?

int Foo::Bar(int count) 
{ 
    int value = 0; 
    for (int i = 0; i < count; i++) { 
     if (m_someDataMemberOfFoo) value++ 
    } 
    return value; 
} 

И объясняет, как некоторые компиляторы держать перечитывая m_someDataMemberOfFoo в каждой итерации, возможно, потому, что его значение может измениться из-за одновременный доступ. Независимо от того, подходит ли компилятору это сделать - можно ли сказать компилятору специально игнорировать любую возможность одновременного доступа ко всему во время выполнения какого-либо метода, чтобы он мог оптимизировать лучше?

Другими словами, могу ли я сообщить ему компилятор, что this is __restrict__ ed?

+4

Любой компилятор, достойный имени, рассмотрит возможность поднятия проверки цикла или, по крайней мере, сохранение 'm_someDataMemberOfFoo' в регистре. Любая программа, которая пытается изменить «m_someDataMemberOfFoo» одновременно с этим кодом, обнаруживает неопределенное поведение. –

+0

@IgorTandetnik: Не обязательно. Это делает необоснованное семантическое предположение. Может быть, 'm_someDataMemberOfFoo' должен изменяться путем одновременной модификации? – einpoklum

+0

Я считаю, что предположение оправдано в контексте. Если 'm_someDataMemberOfFoo' потокобезопасно (скажем,' atomic'), и ожидается, что он будет одновременно изменен, то весь вопрос спорный. Не было бы так, чтобы компиляторы «* some * продолжали перечитывать« m_someDataMemberOfFoo »на каждой итерации» - все компиляторы будут делать это, и для них было бы совершенно разумно и разумно - действительно, потребовалось бы - для этого. –

ответ

4
  1. __restrict__ не стандартизированы в C++, так что этот вопрос может быть решен только на конкретной платформе. Для GCC, вы можете обратиться к __restrict__thisin the same way в const:

    void T::fn() __restrict__ 
    
  2. Там нет потенциала наложения спектров в вашем примере. C++ указывает неопределенное поведение для расчётов данных.

  3. A new system для C++ ограниченных указателей. Вероятно, он будет стандартизован на C++ 17. Поддержка this является одной из заявленных целей дизайна.

+0

Алиасинг - это не то, о чем я беспокоюсь, это одновременный доступ. Предположим, что мой цикл был while (! M_YouRangSir) {mySleep (Miliseconds (1000)); } '... – einpoklum

+0

Кроме того, - предложение кажется очень многословным и неудобным для использования, я хочу, чтобы они делали что-то простое, как '__restrict__', с дополнительными формулировками для двусмысленностей. – einpoklum

+0

@einpoklum В этом контексте aliasing включает одновременный доступ. Если в цикле был критический раздел, ему пришлось бы перечитать член. Если вы хотите использовать ключевое слово 'restrict', вы можете сделать' #define ограничивать [[alias_set()]] '. Атрибуты могут быть помещены в начале объявления или непосредственно перед идентификатором declarator. Я не уверен, как это предложение может применяться к этому, теперь, когда я смотрю на него; примеры только показывают *, позволяющие * сглаживание с помощью 'this'. – Potatoswatter

2

С кодом, который вы опубликовали, код, скомпилированный с любой оптимизацией, вообще не должен перечитывать этот член класса. Тем не менее, возьмите этот подобный код:

void Foo::Bar(int count, int* result) 
{ 
    *result = 0; 
    for (int i = 0; i < count; i++) { 
     if (m_someDataMemberOfFoo) (*result)++; 
    } 
} 

В этом случае компилятор должен предположить, что результат == & m_someDataMemberOfFoo является возможностью, если этот член имеет тип Int. Очевидно, любой разработчик, назвавший его так, заслуживает того, чтобы его лицензия на лицензию отозвалась, но это законно, и компилятор должен правильно это обработать.

Это даже в случае, если вы отметили метод как «const». Метод const не допускается изменять какую-либо часть * этого с помощью этого указателя (за некоторыми исключениями). Тем не менее, члены * этого могут быть юридически изменены другими способами, если фактический объект не является константой.

«Ограничить» в C предназначен для устранения проблемы, и, надеюсь, такая же функция на C++ исправит ее в этом случае.

+0

Не мог компилятор, по крайней мере теоретически, по-прежнему оптимизировать код примера, который вы представили, потому что, даже если он принимает результат == & m_someDataMemberOfFoo, это значение устанавливается равным 0, и приращение никогда не достигается. Если приращение достигнуто, результат не может быть псевдонимом m_someDataMemberOfFoo. (Это никоим образом не отменяет точку, которую вы делаете, просто спрашивая) –

+0

В разговоре, с которым я связан, MSVC компилирует код с m_someDataMemberOfFoo в условие цикла, чтобы повторно прочитать элемент повторно ... – einpoklum