@daniil14056

Почему CLR при генерации Машиного кода не оптимизирует циклы?

Почему CLR .NET не выполняет короче много того что должны оптимизирующие компиляторы выполнять. Оптимизацию циклов, прочие преобразования
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
   static int  Sum1(int[] arr,int n)
   {
       int s = 0;
       for (int i = 0; i < arr.Length; i++)
       {
           if(i<n)         // или вообще вот так if(i==n) что по идеи цикл должно убирать
               s += arr[i];
       }
       return s;
   }
// или такой еще метод
 static int  Sum1(int[] arr,int n)
   {
       int s = 0;
       for (int i = 0; i < arr.Length; i++)
       {
           if(i<n)  
               s += arr[i];
           else(i>n)
              s-=arr[i];
       }
 // почему такой цикл на 2 цикла не преобразуется.
 for (int i = 0; i < n; i++)     s += arr[i];
 for (int i = n; i < len; i++)  s-=arr[i];
       return s;
   }
// или вот
 for(int i=0;i<len;i++)
       if(i%2==0) f1();  
       else         f2();
 // еще заметил для функции выше, которая точно такая как пример выше помимо этого
// не убирает else 
 for(int i=0;i<len;i++)
       if(i%2==0) {
          f1();
           continue;
        }  
       f2();

Почему такой код не оптимизируется в рамках оптимизации циклов?
Я еще заметил циклы не разматываются.
Я думал, что такой код невозможно написать, но примерно такое часто встречается, если смотреть в глубь калбеков. Когда допустим внешняя функция по параметру вызывает функцию, а внутренняя еще раз этот параметр проверяет, к примеру проверки на NullPointer.
И допустим такая функция из 2 мест вызывается, и в 1-ом месте, уже это параметр проверен.
И такое прям часто, и решения как правило добавить параметр, или отдельную функцию написать. Но с бибилотечными функциями так не получится, хотя убрать из них лишние проверки, кажется не сложная задача при компиляции.
Но если так подумать, то вроде как сам компилятор может же сам создать копию функции, с другим кодом, убрав лишние проверки.
  • Вопрос задан
  • 129 просмотров
Решения вопроса 1
AshBlade
@AshBlade Куратор тега C#
Просто хочу быть счастливым
На чем основывалась проверка? Какой инструмент?

Во-первых, У .NET есть двухуровневая система генерации кода. Это Tiered JIT.

0 уровень ничего не оптимизирует. Это для оптимизации старта.
1 уровень уже запускает оптимизации и генерирует оптимальный код. Чтобы запустить его запусить, надо очень много прогнать код.

P.S. именно поэтому BenchmarkDotNet делает очень много WarmUp, Preworkload и других стадий перед запуском реальных бенчмарков.

Во-вторых, в какой конфигурации запускали: Debug или Release?

Если Debug, то ничего удивительного нет - должны сохраниться изначальные строки, чтобы можно было пройтись дебагером. В Release получается каша, из которой ничего не понятно.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1

еще заметил циклы не разматываются

С чего взял? Вроде в core 3.1 добавили разматывание циклов.
Но циклы разматываются очень редко, тк можно стек порвать

Рекомендую посмотреть доклад от Егора Богатова: https://m.youtube.com/watch?v=H1ksFnLjLoY и статьи от него. Сейчас он работает в ms и как раз занимается jit-ом.

Ещё можно задать какие-нибудь вопросы напрямую в чате https://t.me/pro_net
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы