English · Español
Lab 01 — Device Query: conoce tu GPU¶
Objetivo: volcar programáticamente cada spec relevante de la GPU alquilada a JSON, y verificar cada uno contra el datasheet del fabricante.
Tiempo estimado: 60–90 minutos.
Prerrequisito:
lab/00-provision-cloud-gpu.mdcompleto. Una instancia cloud-GPU en marcha concupyfuncionando.
Lo que produces¶
Un directorio experiments/23-device-profile/ que contiene:
device_query.py— tu script de inspección.device_query.json— salida poblada, cada campo no-nulo.comparison.md— tabla de los números de tu GPU vs valores de referencia A100/H100/4090, con notas sobre qué hace diferente a tu GPU.manifest.json.
Los campos a poblar¶
Esquema de device_query.json:
{
"device_count": null,
"device_index": 0,
"name": null,
"compute_capability": {"major": null, "minor": null},
"total_memory_gib": null,
"memory_bus_width_bits": null,
"memory_clock_rate_mhz": null,
"theoretical_hbm_bandwidth_gbs": null,
"multiprocessor_count": null,
"cuda_cores_per_sm": null,
"total_cuda_cores": null,
"tensor_cores_per_sm": null,
"total_tensor_cores": null,
"max_threads_per_sm": null,
"max_threads_per_block": null,
"max_warps_per_sm": null,
"warp_size": 32,
"max_blocks_per_sm": null,
"max_grid_dimensions": [null, null, null],
"max_block_dimensions": [null, null, null],
"register_file_size_per_sm_kib": null,
"max_registers_per_thread": null,
"max_shared_memory_per_block_kib": null,
"shared_memory_per_sm_kib": null,
"l2_cache_size_mib": null,
"clock_rate_mhz": null,
"memory_clock_rate_effective_mhz": null,
"peak_fp32_tflops_cuda_cores": null,
"peak_fp16_tflops_tensor_cores": null,
"peak_bf16_tflops_tensor_cores": null,
"peak_fp8_tflops_tensor_cores_if_supported": null,
"pci_bus_id": null,
"pcie_generation": null,
"pcie_lane_width": null
}
TODOs¶
Bloque A — escribir device_query.py¶
- Usa
cupy.cuda.runtime.getDeviceProperties(0)para el grueso; complementa concupy.cuda.runtime.deviceGetAttributepara campos que no estén endeviceProperties. (Para la Fase 23, no usestorchaunquetorch.cuda.get_device_propertiestambién sea una opción — ver Plan §7.g.) - Calcula campos derivados:
theoretical_hbm_bandwidth_gbs = 2 * memory_clock_rate_mhz * memory_bus_width_bits / 8 / 1000(el factor de 2 es DDR; comprueba si la HBM de tu GPU es DDR — la mayoría lo son, pero documéntalo).total_cuda_cores = sm_count × cuda_cores_per_sm(el "cuda_cores_per_sm" depende de la arquitectura — Ampere = 128 fp32, Hopper = 128 fp32, Turing = 64 fp32; busca tu arch).peak_fp32_tflops_cuda_cores = clock_rate_GHz × total_cuda_cores × 2(el 2 es FMA = mul + add).- Para el pico Tensor Core: complicado, varía según arch. Busca las "operaciones por clock por Tensor Core" para tu compute capability (Ampere = 256 fp16-FMA/clock/tc; Hopper = 512 fp16-FMA/clock/tc). Después
peak_fp16_tflops = clock_GHz × total_tensor_cores × ops_per_clock × 2 (FMA). - Guarda en
device_query.jsoncon cada campo poblado.
Bloque B — verificar contra el datasheet¶
- Abre el whitepaper / datasheet de NVIDIA para tu GPU. Busca el oficial "Peak FP32 TFLOPS", "Peak FP16 Tensor Core TFLOPS", "HBM Bandwidth", "L2 cache size".
- Haz una tabla en
comparison.md: - Tu-GPU medido/consultado | Datasheet | ¿Coincide? (S/N) | Por-qué-si-no
- Cualquier campo donde tu pico calculado difiera del datasheet en >10% necesita explicación. Razones comunes: (a) el clock que consultas es base, no boost; (b) definición diferente de "core"; © reporte dense vs sparse TFLOPS.
Bloque C — explicar la arquitectura en comparison.md¶
Dos párrafos, en tus propias palabras:
- ¿Qué arquitectura es tu GPU? (Ampere, Ada Lovelace, Hopper, etc.) ¿Qué fue nuevo en esa arch frente a la generación anterior? (Por ejemplo, Ampere introdujo TF32 Tensor Cores; Hopper introdujo fp8.)
- ¿Qué hace diferente a tu SKU concreto del flagship de centro de datos? Por ejemplo, RTX 3090 = Ampere de consumo con los mismos SMs que A100 pero menos, boost más rápido, menos HBM (GDDR6X en lugar de HBM2). Anota la implicación práctica: los kernels limitados por ancho de banda en una 3090 corren a ~50% de la velocidad de A100 por la diferencia de bandwidth.
Bloque D — manifest¶
{
"experiment": "23-device-profile",
"date": "YYYY-MM-DD",
"gpu_name": null,
"compute_capability": null,
"versions": {"python": "3.11.x", "cupy": "X.Y.Z"},
"queried_fields_total": null,
"non_null_fields": null,
"datasheet_mismatch_count": null
}
Restricciones¶
- Sin PyTorch todavía — solo
cupyycuda-python. Ver Plan §7.g. - No hardcodees "warp size 32" — consúltalo. Lleva siendo 32 desde siempre, pero si alguien corre esto en AMD con wavefronts de 64, el valor hardcodeado está mal.
- Los campos calculados deben ser derivables de los consultados. Por ejemplo, no pongas
peak_fp16_tflopssi lo sacaste del datasheet — calcúlalo desde clock × tensor cores. El datasheet es la verificación, no la fuente.
Condiciones de parada¶
Listo cuando:
device_query.jsontiene cada campo no-nulo.- La tabla de
comparison.mdtiene todas las celdas "¿Coincide?" rellenas, con explicaciones para los desajustes. - Los párrafos de arquitectura de
comparison.mdestán escritos. manifest.jsoncompleto.
Trampas¶
getDevicePropertiesdevuelve kHz, no MHz, para los campos de clock. Comprueba siempre la unidad comparando con el datasheet.- "Cuda cores por SM" varía según arch. No asumas 128. Busca tu compute capability.
- "Operaciones de Tensor Core por clock" es el número más complicado. Está mal documentado; la fuente más limpia es el whitepaper por arch de NVIDIA. Los docs de Triton también los listan.
- Clock boost vs base. El
clock_rate_mhzde la API suele ser base. Las cargas reales corren a boost. El "peak TFLOPS" del datasheet asume boost.
Cuándo consultar solutions/¶
Tras cumplir todas las condiciones de parada. La referencia en solutions/01-device-query-ref.md (escrita al abrir la fase) muestra el script + una tabla de comparación trabajada para la GPU de referencia (TBD por §7.a).
Siguiente lab: lab/02-bandwidth-test.md.