2011-01-12 35 views
7

Tôi hiện đang làm việc trên một ứng dụng chịu trách nhiệm tính toán hoán vị ngẫu nhiên của một mảng răng cưa.Cách cực kỳ nhanh chóng để sao chép các giá trị của một mảng răng cưa vào một mảng thứ hai?

Hiện tại, phần lớn thời gian trong ứng dụng được sử dụng để sao chép mảng trong mỗi lần lặp (tổng số 1 triệu lần lặp). Trên hệ thống hiện tại của tôi, toàn bộ quá trình mất 50 giây để hoàn thành, 39 trong số những giây đó đã nhân bản mảng đó.

mảng My nhân bản thường xuyên như sau:

public static int[][] CopyArray(this int[][] source) 
    { 
     int[][] destination = new int[source.Length][]; 
     // For each Row 
     for (int y = 0; y < source.Length; y++) 
     { 
      // Initialize Array 
      destination[y] = new int[source[y].Length]; 
      // For each Column 
      for (int x = 0; x < destination[y].Length; x++) 
      { 
       destination[y][x] = source[y][x]; 
      } 
     } 
     return destination; 
    } 

Có cách nào, an toàn hoặc không an toàn, để đạt được tác dụng tương tự như trên, nhanh hơn nhiều?

+1

Bạn đã cố sử dụng các mảng đa chiều thay vì các mảng có răng cưa, tức là 'static int [,]' thay vì 'static int [] []'? –

Trả lời

17

Một trong hai cách này sẽ phù hợp với bạn. Cả hai đều chạy trong khoảng thời gian tương tự và cả hai đều nhanh hơn nhiều so với phương pháp của bạn.

// 100 passes on a int[1000][1000] set size 

// 701% faster than original (14.26%) 
static int[][] CopyArrayLinq(int[][] source) 
{ 
    return source.Select(s => s.ToArray()).ToArray(); 
} 

// 752% faster than original (13.38%) 
static int[][] CopyArrayBuiltIn(int[][] source) 
{ 
    var len = source.Length; 
    var dest = new int[len][]; 

    for (var x = 0; x < len; x++) 
    { 
     var inner = source[x]; 
     var ilen = inner.Length; 
     var newer = new int[ilen]; 
     Array.Copy(inner, newer, ilen); 
     dest[x] = newer; 
    } 

    return dest; 
} 
+0

Như một cứu trợ cho tôi để tìm thấy điều này: btw, có vẻ khá dễ dàng để mở rộng này để kích thước hơn: return source.Select (s => s.Select (p => p.ToArray()). ToArray()). ToArray(); –

0

Bạn đã xem phương pháp C# Array.Clone chưa?

Chỉnh sửa: Thực ra, tôi tin rằng Array.Copy có thể hiệu quả hơn/nhanh hơn cho nhu cầu của bạn.

tôi đã thực hiện một thử nghiệm nhanh và có vẻ như tất cả thay đổi đến đích không ảnh hưởng đến nguồn:

int[] source = new int[3]{1,2,3}; 
int[] destination = new int[source.Length]; 
Array.Copy(source, destination, source.Length); 
destination[0]++; // or destination[0] = destination[0] + 1; 

kết quả trong:

 source = { 1 , 2 , 3 } 
destination = { 2, 2, 3 } 

Có phải đó là kết quả bạn đang tìm kiếm?

public static int[][] CopyArray(int[][] source) 
     { 
      int[][] destination = new int[source.Length][]; 
      Array.Copy(source, destination, source.Length); 
      return destination; 
     } 

về cơ bản sẽ hoàn thành những gì bạn đang tìm kiếm mà tôi tin tưởng.

+3

Điều này sẽ tạo tham chiếu đến mảng ban đầu. Sử dụng Array.Copy, và sau đó sửa đổi một giá trị trong mảng được sao chép, cũng sẽ làm cho mảng ban đầu được sửa đổi. –

0

cách tuần tự hóa/deserializing mảng, nếu bạn sử dụng luồng bộ nhớ và tuần tự nhị phân, tôi nghĩ rằng nó nên được khá nhanh chóng.

+2

Việc tuần tự hóa có thể là các đơn đặt hàng có cường độ chậm hơn so với triển khai hiện tại của anh ấy. –

0

Bạn có thể sử dụng Array.Clone cho vòng lặp bên trong:

public static int[][] CopyArray(this int[][] source) 
{ 
    int[][] destination = new int[source.Length][]; 
    // For each Row 
    for(int y = 0;y < source.Length;y++) 
    { 
     destination[y] = (int[])source[y].Clone(); 
    } 
    return destination; 
} 

Một thay thế cho các vòng lặp bên trong là Buffer.BlockCopy, nhưng tôi đã không đo hiệu suất của nó chống lại Array.Clone - có lẽ đó là nhanh hơn:

destination[y] = new int[source[y].Length]; 
Buffer.BlockCopy(source[y], 0, destination[y], 0, source[y].Length * 4); 

Chỉnh sửa: Buffer.BlockCopy lấy số cho byte để sao chép tham số đếm, chứ không phải số phần tử mảng.

+0

Tôi đã thử giải pháp đầu tiên của bạn. Thật không may, nó chỉ cạo một vài giây trong toàn bộ thời gian chạy. Tôi sẽ thử giải pháp thứ hai của bạn. –

+0

Tùy chọn thứ hai của bạn khá dễ so sánh với tùy chọn đầu tiên. Chỉ cạo một hoặc hai giây trong tổng thời gian so với phương pháp ban đầu của tôi. –

0

Cách sao chép các đối tượng nhanh hơn là không sao chép tất cả - bạn có cân nhắc tùy chọn này không? Nếu bạn chỉ cần tạo các hoán vị, bạn không cần phải sao chép dữ liệu trên mỗi hoán vị - chỉ cần thay đổi mảng. Cách tiếp cận này sẽ không hoạt động tốt nếu bạn cần giữ kết quả của các cuộc gọi trước đó. Trong mọi trường hợp, hãy xem lại mã của bạn để xem liệu bạn có đang sao chép dữ liệu nhiều lần mà bạn phải thực hiện hay không.

+0

Tôi cần các bản sao riêng biệt của mảng, vì mỗi hoán vị cần phải có một bộ làm việc gốc. –

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