大数跨境

cuda13新特性green context

cuda13新特性green context AI Infra之道
2026-03-22
2
导读:背景由于launch的先后顺序和GPU资源的占用情况,使得GPU中不同stream间并行成为机会主义,即使有高

背景

由于launch的先后顺序和GPU资源的占用情况,使得GPU中不同stream间并行成为机会主义,即使有高优先级的任务需要执行,依然需要等到释放足够的GPU资源才能响应高优先级任务,响应延迟很难稳定控制。为了解决这一问题,cuda13.1开始提出了green context(GC), 它在创建时就会关联到一组特定的 GPU 资源, 这样一来,提交到某个 green context 的 GPU 工作,就只能使用分配给它的那些 SM 和工作队列。这样做有助于减少,或者更好地控制,由共享资源使用带来的相互干扰。

使用场景

  1. Dynamic partitioning,根据流量变化动态分配SM;
  2. Low-latency reservation,给关键低时延任务预留一块专用资源;
  3. Overlapped execution,不同任务既有各自保底资源,又共享一部分资源,共享的资源会串行利用;
  4. Nested contexts,先做大粒度划分,再在内部继续细分

使用Green Contexts

Device Resource and Resource Descriptor

struct cudaDevResource {     enum cudaDevResourceType type;     union {         struct cudaDevSmResource sm;         struct cudaDevWorkqueueConfigResource wqConfig;         struct cudaDevWorkqueueResource wq;     }; };
cudaDevResource是统一的资源管理句柄,由于union的存在,一个cudaDevResource句柄只能代表一类资源,这些资源只有三类,分别是SM、workqueue 配置资源和预先存在的 workqueue 资源。

Step 1: Get available GPU resources

创建 green context 的第一步,是获取可用的设备资源,并填充到 cudaDevResource 结构体中。当前有三种可能的起点,相关的 CUDA runtime API 函数签名如下:
根据device:
cudaError_t cudaDeviceGetDevResource(int device, cudaDevResource* resource, cudaDevResourceType type) 
根据 execution context:
cudaError_t cudaExecutionCtxGetDevResource(cudaExecutionContext_t ctx, cudaDevResource* resource, cudaDevResourceType type
根据 stream:
cudaError_t cudaStreamGetDevResource(cudaStream_t hStream, cudaDevResource* resource, cudaDevResourceType type
通常情况下,起点会是一张 GPU device。下面这段代码展示了如何获取某个 GPU 设备上可用的 SM 资源。在cudaDeviceGetDevResource调用成功后,用户就可以查看该资源中可用的 SM 数量。
// 获得SM的信息int current_device = 0// 假设设备编号为 0CUDA_CHECK(cudaSetDevice(current_device));cudaDevResource initial_SM_resources = {};CUDA_CHECK(cudaDeviceGetDevResource(current_device /* GPU device */,                                   &initial_SM_resources /* 待填充的设备资源 */,                                   cudaDevResourceTypeSm /* 资源类型 */));std::cout << "Initial SM resources: " << initial_SM_resources.sm.smCount << " SMs" << std::endl; // 可用 SM 数量// 与资源划分相关的特殊字段(见下面第 3 步)std::cout << "Min. SM partition size: " <<  initial_SM_resources.sm.minSmPartitionSize << " SMs" << std::endl;std::cout << "SM co-scheduled alignment: " <<  initial_SM_resources.sm.smCoscheduledAlignment << " SMs" << std::endl;// 获得workqueue configuration信息int current_device = 0// 假设设备编号为 0CUDA_CHECK(cudaSetDevice(current_device));cudaDevResource initial_WQ_config_resources = {};CUDA_CHECK(cudaDeviceGetDevResource(current_device /* GPU device */,                                   &initial_WQ_config_resources /* 待填充的设备资源 */,                                   cudaDevResourceTypeWorkqueueConfig /* 资源类型 */));std::cout << "Initial WQ config. resources: " << std::endl;std::cout << "  - WQ concurrency limit: " << initial_WQ_config_resources.wqConfig.wqConcurrencyLimit << std::endl;std::cout << "  - WQ sharing scope: " << initial_WQ_config_resources.wqConfig.sharingScope << std::endl;

Step 2: Partition SM resources

获得cudaDevResource后,进行切分,可以通过如下两个API完成。
cudaError_t cudaDevSmResourceSplitByCount(cudaDevResource* result,                                          unsigned int* nbGroups,                                          const cudaDevResource* input,                                          cudaDevResource* remaining,                                          unsigned int useFlags,                                          unsigned int minCount)
创建多个同构分区+一个剩余分区,用户请求把输入的 SM 类型 device resource 划分成 *nbGroups 个同构分组,并且每组至少包含 minCount 个 SM。但最终结果中,实际得到的是一个可能被更新过的*nbGroups 数量的同构分组,每组有 N 个 SM。效果如下图。
cudaError_t cudaDevSmResourceSplit(cudaDevResource* result,                                   unsigned int nbGroups,                                   const cudaDevResource* input,                                   cudaDevResource* remainder,                                   unsigned int flags,                                   cudaDevSmResourceGroupParams* groupParams)
创建多个异构分区。这个 API 会尝试把输入的 SM 类型资源划分成 nbGroups 个有效的 device resource(分组),并把结果放到 result 数组中;每个分组的要求由 groupParams 数组中的对应项指定。还可以选择性地生成一个剩余分区。如果 split 成功,那么如下图所示。
int nbGroups = 2// 按需修改unsigned int default_split_flags = 0;cudaDevResource remainder {}; // 按需修改cudaDevResource result_use_case[2] = {{}, {}}; // 如果还打算加 workqueue 资源,需要加大数组大小cudaDevSmResourceGroupParams group_params_use_case[2] = {    {.smCount = X, .coscheduledSmCount=0, .preferredCoscheduledSmCount = 0, .flags = 0},    {.smCount = Y, .coscheduledSmCount=0, .preferredCoscheduledSmCount = 0, .flags = 0}};CUDA_CHECK(cudaDevSmResourceSplit(&result_use_case[0],                                  nbGroups,                                  &initial_GPU_SM_resources,                                  &remainder,                                  default_split_flags,                                  &group_params_use_case[0]));

Step 3(optional): Add workqueue resources

还可以继续为每个green context追加workqueue资源,这里需要手动设置config参数。
cudaDevResource split_result[2] = {{}, {}};// code to populate split_result[0] not shown; used split API with nbGroups=1// The last resource will be a workqueue resource.split_result[1].type = cudaDevResourceTypeWorkqueueConfig;split_result[1].wqConfig.device = 0// assume device ordinal of 0split_result[1].wqConfig.sharingScope = cudaDevWorkqueueConfigScopeGreenCtxBalanced;split_result[1].wqConfig.wqConcurrencyLimit = 4;

Step 4. Create a Resource Descriptor

切分完资源后,就是为指定的资源生成资源描述符,API如下。
cudaError_t cudaDevResourceGenerateDesc(cudaDevResourceDesc_t *phDesc,                                        cudaDevResource *resources,                                        unsigned int nbResources)

Step 5. Create a Green Context

在创建完资源描述符后,使用cudaGreenCtxCreate来创建context对象,API如下。
cudaError_t cudaGreenCtxCreate(cudaExecutionContext_t *phCtx, cudaDevResourceDesc_t desc, int device, unsigned int flags)

Step 6.  Launching work

要想让一个 kernel 运行在前面创建好的 green context 上,首先需要使用cudaExecutionCtxStreamCreateAPI 为该 green context 创建一个 stream。如果在这个 stream 上通过<<< ... >>> 或 cudaLaunchKernel API启动 kernel,就可以确保这个 kernel 只能使用该 stream 所属 execution context 可用的资源(例如 SM、work queue)。
 // 为之前创建好的 green_ctx 创建 green_ctx_stream CUDA streamcudaStream_t green_ctx_stream;int priority = 0;CUDA_CHECK(cudaExecutionCtxStreamCreate(&green_ctx_stream,                                        green_ctx,                                        cudaStreamDefault,                                        priority));// my_kernel 只能使用 green_ctx_stream 的 execution context 所提供的资源// (按适用情况,包括 SM、work queue)my_kernel<<<grid_dim, block_dim, 0, green_ctx_stream>>>();CUDA_CHECK(cudaGetLastError());

总结

Green Context 的核心价值,不是简单地“限制 kernel 能用多少个 SM”,而是给 CUDA 提供了一种更可控的资源管理方式。它把原本机会式的并行,进一步变成了可规划的并行。通过把 SM 和 workqueue 资源按 context 进行划分,应用可以在低时延、吞吐和隔离性之间做更灵活的权衡。对需要保障关键任务响应时间、减少多 stream 相互干扰、或验证不同资源配比效果的场景来说,Green Context 提供了一种几乎不需要修改 kernel、只需少量 host 侧改造就能落地的新手段。

【声明】内容源于网络
0
0
AI Infra之道
AI infra时代已经到来,大家一起打造中国的AI知识库
内容 16
粉丝 0
AI Infra之道 AI infra时代已经到来,大家一起打造中国的AI知识库
总阅读10
粉丝0
内容16