2012-05-01 23 views
8

Tôi đang cố gắng phân bổ bộ nhớ thiết bị, sao chép vào nó, thực hiện các tính toán trên GPU, sao chép kết quả lại và sau đó giải phóng bộ nhớ thiết bị mà tôi đã cấp phát. Tôi muốn chắc chắn rằng tôi đã không vượt quá giới hạn và tôi muốn xem liệu tôi có đủ bộ nhớ trong không gian bộ nhớ chia sẻ để bỏ một vài mảng hay không.Tại sao CudaFree không có bộ nhớ trống?

Khi tôi cấp phát bộ nhớ thiết bị, không có lỗi nào được trả về. Khi tôi sử dụng cudaMemGetInfo để kiểm tra lượng bộ nhớ được phân bổ, có vẻ như một số cudaMalloc chưa phân bổ bất kỳ bộ nhớ nào. Ngoài ra khi tôi cố gắng giải phóng bộ nhớ, có vẻ như chỉ có một con trỏ được giải phóng.

Tôi đang sử dụng giao diện MATLAB Mexfunction để thiết lập bộ nhớ GPU và khởi chạy hạt nhân. Tại thời điểm này, tôi thậm chí không gọi vào hạt nhân và chỉ trở lại một ma trận đơn vị cho kết quả.

cudaError_t cudaErr; 
size_t freeMem = 0; 
size_t totalMem = 0; 
size_t allocMem = 0; 
cudaMemGetInfo(&freeMem, &totalMem); 
mexPrintf("Memory avaliable: Free: %lu, Total: %lu\n",freeMem, totalMem); 

/* Pointers for the device memory */ 
double *devicePulseDelay, *deviceTarDistance, *deviceScattDistance, *deviceScatterers; 
double *deviceReceivedReal, *deviceReceivedImag; 

/* Allocate memory on the device for the arrays. */ 
mexPrintf("Allocating memory.\n"); 
cudaErr = cudaMalloc((void **) &devicePulseDelay, sizeof(double)*512); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not allocate memory to devicePulseDelay\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("devicePulseDelay: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n",allocMem, totalMem,(freeMem - allocMem)); 
cudaErr = cudaMalloc((void **) &deviceTarDistance, sizeof(double)*512); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not allocate memory to deviceTarDistance\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceTarDistance: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n",allocMem, totalMem,(freeMem - allocMem)); 
cudaErr = cudaMalloc((void **) &deviceScattDistance, sizeof(double)*999*512); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not allocate memory to deviceScattDistance\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceScattDistance: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n",allocMem, totalMem,(freeMem - allocMem)); 
cudaErr = cudaMalloc((void **) &deviceScatterers, sizeof(double)*999); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not allocate memory to deviceScatterers\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceScatterers: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n",allocMem, totalMem,(freeMem - allocMem)); 
cudaErr = cudaMalloc((void **) &deviceReceivedReal, sizeof(double)*999*512); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not allocate memory to deviceReceivedReal\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceReceivedReal: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n",allocMem, totalMem,(freeMem - allocMem)); 
cudaErr = cudaMalloc((void **) &deviceReceivedImag, sizeof(double)*999*512); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not allocate memory to deviceReceivedImag\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceReceivedImag: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n", allocMem, totalMem,(freeMem - allocMem)); 

/* copy the input arrays across to the device */ 
mexPrintf("\nCopying memory.\n"); 
cudaErr = cudaMemcpy(devicePulseDelay, pulseDelay, sizeof(double)*512,cudaMemcpyHostToDevice); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not copy to devicePulseDelay\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("devicePulseDelay: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n",allocMem, totalMem,(freeMem - allocMem)); 
cudaErr = cudaMemcpy(deviceTarDistance, tarDistance, sizeof(double)*512,cudaMemcpyHostToDevice); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not copy to deviceTarDistance\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceTarDistance: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n",allocMem, totalMem,(freeMem - allocMem)); 
cudaErr = cudaMemcpy(deviceScattDistance, scattDistance, sizeof(double)*999*512,cudaMemcpyHostToDevice); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not copy to deviceScattDistance\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceScattDistance: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n",allocMem, totalMem,(freeMem - allocMem)); 
cudaErr = cudaMemcpy(deviceScatterers, scatterers, sizeof(double)*999,cudaMemcpyHostToDevice); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not copy to deviceScatterers\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceScatterers: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n",allocMem, totalMem,(freeMem - allocMem)); 

/* call the kernel */ 
// launchKernel<<<1,512>>>(........); 

/* retireve the output */ 
cudaErr = cudaMemcpy(receivedReal, deviceReceivedReal, sizeof(double)*512*512,cudaMemcpyDeviceToHost); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not copy to receivedReal\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("receivedReal: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n",allocMem, totalMem,(freeMem - allocMem)); 
cudaErr = cudaMemcpy(receivedImag, deviceReceivedImag, sizeof(double)*512*512,cudaMemcpyDeviceToHost); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could not copy to receivedImag\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("receivedImag: Memory avaliable: Free: %lu, Total: %lu, Consumed: %lu\n",allocMem, totalMem,(freeMem - allocMem)); 

/* free the memory. */ 
mexPrintf("\nFree'ing memory.\n"); 
cudaMemGetInfo(&freeMem, &totalMem); 
mexPrintf("Before freeing: Free %lu, Total: %lu\n", freeMem, totalMem); 
cudaErr = cudaFree(devicePulseDelay); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could free devicePulseDelay\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("devicePulseDelay: Memory avaliable: Free: %lu, Total: %lu, Free'd: %lu\n",allocMem, totalMem,(allocMem - freeMem)); 
cudaErr = cudaFree(deviceTarDistance); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could free deviceTarDistance\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceTarDistance: Memory avaliable: Free: %lu, Total: %lu, Free'd: %lu\n",allocMem, totalMem,(allocMem - freeMem)); 
cudaErr = cudaFree(deviceScattDistance); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could free deviceScattDistance\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceScattDistance: Memory avaliable: Free: %lu, Total: %lu, Free'd: %lu\n",allocMem, totalMem,(allocMem - freeMem)); 
cudaErr = cudaFree(deviceScatterers); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could free deviceScatterers\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceScatterers: Memory avaliable: Free: %lu, Total: %lu, Free'd: %lu\n",allocMem, totalMem,(allocMem - freeMem)); 
cudaErr = cudaFree(deviceReceivedReal); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could free deviceReceivedReal\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceReceivedReal: Memory avaliable: Free: %lu, Total: %lu, Free'd: %lu\n",allocMem, totalMem,(allocMem - freeMem)); 
cudaErr = cudaFree(deviceReceivedImag); 
if (cudaErr != cudaSuccess) 
{ 
    mexPrintf("could free deviceReceivedImag\n"); 
    mexPrintf("Error: %s\n",cudaGetErrorString(cudaErr)); 
} 
cudaMemGetInfo(&allocMem, &totalMem); 
mexPrintf("deviceReceivedImag: Memory avaliable: Free: %lu, Total: %lu, Free'd: %lu\n",allocMem, totalMem,(allocMem - freeMem)); 

Đây là kết quả từ này:

 
Memory avaliable: Free: 2523959296, Total: 2818572288 
Allocating memory. 
devicePulseDelay: Memory avaliable: Free: 2522910720, Total: 2818572288, Consumed: 1048576 
deviceTarDistance: Memory avaliable: Free: 2522910720, Total: 2818572288, Consumed: 1048576 
deviceScattDistance: Memory avaliable: Free: 2518716416, Total: 2818572288, Consumed: 5242880 
deviceScatterers: Memory avaliable: Free: 2517667840, Total: 2818572288, Consumed: 6291456 
deviceReceivedReal: Memory avaliable: Free: 2515570688, Total: 2818572288, Consumed: 8388608 
deviceReceivedImag: Memory avaliable: Free: 2513473536, Total: 2818572288, Consumed: 10485760 

Copying memory. 
devicePulseDelay: Memory avaliable: Free: 2513473536, Total: 2818572288, Consumed: 10485760 
deviceTarDistance: Memory avaliable: Free: 2513473536, Total: 2818572288, Consumed: 10485760 
deviceScattDistance: Memory avaliable: Free: 2513473536, Total: 2818572288, Consumed: 10485760 
deviceScatterers: Memory avaliable: Free: 2513473536, Total: 2818572288, Consumed: 10485760 
receivedReal: Memory avaliable: Free: 2513473536, Total: 2818572288, Consumed: 10485760 
receivedImag: Memory avaliable: Free: 2513473536, Total: 2818572288, Consumed: 10485760 

Free'ing memory. 
Before freeing: Free 2513473536, Total: 2818572288 
devicePulseDelay: Memory avaliable: Free: 2513473536, Total: 2818572288, Free'd: 0 
deviceTarDistance: Memory avaliable: Free: 2513473536, Total: 2818572288, Free'd: 0 
deviceScattDistance: Memory avaliable: Free: 2513473536, Total: 2818572288, Free'd: 0 
deviceScatterers: Memory avaliable: Free: 2514522112, Total: 2818572288, Free'd: 1048576 
deviceReceivedReal: Memory avaliable: Free: 2514522112, Total: 2818572288, Free'd: 1048576 
deviceReceivedImag: Memory avaliable: Free: 2514522112, Total: 2818572288, Free'd: 1048576 

tôi cảm thấy như có cái gì đó rõ ràng là tôi đang mất tích. Bất cứ ai có thể giúp giải thích những gì đang xảy ra?

EDIT: nền tảng là cửa sổ 7 có thẻ nhớ Tesla C2050 GPu.

+0

Bạn đang chạy mã này trên nền tảng nào? – talonmies

+0

Cố gắng không ra các giá trị của allocMem và totalMem trước mỗi cuộc gọi đến cudaMemGetInfo() và kiểm tra giá trị trả về của cudaMemGetInfo(). –

+0

zero'ing ra allocMem và totalMem trước mỗi cuộc gọi đến cudaMemGetInfo() không có sự khác biệt. Các cuộc gọi cudaMemGetInfo cũng không trả về bất kỳ lỗi nào. FYI, nền tảng của tôi là các cửa sổ 7 trên một card GPU Tesla C2050. –

Trả lời

11

Quan niệm sai lầm khá phổ biến là malloc trực tiếp nhận phân bổ bộ nhớ từ hệ điều hành máy chủ khi được gọi và free phát hành trực tiếp chúng trở lại hoạt động của máy chủ khi được gọi. Nhưng chúng hầu như không hoạt động như vậy, thay vào đó thư viện chuẩn duy trì một danh sách tròn của bộ nhớ free'd và malloc'd được mở rộng và hợp đồng bằng cách tương tác với hệ điều hành chủ (xem một số câu trả lời trên How do malloc() and free() work? để biết thêm chi tiết nếu bạn quan tâm). Bất kể nó hoạt động như thế nào, điều này dẫn đến một số kết quả không trực quan, bao gồm thực tế là thường không thể phân bổ nhiều bộ nhớ như hệ điều hành miễn phí, các phân bổ đôi khi dường như không thay đổi lượng bộ nhớ trống, và rằng free đôi khi không ảnh hưởng đến dung lượng bộ nhớ mà hệ điều hành nói là miễn phí.

Mặc dù tôi không có gì ngoài bằng chứng thực nghiệm để hỗ trợ điều này, tôi tin rằng CUDA hoạt động chính xác theo cùng một cách. Bối cảnh duy trì danh sách riêng của bộ nhớ malloc'd và free'd, và sẽ mở rộng và hợp đồng bộ nhớ được giữ trong danh sách đó với tư cách là trình điều khiển máy chủ/trình quản lý cửa sổ và chính GPU cho phép. Tất cả phần cứng đều có kích thước trang MMU đặc trưng và có bằng chứng cho thấy kích thước trang trên GPU NVIDIA khá lớn. Điều này ngụ ý có độ chi tiết khá thô trong các cuộc gọi cudaMalloc và đôi khi là malloc dường như không ảnh hưởng đến lượng bộ nhớ miễn phí hoặc tiêu thụ nhiều bộ nhớ hơn yêu cầu và đôi khi các cuộc gọi free dường như không có hiệu lực (Nếu bạn quan tâm, bạn có thể tìm thấy một công cụ nhỏ giúp minh họa hành vi kích thước trang của trình điều khiển CUDA here, mặc dù nó được viết cho phiên bản đầu tiên của API CUDA và có thể cần một vài thay đổi để biên dịch với các phiên bản hiện đại). Tôi tin rằng đây là giải thích có khả năng nhất cho hành vi bạn đang quan sát.

Ngẫu nhiên, nếu tôi chạy phiên bản mã đơn giản mà bạn đã đăng trên MacOS 10.6 với một thiết bị gia đình GT200:

#include <cstdio> 

#define mexPrintf printf 

inline void gpuAssert(cudaError_t code, char *file, int line, 
       bool abort=true) 
{ 
    if (code != cudaSuccess) 
    { 
     mexPrintf("GPUassert: %s %s %d\n", cudaGetErrorString(code), 
      file, line); 
     if (abort) exit(code); 
    } 
} 

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); } 

inline void gpuMemReport(size_t * avail, size_t * total, 
     const char * title = 0, const size_t * free = 0, const bool sense = true) 
{ 
    char tstring[32] = { '\0' }; 
    gpuErrchk(cudaMemGetInfo(avail, total)); 

    if (free) { 
     if (title) { 
      strncpy(tstring, title, 31); 
     } 
     mexPrintf("%s Memory avaliable: Free: %zu, Total: %zu, %s: %zu\n", 
       tstring, *avail, *total, (sense) ? "Allocated\0" : "Freed\0", 
       (sense) ? (*free - *avail) : (*avail - *free)); 
    } else { 
     mexPrintf("Memory avaliable: Free: %zu, Total: %zu\n", *avail, *total); 
    } 
} 

int main() 
{ 
    size_t freeMem = 0; 
    size_t totalMem = 0; 
    size_t allocMem = 0; 

    gpuErrchk(cudaFree(0)); 
    gpuMemReport(&freeMem, &totalMem); 

    double *devicePulseDelay, *deviceTarDistance, *deviceScattDistance, *deviceScatterers; 
    double *deviceReceivedReal, *deviceReceivedImag; 

    mexPrintf("Allocating memory.\n"); 
    gpuErrchk(cudaMalloc((void **) &devicePulseDelay, sizeof(double)*512)); 
    gpuMemReport(&allocMem, &totalMem, "devicePulseDelay:", &freeMem); 

    gpuErrchk(cudaMalloc((void **) &deviceTarDistance, sizeof(double)*512)); 
    gpuMemReport(&allocMem, &totalMem, "deviceTarDistance:", &freeMem); 

    gpuErrchk(cudaMalloc((void **) &deviceScattDistance, sizeof(double)*999*512)); 
    gpuMemReport(&allocMem, &totalMem, "deviceScattDistance:", &freeMem); 

    gpuErrchk(cudaMalloc((void **) &deviceScatterers, sizeof(double)*999)); 
    gpuMemReport(&allocMem, &totalMem, "deviceScatterers:", &freeMem); 

    gpuErrchk(cudaMalloc((void **) &deviceReceivedReal, sizeof(double)*999*512)); 
    gpuMemReport(&allocMem, &totalMem, "deviceReceivedReal:", &freeMem); 

    gpuErrchk(cudaMalloc((void **) &deviceReceivedImag, sizeof(double)*999*512)); 
    gpuMemReport(&allocMem, &totalMem, "deviceReceivedImag:", &freeMem); 

    mexPrintf("\nFree'ing memory.\n"); 
    gpuMemReport(&freeMem, &totalMem); 

    gpuErrchk(cudaFree(devicePulseDelay)); 
    gpuMemReport(&allocMem, &totalMem, "devicePulseDelay:", &freeMem, false); 

    gpuErrchk(cudaFree(deviceTarDistance)); 
    gpuMemReport(&allocMem, &totalMem, "deviceTarDistance:", &freeMem, false); 

    gpuErrchk(cudaFree(deviceScattDistance)); 
    gpuMemReport(&allocMem, &totalMem, "deviceScattDistance:", &freeMem, false); 

    gpuErrchk(cudaFree(deviceScatterers)); 
    gpuMemReport(&allocMem, &totalMem, "deviceScatterers:", &freeMem, false); 

    gpuErrchk(cudaFree(deviceReceivedReal)); 
    gpuMemReport(&allocMem, &totalMem, "deviceReceivedReal:", &freeMem, false); 

    gpuErrchk(cudaFree(deviceReceivedImag)); 
    gpuMemReport(&allocMem, &totalMem, "deviceReceivedImag:", &freeMem, false); 

    return 0; 
} 

tôi nhận được một kết quả khác nhau, nhưng cũng là một thể hiện các hiện tượng tương tự:

Allocating memory. 
devicePulseDelay: Memory avaliable: Free: 202870784, Total: 265027584, Allocated: 1048576 
deviceTarDistance: Memory avaliable: Free: 202870784, Total: 265027584, Allocated: 1048576 
deviceScattDistance: Memory avaliable: Free: 198778880, Total: 265027584, Allocated: 5140480 
deviceScatterers: Memory avaliable: Free: 197730304, Total: 265027584, Allocated: 6189056 
deviceReceivedReal: Memory avaliable: Free: 193638400, Total: 265027584, Allocated: 10280960 
deviceReceivedImag: Memory avaliable: Free: 189546496, Total: 265027584, Allocated: 14372864 

Free'ing memory. 
Memory avaliable: Free: 189546496, Total: 265027584 
devicePulseDelay: Memory avaliable: Free: 189546496, Total: 265027584, Freed: 0 
deviceTarDistance: Memory avaliable: Free: 190595072, Total: 265027584, Freed: 1048576 
deviceScattDistance: Memory avaliable: Free: 194686976, Total: 265027584, Freed: 5140480 
deviceScatterers: Memory avaliable: Free: 195735552, Total: 265027584, Freed: 6189056 
deviceReceivedReal: Memory avaliable: Free: 199827456, Total: 265027584, Freed: 10280960 
deviceReceivedImag: Memory avaliable: Free: 203919360, Total: 265027584, Freed: 14372864 

nào cho thấy rằng hành vi này là phần cứng/OS máy chủ phụ thuộc là tốt.

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