Линейная алгебра на GPU: cuBLAS и cuSPARSE

Задача страницы. Практический каркас для матричных вычислений на облачных GPU: плотная (GEMM/GEMV/батчи) и разрежённая (SpMV/SpMM/разложение) линал, один/много GPU/узлов, дисковая подкачка тайлов, смешанная точность (FP32/FP16/BF16/FP8), наблюдаемость и экономика (TFLOPS_achieved, GB/s, Cost_per_1e12FLOP). Это входная точка для задач линейной алгебры в HPC‑пайплайнах.

TL;DR

  • Плотные матрицы: используйте cuBLAS/cuBLASLt (GEMM, strided‑batched GEMM, GEMV). Для малых матриц—батчи, для очень больших—тайлинг + двойная буферизация.
  • Разрежённые: cuSPARSE (SpMV/SpMM, CSR/COO/ELL/HYB). Сжимайте индексы до int32, следите за nnz и форматами.
  • Много GPU: 1 ранг = 1 GPU; для плотных — 2D‑распределение тайлов + NCCL/UCX‑редукции, для Sp* — разделение по строкам/блокам. См. https://cloudcompute.ru/solutions/multi-gpu/
  • I/O и тайлинг: NVMe‑scratch, H2D/D2H с overlap (2–3 CUDA‑потока), «тёплое»/«холодное» хранилища. См. https://cloudcompute.ru/solutions/storage-data/
  • Смешанная точность: аккумулировать в FP32 при входе FP16/BF16; для FP8 используйте калибровку масштабов. См. https://cloudcompute.ru/solutions/fp8-bf16/ и https://cloudcompute.ru/solutions/performance-tuning/
  • Режимы: большие оффлайн‑батчи — Interruptible (чанк ≤ 120 с, идемпотентные тайлы); SLA‑критичное — On‑Demand. См. https://cloudcompute.ru/solutions/interruptible-patterns/
  • Профили GPU: 24 ГБ (Compact) — батчи малых GEMM и SpMV; 48 ГБ (Balanced) — основной профиль; 80 ГБ (HQ) — супер‑крупные тайлы/разрежённые с большим nnz. Для плотности — MIG. См. https://cloudcompute.ru/solutions/mig/
  • Наблюдаемость: TFLOPS_achieved, GBps_dram, AI=FLOPs/Bytes, p50/p95 kernel_time, gpu_utilization. См. https://cloudcompute.ru/solutions/monitoring-logging/
  • Экономика: Cost_per_1e12FLOP = (c_gpu / U) * (1e12 / FLOPs_per_s) / 3600; для Sp* — Cost_per_1e9NZ. См. https://cloudcompute.ru/solutions/cost-planner/

Сценарии (когда это нужно)

Архитектуры/пайплайны A) Один узел, multi‑GPU, плотные GEMM (тайлинг + overlap)

[Warm Parquet/NPY] -> [Prefetch -> NVMe]
 |
 +--> [Tile Producer CPU] -> [H2D stream A/B] -> [cuBLASLt GEMM stream A/B] -> [D2H stream A/B] -> [Reducer/Writer]

Ключи: 2–3 CUDA‑потока, двойная буферизация, cublasLtMatmul с Tensor Core, аккумулирование FP32.

B) Разрежённые SpMV/SpMM (CSR, много GPU)

[CSR partitions] -> [rank i: rows_i, vals_i, cols_i] --(MPI/UCX for halos)--> [cuSPARSE SpMV] -> [merge/reduce]

Ключи: 1 ранг = 1 GPU, равномерный nnz по рангам, halo‑обмен UCX/RDMA.

C) Многоузловой 2D‑блок‑циклик для GEMM

A,B тайлы -> [p x q процесс‑сетка] -> [панельные передачи NCCL/UCX] -> [локальный GEMM] -> [редукция]

Ключи: панели по строкам/столбцам, минимизировать межузловые шифлы, NVLink внутри узла.

Профили GPU/VRAM/скоростей (ориентиры)

**Профиль** **VRAM** **Плотные задачи** **Разрежённые задачи** **Режим** **Отн. throughput (≈)** **Примечания**
**24 ГБ (Compact)** 24 ГБ Батчи GEMM до ~2–4k, GEMV SpMV/SpMM со средним nnz/row Оба 1.0 Отлично с **MIG** для мелких батчей
**48 ГБ (Balanced)** 48 ГБ Большие тайлы 8–16k Крупные CSR/COO, равномерный nnz Оба 1.5–1.8 База для продакшена
**80 ГБ (HQ)** 80 ГБ 16–32k тайлы, FP8/FP16 с FP32 acc Очень крупный nnz/halo Оба 2.2–2.6 Запас VRAM/кэша, многоузловые

Относительно; итог зависит от размеров, формата и интенсивности памяти.

Конфиги и скелеты

1) C++: cuBLASLt GEMM (FP16→FP32 accumulate)

#include <cublasLt.h>
void gemm_fp16_acc32(const __half* A, const __half* B, float* C,
 int m,int n,int k, int lda,int ldb,int ldc, cudaStream_t s) {
 cublasLtHandle_t lt; cublasLtCreate(&lt);
 cublasLtMatmulDesc_t opDesc; cublasLtMatrixLayout_t Adesc,Bdesc,Cdesc;
 cublasLtMatmulDescCreate(&opDesc, CUBLAS_COMPUTE_32F, CUDA_R_32F);
 cublasOperation_t transN = CUBLAS_OP_N;
 cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_TRANSA, &transN, sizeof(transN));
 cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_TRANSB, &transN, sizeof(transN));
 cublasLtMatrixLayoutCreate(&Adesc, CUDA_R_16F, m, k, lda);
 cublasLtMatrixLayoutCreate(&Bdesc, CUDA_R_16F, k, n, ldb);
 cublasLtMatrixLayoutCreate(&Cdesc, CUDA_R_32F, m, n, ldc);
 float alpha = 1.f, beta = 0.f;
 // эвристики: выбор лучшего алгоритма под матрицы
 cublasLtMatmulPreference_t pref; cublasLtMatmulPreferenceCreate(&pref);
 size_t ws = 1<<26; void* workspace; cudaMalloc(&workspace, ws);
 cublasLtMatmulPreferenceSetAttribute(pref, CUBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &ws, sizeof(ws));
 cublasLtMatmulAlgo_t algo; int returnedResults=0;
 cublasLtMatmulHeuristicResult_t result;
 cublasLtMatmulAlgoGetHeuristic(lt, opDesc, Adesc, Bdesc, Cdesc, Cdesc, pref, 1, &result, &returnedResults);
 if (returnedResults) algo = result.algo;
 cublasLtMatmul(lt, opDesc, &alpha, A, Adesc, B, Bdesc, &beta, C, Cdesc, C, Cdesc, &algo, workspace, ws, s);
 cudaFree(workspace); cublasLtDestroy(lt);
}

2) C++: cuSPARSE SpMV (CSR, float32)

#include <cusparse.h>
void spmv_csr(int m,int n,int nnz,
 const int* d_csrRowPtr,const int* d_csrColInd,
 const float* d_csrVal, const float* d_x, float* d_y, cudaStream_t s) {
 cusparseHandle_t h; cusparseCreate(&h); cusparseSetStream(h, s);
 cusparseSpMatDescr_t A; cusparseDnVecDescr_t x,y;
 cusparseCreateCsr(&A, m, n, nnz, (void*)d_csrRowPtr, (void*)d_csrColInd, (void*)d_csrVal,
 CUSPARSE_INDEX_32I, CUSPARSE_INDEX_32I,
 CUSPARSE_INDEX_BASE_ZERO, CUDA_R_32F);
 cusparseCreateDnVec(&x, n, (void*)d_x, CUDA_R_32F);
 cusparseCreateDnVec(&y, m, (void*)d_y, CUDA_R_32F);
 float alpha=1.f, beta=0.f; size_t ws=0; void* d_ws=nullptr;
 cusparseSpMV_bufferSize(h, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha, A, x, &beta, y, CUDA_R_32F, CUSPARSE_MV_ALG_DEFAULT, &ws);
 cudaMalloc(&d_ws, ws);
 cusparseSpMV(h, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha, A, x, &beta, y, CUDA_R_32F, CUSPARSE_MV_ALG_DEFAULT, d_ws);
 cudaFree(d_ws); cusparseDestroySpMat(A); cusparseDestroyDnVec(x); cusparseDestroyDnVec(y); cusparseDestroy(h);
}

3) Python: CuPy/CSR‑SpMV и strided‑batched GEMM

import cupy as cp, cupyx
# Strided-batched GEMM: (B, M, K) @ (B, K, N) -> (B, M, N)
B, M, K, N = 64, 1024, 1024, 1024
A = cp.random.standard_normal((B,M,K), dtype=cp.float16)
Bmat = cp.random.standard_normal((B,K,N), dtype=cp.float16)
C = A @ Bmat # cuBLASLt + Tensor Cores, acc FP32
# CSR SpMV
m, n = 1_000_000, 1_000_000
Acsr = cupyx.scipy.sparse.random(m, n, density=1e-6, format='csr', dtype=cp.float32)
x = cp.ones((n,), cp.float32); y = Acsr @ x

4) Многоузловой GEMM (Slurm, NCCL/UCX, псевдо)

#!/bin/bash
#SBATCH -J gemm_2d
#SBATCH -N 2
#SBATCH --gpus-per-node=4
#SBATCH -t 01:00:00
#SBATCH --exclusive
module load cuda mpi
export UCX_TLS=rc,ud,sm,self,cuda_copy,cuda_ipc
srun --mpi=pmix_v3 ./gemm_2d_block_cyclic --m 32768 --n 32768 --k 32768 --tile 4096 --panel "nccl"

5) YAML задания (универсально)

job:
 name: "linalg_gemm_spmv_bench_v1"
 mode: "interruptible" # on-demand | interruptible
 nodes: 1
 gpus_per_node: 4
 gpu_profile: "48GB-Balanced"
 network: "rdma"
 io:
 prefetch: ["/warm/matrices/"]
 scratch: "/nvme"
 checkpoint: "/nvme/ckpt"
 interval_seconds: 120
 run:
 entrypoint: "python"
 args: ["/opt/linalg/run.py","--op","gemm,spmv","--m","16384","--n","16384","--k","16384","--csr","/nvme/matrix.csr"]
 hooks:
 on_start: ["python /scripts/prefetch.py"]
 on_checkpoint: ["python /scripts/register_ckpt.py"]
 on_failure: ["python /scripts/requeue.py --backoff"]
``` **Наблюдаемость/метрики/алерты**

См.[ https://cloudcompute.ru/solutions/monitoring-logging/](https://cloudcompute.ru/solutions/monitoring-logging/?utm_source=chatgpt.com) и[ https://cloudcompute.ru/solutions/llm-inference/observability/](https://cloudcompute.ru/solutions/llm-inference/observability/?utm_source=chatgpt.com)

**Плотные (GEMM/GEMV):**

- TFLOPS\_achieved = 2\*M\*N\*K / (t\_s \* 1e12)
- gpu\_utilization, sm\_occupancy, tensor\_core\_active, gld\_throughput, gst\_throughput
- p50/p95 kernel\_time, H2D/D2H\_ms, streams\_inflight

**Разрежённые (SpMV/SpMM):**

- GBps\_dram, nnz\_per\_row, spmv\_time\_ms, spmm\_time\_ms, load\_imbalance
- rmm\_pool\_free\_bytes, gpu\_memory\_used\_bytes

**Многоузловые:**

- allreduce\_time\_ms, shuffle\_bytes, mpi\_wait\_ratio, rdma\_rx/tx\_mb\_s

**Алерты:**

- p95 kernel\_time вырос &gt; X% к базовой трассе.
- gpu\_memory\_used\_bytes → VRAM‑потолок / rmm\_pool\_free\_bytes → 0.
- mpi\_wait\_ratio высокий при низком gpu\_utilization → сеть/распиновка.
- H2D/D2H\_ms растут → слабый префетч/нет overlap.

## **Экономика и формулы**

См.[ https://cloudcompute.ru/solutions/cost-planner/](https://cloudcompute.ru/solutions/cost-planner/?utm_source=chatgpt.com) и <https://cloudcompute.ru/solutions/throughput-vs-latency/>

**GEMM (плотные):**

FLOPs\_total = 2 \* M \* N \* K

TFLOPS\_achieved = FLOPs\_total / (t\_s \* 1e12)

Cost\_per\_1e12FLOP = (c\_gpu / U) \* (1e12 / FLOPs\_per\_s) / 3600

**SpMV/SpMM (разрежённые):**

Ops\_per\_iter ≈ 2 \* nnz

Edges\_per\_s ≈ nnz / t\_s

Cost\_per\_1e9NZ = (c\_gpu / U) \* (1e9 / (nnz\_per\_s)) / 3600

**Roofline (оценка):**

Achievable = min( Peak\_FLOPS, Mem\_BW \* AI )

AI = FLOPs / Bytes\_moved

Поднимайте AI батчированием/блокированием/реюзом.

**Масштабирование (много узлов):**

Speedup(N) = T1 / TN

Scale\_eff(N) = Speedup(N) / N

Выбирайте N, где Scale\_eff приемлема и Cost\_per\_1e12FLOP минимальна.

## **Практики производительности**

- **cuBLASLt:** включайте Tensor Core (FP16/BF16/TF32/FP8), аккумулируйте в FP32; cublasLtMatmul с эвристиками/рабочей памятью.
- **Strided‑batched:** для множеств малых GEMM (до ~512–2048) вместо циклов по вызовам.
- **Тайлинг + overlap:** двойная/тройная буферизация H2D/compute/D2H на разных потоках.
- **Форматы разрежённых:** CSR — базовый, ELL/HYB — при равномерном nnz/row; сортируйте индексы, сжимайте до int32.
- **Баланс nnz:** равномерно делите строки по рангам, избегайте «жирных» строк; пред‑перестроение.
- **Pinned memory/zero‑copy:** используйте закреплённую память, избегайте лишних копий.
- **Многоузловые:** UCX/RDMA, локализуйте обмены внутри узла (NVLink), используйте панельные схемы. См.[ https://cloudcompute.ru/solutions/multi-gpu/](https://cloudcompute.ru/solutions/multi-gpu/?utm_source=chatgpt.com)
- **Смешанная точность:** см. <https://cloudcompute.ru/solutions/fp8-bf16/> — прогоните калибровку скейлов, сравните ошибки с FP32.
- **Микроархитектура:** выравнивание lda/ldb/ldc, крупные leading‑dimensions, избегайте «тонких» матриц.
- **CI/контейнеры:** фиксируйте версии CUDA/библотек; smoke‑бенч и регрессии. См. <https://cloudcompute.ru/solutions/containers-ci-cd/>

## **Безопасность/политики**

См.[ https://cloudcompute.ru/solutions/security/](https://cloudcompute.ru/solutions/security/?utm_source=chatgpt.com)

- **Данные/артефакты:** приватные матрицы/графы — по ролевым доступам, шифрование «на покое».
- **Секреты:** ключи бакетов/репозиториев — через секрет‑хранилище; не попадать в логи.
- **Изоляция:** проекты/неймспейсы; ACL на сети/хранилища; ограничение egress.
- **Ретеншн:** временные тайлы/буферы — автоочистка; публикуются только итоговые матрицы/агрегаты.
- **Аудит:** кто запускал, параметры/версии, куда публиковал результаты.

**Траблшутинг (симптом → причина → решение)**

<table><tbody><tr><td>**Симптом**

</td><td>**Причина**

</td><td>**Решение**

</td></tr><tr><td>Низкий TFLOPS\_achieved на GEMM

</td><td>Мелкие матрицы/нет батчей

</td><td>Использовать strided‑batched GEMM, увеличить тайлы/рабочую память

</td></tr><tr><td>Сильный bound по памяти

</td><td>Низкий AI/много D2H/H2D

</td><td>Блокирование, fusing, overlap H2D/compute, увеличьте реюз

</td></tr><tr><td>Нестабильная точность в FP16/FP8

</td><td>Суммирование в низкой точности

</td><td>Аккумулировать в FP32, калибровать FP8 скейлы

</td></tr><tr><td>Спад на SpMV

</td><td>Несортированные индексы/дисбаланс nnz

</td><td>Сортировка кол‑индексов, баланс строк, смена формата (ELL/HYB)

</td></tr><tr><td>OOM VRAM

</td><td>Индексы 64‑бит/крупные тайлы

</td><td>Сжать до int32, уменьшить tile, перейти на 48–80 ГБ

</td></tr><tr><td>Высокий mpi\_wait\_ratio

</td><td>Сетевые барьеры

</td><td>RDMA/UCX, локализовать обмены, панельные передачи, NUMA‑пиннинг

</td></tr><tr><td>Пиление времени ядра

</td><td>Холодный NVMe/нет overlap

</td><td>Двойная буферизация, предварительный префетч, pinned memory

</td></tr><tr><td>Ошибки shape/leading dim

</td><td>Неверные lda/ldb/ldc

</td><td>Проверить порядки хранения (col‑major в cuBLAS) и шаги

</td></tr></tbody></table>

## **Как запустить в cloudcompute.ru**

1. **Шаблоны:**[ https://cloudcompute.ru/solutions/templates/](https://cloudcompute.ru/solutions/templates/?utm_source=chatgpt.com)
 - «LinAlg Dense (cuBLAS)» и «LinAlg Sparse (cuSPARSE)» — готовые окружения.
 - «HPC MPI (Slurm/K8S)» — многоузловые GEMM/Sp\* с UCX/RDMA.
2. **Профиль GPU:** 24/48/80 ГБ по таблице; много мелких батчей — 24 ГБ + **MIG**; супер‑крупные тайлы — 80 ГБ.
3. **Режим:** оффлайн‑батчи — **Interruptible** (тайл‑чанк ≤ 120 с); SLA‑критичное — **On‑Demand**. См. <https://cloudcompute.ru/solutions/interruptible-patterns/>
4. **Хранилище:** входные матрицы/CSR — «тёплое»; тайлы/рабочие — **NVMe**; публикация — «холодное». См.[ https://cloudcompute.ru/solutions/storage-data/](https://cloudcompute.ru/solutions/storage-data/?utm_source=chatgpt.com)
5. **Оркестрация/CI:** фиксируйте версии CUDA/библиотек; smoke‑бенч (GEMM/SpMV) до масштабирования. См. <https://cloudcompute.ru/solutions/containers-ci-cd/>
6. **Наблюдаемость:** дашборды по TFLOPS\_achieved, GBps\_dram, p95 kernel\_time, GPU/сеть/I‑O. См.[ https://cloudcompute.ru/solutions/monitoring-logging/](https://cloudcompute.ru/solutions/monitoring-logging/?utm_source=chatgpt.com)
7. **Сквозные оптимизации:** смешанная точность и профилировка. См. <https://cloudcompute.ru/solutions/fp8-bf16/> и[ https://cloudcompute.ru/solutions/performance-tuning/](https://cloudcompute.ru/solutions/performance-tuning/?utm_source=chatgpt.com)

**Чек‑лист перед продом**

- Определены размеры/форматы (плотные/CSR/COO/ELL), индексы сжаты до int32 где можно.
- Включён Tensor Core (cuBLASLt), аккумулирование FP32; батчи настроены.
- NVMe‑scratch активен; H2D/compute/D2H перекрываются; тайл ≤ 120 с для Interruptible.
- При многоузловом — UCX/RDMA, 1 ранг = 1 GPU, NUMA‑пиннинг; панельные передачи.
- Метрики/алерты заведены: TFLOPS\_achieved, GBps\_dram, p95 kernel\_time, gpu\_utilization, mpi\_wait\_ratio, io\_\*.
- Экономика посчитана: Cost\_per\_1e12FLOP / Cost\_per\_1e9NZ; выбран профиль 24/48/80 ГБ.
- Политики безопасности/ретенции применены; логи без секретов.
- Smoke‑бенч подтверждает стабильность на 1/2/М узлах.

**Навигация**

- Хаб HPC: <https://cloudcompute.ru/solutions/hpc/>
- Родственные разделы:
 
 - Граф‑аналитика (cuGraph): <https://cloudcompute.ru/solutions/hpc/graph-analytics/>
 - CFD на GPU (OpenFOAM‑CUDA): <https://cloudcompute.ru/solutions/hpc/openfoam-gpu/>
 - Монте‑Карло: <https://cloudcompute.ru/solutions/hpc/monte-carlo/>
 - Оптимизация/матпрограммирование: <https://cloudcompute.ru/solutions/hpc/optimization/>
- Сквозные:
 
 - Multi‑GPU и топологии:[ https://cloudcompute.ru/solutions/multi-gpu/](https://cloudcompute.ru/solutions/multi-gpu/?utm_source=chatgpt.com) • MIG: <https://cloudcompute.ru/solutions/mig/>
 - Данные/хранилище:[ https://cloudcompute.ru/solutions/storage-data/](https://cloudcompute.ru/solutions/storage-data/?utm_source=chatgpt.com)
 - Контейнеры/CI/CD: <https://cloudcompute.ru/solutions/containers-ci-cd/>
 - Наблюдаемость и логи:[ https://cloudcompute.ru/solutions/monitoring-logging/](https://cloudcompute.ru/solutions/monitoring-logging/?utm_source=chatgpt.com) •[ https://cloudcompute.ru/solutions/llm-inference/observability/](https://cloudcompute.ru/solutions/llm-inference/observability/?utm_source=chatgpt.com)
 - Производительность:[ https://cloudcompute.ru/solutions/performance-tuning/](https://cloudcompute.ru/solutions/performance-tuning/?utm_source=chatgpt.com) • <https://cloudcompute.ru/solutions/fp8-bf16/> • <https://cloudcompute.ru/solutions/throughput-vs-latency/>
 - RAPIDS/ETL: <https://cloudcompute.ru/solutions/rapids/> • <https://cloudcompute.ru/solutions/spark-rapids/>

Готовы запустить?

Запустить GPU-сервер