Насколько быстрее C ++, чем C #? - PullRequest
       122

Насколько быстрее C ++, чем C #?

219 голосов
/ 26 сентября 2008

Или сейчас наоборот?

Из того, что я слышал, есть некоторые области, в которых C # оказывается быстрее, чем C ++, но у меня никогда не было смелости проверить это самостоятельно.

Думаю, что любой из вас мог бы подробно объяснить эти различия или указать мне правильное место для информации по этому вопросу.

Ответы [ 27 ]

9 голосов
/ 26 сентября 2008

Как обычно, это зависит от приложения. Есть случаи, когда C #, вероятно, ничтожно медленнее, и другие случаи, когда C ++ работает в 5 или 10 раз быстрее, особенно в тех случаях, когда операции могут быть легко SIMD'd.

9 голосов
/ 26 сентября 2008

Я знаю, что это не то, что вы спрашивали, но C # часто быстрее пишет , чем C ++, что является большим бонусом в коммерческой среде.

7 голосов
/ 29 декабря 2015

C / C ++ может работать значительно лучше в программах, где имеются либо большие массивы, либо тяжелые циклы / итерации по массивам (любого размера). Это причина того, что графика обычно намного быстрее в C / C ++, потому что тяжелые операции с массивами лежат в основе почти всех графических операций. .NET известен своей медлительностью в операциях индексации массивов из-за всех проверок безопасности, и это особенно верно для многомерных массивов (и, да, прямоугольные массивы C # даже медленнее, чем зубчатые массивы C #).

Бонусы C / C ++ наиболее заметны, если вы будете придерживаться указателей и избегать Boost, std::vector и других высокоуровневых контейнеров, а также inline для каждой маленькой возможной функции. По возможности используйте массивы старой школы. Да, вам потребуется больше строк кода, чтобы выполнить то же самое, что вы сделали в Java или C #, так как вы избегаете высокоуровневых контейнеров. Если вам нужен динамически изменяемый массив, вам просто нужно не забыть соединить ваш new T[] с соответствующим оператором delete[] (или использовать std::unique_ptr) - цена за дополнительную скорость заключается в том, что вы должны кодировать более тщательно. Но в обмен на это вы избавляете себя от накладных расходов на управляемую память / сборщик мусора, которые могут легко составлять 20% или более времени выполнения сильно ориентированных на объект программ как на Java, так и на .NET, а также массивных управляемых программ. затраты на индексацию массива памяти. Приложения C ++ также могут извлечь выгоду из некоторых изящных переключателей компилятора в определенных конкретных случаях.

Я опытный программист на C, C ++, Java и C #. Недавно у меня был редкий случай реализовать точно такую ​​же алгоритмическую программу на последних 3 языках. В программе было много математических и многомерных операций с массивами. Я сильно оптимизировал это на всех 3 языках. Результаты были типичными для того, что я обычно вижу в менее строгих сравнениях: Java была примерно в 1,3 раза быстрее, чем C # (большинство JVM более оптимизированы, чем CLR), а версия необработанного указателя на C ++ оказалась примерно в 2,1 раза быстрее, чем C # . Обратите внимание, что программа на C # использовала только безопасный код & mdash; по моему мнению, вы можете также кодировать его на C ++ перед использованием ключевого слова unsafe.

Чтобы никто не подумал, что я что-то имею против C #, я в заключение скажу, что C #, вероятно, мой любимый язык. Это самый логичный, интуитивно понятный и быстрый язык разработки, с которым я когда-либо сталкивался. Я делаю все свои прототипы в C #. Язык C # имеет много небольших, тонких преимуществ перед Java (да, я знаю, что у Microsoft была возможность исправить многие недостатки Java, войдя в игру с опозданием и, возможно, скопировав Java). Тост за класс Java Calendar кто-нибудь? Если Microsoft когда-либо приложит реальные усилия для оптимизации CLR и .NET JITter, C # может серьезно вступить во владение. Я, честно говоря, удивлен, что они еще не сделали & mdash; они так много сделали прямо на языке C #, почему бы не сделать это с помощью мощных оптимизаций компилятора? Может быть, если мы все умоляем.

7 голосов
/ 26 сентября 2008

> Из того, что я слышал ...

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

Как вы собираетесь решить, являются ли вещи, которые люди говорят здесь, более или менее заслуживающими доверия, чем то, что вы изначально слышали?

Одним из способов было бы попросить доказательств .

Когда кто-то утверждает, что «есть области, в которых C # оказывается быстрее, чем C ++» спрашивает их почему они говорят, что , просят показать вам измерения, просят их показать вам программы. Иногда они просто ошиблись. Иногда вы обнаружите, что они просто выражают мнение, а не делятся чем-то, что они могут показать как правду.

Часто информация и мнение смешиваются в том, что люди утверждают, и вам придется попытаться выяснить, что есть что. Например, из ответов на этом форуме:

  • "Принять контрольные показатели на http://shootout.alioth.debian.org/ с большим скептицизмом, как они в основном проверяют арифметический код, который, скорее всего, не похож на твой код вообще. "

    Спросите себя, действительно ли вы понять, что "это во многом тест арифметический код " означает, а затем спросите себя, есть ли у автора на самом деле показал вам, что его требование правда.

  • "Это довольно бесполезный тест, поскольку он действительно зависит от того, насколько хорошо отдельные программы были оптимизировано; Мне удалось ускорить некоторые из них в 4-6 раз и более, давая понять, что сравнение между неоптимизированными программами довольно глупо. "

    Спросите себя, есть ли у автора на самом деле показал вам, что ему удалось «ускорить некоторые из них на 4-6 раз или больше "- это легко сделать заявление!

6 голосов
/ 01 апреля 2010

.NET языки могут быть такими же быстрыми, как код C ++, или даже быстрее, , но код C ++ будет иметь более постоянную пропускную способность , поскольку среда выполнения .NET должна приостанавливаться для GC , даже если он очень умен в своих паузах.

Таким образом, если у вас есть код, который должен постоянно работать быстро без какой-либо паузы, .NET в какой-то момент будет вводить задержку , даже если вы очень осторожны с GC времени выполнения.

5 голосов
/ 30 апреля 2009

При «смущающе параллельных» проблемах при использовании Intel TBB и OpenMP на C ++ я наблюдал примерно 10-кратное увеличение производительности по сравнению с аналогичными (чисто математическими) проблемами, выполняемыми с C # и TPL. SIMD - это одна из областей, где C # не может конкурировать, но у меня также сложилось впечатление, что TPL имеет значительные накладные расходы.

Тем не менее, я использую C ++ только для задач, критичных к производительности, где я знаю, что смогу многопоточность и быстро получу результаты. Для всего остального C # (а иногда и F #) просто отлично.

5 голосов
/ 26 сентября 2008

Это очень расплывчатый вопрос без реальных окончательных ответов.

Например; Я бы лучше играл в 3D-игры, созданные на C ++, чем на C #, потому что производительность, безусловно, намного лучше. (И я знаю XNA и т. Д., Но это совсем не похоже на реальную вещь).

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

4 голосов
/ 11 декабря 2008

Приложения, требующие интенсивного доступа к памяти, например. манипуляции с изображениями обычно лучше писать в неуправляемой среде (C ++), чем в управляемой (C #) Оптимизированные внутренние циклы с арифметикой указателей намного легче контролировать в C ++. В C # вам, возможно, придется прибегнуть к небезопасному коду, чтобы даже приблизиться к той же производительности.

4 голосов
/ 27 сентября 2008

Теоретически, для долго работающих приложений серверного типа, JIT-скомпилированный язык может стать на намного быстрее, чем нативно скомпилированный аналог. Поскольку JIT-скомпилированный язык обычно сначала компилируется на довольно низкоуровневый промежуточный язык, вы можете в любом случае выполнить многоуровневую оптимизацию прямо во время компиляции. Большим преимуществом является то, что JIT может продолжать перекомпилировать фрагменты кода на лету, поскольку он получает все больше и больше данных о том, как используется приложение. Он может организовать наиболее распространенные пути кода, чтобы прогнозирование ветвлений выполнялось как можно чаще. Он может переупорядочивать отдельные блоки кода, которые часто вызываются вместе, чтобы держать их в кэше. Это может затратить больше усилий на оптимизацию внутренних циклов.

Я сомневаюсь, что это делается .NET или любой из JRE, но это было исследовано еще, когда я учился в университете, так что не исключено, что подобные вещи могут попасть в реальный мир в какой-то момент в ближайшее время.

4 голосов
/ 10 мая 2011

Я тестировал vector в эквиваленте C ++ и C # - List и простых двумерных массивах.

Я использую версии Visual C # / C ++ 2010 Express. Оба проекта являются простыми консольными приложениями, я тестировал их в стандартном (без пользовательских настроек) режиме выпуска и отладки. Списки C # работают на моем компьютере быстрее, инициализация массива также быстрее в C #, математические операции выполняются медленнее.

Я использую Intel Core2Duo P8600 @ 2,4 ГГц, C # - .NET 4.0.

Я знаю, что реализация вектора отличается от списка C #, но я просто хотел протестировать коллекции, которые я буду использовать для хранения своих объектов (и возможности использования средства доступа к индексам).

Конечно, вам нужно очистить память (скажем, для каждого использования new), но я хотел сохранить код простым.

C ++ векторный тест :

static void TestVector()
{
    clock_t start,finish;
    start=clock();
    vector<vector<double>> myList=vector<vector<double>>();
    int i=0;
    for( i=0; i<500; i++)
    {
        myList.push_back(vector<double>());
        for(int j=0;j<50000;j++)
            myList[i].push_back(j+i);
    }
    finish=clock();
    cout<<(finish-start)<<endl;
    cout<<(double(finish - start)/CLOCKS_PER_SEC);
}

Проверка списка C #:

private static void TestVector()
{

    DateTime t1 = System.DateTime.Now;
    List<List<double>> myList = new List<List<double>>();
    int i = 0;
    for (i = 0; i < 500; i++)
    {
        myList.Add(new List<double>());
        for (int j = 0; j < 50000; j++)
            myList[i].Add(j *i);
    }
    DateTime t2 = System.DateTime.Now;
    Console.WriteLine(t2 - t1);
}

C ++ - массив:

static void TestArray()
{
    cout << "Normal array test:" << endl;
    const int rows = 5000;
    const int columns = 9000;
    clock_t start, finish;

    start = clock();
    double** arr = new double*[rows];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    finish = clock();

    cout << (finish - start) << endl;

    start = clock();
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    finish = clock();

    cout << (finish - start) << endl;
}

C # - массив:

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

}

Время: (выпуск / отладка)

C ++

  • 600/606 мс инициализация массива,
  • 200/270 мс заполнение массива,
  • 1сек / 13сек вектор инициализации и заполнения.

(Да, 13 секунд, у меня всегда возникают проблемы со списками / векторами в режиме отладки.)

C #:

  • 20/20 мс инициализация массива,
  • 403/440 мс заполнение массива,
  • 710/742 мс. Начало и заполнение списка.
...