2011-12-30 53 views
24

Khi tôi chạy chương trình CUDA của tôi mà phân bổ chỉ một lượng nhỏ bộ nhớ toàn cầu (dưới 20 M), tôi nhận được một "ra khỏi bộ nhớ" lỗi. (Từ bài viết của người khác, tôi nghĩ rằng vấn đề là có liên quan đến sự phân mảnh bộ nhớ) Tôi cố gắng tìm hiểu vấn đề này, và nhận ra tôi có một vài câu hỏi liên quan đến quản lý bộ nhớ CUDA.Bộ nhớ CUDA được quản lý như thế nào?

  1. Có khái niệm bộ nhớ ảo trong CUDA không?

  2. Nếu chỉ có một hạt nhân được phép chạy đồng thời trên CUDA, sau khi kết thúc, tất cả bộ nhớ được sử dụng hoặc cấp phát đã được phát hành chưa? Nếu không, khi những bộ nhớ này được phát hành miễn phí?

  3. Nếu có nhiều hơn một hạt nhân được phép chạy trên CUDA, làm thế nào họ có thể chắc chắn rằng bộ nhớ họ sử dụng không trùng nhau?

Có ai giúp tôi trả lời những câu hỏi này không? Cảm ơn

Chỉnh sửa 1: hệ điều hành: x86_64 GNU/Linux Phiên bản CUDA: 4.0 Thiết bị: Geforce 200, Đây là một trong GPUS được gắn vào máy và tôi không nghĩ đó là thiết bị hiển thị.

Chỉnh sửa 2: Sau đây là những gì tôi nhận được sau khi làm một số nghiên cứu. Vui lòng sửa tôi.

  1. CUDA sẽ tạo một ngữ cảnh cho mỗi chuỗi máy chủ. Bối cảnh này sẽ tiếp tục thông tin như những phần của bộ nhớ (bộ nhớ trước khi giao hoặc bộ nhớ cấp phát động) đã được dành riêng cho ứng dụng này để ứng dụng khác không thể chỉnh sửa nó. Khi ứng dụng này kết thúc (không phải hạt nhân), phần bộ nhớ này sẽ được giải phóng.

  2. nhớ CUDA được duy trì bởi một danh sách liên kết. Khi một ứng dụng cần cấp phát bộ nhớ, nó sẽ đi qua danh sách liên kết này để xem nếu có bộ nhớ liên tục có sẵn để phân bổ. Nếu nó không tìm thấy một đoạn như vậy, lỗi "hết bộ nhớ" sẽ báo cáo cho người dùng mặc dù tổng kích thước bộ nhớ có sẵn lớn hơn bộ nhớ được yêu cầu. Và đó là vấn đề liên quan đến phân mảnh bộ nhớ.

  3. cuMemGetInfo sẽ cho bạn biết số lượng bộ nhớ là miễn phí, nhưng không nhất thiết bạn có thể phân bổ bộ nhớ trong phân bổ tối đa do phân mảnh bộ nhớ.

  4. Trên nền tảng Vista (WDDM), có thể thực hiện ảo hóa bộ nhớ GPU. Đó là, nhiều ứng dụng có thể phân bổ gần như toàn bộ bộ nhớ GPU và WDDM sẽ quản lý trao đổi dữ liệu trở lại bộ nhớ chính.

câu hỏi mới: 1. Nếu bộ nhớ dành riêng trong bối cảnh sẽ được phát hành đầy đủ sau khi ứng dụng đã được chấm dứt, phân mảnh bộ nhớ nên không tồn tại. Phải có một số loại dữ liệu còn lại trong bộ nhớ. 2. Có cách nào để cơ cấu lại bộ nhớ GPU không?

+0

Bạn có thể chỉnh sửa câu hỏi để bao gồm hệ điều hành, phiên bản GPU và cuda nào bạn đang sử dụng hay không và liệu GPU có phải là thiết bị hiển thị hay không hiển thị hay không. Nó sẽ mang một câu trả lời đúng cho câu hỏi của bạn. – talonmies

+0

Để trả lời các câu hỏi phụ - phân mảnh có thể quan sát được xảy ra * trong ngữ cảnh *, và không có cách nào thay đổi ánh xạ bộ nhớ trong GPU, tất cả được xử lý bởi trình điều khiển máy chủ. – talonmies

+0

Khi bạn giải thích, phân bổ ngữ cảnh bao gồm phân bổ tĩnh ngữ cảnh, phân bổ người dùng ngữ cảnh và vùng thời gian chạy ngữ cảnh CUDA. Tôi nghĩ rằng kích thước của phân bổ tĩnh ngữ cảnh và phân bổ người dùng ngữ cảnh được quyết định trước. Vì vậy, tôi nghĩ nguyên nhân duy nhất của sự phân mảnh bộ nhớ là heap thời gian chạy theo ngữ cảnh chỉ dựa trên kiến ​​trúc Fermi. Đúng không? Tôi đoán hệ thống sẽ phân bổ trước một đoạn bộ nhớ cho heap thời gian chạy theo ngữ cảnh để phân bổ bộ nhớ động trong hạt nhân được kích hoạt. – xhe8

Trả lời

24

Bộ nhớ thiết bị có sẵn để mã của bạn trong thời gian chạy được về cơ bản tính như

Free memory = total memory 
       - display driver reservations 
       - CUDA driver reservations 
       - CUDA context static allocations (local memory, constant memory, device code) 
       - CUDA context runtime heap (in kernel allocations, recursive call stack, printf buffer, only on Fermi and newer GPUs) 
       - CUDA context user allocations (global memory, textures) 

nếu bạn đang nhận được một ra thông điệp bộ nhớ, sau đó có khả năng là một hoặc nhiều trong số ba mục đầu tiên đang tiêu thụ hầu hết bộ nhớ GPU trước khi mã người dùng của bạn cố gắng lấy bộ nhớ trong GPU. Nếu, như bạn đã chỉ ra, bạn không chạy trên GPU hiển thị, thì ngữ cảnh phân bổ tĩnh là nguồn có khả năng nhất của vấn đề của bạn. CUDA hoạt động bằng cách phân bổ trước tất cả bộ nhớ mà bối cảnh yêu cầu tại thời điểm ngữ cảnh được thiết lập trên thiết bị. Có rất nhiều thứ được phân bổ để hỗ trợ ngữ cảnh, nhưng người tiêu dùng lớn nhất trong ngữ cảnh là bộ nhớ cục bộ. Thời gian chạy phải đặt trước số lượng bộ nhớ cục bộ tối đa mà bất kỳ hạt nhân nào trong ngữ cảnh sẽ tiêu thụ cho số chuỗi tối đa mà mỗi bộ xử lý đa có thể chạy đồng thời, cho mỗi bộ xử lý trên thiết bị. Điều này có thể chạy vào hàng trăm MB bộ nhớ nếu một hạt nhân bộ nhớ cục bộ nặng được tải trên một thiết bị với rất nhiều bộ xử lý đa.

Cách tốt nhất để xem điều gì có thể xảy ra là viết chương trình máy chủ không có mã thiết bị để thiết lập ngữ cảnh và gọi cudaMemGetInfo. Điều đó sẽ cho bạn biết dung lượng bộ nhớ mà thiết bị có với chi phí ngữ cảnh tối thiểu trên đó. Sau đó, bạn chạy mã có vấn đề, thêm cùng một cuộc gọi cudaMemGetInfo trước cuộc gọi cudaMalloc đầu tiên sau đó sẽ cung cấp cho bạn lượng bộ nhớ mà bối cảnh của bạn đang sử dụng. Điều đó có thể cho phép bạn có được một xử lý của nơi bộ nhớ đang đi. Rất khó phân mảnh đó là vấn đề nếu bạn gặp sự cố trong cuộc gọi cudaMalloc đầu tiên.

+0

tài năng, cảm ơn thông tin của bạn. Nó rất hữu ích. Một câu hỏi nữa, liệu có thể có nhiều bối cảnh tồn tại trong bộ nhớ thiết bị? – xhe8

+0

Có thể, nhưng một chuỗi nhất định chỉ có thể chứa một ngữ cảnh duy nhất trên một thiết bị cụ thể. Kịch bản thông thường sẽ là hai quá trình cố gắng chạy trên cùng một GPU cùng một lúc hoặc một ứng dụng đa luồng mở hai bối cảnh với hai luồng. Sau này là khó khăn hơn để làm trong CUDA 4 hơn nó được sử dụng để được. – talonmies

+0

Vậy cơ chế nào được sử dụng để cấp phát bộ nhớ cho nhiều ngữ cảnh? Làm thế nào hệ thống có thể đảm bảo các bối cảnh khác nhau sẽ được phân bổ phần bộ nhớ khác nhau? – xhe8

4
  1. Bộ nhớ ngoài chip GPU được phân tách trong bộ nhớ cục bộ, cục bộ và không đổi. Ba loại bộ nhớ này là một khái niệm bộ nhớ ảo. Toàn bộ bộ nhớ là miễn phí cho tất cả các chủ đề, địa phương chỉ dành cho một chủ đề (chủ yếu được sử dụng để đăng ký tràn) và bộ nhớ liên tục được lưu trữ bộ nhớ toàn cục (chỉ có thể ghi từ mã máy chủ). Hãy xem 5.3.2 từ Hướng dẫn lập trình CUDA C.

  2. EDIT: loại bỏ

  3. Memory phân bổ qua cudaMalloc không bao giờ chồng lên nhau. Đối với bộ nhớ, hạt nhân cấp phát trong suốt thời gian chạy phải đủ bộ nhớ. Nếu bạn đã hết bộ nhớ và cố gắng khởi động hạt nhân (chỉ có đoán từ tôi), bạn sẽ nhận được thông báo lỗi "lỗi không xác định". Trình điều khiển hơn là không thể khởi động và/hoặc thực thi hạt nhân.

+0

Cảm ơn bạn đã trả lời. Nhưng tôi nghĩ rằng tôi muốn giải thích mức độ thấp hơn. Tôi đã học được từ các bài viết khác rằng việc quản lý bộ nhớ CUDA có điều gì đó để đối phó với các ngữ cảnh và một số cấu trúc dữ liệu, nhưng tôi muốn giải thích nhiều hơn để tôi có thể tìm ra vấn đề bộ nhớ trong chương trình của mình. – xhe8

+0

Câu trả lời thứ hai của bạn phần lớn là sai. Bộ nhớ phạm vi hạt nhân được * phân bổ trước * tại thời điểm ngữ cảnh được thiết lập trên một thiết bị. Nội dung của bộ nhớ cục bộ chỉ hợp lệ trong thời gian chạy hạt nhân, nhưng chính bộ nhớ được dành riêng khi bối cảnh được thiết lập. Bộ nhớ động được cấp phát từ một đống thời gian chạy cũng được bảo lưu trong bối cảnh thời gian thiết lập ngữ cảnh và nó vẫn có thể truy cập và hợp lệ cho cuộc sống của ngữ cảnh, chứ không phải hạt nhân. Có một cuộc gọi API để thao tác kích thước heap khi chạy từ kích thước mặc định, nếu được yêu cầu. – talonmies

+0

@talonmies cảm ơn vì đã sửa tôi –

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