Re[114]: Мнение: объектно-ориентированное программирование —
От: alex_public  
Дата: 15.11.19 07:57
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Если бы мы говорили об императивном языке, то информация о чистоте функциии позволяла бы компилятору делать всякие полезности типа:


S>
S>for(int i=0; i<a.GetLength(); i++)
S>  average += a[i]/a.GetLength();
S>

S>=>
S>
S>var tmp = a.GetLength();
S>for(int i=0; i<tmp; i++)
S>  average += a[i]/tmp;
S>

S>Современный CLR устраняет только первый вызов (и сравнение) для встроенных типов — то есть имеем хардкод. Не существует способа, кроме инлайнинга, который бы помог сделать loop invariant reduction в подобных сценариях.
S>Наличие pure как двустороннего контракта позволяет делать такие трансформации.

Тут на самом деле не всё так просто — надо чтобы компилятор мог гарантированно видеть неизменность переменной "a" внутри цикла. Например в C++ компилятор проводит эту оптимизацию для любых пользовательских типов без всяких модификаторов чистоты. Однако при этом в некоторых специфических случаях она не срабатывает, т.к. компилятор видит потенциальную возможность изменения переменной (хотя на самом деле никаких изменений естественно нет).

Так что лучше сразу писать for(int i=0, е=a.GetLength(); i<е; i++), ну или использовать range for, которые транслируется (во всяком случае в C++) как раз в такую конструкцию.

P.S. Если вдруг кто-то думает, что оптимизация выше — это какая то непринципиальная ерунда с экономией пары процессорных тиков, то это совсем не так. Например если мы всё же используем запись цикла в первом варианте и оптимизация с a.GetLength не пройдёт, то это автоматически заблокирует нам автовекторизацию этого цикла. А это уже может быть реальным провалом в быстродействие в десятки раз.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.