gcc C/C++ не предполагает псевдонима указателя

Недавно прочитал, что основная причина, по которой fortran быстрее, чем c/c++ в числовых вычислениях, заключается в том, что нет сглаживания указателя.

По-видимому, использование ключевых слов restrict или __restrict__ позволяет в каждом конкретном случае указывать на отсутствие алиасинга указателя для данного элемента памяти.

Компилятор icc, по-видимому, имеет опцию -fno-alias, которая позволяет глобально предположить, что псевдонимы отсутствуют. В gcc есть -fno-strict-aliasing, который применяется только к подмножеству всех ситуаций с псевдонимами.

Есть ли опция в gcc или есть случаи, когда псевдонимы не предполагаются при использовании определенных флагов оптимизации?


person vkubicki    schedule 04.09.2011    source источник
comment
Что касается -fno-strict-aliasing GCC, у вас все наоборот. Параметр заставляет компилятор беспокоиться о том, что могут существовать некоторые псевдонимы. По умолчанию предполагается, что эти псевдонимы не существуют.   -  person Pascal Cuoq    schedule 04.09.2011
comment
Случаи, когда ключевое слово restrict имеет значение, на самом деле довольно редки, и обычно довольно очевидно, где оно имеет значение. Этот документ весьма информативен и подчеркивает тот факт, что порядок загрузки и хранения также имеет значение. Но, как я уже говорил, случаи, когда вы будете использовать такую ​​оптимизацию, довольно очевидны.   -  person Alexandre C.    schedule 04.09.2011
comment
Я не думаю, что GCC имеет что-то похожее на   -  person Royi    schedule 01.05.2020


Ответы (1)


GCC имеет параметр -fstrict-aliasing, который включает глобальную оптимизацию псевдонимов и ожидает, что вы убедитесь, что ничто не будет неправомерно псевдонимом. Думаю, эта оптимизация включена для -O2 и -O3.

Однако C++ имеет четко определенные правила псевдонимов, и код, соответствующий стандарту, не будет конфликтовать со строгим псевдонимом. В частности, это означает, что вам не разрешен доступ к одной переменной через указатель на другой тип:

float f;
int * p = reinterpret_cast<int*>(&f);  // uh-oh
*p = 0x3FF00000;                       // breaks strict aliasing

Важным исключением из этого правила является то, что вы всегда можете получить доступ к любой переменной через указатель на char. (Это необходимо для сериализации через операции ввода-вывода.)

Правила псевдонимов не помогают компилятору узнать, являются ли какие-либо указатели одного и того же типа псевдонимами друг друга. Учти это:

void add(float * a, float * b, float * c) { *c = *a + *b; }

Здесь компилятор не может знать, указывает ли c на другую память, чем a или b, и должен быть осторожен. Я думаю, что именно здесь restrict имеет значение, по сути, обещая, что float * restrict c означает, что никто не использует псевдоним c.

person Kerrek SB    schedule 04.09.2011
comment
Я думаю, что ваш анализ верен: это именно те пятна, для которых был введен restrict. См. также cellperformance.beyond3d.com/articles/2006/ 05/ для получения дополнительной информации, в том числе о том, как написать функцию с использованием указателей restrict, чтобы подсказать компилятору, как планировать загрузку и сохранение. - person Alexandre C.; 04.09.2011
comment
Этот ответ очень поучителен, но не отвечает на вопрос. Мне трудно поверить, что нет эквивалента -fnoalias, кроме ручного добавления ограничения везде в вашем приложении. - person Saiph; 14.11.2019
comment
Я думаю, что ОП говорил о псевдонимах двух разных указателей, указывающих на один и тот же адрес, что препятствует оптимизации. В то время как флаг GCC касается алисинга типов, а не адресов. Если я неправильно прочитал документацию. - person Royi; 01.05.2020