2009-06-23 36 views
7

Bối cảnh: Tôi đang viết một chương trình C++ làm việc với số lượng lớn dữ liệu địa lý và muốn tải các khối lớn để xử lý tại một lần duy nhất. Tôi bị ràng buộc làm việc với một ứng dụng được biên dịch cho các máy 32 bit. Máy tôi đang thử nghiệm đang chạy một hệ điều hành 64 bit (Windows 7) và có 6 gig ram. Sử dụng MS VS 2008.Bạn có thể phân bổ bộ nhớ bao nhiêu bộ nhớ?

Tôi có đoạn mã sau:

byte* pTempBuffer2[3]; 
try 
{ 
    //size_t nBufSize = nBandBytes*m_nBandCount; 
    pTempBuffer2[0] = new byte[nBandBytes]; 
    pTempBuffer2[1] = new byte[nBandBytes]; 
    pTempBuffer2[2] = new byte[nBandBytes]; 
} 
catch (std::bad_alloc) 
{ 
    // If we didn't get the memory just don't buffer and we will get data one 
    // piece at a time. 
    return; 
} 

Tôi đã hy vọng rằng tôi sẽ có thể cấp phát bộ nhớ cho đến khi ứng dụng đạt đến giới hạn 4 GB 32 bit địa chỉ. Tuy nhiên, khi nBandBytes là 466,560,000 thì lệnh ném mới std :: bad_alloc trong lần thử thứ hai. Ở giai đoạn này, giá trị bộ nhớ (làm việc) cho quá trình này là 665,232 K Vì vậy, tôi dường như không thể có được một bộ nhớ được phân bổ.

Đã có một số đề cập đến giới hạn 2 gig cho các ứng dụng trong Windows 32 bit có thể được mở rộng đến 3 gig với khóa chuyển đổi/3 GB cho win32. Đây là lời khuyên tốt trong môi trường đó, nhưng không liên quan đến trường hợp này.

Bạn có thể cấp bộ nhớ bao nhiêu trong hệ điều hành 64 bit với ứng dụng 32 bit?

+0

Tôi đã tìm thấy tài liệu tham khảo này trên web: "Nếu bạn đang chạy dưới dạng ứng dụng 32 bit trên hệ điều hành 64 bit thì bạn sẽ nhận được tất cả không gian địa chỉ 4G và tất cả có thể được hỗ trợ bởi bộ nhớ vật lý (nếu bạn có RAM) ngay cả khi bạn không sử dụng các con trỏ 64 bit. " từ blog: http://blogs.msdn.com/ricom/archive/2009/06/10/visual-studio-why-is-there-no-64-bit-version.aspx – Bill

+0

Trên máy 32 bit của tôi, tôi có thể phân bổ 466.560.000 × 3 byte trong thử nghiệm đơn giản. Dường như bộ nhớ quá trình đã bị phân mảnh tại điểm phân bổ trong trường hợp của bạn. –

+1

Tôi gặp khó khăn khi chọn câu trả lời để đánh dấu đúng vào câu hỏi này. Tôi tin rằng câu trả lời là phức tạp và phụ thuộc vào nhiều yếu tố. Các tệp ánh xạ bộ nhớ là một câu trả lời hay, nhưng nguyên nhân gốc rễ của vấn đề này dường như là phân mảnh bộ nhớ. bke1 chỉ ra các công cụ tốt để xem bộ nhớ, và nhiều người đã nói về phân mảnh bộ nhớ, nhưng tôi chọn câu trả lời đầu tiên đã nêu rõ vấn đề và đưa ra giới hạn cứng (4 Gig dưới 64 bit và cờ phải.) – Bill

Trả lời

10

Nhiều như hệ điều hành muốn cung cấp cho bạn. Theo mặc định, Windows cho phép quy trình 32 bit có 2GB không gian địa chỉ. Và điều này được chia thành nhiều phần. Một khu vực được đặt sang một bên cho ngăn xếp, những vùng khác cho mỗi tệp thi hành và dll được tải. Bất kỳ thứ gì còn lại đều có thể được phân bổ động, nhưng không có gì đảm bảo rằng nó sẽ là một phần tiếp giáp lớn. Nó có thể là một số phần nhỏ hơn của một vài trăm MB mỗi.

Nếu bạn biên dịch với cờ LARGEADDRESSAWARE, Windows 64-bit sẽ cho phép bạn sử dụng không gian địa chỉ 4GB đầy đủ, mà nên giúp một chút, nhưng nhìn chung,

  • bạn không nên giả định rằng có sẵn bộ nhớ là tiếp giáp. Bạn có thể làm việc với nhiều phân bổ nhỏ hơn thay vì một vài phân bổ lớn hơn và
  • Bạn nên biên dịch nó dưới dạng ứng dụng 64 bit nếu bạn cần nhiều bộ nhớ.
+0

"bạn không nên giả định rằng bộ nhớ có sẵn là tiếp giáp. Bạn sẽ có thể làm việc với nhiều phân bổ nhỏ hơn thay vì một vài cái lớn, và" Điều này là sai khi cửa sổ sử dụng bộ nhớ phân trang và ứng dụng nó tiếp giáp với một chunk lớn – Lodle

+1

Lodle, bạn đang bối rối không gian địa chỉ và không gian địa chỉ miễn phí. Ví dụ. một trong những dạng phân mảnh phổ biến nhất là do chính mã của bạn gây ra. EXE và DLL không tải bắt đầu từ 0x00000000. – MSalters

+0

@Lodle: Không, ứng dụng nhìn thấy một không gian địa chỉ tiếp giáp, nhưng các biến exe, dll, stack và static đều được tải tại các địa chỉ khác nhau trong không gian địa chỉ đó. – jalf

6

trên cửa sổ 32 bit, quy trình bình thường có thể mất tối đa 2 GB, nhưng với khóa chuyển đổi /3GB có thể đạt tới 3 GB (đối với cửa sổ 2003).

nhưng trong trường hợp của bạn, tôi nghĩ bạn đang phân bổ bộ nhớ tiếp giáp và do đó ngoại lệ đã xảy ra.

+3

+1 - không bao giờ được coi là thực tế là phân bổ một mảng liền kề chỉ có thể cung cấp cho bạn số tiền lớn nhất của bộ nhớ "liền kề" miễn phí! Điểm thực sự tốt. –

+1

Nút chuyển đổi/3GB hơi nguy hiểm. Nhiều trình điều khiển không được kiểm tra với công tắc, vì vậy chúng có thể trở nên không ổn định khi hệ điều hành bị giới hạn ở mức 1 GB. Mặc dù vậy, nó không quan trọng, vì anh ta đang chạy trên một Windows 64-bit. – jalf

+1

Để giúp tôi hiểu bạn nói gì, tôi sẽ cố gắng và diễn đạt lại nó. Bạn có nói rằng nếu tôi phân bổ bộ nhớ trong các khối nhỏ hơn tôi sẽ có thể nhận được tổng số bộ nhớ được phân bổ? – Bill

1

Với nBandBytes ở 466.560.000, bạn đang cố gắng phân bổ 1,4 GB. Một ứng dụng 32 bit thường chỉ có quyền truy cập vào 2 GB bộ nhớ (nhiều hơn nếu bạn khởi động với/3GB và tệp thực thi được đánh dấu là không gian địa chỉ lớn nhận biết). Bạn có thể khó khăn để tìm thấy rằng nhiều khối không gian địa chỉ liền kề cho khối lượng lớn bộ nhớ của bạn.

Nếu bạn muốn phân bổ gigabyte bộ nhớ trên hệ điều hành 64 bit, hãy sử dụng quy trình 64 bit.

+0

Bạn nhận được 1.4GB như thế nào? Bạn có giả định một byte là 4 byte? : p – jalf

+0

3 * 466.560.000. Anh ấy đang phân bổ 3 mảng. – Michael

+0

Đúng, tôi đã hy vọng có thể phân bổ 1,3 GB bộ nhớ, và đã rất ngạc nhiên khi tôi không thể. – Bill

1

Bạn có thể phân bổ tổng cộng khoảng 2GB cho mỗi quy trình. This article (PDF) giải thích chi tiết. Tuy nhiên, bạn có thể sẽ không thể có được một khối liền kề duy nhất thậm chí gần với khối lớn đó.

1

Thậm chí nếu bạn phân bổ theo khối nhỏ hơn, bạn không thể nhận được bộ nhớ mình cần, đặc biệt nếu chương trình xung quanh có hành vi bộ nhớ không thể đoán trước hoặc nếu bạn cần chạy trên các hệ điều hành khác nhau. Theo kinh nghiệm của tôi, không gian heap trên một quá trình 32-bit mũ vào khoảng 1.2GB.

Với số lượng bộ nhớ này, tôi khuyên bạn nên viết thủ công vào đĩa. Quấn mảng của bạn vào một lớp quản lý bộ nhớ và ghi vào các tệp tạm thời khi cần thiết. Hy vọng rằng các đặc điểm của chương trình của bạn là như vậy mà bạn có hiệu quả có thể bộ nhớ cache các phần của dữ liệu mà không cần nhấn đĩa quá nhiều.

4

Bạn có thể phân bổ bộ nhớ nhiều như tệp trang của bạn sẽ cho phép bạn - ngay cả khi không có nút chuyển đổi/3GB, bạn có thể cấp 4GB bộ nhớ mà không gặp nhiều khó khăn.

Đọc this article để biết tổng quan tốt về cách suy nghĩ về bộ nhớ vật lý, bộ nhớ ảo và không gian địa chỉ (cả ba đều là những thứ khác nhau). Tóm lại, bạn có chính xác bộ nhớ vật lý nhiều như RAM, nhưng ứng dụng của bạn thực sự không tương tác với bộ nhớ vật lý đó - nó chỉ là một nơi thuận tiện để lưu trữ dữ liệu trong bộ nhớ ảo của bạn. Bộ nhớ ảo của bạn bị giới hạn bởi kích thước tệp trang của bạn và số tiền mà ứng dụng của bạn có thể sử dụng bị giới hạn bởi số lượng ứng dụng khác đang sử dụng (mặc dù bạn có thể phân bổ nhiều hơn, cung cấp cho bạn thực sự không sử dụng ứng dụng đó). Không gian địa chỉ của bạn trong thế giới 32 bit là 4GB. Trong số đó, 2 GB được cấp cho hạt nhân (hoặc 1GB nếu bạn sử dụng công tắc/3BG). Trong số 2GB còn lại, một số sẽ được sử dụng hết bởi ngăn xếp của bạn, một số chương trình bạn đang chạy, (và tất cả các dll, v.v.). Nó sẽ bị phân mảnh, và bạn sẽ chỉ có thể nhận được rất nhiều không gian tiếp giáp - đây là nơi phân bổ của bạn không thành công. Nhưng vì không gian địa chỉ đó chỉ là một cách thuận tiện để truy cập vào bộ nhớ ảo mà bạn đã cấp phát cho bạn, bạn có thể phân bổ bộ nhớ nhiều hơn và mang từng phần của nó vào không gian địa chỉ của bạn một vài lần.

Raymond Chen has an example cách phân bổ bộ nhớ 4GB và phần bản đồ của nó vào một phần không gian địa chỉ của bạn.

Trong Windows 32 bit, phân bổ tối đa là 16TB và 256TB trong Windows 64 bit.

Và nếu bạn thực sự hiểu cách hoạt động của quản lý bộ nhớ trong Windows, hãy đọc this article.

2

Trong dự án ElephantsDream, Blender Foundation với Blender 3D có các vấn đề tương tự (mặc dù trên Mac). Không thể bao gồm liên kết nhưng vấn đề phân bổ bộ nhớ google: blender3d và nó sẽ là mục đầu tiên.

Giải pháp liên quan đến Lập bản đồ tệp. Bản thân bạn chưa thử bản thân ở đây: http://msdn.microsoft.com/en-us/library/aa366556(VS.85).aspx

1

Sysinternals VMMap là điều tuyệt vời để điều tra phân mảnh không gian địa chỉ ảo, có thể hạn chế số lượng bộ nhớ tiếp giáp mà bạn có thể phân bổ. Tôi khuyên bạn nên đặt nó để hiển thị không gian trống, sau đó sắp xếp theo kích thước để tìm các khu vực miễn phí lớn nhất, sau đó sắp xếp theo địa chỉ để xem những gì đang tách biệt với các khu vực miễn phí lớn nhất (có thể là các DLL bị xóa, vùng nhớ chia sẻ hoặc các vùng khác).

Tránh phân bổ tiếp giáp rất lớn có thể là tốt nhất, như những người khác đã đề xuất.

Đặt LARGE_ADDRESS_AWARE=YES (như được đề xuất) là tốt, miễn là các thư viện mà ứng dụng của bạn phụ thuộc tương thích với nó. Nếu bạn làm như vậy, bạn nên kiểm tra mã của mình bằng khóa đăng ký AllocationPreference được đặt để bật phân bổ địa chỉ ảo từ trên xuống.

+0

Ý tưởng hay - Tôi sẽ thử VMMap. – Bill

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