# User Manual ## Index - [Config](#Config) - [Scheduling GPUs](#Scheduling-GPUs) ## Config ### Config QuickStart 1. Config `skuTypes` **Description:** A `skuType` defines a **resource unit** in all resource dimensions. Notes: 1. It is like the [Azure VM Series](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes-gpu) or [GCP Machine Types](https://cloud.google.com/compute/docs/machine-types). 2. Currently, the `skuTypes` is not directly used by HivedScheduler, but it is used by [OpenPAI RestServer](https://github.com/microsoft/pai/tree/master/src/rest-server) to setup proportional Pod resource requests and limits. So, if you are not using with [OpenPAI RestServer](https://github.com/microsoft/pai/tree/master/src/rest-server), you can skip to config it. **Example:** Assume you have some `K80` nodes of the same SKU in your cluster, and you want to schedule Pods on them: 1. Using `kubectl describe nodes` to check if these `K80` nodes have nearly the same ([Allocatable Resources](https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources) - [All Daemon Pods Requests, such as Pods for Device Plugin, Network Plugin, etc](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container)), especially for gpu, cpu, memory. If not, please fix it. Assume the aligned minimal resources are: 4 gpus, 23 cpus, and 219GB memory. 2. Then proportionally, each gpu request should also has floor(23/4)=5 cpus and floor(219/4)=54GB memory along with it, so config the `K80` `skuType` as below: ```yaml physicalCluster: skuTypes: K80: gpu: 1 cpu: 5 memory: 54Gi ``` 2. Config `cellTypes` **Description:** A `cellType` defines a **resource topology** of a `skuType`. Notes: 1. `skuTypes` are also `cellTypes`, but they are all leaf `cellTypes` which do not have internal topology anymore. **Example:** 1. Using `nvidia-smi topo --matrix` to figure out the gpu topology on one above `K80` node: ``` GPU0 GPU1 GPU2 GPU3 CPU Affinity GPU0 X NODE NODE NODE 0-11 GPU1 NODE X NODE NODE 0-11 GPU2 NODE NODE X NODE 0-11 GPU3 NODE NODE NODE X 0-11 ``` 2. These 4 gpus are equivalent under the node, so config the `K80-NODE` `cellType` as below: ```yaml physicalCluster: cellTypes: K80-NODE: childCellType: K80 childCellNumber: 4 isNodeLevel: true ``` 3. Assume you have 3 above `K80` nodes under the same network switch or as a pool, so config the `K80-NODE-POOL` `cellType` as below: ```yaml physicalCluster: cellTypes: K80-NODE-POOL: childCellType: K80-NODE childCellNumber: 3 ``` 3. Config `physicalCells` **Description:** A `physicalCell` defines a **resource instance**, i.e. a `cellType` instantiated by a specific set of physical devices. **Example:** 1. Assume above 3 `K80` nodes have K8S node names `node1`, `node2` and `node3`, so config a `K80-NODE-POOL` `physicalCell` as below: ```yaml physicalCluster: physicalCells: - cellType: K80-NODE-POOL cellChildren: - cellAddress: node1 - cellAddress: node2 - cellAddress: node3 ``` 4. Config `virtualClusters` **Description:** A `virtualCluster` defines a **resource guaranteed quota** in terms of `cellTypes`. **Example:** 1. Assume you want to partition above 3 `K80` nodes to 2 virtual clusters: vc1 with 1 node and vc2 with 2 nodes, so config `vc1` and `vc2` `virtualCluster` as below: ```yaml virtualClusters: vc1: virtualCells: - cellType: K80-NODE-POOL.K80-NODE cellNumber: 1 vc2: virtualCells: - cellType: K80-NODE-POOL.K80-NODE cellNumber: 2 ``` Notes: 1. The name of `virtualCluster` should be constrained by the [K8S naming convention](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). 2. The `virtualCells.cellType` should be full qualified and should be started with a `cellType` which is explicitly referred in `physicalCells`. 5. Put it together **Example:** Finally, after above steps, your config would be: ```yaml physicalCluster: skuTypes: K80: gpu: 1 cpu: 5 memory: 54Gi cellTypes: K80-NODE: childCellType: K80 childCellNumber: 4 isNodeLevel: true K80-NODE-POOL: childCellType: K80-NODE childCellNumber: 3 physicalCells: - cellType: K80-NODE-POOL cellChildren: - cellAddress: node1 - cellAddress: node2 - cellAddress: node3 virtualClusters: vc1: virtualCells: - cellType: K80-NODE-POOL.K80-NODE cellNumber: 1 vc2: virtualCells: - cellType: K80-NODE-POOL.K80-NODE cellNumber: 2 ``` ### Config Detail [Detail Example](../example/config) ## Scheduling GPUs To leverage this scheduler to schedule GPUs, if one container in the Pod want to use the allocated GPUs for the whole Pod, it could contain below environment variables: * NVIDIA GPUs ```yaml env: - name: NVIDIA_VISIBLE_DEVICES valueFrom: fieldRef: fieldPath: metadata.annotations['hivedscheduler.microsoft.com/pod-leaf-cell-isolation'] ``` The scheduler directly delivers GPU isolation decision to [nvidia-container-runtime](https://github.com/NVIDIA/nvidia-container-runtime) through Pod Env `NVIDIA_VISIBLE_DEVICES`. * AMD GPUs ```yaml env: - name: AMD_VISIBLE_DEVICES valueFrom: fieldRef: fieldPath: metadata.annotations['hivedscheduler.microsoft.com/pod-leaf-cell-isolation'] ``` The scheduler directly delivers GPU isolation decision to [rocm-container-runtime](https://github.com/abuccts/rocm-container-runtime) through Pod Env `AMD_VISIBLE_DEVICES`. The annotation referred by the env will be populated by scheduler when bind the pod. If multiple containers in the Pod contain the env, the allocated GPUs are all visible to them, so it is these containers' freedom to control how to share these GPUs.