c# - C++ 数组 vs C# ptr 速度混淆

标签 c# c++ arrays performance

我正在用 C# 重写一个高性能 C++ 应用程序。 C# 应用程序明显比 C++ 原始版本慢。分析告诉我,C# 应用程序将大部分时间花在访问数组元素上。因此我创建了一个简单的数组访问基准。我得到的结果与 others doing a similiar comparison 完全不同.

C++代码:

#include <limits>
#include <stdio.h>
#include <chrono>
#include <iostream>

using namespace std;
using namespace std::chrono;

int main(void)
{
    high_resolution_clock::time_point t1 = high_resolution_clock::now();

    int xRepLen = 100 * 1000;
    int xRepCount = 1000;

    unsigned short * xArray = new unsigned short[xRepLen];
    for (int xIdx = 0; xIdx < xRepLen; xIdx++)
        xArray[xIdx] = xIdx % USHRT_MAX;

    int * xResults = new int[xRepLen];

    for (int xRepIdx = 0; xRepIdx < xRepCount; xRepIdx++)
    {

        // in each repetition, find the first value, that surpasses xArray[xIdx] + 25 - i.e. we will perform 25 searches
        for (int xIdx = 0; xIdx < xRepLen; xIdx++)
        {
            unsigned short xValToBreach = (xArray[xIdx] + 25) % USHRT_MAX;
            xResults[xIdx] = 0;

            for (int xIdx2 = xIdx + 1; xIdx2 < xRepLen; xIdx2++)
            if (xArray[xIdx2] >= xValToBreach)
            {
                xResults[xIdx] = xIdx2; break;
            }

            if (xResults[xIdx] == 0)
                xResults[xIdx] = INT_MAX;
        }
    }

    high_resolution_clock::time_point t2 = high_resolution_clock::now();
    auto duration = duration_cast<milliseconds>(t2 - t1).count();
    cout << "Elasped miliseconds " << duration;
    getchar();
}

C#代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace arrayBenchmarkCs
{
    class Program
    {
        public static void benchCs()
        {
            unsafe
            {
                int xRepLen = 100 * 1000;
                int xRepCount = 1000;

                ushort[] xArr = new ushort[xRepLen];
                for (int xIdx = 0; xIdx < xRepLen; xIdx++)
                    xArr[xIdx] = (ushort)(xIdx % 0xffff);

                int[] xResults = new int[xRepLen];

                Stopwatch xSw = new Stopwatch(); xSw.Start();
                fixed (ushort * xArrayStart = & xArr [0])
                {
                    for (int xRepIdx = 0; xRepIdx < xRepCount; xRepIdx++)
                    {

                        // in each repetition, go find the first value, that surpasses xArray[xIdx] + 25 - i.e. we will perform 25 searches
                        ushort * xArrayEnd = xArrayStart + xRepLen;
                        for (ushort* xPtr = xArrayStart; xPtr != xArrayEnd; xPtr++)
                        {
                            ushort xValToBreach = (ushort)((*xPtr + 25) % 0xffff);
                            int xResult = -1;
                            for (ushort * xPtr2 = xPtr + 1; xPtr2 != xArrayEnd; xPtr2++)
                                if ( *xPtr2  >= xValToBreach)
                                {
                                    xResult = (int)(xPtr2 - xArrayStart);
                                    break;
                                }

                            if (xResult == -1)
                                xResult = int.MaxValue;

                            // save result
                            xResults[xPtr - xArrayStart] = xResult;
                        }
                    }
                }   // fixed

                xSw.Stop();

                Console.WriteLine("Elapsed miliseconds: " + (xSw.ElapsedMilliseconds.ToString("0"));
            }
        }

        static void Main(string[] args)
        {
            benchCs();
            Console.ReadKey();
        }
    }
}

在我的工作计算机 (i7-3770) 上,C++ 版本比 C# 版本快大约 2 倍。在我的家用电脑 (i7-5820K) 上,C++ 比 C# 版本快 1.5 倍。两者都是在发布中衡量的。我希望通过在 C# 中使用指针,我可以避免数组边界检查,并且两种语言的性能相同。

所以我的问题如下:

  • 其他人发现 C# 的速度与 C++ 相同?
  • 如果不通过指针,我如何才能将 C# 性能提高到 C++ 级别?
  • 不同计算机上不同加速的驱动因素是什么?

非常感谢任何提示, 丹尼尔

最佳答案

您不会得到这种以 C++ 速度运算的硬核数字。使用指针算术和不安全的代码可以让您达到一定程度(如果删除不安全和固定的部分,它的速度将再次减半)。 C# 未编译为 native 代码,它运行的代码充满了额外的检查和内容。

如果您愿意使用不安全,那么真的没有什么能阻止您将 C++ 性能关键的东西编码到混合模式程序集中,并从您的 C# 胶水代码中调用它。

关于c# - C++ 数组 vs C# ptr 速度混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35649228/

相关文章:

c# - 如何安全地实现从Windows服务到公共(public)WebApi的 Multi-Tenancy 访问

c++ - 是否可以初始化未命名结构的 std::array?

c++ - 如何使用 C++ 创建文件的拷贝

将数组的一部分复制到自身?

c# - 在 Avalonia 中根据 DataContext 属性选择 DataTemplate

c# - 如何从javascript中的DirectMethod获取返回值(值类型为Ext.Net.Panel)并将其添加到Ext.Net.TabPanel?

c# - 为什么XDeclaration会忽略我设置的编码参数

c++ - 为什么此 2D vector 会导致段错误(核心已转储)

javascript - 迭代并获取字符串中每个由\n 分隔符分隔的值的元素,而不使用 split

JavaScript 匹配数组和拼接但失败