2016-02-26 18 views
6

Tôi đang viết lại ứng dụng C++ hiệu năng cao cho C#. Ứng dụng C# chậm hơn đáng kể so với bản gốc C++. Profiling cho tôi biết rằng ứng dụng C# dành nhiều thời gian nhất để truy cập vào các phần tử mảng. Do đó tôi tạo ra một tiêu chuẩn truy cập mảng đơn giản. Tôi nhận được kết quả hoàn toàn khác so với others doing a similiar comparison.Mảng C++ và sự nhầm lẫn tốc độ C# ptr

C++ mã:

#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# mã:

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(); 
     } 
    } 
} 

Trên máy tính công việc của tôi (i7-3770), phiên bản C++ là khoảng 2x nhanh hơn so với phiên bản C#. Trên máy tính gia đình của tôi (i7-5820K) C++ nhanh hơn phiên bản C# 1,5 lần. Cả hai đều được đo lường trong bản phát hành. Tôi hy vọng rằng bằng cách sử dụng con trỏ trong C# tôi sẽ tránh kiểm tra ranh giới mảng và hiệu suất sẽ giống nhau trong cả hai ngôn ngữ.

Vì vậy, câu hỏi của tôi như sau:

  • nhà đến những người khác đang tìm C# là có tốc độ tương tự như C++?
  • làm cách nào để có được hiệu suất C# ở cấp C++ nếu không qua con trỏ?
  • điều gì có thể là trình điều khiển các tính năng tăng tốc khác nhau trên các máy tính khác nhau?

Bất kỳ gợi ý được nhiều đánh giá, Daniel

+0

Tôi hy vọng bạn đang thực hiện điểm chuẩn mà không có trình gỡ lỗi (CTRL + F5 thay vì F5 trong Visual Studio) – xanatos

+0

@xanatos: Có. Cảm ơn cho các phím tắt mặc dù. –

+0

* ushort * xArrayEnd = xArrayStart + xRepLen; * Bạn có thể di chuyển điều này ra ngoài chu kỳ 'for' – xanatos

Trả lời

0

Bạn sẽ không nhận được loại số Hardcore crunching để ++ tốc độ C. Sử dụng số học con trỏ và mã không an toàn giúp bạn có một số cách có (nó gần như một nửa là chậm lại nếu bạn loại bỏ các phần không an toàn và cố định). C# không được biên dịch thành mã gốc, và mã mà nó đang chạy có đầy đủ các kiểm tra và nội dung bổ sung.

Nếu bạn sẵn sàng đi unsafe thì thực sự không có gì ngăn bạn mã hóa công cụ quan trọng hiệu suất C++ của bạn vào một cụm chế độ hỗn hợp và gọi từ mã keo C# của bạn.

+0

Cảm ơn bạn đã chỉ cho tôi theo hướng đó. Các bài viết (số lượng nhỏ) tôi đã đọc điểm đến thực tế là việc chuyển đổi thời gian chạy từ mã được quản lý sang không được quản lý và ngược lại là chậm. Điều đó thực sự là như vậy trong kinh nghiệm của bạn? –

+0

Nó không giống như làm điều đó một lần mất một thời gian dài, nhưng làm nó rất nhiều lần trong một vòng lặp sẽ là xấu. Lý tưởng nhất là bạn có được mọi thứ đã sẵn sàng trong C#, sau đó trao tất cả cho C++ và nó có thể làm tất cả các vòng lặp và toán học. Sau đó, nó gói các kết quả đó trở lại và bạn có thể quay trở lại tất cả các lợi ích của thế giới được quản lý, đã thực hiện các phép tính của bạn tốt đẹp và nhanh chóng. –

Các vấn đề liên quan