比较c#,c ++和java性能(c#的奇怪行为)

6 c# c++ java multithreading netbeans

我用c ++,c#和java实现Floyd-Warshall算法.每种语言中,我使用串行和并行执行测试后的结果是:
(过去时间仅供主要功能和读取文件的变量,英迪和......没有测量.)
在这里下载源 源代码

C++

  • IDE:Netbeans
  • 编译:MinGW-4.8.1
  • 顺序时间:9.333000
  • 平行时间:2.539000
  • 使用OpenMp的Prallel

if NumOfThreads= 1则是Sequential else is Parallel

变量

#define n 1000 /* Then number of nodes */
double dist[n][n];

    void floyd_warshall(int NumOfThreads) {
    int i, j, k;
         omp_set_num_threads(NumOfThreads);
    for (k = 0; k < n; ++k)
       #pragma omp parallel for private(i,j)
        for (i = 0; i < n; ++i)
            for (j = 0; j < n; ++j)
                    if ((dist[i][k] * dist[k][j] != 0) && (i != j))
                     if ((dist[i][k] + dist[k][j] < dist[i][j]) || (dist[i][j] == 0))
                        dist[i][j] = dist[i][k] + dist[k][j];    }
Run Code Online (Sandbox Code Playgroud)

java的

  • IDE:Netbeans
  • 编译器:Netbeans默认
  • 顺序时间:11.632
  • 平行时间:3.089
  • -Xms512m -Xmx1024m
  • import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Future;

java变量

 public final int numNodes =1000;

    public final double[][] costs= new double[numNodes][numNodes] ;
Run Code Online (Sandbox Code Playgroud)

我没有把java代码放在这里,因为它的工作正常(我认为)

C#

  1. IDE:Visual Studio 2012
  2. 编译器:Visual Studio 2012默认
  3. 连续时间:31.312
  4. 平行时间:8.920
  5. 使用System.Threading.Tasks;

变量

  const int n = 1000;
    static double[,] dist = new double[n, n];
Run Code Online (Sandbox Code Playgroud)

并行代码

   static  void floyd_warshall(ParallelOptions pOp)
    {
        int k;     
        for (k = 0; k < n; ++k)
            Parallel.For<int>(0, n, pOp, () => 0, (i, loop, j) =>
                {
              for (j = 0; j < n; ++j)
               if ((dist[i, k] * dist[k, j] != 0) && (i != j))
                  if ((dist[i, k] + dist[k, j] < dist[i, j]) || (dist[i, j] == 0))
                            dist[i, j] = dist[i, k] + dist[k, j];
                    return 0;
                }, (j) => { });
Run Code Online (Sandbox Code Playgroud)

单一代码

 static void floyd_warshallSingle()
  {
      int i, j, k;
      for (k = 0; k < n; ++k)
          for (i = 0; i < n; ++i)
              for (j = 0; j < n; ++j)

                  if ((dist[i,k] * dist[k,j] != 0) && (i != j))

                      if ((dist[i,k] + dist[k,j] < dist[i,j]) || (dist[i,j] == 0))
                          dist[i,j] = dist[i,k] + dist[k,j];
  }
Run Code Online (Sandbox Code Playgroud)

我的c#实现有什么问题?
所有人都使用相同的文件
我的问题是为什么用c#解决这个算法需要更多的时间?java和c ++的运行时间几乎相同,但我认为我用c#实现是错误的,因为c#和c ++之间的区别很奇怪!
请帮我改进我的C#实现或命名一些原因谢谢!

编辑1


我将我的数组更改为锯齿状数组,结果更改为:

  • 连续时间:19.22
  • 平行时间:4.903

仍然是c#和c ++或java之间的巨大差异!任何想法为什么?
新变量

const int n = 1000;
    static double[][] dist = new double[n][];
Run Code Online (Sandbox Code Playgroud)

新代码:

static void floyd_warshallSingle()
  {
      int i, j, k;
      for (k = 0; k < n; ++k)
          for (i = 0; i < n; ++i)
              for (j = 0; j < n; ++j)

                  if ((dist[i][k] * dist[k][j] != 0) && (i != j))

                      if ((dist[i][k] + dist[k][j] < dist[i][j]) || (dist[i][j] == 0))
                          dist[i][j] = dist[i][k] + dist[k][j];
  }



   static  void floyd_warshall(ParallelOptions pOp)
    {
        int k;     
        for (k = 0; k < n; ++k)
            Parallel.For<int>(0, n, pOp, () => 0, (i, loop, j) =>
                {
                    for (j = 0; j < n; ++j)
                        if ((dist[i][k] * dist[k][j] != 0) && (i != j))
                            if ((dist[i][ k] + dist[k][j] < dist[i][ j]) || (dist[i][j] == 0))
                                dist[i][ j] = dist[i][k] + dist[k][j];

                    return 0;
                }, (j) => { });
    }
Run Code Online (Sandbox Code Playgroud)

Jim*_*hel 1

确定是否是数组边界检查,或者至少确定数组边界检查是否是问题的一部分的一种方法是删除一些索引计算。例如:

    static void floyd_warshallSingle()
    {
        int i, j, k;
        for (k = 0; k < n; ++k)
        {
            var distk = dist[k];
            for (i = 0; i < n; ++i)
            {
                var disti = dist[i];
                for (j = 0; j < n; ++j)
                    if ((i != j) && (disti[k] * distk[j] != 0))
                        if ((disti[j] == 0) || disti[k] + distk[j] < disti[j])
                            disti[j] = disti[k] + distk[j];
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

这里我所做的只是用作distk对 的引用dist[k]。我怀疑编译器已经在进行这种优化,这很可能就是您从矩形数组变为锯齿状数组时实现性能增益的方式。但值得一看。

另外,您说您在没有附加调试器的情况下运行。我假设您也在运行发布版本?所有三个程序(C++、Java 和 C#)运行的位数是否相同?也就是说,它们都是 64 位可执行文件吗?所有 32 位可执行文件?使用 C# 时要小心,因为可以在项目选项中打开“首选 32 位”标志。这可能会导致您在使用“任何 CPU”进行编译时以 32 位模式运行,即使在 64 位系统上也是如此。