ultima tutorial test geforce c++ linux memory cuda

c++ - tutorial - nvidia cuda



CUDA y memoria fija(página bloqueada) ¿no está bloqueada la página? (1)

Intento averiguar si CUDA (o la implementación OpenCL) dice la verdad cuando requiero memoria clavada (página bloqueada).

cudaMallocHost y miré los valores /proc/meminfo Mlocked y Unevictable , ambos permanecen en 0 y nunca suben ( /proc/<pid>/status informes de /proc/<pid>/status VmLck también como 0). Utilicé mlock para bloquear la memoria de la página y los valores subieron como se esperaba.

Entonces, dos posibles razones para este comportamiento podrían ser:

  1. No obtengo memoria bloqueada de la API CUDA y el cudaSuccess es falso
  2. CUDA puentea los contadores del sistema operativo para la memoria bloqueada de la página porque CUDA hace algo de magia con el kernel de Linux

Entonces, la pregunta real es: ¿por qué no puedo obtener los valores de la memoria bloqueada de la página del sistema operativo cuando uso CUDA para asignar memoria bloqueada?

Además: ¿Dónde puedo obtener los valores correctos si no provienen de /proc/meminfo o /proc/<pid>/status ?

¡Gracias!

Sistema: Ubuntu 14.04.01 LTS; CUDA 6.5; Nvidida Driver 340.29; Nvidia Tesla K20c


Parece que el asignador fijado en CUDA 6.5 bajo el capó está usando mmap() con MAP_FIXED. Aunque no soy un experto en sistemas operativos, creo que esto tendrá el efecto de "fijar" la memoria, es decir, garantizar que su dirección nunca cambie.

Consideremos un programa de prueba corto:

#include <stdio.h> #define DSIZE (1048576*1024) int main(){ int *data; cudaFree(0); system("cat /proc/meminfo > out1.txt"); printf("*$*before alloc/n"); cudaHostAlloc(&data, DSIZE, cudaHostAllocDefault); printf("*$*after alloc/n"); system("cat /proc/meminfo > out2.txt"); cudaFreeHost(data); system("cat /proc/meminfo > out3.txt"); return 0; }

Si ejecutamos este programa con strace y strace la parte de salida entre las instrucciones printf , tenemos:

write(1, "*$*before alloc/n", 16*$*before alloc) = 16 mmap(0x204500000, 1073741824, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, 0, 0) = 0x204500000 ioctl(11, 0xc0304627, 0x7fffcf72cce0) = 0 ioctl(3, 0xc0384657, 0x7fffcf72cd70) = 0 write(1, "*$*after alloc/n", 15*$*after alloc) = 15

(Tenga en cuenta que 1073741824 es exactamente un gigabyte, es decir, el mismo que el 1048576 * 1024 solicitado)

Revisando la descripción de mmap , tenemos:

dirección da una dirección de inicio preferida para la asignación. NULL no expresa preferencia. Cualquier mapeo previo en esa dirección se elimina automáticamente. La dirección que proporcione puede cambiarse, a menos que use el indicador MAP_FIXED.

Por lo tanto, suponiendo que el comando mmap es exitoso, la dirección de memoria solicitada será reparada y, por lo tanto, la memoria se "fijará".

Aparentemente, este mecanismo no usa mlock() , por lo que las páginas bloqueadas no cambian, antes y después. Sin embargo, esperaríamos un cambio en la estadística de mapeo, y si difirimos el out1.txt y out2.txt producidos por el programa anterior, vemos (extraído):

< Mapped: 87488 kB --- > Mapped: 1135904 kB

La diferencia es aproximadamente un gigabyte, la cantidad de memoria "fijada" solicitada.