2016-06-02 26 views
8

Tôi đang tìm một cách để giữ cấu trúc mảng thưa thớt lớn 3d vào bộ nhớ mà không lãng phí nhiều bộ nhớ. Ở đây tôi đã thực hiện một thử nghiệm với các mảng của chờ đợi:Cách mảng lớn phân bổ bộ nhớ?

using System; 
using System.Diagnostics; 
using System.Runtime; 

namespace ConsoleApp4 
{ 
    public class Program 
    { 
     static Process proc = Process.GetCurrentProcess(); 
     const int MB = 1024 * 1024; 
     const int IMAX = 5; 
     const int JMAX = 100000000; 
     public static void ShowTextWithMemAlloc(string text) 
     { 
      proc.Refresh(); 
      Console.WriteLine($"{text,-30}WS64:{proc.WorkingSet64/MB,5}MB PMS64:{proc.PrivateMemorySize64/MB,5}MB"); 
      Console.ReadKey(); 
     } 
     public static void Main(string[] args) 
     { 
      Console.Write(" "); 
      ShowTextWithMemAlloc("Start."); 
      long[] lArray = new long[IMAX * JMAX]; 
      long[] l1Array = new long[IMAX * JMAX]; 
      long[] l2Array = new long[IMAX * JMAX]; 
      long[] l3Array = new long[IMAX * JMAX]; 
      ShowTextWithMemAlloc("Arrays created."); 
      lArray[IMAX * JMAX - 1] = 5000; 
      l1Array[IMAX * JMAX - 1] = 5000; 
      l2Array[IMAX * JMAX - 1] = 5000; 
      l3Array[IMAX * JMAX - 1] = 5000; 
      ShowTextWithMemAlloc("Last elements accessed."); 
      for (var i=IMAX-1; i>= 0; i--) 
      { 
       for (var j=0; j<JMAX; j++) 
       { 
        lArray[i * JMAX + j] = i * JMAX + j; 
       } 
       ShowTextWithMemAlloc($"Value for row {i} assigned."); 
      } 
      //lArray = new long[5]; 
      //l1Array = null; 
      //l2Array = null; 
      //l3Array = null; 
      //GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; 
      //GC.Collect(); 
      //ShowTextWithMemAlloc($"GC.Collect done."); 
      ShowTextWithMemAlloc("Stop."); 
     } 
    } 
} 

Nếu bạn muốn kiểm tra nó thiết lập các biến môi trường COMPlus_gcAllowVeryLargeObjects (Project Properties -> Debug) đến 1 hoặc thay đổi JMAX. Và đây là đầu ra:

Start.      WS64: 14MB PMS64: 8MB 
Arrays created.    WS64: 15MB PMS64:15360MB 
Last elements accessed.  WS64: 15MB PMS64:15360MB 
Value for row 4 assigned.  WS64: 779MB PMS64:15360MB 
Value for row 3 assigned.  WS64: 1542MB PMS64:15360MB 
Value for row 2 assigned.  WS64: 2305MB PMS64:15361MB 
Value for row 1 assigned.  WS64: 3069MB PMS64:15361MB 
Value for row 0 assigned.  WS64: 3832MB PMS64:15362MB 
Stop.       WS64: 3844MB PMS64:15325MB 

Khi tôi thấy mức tiêu thụ bộ nhớ trong Trình quản lý tác vụ giống như trong Process.WorkingSet64. Số thực là gì? Tại sao bộ nhớ được phân bổ khi gán? Là một mảng thực sự là một bộ nhớ phân bổ liên tục? Là một mảng một mảng? Người ngoài hành tinh có tồn tại không? (Kịch nhạc nền)

Episode 2: Chúng tôi làm cho một sự thay đổi nhỏ:

  //lArray[i * JMAX + j] = i * JMAX + j; 
      var x= lArray[i * JMAX + j]; 

và không có gì thay đổi (trong đầu ra). Sự khác biệt giữa tồn tại và không tồn tại ở đâu? (nhạc nền kịch tính hơn) Bây giờ chúng tôi đang chờ câu trả lời từ một trong những người bí ẩn (Họ có một số và một chữ 'k' nhỏ dưới tên của họ).

Episode 3: Một sự thay đổi:

//lArray[IMAX * JMAX - 1] = 5000; 
    //l1Array[IMAX * JMAX - 1] = 5000; 
    //l2Array[IMAX * JMAX - 1] = 5000; 
    //l3Array[IMAX * JMAX - 1] = 5000; 
    //ShowTextWithMemAlloc("Last elements accessed."); 
    long newIMAX = IMAX-3; 
    long newJMAX = JMAX/10; 
    for (var i=0; i<newIMAX; i++) 
    { 
     for (var j=0; j<newJMAX; j++) 
     { 
      lArray[i * newJMAX + j] = i * newJMAX + j; 
      //var x= lArray[i * JMAX + j]; 
     } 
     //ShowTextWithMemAlloc($"Value for row {i} assigned."); 
    } 
    ShowTextWithMemAlloc($"{newIMAX*newJMAX} values assigned."); 

Sản lượng:

Start.        WS64: 14MB PMS64: 8MB 
Arrays created.     WS64: 15MB PMS64:15369MB 
20000000 values assigned.   WS64: 168MB PMS64:15369MB 
Stop.        WS64: 168MB PMS64:15369MB 

PMS64 cho một mảng (15.369-8)/4 = 3840MB Đây không phải là thưa thớt mảng, nhưng một phần mảng đầy;). Tôi đang sử dụng đầy đủ 168MB này.

Trả lời một số câu hỏi "Tại sao bạn không sử dụng kích thước chính xác?". Bởi vì tôi không biết? Dữ liệu có thể đến từ một số SQL do người dùng xác định. "Tại sao bạn không thay đổi kích thước nó?". Thay đổi kích thước tạo một mảng mới và sao chép các giá trị. Đây là thời gian để sao chép, bộ nhớ và vào cuối GC ác đến và ăn bạn.

Tôi đã lãng phí bộ nhớ. (Tôi không nhớ. Người ngoài hành tinh ?!) Và khi có, bao nhiêu? 0, (3840-168) MB hoặc (15369-8-168) MB?

Lời kết:

Nhận xét hoặc nhận xét?

là bộ nhớ tiếp giáp thực sự là bộ nhớ tiếp giáp?

Câu trả lời có đưa ra câu trả lời không? Bí ẩn. (more music)

(Scully: Mulder, cóc chỉ rơi từ trên trời xuống Mulder:!. Tôi đoán dù họ không mở)

Cảm ơn tất cả các bạn!

+3

* Là một mảng thực sự là bộ nhớ được cấp phát liên tục? Là một mảng một mảng? Người ngoài hành tinh có tồn tại không? Vâng. Có lẽ, nhưng chúng * xa *. –

+1

Tôi nghi ngờ câu hỏi (thực sự thú vị) mà bạn có thể đã bỏ lỡ là "Bộ nhớ thực sự là bộ nhớ"? ... và có lẽ "được rồi, nhưng khi bộ nhớ là bộ nhớ, bộ nhớ tiếp giáp thực sự là bộ nhớ tiếp giáp?" - Không, tôi thực sự không biết đủ về điều này để viết một câu trả lời. – moreON

Trả lời

6

Bộ làm việc không phải là lượng bộ nhớ được cấp phát. Đó là tập hợp các trang hiện có sẵn cho quy trình. Windows thực hiện các chính sách khác nhau xung quanh đó và số lượng thường khó giải thích.

Ở đây, bộ nhớ có thể đã được yêu cầu bằng 0 từ OS. Việc truy cập đầu tiên vào một trang thực sự làm cho một trang zeroed có sẵn.

Bạn nên xem các byte riêng tư.

Bạn không thể phân bổ thưa mảng .NET. Có lẽ, bạn nên xem xét sử dụng một số cấu trúc dữ liệu cung cấp ấn tượng của một mảng thưa thớt.

Có phải mảng thực sự là bộ nhớ được cấp phát liên tục không?

Có, từ góc độ của CLR và mã .NET đang chạy. Các hệ điều hành có thể chơi thủ đoạn mặc dù như lazily lỗi trong các trang trên đọc hoặc viết đầu tiên.

Đối với "Tập 2", câu trả lời là lỗi xảy ra đối với lần đọc cũng như để ghi. Tôi không hoàn toàn theo dõi tập 3 nhưng tôi cho rằng nó chỉ chạm vào ít trang hơn.

Did I lãng phí bộ nhớ

Đây là phức tạp hơn để nói. Miễn là các trang không được chạm vào, chúng không thể chất được sử dụng. Họ có thể được sử dụng cho bộ nhớ cache tập tin ví dụ hoặc cho các chương trình làm việc khác của cư dân. Tuy nhiên, chúng được tính vào phí cam kết của hệ thống. Windows đảm bảo với bạn rằng nó có thể làm cho các trang đó có sẵn cho bạn. Bạn sẽ không hết bộ nhớ khi truy cập bộ nhớ ngẫu nhiên. Linux không đảm bảo điều đó. Nó có kẻ giết người OOM như một sự giảm nhẹ.

Trong trường hợp cực đoan, nếu bạn phân bổ 1TB như vậy, bạn cần tổng dung lượng RAM và kích thước tệp hoán trang vượt quá 1 TB, mặc dù không có khoảng trống nào có thể sẽ được sử dụng.

Cân nhắc sử dụng các tệp được ánh xạ bộ nhớ. Ở đây, các tập tin là các cửa hàng sao lưu và RAM được xử lý như một bộ nhớ cache. Điều này sẽ hành xử chính xác theo cùng một cách.

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