1

Недавно я узнал, что во время выполнения можно сгенерировать код C#, и я хотел бы использовать эту функцию. У меня есть код, который выполняет некоторые очень простые геометрические вычисления, такие как вычисления пересечений линейных плоскостей, и я думаю, что я мог бы получить некоторые преимущества в производительности за счет создания специализированного кода для некоторых методов, потому что многие вычисления выполняются для одной и той же плоскости или одной и той же линии и снова. Специализируясь на коде, который вычисляет пересечения, я думаю, что я мог бы получить некоторые преимущества в производительности.Деревья выражений против IL.Emit для специализации во время выполнения

Проблема в том, что я не уверен, с чего начать. От чтения нескольких сообщений в блогах и просмотра документации MSDN я столкнулся с двумя возможными стратегиями для генерации кода во время выполнения: деревья выражений и IL.Emit. Использование деревьев выражений кажется намного проще, потому что нет необходимости изучать что-либо о OpCodes и других связанных с MSIL сложностях, но я не уверен, что деревья выражений так же быстро, как созданные вручную MSIL. Так есть ли какие-либо предложения по тому методу, с которым мне следует идти?

ответ

4

Выполнение обоих параметров, как правило, одинаково, поскольку деревья выражений внутренне пересекаются и испускаются как IL, используя те же основные системные функции, которые вы использовали бы сами. Теоретически возможно испускать более эффективный ИЛ с использованием низкоуровневых функций, но я сомневаюсь, что будет практически любой существенный прирост производительности. Это будет зависеть от задачи, но я не прибег к какой-либо практической оптимизации испускаемого ИЛ, по сравнению с той, которая испускается деревьями выражений.

Я настоятельно рекомендую получить инструмент под названием ILSpy, который объединяет сборки CLR с обратной компоновкой. С этим вы можете смотреть на код, фактически проходящий через деревья выражений и на самом деле испускающий ИЛ.

И, наконец, оговорка. Я использовал деревья выражений в парсере языка, где вызовы функций привязаны к правилам грамматики, которые компилируются из файла во время выполнения. Скомпилированный ключ здесь. Для многих проблем я сталкивался, когда то, что вы хотите достичь, известно во время компиляции, тогда вы не получите большую производительность при генерации кода времени исполнения. Некоторые оптимизации CLR JIT также могут быть недоступны для динамического кода. Это только мнение моей практики, и ваш домен будет отличаться, но если производительность критическая, я предпочел бы посмотреть на собственный код, сильно оптимизированные библиотеки. Некоторая работа, которую я сделал, будет медленной, если не использовать LAPACK/MKL. Но это всего лишь часть совета, которого не просили, поэтому возьмите его с солью.

+2

Я бы добавил, что написание собственного ИЛ чревато возможностью пропустить оптимизации, которые может найти компилятор C#. Вы можете захотеть исправить фактический C# и использовать компилятор C# для генерации результирующих ассемблеров: http://msdn.microsoft.com/en-us/library/microsoft.csharp.csharpcodeprovider.aspx –

+0

@ChrisShain, к сожалению, компилятор C# не делает ни одной из интересных возможных оптимизаций. По какой-то причине даже C++/CLI делает гораздо больше. Вот почему я предпочитаю генерировать код самостоятельно, минуя ограниченные возможности оптимизации C#. Есть вещи, которые очень легко реализовать, но отсутствуют в C# - правильное постоянное распространение, специализация с постоянными аргументами (с инкрустацией), анализ региона и устранение выделения, разворот циклов, слияние переменных, циклический подъем подъемников и т. Д. –

+2

Причина, по которой C# компилятор не делает эти оптимизации, заключается в том, что эта ответственность лежит в компиляторе JIT. Примером здесь является то, что путем перемещения оптимизаций, таких как циклическое разворачивание в JIT-компилятор, они применяются ко всем .NET-языкам. Конечно, JIT-компилятор делает цикл разворачивания, inlining и многое другое. –

2

Если бы я был в вашей ситуации, я бы попробовал альтернативы от высокого уровня до низкого уровня, увеличив «необходимое время & усилий» и уменьшив порядок повторного использования, и я бы остановился, как только производительность была достаточно хорошей для времени бытия, а именно:

  • первый, я бы проверить, если Math.NET, LAPACK или другие подобные числовые библиотеки уже имеет аналогичные функциональные возможности, или я могу адаптировать/продлить код для моих потребностей;

  • второй, я бы попробовал деревья выражений;

  • В-третьих, я бы проверил Roslyn Project (даже если он находится в предварительной версии);

  • Четвертый, я бы подумал о написании общих процедур с небезопасным кодом С;

  • [пятый, я думаю об уходе и начать новую карьеру в другой профессии :)],

  • и только если ни один из них не работает, я бы так безнадежно пытаться излучающие IL во время выполнения.

Но, возможно, я склонен к подходам низкого уровня; ваш опыт, опыт и точка зрения могут быть разными.

+1

Испускание il - главная боль в ###, но вы много узнаете о том, как внутренние работы clr !!! – Peter

Смежные вопросы