На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Производительность Си в сравнении с Rust
    Добрый вечер!
    Почему Си с компилятором GCC уступает в производительности Rust? Объясните доходчиво, пожалуйста. Источник тут https://benchmarksgame-team.pages.debian.ne...stest/rust.html
    Спасибо.
      1) Если смотреть тесты, то в половине случаев.
      2) И надо все делать самим.
      3) Для теста, мне кажется, надо более длительные тесты...

      Под линуксом наверно стабильно, но один из тестов на С++ под форточками (рабочий комп) у меня был приличный разброс результатов
      0.0167395s
      0.0106386s
      0.0140187s
      Сообщение отредактировано: Black_Dragon -
        Цитата Sunless @
        Почему Си с компилятором GCC уступает в производительности Rust? Объясните доходчиво, пожалуйста. Источник тут https://benchmarksgame-team.pages.debian.ne...stest/rust.html

        Потому что это говнотесты, там нет сравнения Си и Rust, там больше похоже на какую то олимпиадку студентов на разных языках. В одном языке значит они юзают один алгоритм, в другом языке другой алгоритм. Т.е. по сути просто сравниваются разные алгоритмы на разных языках. Так себе сравнение быстродействия языков. Больше похоже на сравнение программеров.
        Даже судя по написанному в комментарии в шапке каждого исходника, можно сделать вывод что писали тесты разные люди. На Си писал Джон, на Rust писал Alex, Murtaza, Steven, etc.


        Добавлено
        https://benchmarksgame-team.pages.debian.ne...ide-rust-7.html
        https://benchmarksgame-team.pages.debian.ne...tide-gcc-1.html

        Видно же что совершенно разные алгоритмы.

        Или вот:
        https://benchmarksgame-team.pages.debian.ne...rot-rust-7.html
        https://benchmarksgame-team.pages.debian.ne...brot-gcc-6.html

        Rust:
        ExpandedWrap disabled
          pub fn mbrot8(out: &mut u8, cr: &Vecf64, ci: Constf64) {
              let mut zr = Arr::splat(0f64);
              let mut zi = Arr::splat(0f64);
              let mut tr = Arr::splat(0f64);
              let mut ti = Arr::splat(0f64);
              let mut absz = Arr::splat(0f64);
           
              for _ in 0..MAX_ITER / 5 {
                  for _ in 0..5 {
                      zi = (zr + zr) * zi + ci;
                      zr = tr - ti + cr;
                      tr = zr * zr;
                      ti = zi * zi;
                  }
           
                  absz = tr + ti;
                  if absz.iter().all(|&t| t > 4.) {
                      return;
                  }
              }
           
              *out = absz.iter().enumerate().fold(0, |accu, (i, &t)| {
                  accu | if t <= 4. { 0x80 >> i } else { 0 }
              });
          }


        Си
        ExpandedWrap disabled
          inline void calcSum(__m128d *r, __m128d *i, __m128d *sum, __m128d *init_r, __m128d init_i)
          {
              for(long pair=0; pair<4; pair++)
              {
                  __m128d r2 = r[pair] * r[pair];
                  __m128d i2 = i[pair] * i[pair];
                  __m128d ri = r[pair] * i[pair];
           
                  sum[pair] = r2 + i2;
           
                  r[pair]=r2 - i2 + init_r[pair];
                  i[pair]=ri + ri + init_i;
              }
          }
           
          inline unsigned long mand8(__m128d *init_r, __m128d init_i)
          {
              __m128d r[4], i[4], sum[4];
              for(long pair=0; pair<4; pair++)
              {
                  r[pair]=init_r[pair];
                  i[pair]=init_i;
              }
           
              unsigned long pix8 = 0xff;
           
              for (long j = 0; j < 6; j++)
              {
                  for(long k=0; k<8; k++)
                      calcSum(r, i, sum, init_r, init_i);
           
                  if (vec_nle(sum, 4.0))
                  {
                      pix8 = 0x00;
                      break;
                  }
              }
              if (pix8)
              {
                  calcSum(r, i, sum, init_r, init_i);
                  calcSum(r, i, sum, init_r, init_i);
                  clrPixels_nle(sum, 4.0, &pix8);
              }
           
              return pix8;
          }


        В первом исходнике на Rust 2 вложенных цикла, во втором на Си - 3 вложенных цикла. Что с чем тут сравнивается?
        Я вообще не понимаю что там с чем сравниватся, и что это за херотень.
        Сообщение отредактировано: Wound -
          Цитата Sunless @
          Почему Си с компилятором GCC уступает в производительности Rust? Объясните доходчиво, пожалуйста. Источник тут https://benchmarksgame-team.pages.debian.ne...stest/rust.html

          Да тем тесты дебильные. Например, в pi-digits в расте они подключают gmp и пишут safe обёртку над ним. Что они хотели этим протестировать - мне неведомо.
          А если абстрагироваться от этих конкретных тестов, то исходник на расте предоставляет компилятору больше информации и, соответственно, у него больше возможностей для оптимизации. Например, если у тебя в расте есть mut ссылка, то компилятор будет знать, что никто другой на неё не указывает, и будет генерировать код, который бы сгенерировал сишный код с указателями, объявленными как restrict. Также наверняка не последнюю роль оптимизации llvm играют, т.е. если взять вместо gcc clang, то разрыв будет меньше при одинаковых алгоритмах.
            Цитата Wound @
            Больше похоже на сравнение программеров

            Тоже в исходниках "запутался".
            Получается так, есть какая-то обобщенная задача, и кто из программеров разработает алгоритм и напишет быструю реализацию.
              То есть языка производительнее Си с человеческим синтаксисом не может быть, там же очень простой синтаксис для анализа?
                Цитата Sunless @
                То есть языка производительнее Си с человеческим синтаксисом не может быть
                Может. Си++.
                  Почему он производительнее? У него же сложнее синтаксис. Улучшают ли авторы стандартов С/С++ производительность языков?
                    Sunless
                    Процессор не обрабатывает языки высокого уровня.
                    Компиляторы "конвертируют" язык в инструкции процессора.
                    И для большинства разных языков, выражение a=b+1 будет кодироваться одинаково.
                    Но оптимизация и другие особенности зависит от компилятора.

                    Как борщ, если дать одинаковые ингредиенты, то он будет приготовлен за разное время и немного по разному...
                      Black_Dragon, истину глаголишь! :good:

                      Но есть одно "но" ... не все компиляторы копилячут в инструкции процессора, некоторые в байт код, некоторые в шитый код.
                        Есть ли универсальный способ, чтобы проверить, какой из компиляторов сгенерировал более оптимальную программу? Может, даже есть готовое сравнение C,C++,Rust, на которое вы бы посоветовали обратить внимание?
                          Цитата Sunless @
                          Есть ли универсальный способ, чтобы проверить, какой из компиляторов сгенерировал более оптимальную программу
                          :no: Даже нет универсального способа проверять производительность, не то чтобы проверять оптимизированность. Берём, к примеру, две программы, запускаем на одном процессоре, выигрывает первая; запускаем их же на другом, выигрывает вторая. :-?
                            JoeUser
                            Знаем.... Межплатформенные языки, Java, например, если память не подводит.

                            Qraizer
                            Было у меня такое. Любитель оптимизировать расчеты просто, так и через OpenMP.
                            В одной программе были несколько разных тестовых кусков кода (оптимизировал и тестил), и сравнивал i7-4770 (ddr3) и i5-6500 (ddr4) (рабочий и домашний). Часть кода была быстрее на одном проце, другая часть на другом.
                              Всё-таки не совсем понятно, почему ядра ОС и серверы пишут на Ассемблере и Си и не переписывают на другие языки, если осталььные языки их могут обогнать.
                              P.S.
                              Подскажите, как здесь найти список своих тем?
                              Сообщение отредактировано: Sunless -
                                Цитата Sunless @
                                не переписывают на другие языки, если осталььные языки их могут обогнать.

                                1) Вы знаете сколько кода в ОС-ах? И как вы себе представляете "переписать", а если еще что-то новое, быстрое появиться, опять переписывать?
                                2) Другие языки не быстрее. Языки высокого уровня (могут) внедряют разные защиты, например, проверка границ массива, а это накладные расходы...
                                3) Всякие ООП тоже имеют накладные расходы....

                                ОС-ы пишут очень профессиональные программисты, и весь контроль за работой кода и логики на них, а не на авторах библиотек или компилятора.
                                Например, перед тем как работать с указателем, надо проверить его на валидность, чтоб не получить крах программы по доступам.
                                Но в логике твой программы 100% дойдя до этого места указатель будет точно валиден и тебе не нужен код, где он будет лишний раз проверяться. По этому тебе не нужна библиотека, в которой есть лишние проверки, так как тебе нужно быстродействие.
                                  Цитата Black_Dragon @
                                  3) Всякие ООП тоже имеют накладные расходы....

                                  Вот это спорно. По крайней мере если как альтернативу рассматривать плюсы.
                                    Цитата OpenGL @
                                    Вот это спорно

                                    if (pointer != nullptr) - уже накладные расходы, а в ООП тоже будут доп проверки, вычисления. Откуда узнать, какую виртуальную функцию вызвать или это лишний переход, доступ сделать для этого? ООП за бесплатные такты процессора не реализуем. Ну может быть типа простой вариант, когда ты тупо наследуешь...

                                    Просто, что мы рассматриваем. Одно дело, когда это ОС или жесткий реалтайм, тут борьба за быстродействие до тактов и лишних инструкций. Имхо.
                                      В других языках может быть и по другому, но конкретно в Плюсах ООП бесплатен. Объектная модель такова, что написанные руками аналоги будут точно такими же. К примеру виртуальные методы представлены просто указателями на функции, и если переписать полиморфизм на C, получится то же самое.

                                      Добавлено
                                      Цитата
                                      Подскажите, как здесь найти список своих тем?
                                      Попробуй ткнуть в «Профиль» под своим ником, зайти в профиль и найти что-то вроде «темы этого участника».
                                        Цитата Black_Dragon @
                                        if (pointer != nullptr) - уже накладные расходы, а в ООП тоже будут доп проверки, вычисления.

                                        Я не понимаю, о каких накладных расходах и дополнительных проверках идёт речь. Если тебе надо проверять указатель на nullptr в плюсах, то надо делать это и в си. Если в программе на си это делать не надо (например, потому что он был проверен уровнем выше), то и в плюсах тебе ничто не мешает построить систему аналогично.

                                        Цитата Black_Dragon @
                                        Откуда узнать, какую виртуальную функцию вызвать или это лишний переход, доступ сделать для этого?

                                        Он и в си будет делаться, если тебе нужна динамическая диспетчеризация, при помощи набора указателей на функции. Это ровно такая же VMT, только написанная руками.

                                        Цитата Black_Dragon @
                                        Просто, что мы рассматриваем. Одно дело, когда это ОС или жесткий реалтайм, тут борьба за быстродействие до тактов и лишних инструкций. Имхо.

                                        Лично я о том, что не на всех языках у тебя будут получаться лишние инструкции в сравнении с Си. С++ - достаточно тонкая прослойка над ним. Если отключить RTTI и исключения (а ядро ОС, если бы писалось на плюсах, писалось бы без них), то вообще не будет никакого оверхеда. С растом чуть сложнее, в нём у тебя у объектов с деструктором есть drop flag, который обязательно проверяется при выходе из скопа, в нём для полиморфизма используются fat pointers, так что на язык без оверхеда в сравнении с си он всё-таки плохо тянет, но и в нём он настолько мал, что, вероятно, даже в ядре ОС это не будет особо важным.
                                          Какой из языков сложнее - C или Rust?
                                            Цитата Sunless @
                                            Всё-таки не совсем понятно, почему ядра ОС и серверы пишут на Ассемблере и Си и не переписывают на другие языки, если осталььные языки их могут обогнать.

                                            Исторически сложилось, что ассемблер и си - это языки, на которых писались все системные шляпы (оси и их компоненты). Для этого существует уже много наработок, подходов и состоявшееся комьюнити.

                                            1) Когда выгодно использовать ассемблер?
                                            Когда ты на 100% уверен, что твой код наиболее эффективен.
                                            Как правило, это относительно мелкие, продуманные участки программы.

                                            2) Когда лучше использовать Си вместо ассемблера?
                                            Когда ты пишешь достаточно объемные участки кода, либо неспецифичные.
                                            Тогда разумно полагаться на компилятор и линкер. Ведь они умеют неплохо
                                            оптимизировать код. Простой пример. Ты пересобираешь ядро, мир *nix
                                            системы. Пересобираешь именно под себя. Ты вправе задать компилятору
                                            флаг, который укажет оптимизировать код именно под нужное тебе семейство
                                            процессоров. В результате некоторые участки кода будут задействовать те
                                            фичи, которые есть в твоем процессоре, и которые будут более удачным
                                            решением, нежели ты их заменишь командами общего назначения.

                                            3) Когда лучше использовать С++ (или Rust) вместо Си?
                                            Когда ты осознанно можешь выделить так называемые абстракции с нулевой
                                            стоимостью ("zero-cost abstractions"). Иными словами, используя абстракции
                                            более высокого уровня, которые дают удобство программисту, ты должен
                                            осознавать, что это повлияет на качество (скорость, потребляемые ресурсы)
                                            несущественно, либо вообще не повлияет. В принципе это можно отнести
                                            и ко всем языкам, но в языках более высокого уровня проще напороться на
                                            незаметные на первый взгляд оверхеды.

                                            4) Когда лучше использовать Rust вместо С/C++?
                                            Тут скорее дело вкусовщины, практики, наличия комьюнити, наличие цели.
                                            Лично мне Rust очень симпатичен. Но, если подворачивается практическая
                                            задача, да еще есть и ограничение по времени - я даже не заморачиваюсь,
                                            и начинаю ее решать, используя С++. Все просто - наличие практики. Так
                                            даже сотня написанных хэлоу-ворлдов на Rust не сделают этот язык твоим
                                            рабочим инструментом. Только реальный/реальные проекты, только время.
                                            Отсутствие уже устоявшихся стереотипов в разработке на других языках
                                            возможно даже будет бонусом.

                                            Все написанное выше - ИМХО. Ошибаться право имею! :)

                                            Добавлено
                                            Цитата OpenGL @
                                            С растом чуть сложнее, в нём у тебя у объектов с деструктором есть drop flag

                                            В Rust, также как и в C++, ты можешь отдельные (наиболее требовательные) участки кода писать в стиле процедурного программирования, не так ли? Ну а если совсем уже невмоготу - использовать unsafe блоки. Тогда от оверхеда вообще можно избавится.
                                              Цитата JoeUser @
                                              Тогда от оверхеда вообще можно избавится.

                                              Можно, но это неудобно, т.к. не будет ни трейтов (и динамическую диспетчеризацию придётся писать руками), ни деструкторов (и, если в си можно воспользоваться либо attribute cleanup, либо goto, то тут ничего из этого нет), и с массивами придётся работать исключительно через unsafe, чтобы проверок индексов не было. Проще уж на чистом си или плюсах тогда, если цель - ни грамма оверхеда.
                                                Цитата OpenGL @
                                                Можно, но это неудобно, т.к. не будет ни трейтов (и динамическую диспетчеризацию придётся писать руками), ни деструкторов (и, если в си можно воспользоваться либо attribute cleanup, либо goto, то тут ничего из этого нет), и с массивами придётся работать исключительно через unsafe, чтобы проверок индексов не было. Проще уж на чистом си или плюсах тогда, если цель - ни грамма оверхеда.

                                                Иными словами, писать с использованием того, что "есть" только в Си - так почему же в Си удобнее? ;) ИМХО, у Раста синтаксис не хуже, а порой и наоборот красивее и лаконичнее. Но цель "ни грамма оверхеда", сам понимаешь - это чаще утопия, чем обязательное требование.
                                                  Цитата JoeUser @
                                                  Иными словами, писать с использованием того, что "есть" только в Си - так почему же в Си удобнее?

                                                  Потому что это такой уровень, что плюсы раста становятся ограничением. Из преимуществ будет разве что его enum, tuples, паттерн-матчинг и возможность что-нибудь деструктурировать с его помощью. Но зато всё остальное, что нужно на этом уровне, становится таким неудобным, что ну его нафиг :)
                                                  Впрочем, ты прав в том, что спуск на такой низкий уровень почти никогда не нужен. А даже если он будет нужен, то не факт, что там придётся городить какие-то сложные вещи, которые потребуют деструкторов. Но как камень в огород раста "а вот это на плюсах делается просто" сойдёт.
                                                    Вот так пришлось извращаться (не мне):
                                                    Инкремент элементов вектора
                                                    Сообщение отредактировано: Black_Dragon -
                                                      Развивается ли стандарт Си в сторону роста производительности программ на этом языке в то время, как создаются языки наподобие Rust? Сам не шибко следил за стандартами,поэтому инетерсуюсь у вас, как более опытных товарищей.
                                                        Цитата Sunless @
                                                        Развивается ли стандарт Си в сторону роста производительности программ

                                                        Нет, не развивается в этом направлении. Си - знатный сторожил, и пережил уже многие взлеты/падения, тихонько наблюдая со стороны. А вот С++ в тренде движухи! Недавно я мельком зацепил тему концептов с++20, прикольная штука (если я не плыву - привет Раст). Ну а в плане именно быстродействия, тут не так! Быстродействие на фоне языка - определяется реализациями компиляторов. А быстродействие стандартной либы - определяется ее "доработками".

                                                        Нельзя так вот сказать, мол новый стандарт Си++ стал лучше языка-N (пусть того же Раста). Да, идут видоизменения, как в плане изменения (оптимизации) кода, так и в плане последующей сборки. Они идут. Они идут постоянно. Но не в языке дело, и слава Богу.

                                                        Простой пример.

                                                        Я начинал изучать язык Perl с 1998 года, там была версия 4. Потом перескочил на версию 5 вообще, как по маслу. Грамотные фиксы, лайт-модификации. Но потом вышел Perl 6. С конкретными видоизменениями, в том числе и синтаксиса. Оно мне надо? Оно мне не надо!

                                                        Так будет и с Си++, если "перегнут черту" - будут обосратушки. Но тут парни видимо трезвее, ИМНО.
                                                          С развивается в сторону общей оптимизации. А так C достаточно близко к аппаратной архитектуре, какими-то изменениями языка редко получается повысить его быстродействие. Из того, что помню, только добавление более быстрых вызовов функций с передачей параметров через регистры и встраивание функций.
                                                            Народ, обычно, заморачивается под ручное программирование векторных операций AVX
                                                            Умножение матриц: эффективная реализация шаг за шагом
                                                            Сообщение отредактировано: Black_Dragon -
                                                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                            0 пользователей:


                                                            Рейтинг@Mail.ru
                                                            [ Script execution time: 0,0761 ]   [ 17 queries used ]   [ Generated: 16.04.24, 12:00 GMT ]