Дмитpий Hecтepук

Блог о программировании — C#, F#, C++, архитектура, и многое другое

Воскрешение языка С++

23 комментария


Сдается мне, что на всей нашей круглой планете вряд ли можно найти человека, который мог бы с уверенностью сказать, в чем заключается стратегия Microsoft относительно разработки в целом. Жив ли WPF, что будет с Silverlight для веба, откуда такой ажиотаж вокруг HTML 5 и причем тут, наконец, С++? Иногда мне кажется что ни у кого нет ответов на эти вопросы, и что в погоне за добычей (добычей тут может быть, например, рынок планшетов), не возбраняется полностью смешать все карты и начать заново.

Тем не менее, мы должны признать, что по крайней мере в свете анонсов касательно WinRT, язык программирования С++ снова становится более актуальным чем ранее. Да и не только сам С++. Ведь фактически то, что нас ждет, это некая реинкарнация COM, правда с другими терминами и, возможно, меньшим количеством проблем. (Ведь неслучайно PIA – Primary Interop Assembly – расшифровывается также как Pain In the Ass;)

Если быть честно-откровенными, то тот С++ который предлагает нам Microsoft – это совсем не «стандартные» плюсы. Хотя, точно так же как и в случае с C++/CLI, остается возможность использования «труъ» кода, который был написан ранее. Но вот уже в 3й раз нам предлагают некую магию.

Почему в 3й? Ну, 1м разом я считаю все те изменения языка, которые не были стандартизованы. С Java/Visual J++ такое не прошло т.к. там правила ныне отошедшая на покой компания Sun, в случае же с С++ не нашлось стороны, которая единолично планировала бы получать доходы с этого языка. Поэтому Microsoft могла сделать все, что угодно – добавить поддержку свойств (да-да, свойств в стиле C#) с помощью __declspec(property), замутить поддержку COM с помощью #import, ну и так далее. Вторым вмешательством в С++ можно считать MC++ и с последствии С++/CLI, который добавил массу ненужных ключевых слов, а также эти ненавистные шляпки (^) для классов. Ну и так далее.

Впрочем, создание C++/CLI было вынужденным. Я это начал понимать только тогда, когда начал встречать кросс-платформенные (!) библиотеки на С++ которые компилировались, помимо обычного С++, еще и с «управляемой прослойкой» для .Net языков. Идея в принципе оказалась правильной – дать .Net разработчикам всю мощь С++ библиотек без особого напряжения в виде P/Invoke или надобности обращать С++ библиотеки в COM.

Ну и наконец, шаг 3й – это полностью узаконить любые новшества в С++ сделав его одним из официальных языков разработки для Windows. Это на самом деле лицемерие – ведь для Windows итак можно писать на «плюсах» используя MFC или даже WTL. Но уверен что мало кто этим занимается. Потери от этого больше, чем потери от требования наличия .Net Framework Client Profile на компьютере. Кстати – недавно в процессе тестирования лицезрел что происходит если поставить ClickOnce-программу которая использует .Net 4 на Windows XP. Инсталлятор сам скачивает и устанавливает framework. Это конечно нехилый download, но большинство людей 100-мегабайтные файлы уже практически не пугают.

Так вот, хотите вы этого или нет, С++ будет использоваться Microsoft в своих целях, связанных с разработкой под Windows. Но это конечно не значит что вы не сможете получить от этого бенефиты, даже если пишете на .Net.

Приемущества С++

Давайте определимся с тем, что же дает нам С++ чего не может дать тот же C#.

Ручное управление памятью. У меня в голове иногда случаются страшные баталии, связанные с тем, нужно ли делать объект структурой или классом. В принципе, в .Net нам пытаются навязать ограничение, связанное с размером объекта – дескать, если маленький то можно и структуру, а иначе ни-ни. Но это подразумевает что мы, разработчики, наивно делаем pass by value и тем самым поедаем память. Что не всегда так.

Доступ к высокопроизводительным инструкциям процессора. Возьмем например SIMD. Думаю можно с большой степенью уверенности сказать, что JIT-компилятор не оптимизирует и никогда не будет оптимизировать код под SIMD. Соответственно, мы с Microsoft.Net начинаем проигрывать даже Mono, где есть соответствующий пакет.

Прямой доступ к намного более зрелым и продуманным библиотекам. Это более сумеречный бенефит, т.к. API таких библиотек порой ужасно. Но надо смотреть не только на API но и на производительность.

О да, я же забыл упомянуть о самом важном – Microsoft ныне разрабатывает свои библиотеки для С++. Примером такой библиотеки может быть вышеупомянутая Parallel Patterns Library (PPL), которая с одной стороны может считаться «неуправляемым» аналогом .Net’ного TPL, а с другой – конкурентом Intel Threading Building Blocks (TBB). Но на этом все не останавливается – Microsoft работает еще на одной библиотекой под названием C++ Accelerated Massive Parallelism (AMP), которая будет заниматься поддержкой вычислений как на CPU так и на GPU.

Программирование для GPU заслуживает отдельную заметку. На данный момент, графические процессоры можно программировать с помощью OpenCL (вариации языка С++ для различных устройств), CUDA C (подобия С++ для чипов NVidia, кстати с прекрасным тулсетом для Visual Studio). Существуют также решения на .Net, такие как исследовательский проект Microsoft Accelerator (который, насколько я знаю, также работает с FPGA) или коммерческое решение GPU.NET.

Недостатки С++

С++ архаичен. Использовать его для ООП – делать себе плохо. Даже со всеми новшествами C++ 2011 является динозавром, пусть и динозавром который пока не думает вымирать. С другой стороны, С++ прекрасно подходит для производительных алгоритмов.

Приведу пример. Мне в TypograFix нужно обрабатывать Bitmap’ы. Если использовать .Net, то единственная возможность получить более-менее вменяемую скорость по обработке картинок – это использовать unsafe. Что как бы само по себе не очень эффективно, но даже если у вас получится, вы не сможете эффективно настроить параллелизацию unsafe кода. (Автор пробовал использовать TPL и unsafe, с весьма мутными результатами.)

Еще одна проблема – это нехватка инструментария. Отладчики конечно есть, но вот анализа кода в стиле Решарпера мне очень нехватает. А ведь это как раз тот «небезопасный» язык, в котором так нужны всяческие проверки, причем чем их больше, тем лучше.

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

AMP

У инициативы AMP есть одно существенное приемущество – над этой технологией работают AMD и NVidia, две компании которые держат рынок графических карт (лично я тяготею к AMD потому что у них есть Eyefinity). Работают они над ней, конечно, с Microsoft, т.к. у всех трех компаний есть уклон в сторону различных процессоров. Кстати, в случае с Microsoft, это конечно же ARM, о котором вы все уже наверняка наслышаны. Соответственно идея, как мне кажется, в том, чтобы иметь код (возможно даже код низкого уровня – драйвера, кодеки, и т.п.) который мог бы выжать максимум возможностей из любого процессора.

С другой стороны, по крайней мере для GPU, поддержка идет по наименьшему знаменателю, и этот знаменатель называется DirectCompute. Поэтому неизвестно, будет ли AMP настолько эффективен как например CUDA C или кросскомпиляция, скажем, C# в NVidia PTX (именно это делает GPU.NET). Также непонятно, придется ли писать fallback-код для CPU в случае отсутствия девайса с поддержкой DirectCompute – если это придется делать, то часть шарма данного подхода пропадет, т.к. это точно не «write once, run everywhere».

Intel C++

Microsoft не является единственной компанией, которая выпускает компилятор С++. Intel тоже делает компилятор, в большей степени заточенный на свои процессоры, с неплохой интеграцией в Visual Studio. Важен не только сам компилятор (а он хорош), но и тулсет – отладчик, профилировщик, библиотеки. Все это на высоте. Библиотеки, например, работают более резво на процессорах AMD чем библиотеки самой AMD.

На сегодняшний день я готов работать только с компилятором Intel. Я не использую C++/CLI, мне хватает P/Invoke. На самом деле, технология P/Invoke – настолько простая и понятная, что я не чувствую особого стеснения когда пишу часть проекта на C# а часть на С++. Что P/Invoke не поддерживает так это, конечно же, ООП и возможность передавать туда-сюда классы, но тут я скажу вот что: если вы используете С++ именно для ООП (или для взаимодействия с .Net) – вы делаете что-то не так. На С++ нужно писать производительные алгоритмы, или использовать уже существующие библиотеки (например, Intel TBB, MKL или IPP). Потреблять ООП-структуры там бесполезно, но с другой стороны, не возбраняется потреблять оттуда COM. Например, когда только вышли библиотеки Direct2D/DirectWrite, я захотел ими воспользоваться в WPF-проекте и просто написал C++ DLL’ку, которая рисовала в «залоченый» System.Drawing.Bitmap. Никаких проблем.

OpenMP

OpenMP – это поддержка декларативной параллелизации на С++. Это может показаться шуткой, но на самом деле это старая, проверенная временем технология, которая работает. Для большинства случаев data-level параллелизации в стиле parallel_for() подходит именно OpenMP. Я много где использую именно OpenMP, оставляя Intel TBB для более сложных задач, где автоматический подход не сработает.

Конечно, в .Net есть некий аналог – использование TPL и надежда на то, что JIT-компилятор магическим способом оптимизирует и «векторизует» сгенерированный код. Но это достаточно наивно. Пока вы проверяете индекс элемента доступа к массиву, вы теряете в производительности. Как только вы это отключите, у вас начнутся уже другие проблемы.

Если честно, я не большой фанат TPL. Для простеньких случаев в которые не хочется вникать, я просто пишу Parallel.Invoke или вставляю AsParallel() в цепочку LINQ-запроса и надеюсь на лучшее. Но если мне нужно почитать дистанцию Левенштейна на огромном наборе данных, то я даже напрягаться не буду – отошлю все данные в неуправляемый код, а там уж сделаю все «правильно».

Заключение

Я надеюсь, что повышенное внимание к С++ приведет к улучшению редактора. Правильный IntelliSense уже будет достижением. А что еще надо – ах да, возможно какой-нибудь генератор P/Invoke оберток и соответствующей документации для того чтобы упростить процесс.

К слову скажу, что недавно пытался найти нормальный блог по С++ путем вбивания “с++ блог” в гугле. Гугл выдал какой-то мусор. Если кто-то знает интересные блоги на русском, дайте ссылочку в комментариях. Спасибо.

Реклама

Written by Dmitri

30 октября 2011 в 0:13

Опубликовано в Programming

Tagged with

комментария 23

Subscribe to comments with RSS.

  1. отрефлексировал на просьбу о блогах, но по своему. Вам не известны случайно хорошие .NET врапперы к MPIR? (порт GMP под VS)

    Константин Жук

    30 октября 2011 at 0:38

    • К сожалению, не знаю. Гуглом нашел нечто под названием X-MPIR, но не знаю, какого эта библиотека качества.

      Dmitri

      30 октября 2011 at 8:00

  2. Алёна С++? /* блог */

    Например

    30 октября 2011 at 14:11

    • Это новостной блог, на котором нет ни одной строчки кода. Абсолютно неинтересно. Хотя, OVER 1000 подписчиков, вау. (Название блога вообще отдельная тема. Дима C#? :)

      Dmitri

      30 октября 2011 at 16:30

  3. Увы, но С++ — живой труп, шевелиться который заставляют только бегемоты типа Мелкософта ввиду большой кучи легаси библиотек. Новому поколению все эти двоеточия-крышечки-new-smart_ptr нафик не упёрлись. Как не упёрлись эфемерные преимущества необычного порошка над обычным. Ну скажите, кому сейчас нужна скорость? Только утилитарным алгоритмам, которые запросто дёргаются через врапперы. «Ручное упр. памятью»??? Не смешите мой дисковод! Эта чёртова схема «запросил-освободил» испортила не один километр нервов!! Прямая аналогия с «коробкой-автомат», где 0.0001% водителей в 0.0001% случаев могут получить преимущество «ручной передачи». Даже если С++ притянуть за уши к C# (что и сделано в С++11), он никогда не будет таким же простым и удобным, ибо порочен архитектурно. Так что спите спокойно, изучайте D/C# и пребудет с вами крупножёсткая сила. :)

    Vincent

    30 октября 2011 at 23:02

    • Спасибо за комментарий! Вы во многом правы, но те утилитарные алгоритмы кто-то же должен написать, особенно если они не поставляются «из коробки» вроде IPP. Насчет архитектурной порочности я во многом согласен, но заметьте, я и не предлагаю использовать С++ ради ООП.

      Dmitri

      30 октября 2011 at 23:37

      • Ну а кто заставляет писать «утилиты» на С++?? (тем более, что его ООП возможности не нужны) Вполне подойдёт обычный Си, понятный каждому студенту. В результате очень быстро пишем на C#, в исключительных случаях дёргая нативные Си-утилитки.

        Vincent

        31 октября 2011 at 16:06

        • Тут бывает происходит вот что: хочется иметь конфигурируемые алгоритмы. А сделовательно сразу же вступает в игру наследование и прочие вещи. Понятное дело что можно пытаться работать и без них, но… короче палка о двух концах. Это как в F# — там с одной стороны ООП как бы и не нужно, но когда начинаешь писать код для последующего расширения и поддерживания, начинаешь пересматривать свои принципы.

          Dmitri

          31 октября 2011 at 20:43

    • Конечно-конечно…
      Не хотелось бы разводить холивар и флуд, но все-таки.
      Как мне кажется, это единственный язык, который никуда не денется, пока есть компьютеры и вот почему:
      1) С++ — это стандарт, а значит работает не только на Windows, но и на Linux, Mac OS X, *NIX BSD и т.д. Те же C# и Java работают кое-как на Linux и Mac OS X, при этом основные баталии идут в стане лицензий и стандартов на эти языки
      2) задачи которые требуют с одной стороны производительности сравнимой с С и с другой стороны, поддержку ООП и шаблонов:
      — высоконагруженные 3D игры для PC и консолей
      — математические пакеты
      — высоконагруженные веб-проекты (посмотрите вакансии ведущих поисковиков, в частности Яндекс, там достаточно большая доля вакансий — С++, я например насчитал 20 вакансий. В других компаниях, например, в Microsoft аналогично (Алена С++ как раз работает С++-разработчикоа в Microsoft в Редмонде))
      — производительные мобильные приложения (Android NDK, BlackBerry Native SDK, Symbian)
      — интерфейсы к другим языкам программирования (например, XS для Perl)
      — кроссплатформенная разработка (Qt, wxWidgets)

      Что касается блогов про С++:
      http://alexott-ru.blogspot.com/
      http://easy-coding.blogspot.com/
      http://cpptruths.blogspot.com/
      http://habrahabr.ru/hub/cpp/posts/

      TheAthlete

      17 апреля 2012 at 14:51

      • «Стандарты» в ИТ — это такая натянутая вещь, которая существует только на бумаге. SQL — стандарт? Ога! А теперь возьмите любую базу из MS SQL (в виде SQL конечно) и перенесите в MySQL — обломитесь! С++ — аналогично, пара пердунов зафиксировала свои мысли в 90-ых, но языку-то нужны фичи, а не идеи консерваторов! Результат — ни gcc, ни vc++, ни intel c++ несовместимы. Да и боссу абсолютно фиолетовы ваши «стандарты», ему нужны решения и ещё вчера! И тут на сцену выходят языки, где быстро и без граблей можно ваять целые «интыпрайзы».

        Vincent

        17 апреля 2012 at 15:29

      • Далее… 2)
        Задач на производительность — полно, но каков КПД «выжимки»?? Ну сделал ты алгоритм в С++ на 10% быстрее, чем в C# (это если ты вообще мастер оптимизаций), смысл? Затрат времени — точно больше, «хитровыписанный» и непереносимый код — тоже вам в минус (если трюкачествовали со всякими MMX). Зато тот же C# параллелится на несколько процев, с форой обгоняя оптимизации на одном ЦПУ.
        Кроме того, корень медлительности как правило сидит в алгоритмах, а не регистрах.

        Vincent

        17 апреля 2012 at 15:38

        • возьмите любую базу из MS SQL (в виде SQL конечно) и перенесите в MySQL:
          мне казалось уже давно всем ясно, что для MS стандарты побоку…
          ни gcc, ни vc++, ни intel c++ несовместимы
          странная вещь — у меня совместимы((
          Может проблема решается изучением дополнительной информации?

          алгоритм в С++ на 10% быстрее, чем в C# (это если ты вообще мастер оптимизаций)
          а Вы вообще в код mscorlib.dll глядели? Да там элементарный System.Math.Cos через маршалинг делается… Исключая проверки потокобезопасности уже получаем приличный выигрыш. И кстати, после ngen`a они никуда не исчезают.
          Просто возьмите, ради эксперимента, и перепишите любой алгоритм, активно использующий CPU&Mem (математический, парсинг строк и тд) и в профайлер… и не позорьтесь больше.

          тот же C# параллелится на несколько процев
          вот-ведь незадача — а плюсы прокляты чукотским шаманом и никак не хотят)))
          Параллелится не язык, а код. А вот заставить его работать как должно — это и есть задача программиста.
          Ну а время зависит от степени владения инструментом.

          PS: интересно было-бы посмотреть на Вашу производительность труда, посади Вас за систему на основе Atom с ОС, IDE и дебагером написанных на целиком .net платформе…)) А вот меня нетбук+XP/Linux+VS2010/gcc в командировках пока устраивает…

          Sh

          26 июля 2012 at 1:21

        • ISO — это не «натянутая вещь», а предсказуемость и совместимость
          если взять linux, то противопоставить можно лишь mono, а теперь берём qt — и сообщество mono тихо курит в сторонке (чисто по количеству разбора полётов)…
          берём Intel TBB + IPP + MKL + OpenCV и параллельный С# с форой отправляется лесом в той массе задач, где действительно нужна производительность…

          developer

          27 ноября 2013 at 20:07

  4. По поводу генератора P/Invoke оберток:
    Посмотрите на «PInvoke Interop Assistant» http://clrinterop.codeplex.com/releases/view/14120.
    В моем случае он пару раз облегчал данную задачу.

    Vladimir Datsyuk

    31 октября 2011 at 11:45

    • Ммм, а какая лицензия у этой штуки? Этот код можно встроить в свой коммерческий продукт?

      Dmitri

      31 октября 2011 at 12:39

  5. Видимо Microsoft Limited Public License (Ms-LPL) http://clrinterop.codeplex.com/license. По поводу коммерческого использования — в этих вопросах не являюсь специалистом. В тексте лицензии нет запрещения, в википедии написано что можно. Я использовал лишь как инструмент для превращения заголовочных файлов в классы обертки на С#.

    Vladimir Datsyuk

    31 октября 2011 at 14:55

    • К сожалению, там достаточно наивный парсер, который не разбирает макросы. А следовательно, заголовочный файл IPP, где используются макросы для определения методов, не распарсить. Вот пример того как там определяются функции:

      IPPAPI(IppStatus, ippsEncodeRLE_8u, ( Ipp8u** ppSrc, int* pSrcLen, Ipp8u* pDst, int* pDstLen ))
      

      Dmitri

      31 октября 2011 at 15:36

  6. Про блоги.
    Не сказать, что чисто про C++, скорее про весь стек технологий Microsoft, но посмотрите у меня, может что интересного найдете: http://mrnone.blogspot.com .
    Кстати, крайние заметки как раз про PPL на C++ были.

    Mr. None

    31 октября 2011 at 20:11

    • А вот это уже намного интересней, спасибо, подписался. Попутно узнал о Asynchronous Agents Library — надо будет проштудировать тему. Кстати, у меня вопрос в тему: а библиотеки Microsoft вроде PPL, AAL и т.п. — они будут компилироваться Intel’евским компилятором? Или там как всегда какие-то завязки на внутреннюю магию?

      Dmitri

      31 октября 2011 at 20:40

      • Насчет завязок на компилятор не знаю — не проверял. Проверьте — тоже интересно… Точно есть завязки на версию ОС: минимальное требование — XP SP3.

        Mr. None

        1 ноября 2011 at 21:22

        • Ну это само по себе не очень хорошо. Я узнал что TBB и PPL имеют одинаковый интерфейс, с той разницей что в TBB есть алгоритмы которых нет в PPL. Насчет AAL я не смотрел и в принципе пока мне не понадобится я сам наверное на это не буду смотреть. TBB я использовать готов хотя у меня и OpenMP достаточно неплохо работает. :)

          Dmitri

          1 ноября 2011 at 21:26

        • добавлю, что на сколько мне известно в openmp — на практике task stealing не используется, а в TBB свой планировщик, который решает эту задачу, что есть боольшой гуд…

          developer

          27 ноября 2013 at 19:54

  7. «..На С++ нужно писать производительные алгоритмы..» — Это вряд ли, скорее на старом добром С

    Марк

    8 ноября 2011 at 12:21


Оставить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: