C++ и c# скорость сравнены

Я волновался по поводу скорости C#, когда она имеет дело с тяжелыми вычислениями, когда необходимо использовать необработанную мощность ЦП.

Я всегда думал, что C++ намного быстрее, чем C# когда дело доходит до вычислений. Таким образом, я сделал некоторые быстрые тесты. Первый тест вычисляет простые числа <целое число n, второй тест вычисляет некоторые pandigital числа. Идея для второго теста прибывает отсюда: Числа Pandigital

C# главное вычисление:

using System;
using System.Diagnostics;

class Program
{

    static int primes(int n)
    {

        uint i, j;
        int countprimes = 0;

        for (i = 1; i <= n; i++)
        {
            bool isprime = true;

            for (j = 2; j <= Math.Sqrt(i); j++)

                if ((i % j) == 0)
                {
                    isprime = false;
                    break;
                }

            if (isprime) countprimes++;
        }

        return countprimes;
    }



    static void Main(string[] args)
    {
        int n = int.Parse(Console.ReadLine());
        Stopwatch sw = new Stopwatch();

        sw.Start();
        int res = primes(n);
        sw.Stop();
        Console.WriteLine("I found {0} prime numbers between 0 and {1} in {2} msecs.", res, n, sw.ElapsedMilliseconds);
        Console.ReadKey();
    }
}

Вариант C++:

#include 
#include 
#include 

int primes(unsigned long n) {
unsigned long i, j;
int countprimes = 0;
  for(i = 1; i <= n; i++) {
      int isprime = 1;
      for(j = 2; j < sqrt((float)i); j++) 
          if(!(i%j)) {
        isprime = 0;
        break;
   }
    countprimes+= isprime;
  }
  return countprimes;
}

int main() {
 int n, res;
 cin>>n;
 unsigned int start = clock();

 res = primes(n);
 int tprime = clock() - start;
 cout<<"\nI found "<

Когда я запустил тест, пытающийся найти начала <чем 100 000, вариант C# законченный через 0,409 секунды и вариант C++ за 0,614 секунды. Когда я выполнил их для 1 000 000 C#, законченных через 6,039 секунд и C++ приблизительно через 12,987 секунд.

Pandigital тестируют в C#:

using System;
using System.Diagnostics;

class Program
{
    static bool IsPandigital(int n)
    {
        int digits = 0; int count = 0; int tmp;

        for (; n > 0; n /= 10, ++count)
        {
            if ((tmp = digits) == (digits |= 1 << (n - ((n / 10) * 10) - 1)))
                return false;
        }

        return digits == (1 << count) - 1;
    }

    static void Main()
    {
        int pans = 0;
        Stopwatch sw = new Stopwatch();
        sw.Start();

        for (int i = 1; i <= 123456789; i++)
        {
            if (IsPandigital(i))
            {
                pans++;
            }
        }
        sw.Stop();
        Console.WriteLine("{0}pcs, {1}ms", pans, sw.ElapsedMilliseconds);
        Console.ReadKey();
    }
}

Pandigital тестируют в C++:

#include 
#include 

using namespace std;

int IsPandigital(int n)
    {
        int digits = 0; int count = 0; int tmp;

        for (; n > 0; n /= 10, ++count)
        {
            if ((tmp = digits) == (digits |= 1 << (n - ((n / 10) * 10) - 1)))
                return 0;
        }

        return digits == (1 << count) - 1;
    }


int main() {
   int pans = 0;
   unsigned int start = clock();

   for (int i = 1; i <= 123456789; i++)
   {
      if (IsPandigital(i))
      {
        pans++;
      }
   }
   int ptime = clock() - start;
   cout<<"\nPans:"<

Вариант C# работает через 29,906 секунд и C++ приблизительно через 36,298 секунд.

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

Кто-либо может объяснить это? C# является jitted, и C++ компилируется собственный компонент, таким образом, нормально, что C++ будет быстрее, чем вариант C#.

Спасибо за ответы!

Я имею, восстановил все тесты для конфигурации Выпуска.

Сначала протестируйте (простые числа)

C# (числа <100,0000): 0,189 секунды C++ (числа <100,0000): 0,036 секунды

C# (числа <1,000,000): 5 300 секунд C++ (числа <1,000,000): 1,166 секунды

Второй тест (pandigital числа):

C#: 21,224 секунды C++: 4,104 секунды

Так, все изменилось, теперь C++ намного быстрее. Моя ошибка состоит в том, что я имею, запустил тест для Настройки отладочного процесса. Я могу видеть некоторое улучшение скорости, если я выполнил исполняемые файлы C# через ngen?

Причина я пытался сравнить C# и C++, состоит в том, потому что я знаю некоторые основы обоих, и я хотел изучить API, имеющий дело с GUI. Я думал, что WPF хорош поэтому, учитывая, что я нацелен на рабочий стол, я хотел видеть, может ли C# обеспечить достаточно скорости и производительности когда дело доходит до использования чистая мощность ЦП для вычислений различных вычислений (файл archivers, криптография, кодеки и т.д.). Но кажется, что печально C# не может идти в ногу с C++ когда дело доходит до скорости.

Так, я предполагаю, что навсегда застряну с этим Сложным вопросом вопроса на WPF, Win32, MFC, и я буду более новая находка подходящий API.

6
задан Community 23 May 2017 в 12:00
поделиться

10 ответов

Почему вы предполагаете, что jit-код медленнее, чем собственный код? Единственным штрафом за скорость будет фактическое дрожание, которое происходит только один раз (вообще говоря). Учитывая программу с продолжительностью работы 30 секунд, мы говорим о незначительной части общей стоимости.

Думаю, вы можете спутать jit-код с интерпретируемым кодом, который компилируется построчно. Между ними есть довольно значительная разница.

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

Изменить - я должен указать еще на одну вещь, а именно, что эта строка:

for (j = 2; j <= Math.Sqrt(i); j++)

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

9
ответ дан 8 December 2019 в 02:11
поделиться

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

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

2
ответ дан 8 December 2019 в 02:11
поделиться

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

12
ответ дан 8 December 2019 в 02:11
поделиться

генератор простых чисел в C ++ неверен

i ^ (1/2) == i xor 0

^ - побитовый оператор xor а / - целочисленное деление.

1-е изменение , это правильно, но неэффективно: Поскольку i xor 0 == i, сито останавливается не на sqrt (i), а на i.

2-е изменение:

Просеивание можно сделать немного более эффективным. (Вам нужно только вычислить sqrt (n)). Вот как я реализовал Сито Эратосфена для собственного использования (хотя это и в C99):

void sieve(const int n, unsigned char* primes)
{
        memset(primes, 1, (n+1) * sizeof(unsigned char));

        // sieve of eratosthenes
        primes[0] = primes[1] = 0;
        int m = floor(sqrt(n));
        for (int i = 2; i <= m; i++)
                if (primes[i]) // no need to remove multiples of i if it is not prime
                        for (int j = i; j <= (n/i); j++)
                                primes[i*j] = 0;
}
11
ответ дан 8 December 2019 в 02:11
поделиться

Это занимает намного больше времени, потому что алгоритм неправильный.

for(j = 2; j < (i^(1/2)); j++) 

это то же самое, что

for(j = 2; j < (i^0); j++) 

это то же самое, что

for(j = 2; j < i; j++) 

i намного больше, чем sqrt(i). Если смотреть только на время работы, то оно на порядок больше, чем должно быть в реализации на C++.

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

6
ответ дан 8 December 2019 в 02:11
поделиться

Перекомпилируйте программу C ++ с включенной полной оптимизацией и повторно запустите тесты. C # jit оптимизирует код при его jit, поэтому вы сравнили оптимизированный код C # /. NET с неоптимизированным C ++.

3
ответ дан 8 December 2019 в 02:11
поделиться

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

Первый тест не имеет смысла даже как сравнение неоптимизированного поведения из-за ошибки в вашем коде; Math.Sqrt(i) возвращает квадратный корень из i, i^(1/2) возвращает i - так что C++ делает гораздо больше работы, чем C#.

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

0
ответ дан 8 December 2019 в 02:11
поделиться

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

Billy O'Neal - в чем разница между выделением большого буфера и использованием только небольшой его части и использованием динамически выделяемой вещи, такой как вектор, выражаясь низким языком? Как только большой буфер был выделен - никто не беспокоится о неиспользуемом материале. Никаких дополнительных операций поддержки не требуется. В то время как для динамических вещей, таких как вектор, требуется постоянная проверка границ памяти, чтобы не выходить за ее пределы. Помните, что программисты на C++ не только ленивы (что очень верно, я признаю), но и умны.

0
ответ дан 8 December 2019 в 02:11
поделиться

Как насчет этого:

for(sqrti = 1; sqrti <= 11112; sqrti++) {
  int nexti = (1+sqrti)*(1+sqrti)
  for (i = sqrti*sqrti; i < nexti; i++)
  {
    int isprime = 1;
    for(j = 2; j < sqrti; j++) 
        if(!(i%j)) {
      isprime = 0;
      break;
    }
  }

} countprimes+= isprime; }

0
ответ дан 8 December 2019 в 02:11
поделиться

Это устойчивый миф, что JIT-компилятор в управляемом коде генерирует машинный код, который намного менее эффективен, чем тот, который генерируется компилятором C/C++. Управляемый код обычно выигрывает в управлении памятью и математике с плавающей запятой, C/C++ обычно выигрывает, когда оптимизатор кода может потратить гораздо больше времени на оптимизацию кода. В целом, управляемый код составляет около 80%, но это полностью зависит от тех 10% кода, где программа проводит 90% своего времени.

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

2
ответ дан 8 December 2019 в 02:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: