c++ and c# speed compared

2020-07-11 07:39发布

I was worried about C#'s speed when it deals with heavy calculations, when you need to use raw CPU power.

I always thought that C++ is much faster than C# when it comes to calculations. So I did some quick tests. The first test computes prime numbers < an integer n, the second test computes some pandigital numbers. The idea for second test comes from here: Pandigital Numbers

C# prime computation:

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++ variant:

#include <iostream>
#include <ctime>
#include <cmath>

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 "<<res<<" prime numbers between 1 and "<<n<<" in "<<tprime<<" msecs.";
 return 0;
}

When I ran the test trying to find primes < than 100,000, C# variant finished in 0.409 seconds and C++ variant in 0.614 seconds. When I ran them for 1,000,000 C# finished in 6.039 seconds and C++ in about 12.987 seconds.

Pandigital test in 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 test in C++:

#include <iostream>
#include <ctime>

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:"<<pans<<" time:"<<ptime;  
   return 0;
}

C# variant runs in 29.906 seconds and C++ in about 36.298 seconds.

I didn't touch any compiler switches and both C# and C++ programs were compiled with debug options. Before I attempted to run the test I was worried that C# will lag well behind C++, but now it seems that there is a pretty big speed difference in C# favor.

Can anybody explain this? C# is jitted and C++ is compiled native so it's normal that a C++ will be faster than a C# variant.

Thanks for the answers!

I've redid all tests for the Release configuration.

First test (prime numbers)

C# (numbers < 100,0000): 0.189 seconds C++ (numbers < 100,0000): 0.036 seconds

C# (nummbers < 1,000,000): 5.300 seconds C++ (nummbers < 1,000,000): 1.166 seconds

Second test (pandigital numbers):

C#: 21.224 seconds C++: 4.104 seconds

So, everytthing have changed, now C++ is much faster. My mistake is that I've ran the test for Debug configuration. Can I see some speed improvement if I ran the C# executables through ngen?

The reason I tried to compare C# and C++ is because I know some basics of both and I wanted to learn an API dealing with GUI. I was thinking that WPF is nice so given that I'm targeting the desktop, I wanted to see if C# can deliver enough speed and performance when it comes to use sheer CPU power to compute various calculations (file archivers, cryptography, codecs etc). But it seems that sadly C# can't keep pace with C++ when it comes to speed.

So, I'm assuming I will be forever stuck with this question Tough question on WPF, Win32, MFC, and I'll newer find an suitable API.

10条回答
乱世女痞
2楼-- · 2020-07-11 08:18

Why would you assume that jitted code is slower than native code? The only speed penalty would be the actual jitting, which only happens once (generally speaking). Given a program with a 30-second running time, we are talking about a minuscule portion of the total cost.

I think you may be confusing jitted code with interpreted code, which is compiled line-by-line. There's a pretty significant difference between the two.

As others have pointed out, you also need to run this in release mode; debug mode turns off most optimizations, so both versions will be slower than they should be (but by different amounts).

Edit - I should point out one other thing, which is that this line:

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

Is incredibly inefficient and may interfere with the benchmarking. You should be calculating Math.Sqrt(i) outside of the inner loop. It's possible that this will slow down both versions by an equivalent amount, but I'm not sure, different compilers will perform different optimizations.

查看更多
仙女界的扛把子
3楼-- · 2020-07-11 08:18

It's taking so much longer because the algorithm is wrong.

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

is the same as

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

is the same as

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

i is a lot bigger than sqrt(i). Looking at just running time, it's an order of magnitude larger that it should be in the C++ implementation.

Also, like everybody else is saying, I don't think it makes sense to do performance testing in debug mode.

查看更多
Evening l夕情丶
4楼-- · 2020-07-11 08:20

You need to compile C++ in release mode and enable optimiziations to get the performance results you are looking for.

查看更多
神经病院院长
5楼-- · 2020-07-11 08:20

Both tests are invalid because you've compiled without optimizations.

The first test is meaningless even as a comparrison of unoptimized behaviour, because of an error in your code; Math.Sqrt(i) returns the square root of i, i^(1/2) returns i - so the C++ is doing much more work than the C#.

More generally, this isn't a useful thing to do - you're trying to create a synthetic benchmark that has little to no relevence to real world usage.

查看更多
登录 后发表回答