Pull to refresh

Comments 48

ХабраРедактор не забыл про кат, а вы забыли
А где тесты сравнения скорости вычисления вашего «заклятого» кода и обычного, через операторы +-*/ ???
Ммм. Не ставил задачи протестировать разницу в скорости. Но сразу могу сказать, что «заклятый» код выполняет непосредственно сопроцессор в связке с процессором. Код на C# претерпит jit-компиляцию, которая скорее всего приведет к такой же конструкции.
Однако цель статьи не демонстрация преимущества скорости конкретного примера, а скорее демонстрация того, как можно использовать дополнительные возможности процессора, чего не может компилятор C#. Например, Вы можете писать на инструкциях SSE 2,3,4 и более, 3DNow (технология AMD) и прочих. В принципе, можно воспользоваться утилитой .NET ngen.exe, чтобы сгенерировать образы нативных кодов для Ваших .NET сборок, но не всегда это получается.
Кроме этого, в этой статье только пример того, как это делается, я упоминал, что при наличии интереса можно развить это направление и динамически генерировать себе любой код. При это не надо никаких MSIL инъекций и прочего, пишите на нативном коде и используйте его в своих программах на C#
Например, Вы можете писать на инструкциях SSE 2,3,4 и более, 3DNow (технология AMD) и прочих.

Насчёт SSE лучше смотрите в сторону Mono.Simd.
Надеюсь и в родном Microsoft .Net такое со временем появится.
В принципе, можно воспользоваться утилитой .NET ngen.exe, чтобы сгенерировать образы нативных кодов для Ваших .NET сборок, но не всегда это получается.

В большинстве случаев это и не нужно.
Если действительно есть «узкое место» в производительности, намного логичнее реализовать его в native dll.
… можно развить это направление и динамически генерировать себе любой код. При это не надо никаких MSIL инъекций и прочего, пишите на нативном коде и используйте его в своих программах на C#

Протестируйте производительность своего варианта.
После этого Вы и сами поймёте почему практическая ценность Вашего решения близится к 0.
с появлением лямбда выражений, и если нужны операции обработки большой коллекции, перед первым вызовом можно генерировать подобный код на основе лямбда дерева, а дальше только вызывать его для обработки элемента коллекции. будет больше чем занятно) и что-то мне кажется, что кто-то уже должен был подобное реализовать…
Кодогенерация на нативном коде. Быстро работает, есть ощущение, что процессор делает то, что Вы ему сказали =)
Мне очень пригодилось для мат.расчетов в программе, которую я написал. Вводите формулу, программа ее парсит и генерирует нативный код. Первая версия генерировала с помощью Reflection API, но потом отказался ради увеличения скорости.
«есть ощущение, что процессор делает то, что Вы ему сказали» это чесание ЧСВ, а не практическая ценнность.

Практическая ценность это что-то вроде. Написание кода заняло 20 часов, расчёты без данной оптимизации выполнялись 1000 часов, ускорение 23%, съэкономлено 1000 * 0.23 — 20 = 210 часов.
Ну как же? Вот решили Вас, предположим, уволить, и Вам требуется оставить после себя код, обладающий минимальной совместимостью и максимальной сложностью сопровождения. Что будете делать? =)
UFO just landed and posted this here
А) JIT-компилятор возможно знает SSE и прочие (сомневаюсь правда). Статья для тех, кто хочет делать это своими руками.
Б) С++ затем, что в нем есть указатели на функции, что позволяет передать управление в начало массива. Да, можно подключить функцию, но ведь и можно на С++ написать обертку (я упоминал об этом) и генерировать любой код в любое удобное для Вас время. Причем код нативный с удобными для Вас инструкциями процессора.
С) Когда я этим начал заниматься, Mono был на стадии зачатия, даже MonoDevelop еще не существовала.
UFO just landed and posted this here
jit-компилятор отлично знает про SSE и прочие
UFO just landed and posted this here
Ну как бы в статье написано как не компилить на Си, а заливать код в память (причем с учетом «архитектуры») и выполнять оттуда. Это несколько другое.
А чтобы jit-у лучше жилось на текущей машине, то можно воспользоваться ngen.exe, которая создаст для Вашей сборки образ нативного кода, который будет учитывать разные особенности машины, и .NET будет этот оптимизированный образ использовать при выполнении кода из Вашей сборки.
UFO just landed and posted this here
Согласен. А у Вас есть вариант как динамически сгенерировать нативный код и тут же его подключить к основному языку разработки (в моем случае C#)?
UFO just landed and posted this here
C# не предназначен для работы с нативным кодом. Если вам нужен MSIL (который замечательно компилируется JIT-ом в MMX, SSE, 3DNow! и прочие расширения в зависимости от текущего процессора), то это Reflection.Emit.

Если бы вы написали разборщик выражений, который бы через Reflection.Emit генерировал MSIL — пользы было бы больше.
рискну утверждать, что интегрированный FPU в CPU был в процессорах Intel уже в Pentium (если не раньше).
У 386DX встроенного сопра не было. От SX он отличался шириной шины данных.
Да, утверждение, что он появился в PIII, меня тоже неслабо развеселило…
вообще, если все это нужно для реализации математических вычислений, то еще лет 7 назад Intel и AMD уже распространяли собственные библиотеки с реализацией всех основных функций, максимально использующие возможности процессоров

есть также открытые коды реализации функций из матлаба, но в них было много ошибок, и нужно пошагово проверять реализацию алгоритмов, хотя может быть с годами часть пофиксили

но в целом, если алгоритм нормально написан, то его можно реализовать просто на C#, с небольшими вставками MSIL-ассемблера, и скорость работы будет приемлемая
опять же, для SSE можно вызывать библиотеки от производителя процессора
В плюсах встроенный ассемблер (__asm) не жует MMX?
UFO just landed and posted this here
А как насчет раздельной компиляции с последующей линковкой?

Воспользоваться нормальным ассемблером, сделать объектный файл и слинковать его с плюсовым кодом в виде DLL. А дальше DLLImport.
на то он и Assembler. Он всё жуёт.
Генерацией на MSIL я баловался раньше. Это вообще говоря намного проще.
Но как ни крути, jit не всегда улавливает мысли разработчика. Я честно не знаю, не видел ядра jit-компилятора. Но вот вопрос: если мы работаем с огромным массивом данных (double) (миллиарды элементов), то мы можем обрабатывать сразу по 2-4 элемента в такт с помощью SSE2 — 4; вот и скажите, jit-компилятор соптимизирует это в реально возможный код на машинных кодах (кстати, не все компиляторы С++ это могу, если не все. Приходится это делать в отдельном проекте на ассемблере и объектный файл прикручивать к проекту С++)?
Нет, если это дает реальный прирост производительности — всегда пожалуйста.

Но для этого надо померять ее, производительность то.
Меня терзают смутные сомнения, что JIT-компилер отлично знает об особенностях текущей платформы, на которой выполняется код, и сразу генерирует оптимизированный под нее код. Это какбэ одна из задач JIT-компилятора.
Это хорошо для обучения программированию FPU. Практической ценности здесь нет.
Оптимизация, о которой вы говорите — это МИКРО-оптимизация, которая влияет разве что при брутальном переборе в 8 потоков чего нибудь супер-математического.
На хабре неуместны статьи, помогающие тем, у кого редкие цели и математические задачи?
Т.е. не так я хотел сказать, пардон.
«Не имеют практической ценности статьи, помогающие достичь непопулярных целей, с математической основой?»
И как это понять, «хорошо для обучения программированию FPU», но «практической ценности нет», а зачем тогда обучение?
Задачи всякие бывают, и часто упирающиеся в вычисления, а не то, что попсовей, типа растолкать куда-то записи по таблицам в БД. При этом программист может предпочитать свой любимый C#, и, я думаю, наверняка сейчас многие с интересом прочтут эту статью, и возможно «давно ее ждали».
Хотелось бы чтобы каждый из Вас, прочитав статью, извлек из нее что-то полезное для себя.
Надеюсь, кому-нибудь это поможет в решении той или иной задачи (не важно какого проекта).
Спасибо lostmsu за наводку на Marshal.GetDelegateForFunctionPointer().

Таким образом, мы можем исключить С++ и переписать все на C#.

Вот здесь есть пример использования генерации нативного кода непосредственно на C#.
Пройдя по ссылке увидите сам способ реализации, а как заполнять массив опкодами я рассказал в моем посте.
UFO just landed and posted this here
В смысле, реализацией?
Вы пишите свою версию среды?
UFO just landed and posted this here
UFO just landed and posted this here
извращение это — заниматься низкоуровневым программированием из языка высокого уровня
UFO just landed and posted this here
Бред — с тем же успехом можно было написать «Программирование сопроцессора из плагина Winamp/Foobar/utorrent/С++/VB/Java»
Sign up to leave a comment.

Articles

Change theme settings