The goal of this RFC is to discuss how we can expose the GPU support that was recently added to containerd by @crosbymichael in this PR: containerd/containerd#2330
Since there are multiple ways of implementing this, I think it makes sense to start with the user experience, i.e. the CLI. If we can agree on the format, the next step will be that I write a PR for API changes in the github.com/docker/docker/api/types package. My rationale being that if we decide to not allow some configuration options in the CLI, it would be useless to have api/types expose it. As a concrete example, if we don't allow passing options on a per-GPU basis, it shouldn't be part of the API.
After discussing with @crosbymichael, he advised to limit the support to GPUs. We are excluding other types of specialized hardware such as FPGAs, InfiniBand, ASICs... from this RFC.
This RFC introduces some vocabulary, then presents the approach I find is the most compelling.
GPU Vendors
- While the containerd PR is only for NVIDIA GPUs, the CLI should be able to support multiple vendors.
- For simplicity, we should enforce the GPU vendor to be a lowercase string with no special characters.
e.g. nvidia, intel or amd.
- Reverse-DNS notation (e.g.
com.nvidia) is too verbose and should probably be avoided for a CLI.
- The list of support GPU vendors could be hardcoded in the CLI and checked, since it's unlikely to change quickly, but it is not a requirement.
GPU identifiers
- GPU support should not be a boolean flag like
--with-gpus, users should be able to select a subset of all GPUs, similarly to --cpuset-cpus: nvidia=0,1,2,3
- We should not assume a numerical identifier for GPUs (unlike
--cpuset-cpus), GPUs can have a string representation, for instance a UUID: nvidia=GPU-fef8089b-4820-abfc-e83e-94318197576e
- The CLI can only verify the basic format of GPU identifiers, it can't detect if they are ultimately valid (e.g. if the GPU exists or not), this will be done later and will be vendor-specific.
GPU options
Suggested approach
Add two CLI options:
--gpus for specifying a list of GPUs (like --cpuset-cpus)
--gpus-opt for specifying a list of GPU options (like --storage-opt)
docker run --gpus nvidia=0,1,2,3 --gpus nvidia=GPU-abcd --gpus-opt nvidia.capabilities=compute --gpus-opt nvidia.kmods=true
The important element being the vendor name, which serves as a key for specifying options and identifiers.
I think this is easy to read since you don't have to pack everything in a single argument.
If we want per-GPU options, we can introduce some sort of indexing in --gpus-opt:
--gpus-opt nvidia.0.limit_mem=2GB
--gpus-opt nvidia[0].limit_mem=2GB
Discarded approaches
I think the approach above is the best, but here are some thoughts on other possibilities.
Single CSV argument
Similar to --mount, add a new argument --gpus which expects a CSV value.
docker run --gpus vendor=nvidia,options=capabilities=compute,options=kmods=true,0,1,2,3,GPU-abcd
This is explicit and everything is contained in one option, but it's also bizarre since we have nested equal signs, and we have to expand the list of GPU identifiers as multiple arguments, to avoid needing complicated quoting from the shell.
A follow-up question would then be: can you specify multiple times the same vendor? If yes, what if the listed options don't match?
Similar to --device
Add a new argument --gpus which expects 2 or 3 strings separated by :
docker run --gpus nvidia:0,1,2,3,GPU-abcd:capabilities=compute,kmods=true
Less problematic than approach above, but hard to read.
NVIDIA specific
Same than the suggested approach, but without being generic:
docker run --nvidia-gpus 0,1,2,3 --nvidia-gpus GPU-abcd --nvidia-opt capabilities=compute --nvidia-opt kmods=true
It removes the need to use the vendor name as the key, and is fine for now, but is likely to be removed in the future if we add more vendors. Also, this doesn't match the approach used by the containerd PR.
The goal of this RFC is to discuss how we can expose the GPU support that was recently added to containerd by @crosbymichael in this PR: containerd/containerd#2330
Since there are multiple ways of implementing this, I think it makes sense to start with the user experience, i.e. the CLI. If we can agree on the format, the next step will be that I write a PR for API changes in the
github.com/docker/docker/api/typespackage. My rationale being that if we decide to not allow some configuration options in the CLI, it would be useless to haveapi/typesexpose it. As a concrete example, if we don't allow passing options on a per-GPU basis, it shouldn't be part of the API.After discussing with @crosbymichael, he advised to limit the support to GPUs. We are excluding other types of specialized hardware such as FPGAs, InfiniBand, ASICs... from this RFC.
This RFC introduces some vocabulary, then presents the approach I find is the most compelling.
GPU Vendors
e.g.
nvidia,inteloramd.com.nvidia) is too verbose and should probably be avoided for a CLI.GPU identifiers
--with-gpus, users should be able to select a subset of all GPUs, similarly to--cpuset-cpus:nvidia=0,1,2,3--cpuset-cpus), GPUs can have a string representation, for instance a UUID:nvidia=GPU-fef8089b-4820-abfc-e83e-94318197576eGPU options
nvidia.capabilities = compute.limit_mem[0] = 2GB limit_mem[1] = 6GB.Suggested approach
Add two CLI options:
--gpusfor specifying a list of GPUs (like--cpuset-cpus)--gpus-optfor specifying a list of GPU options (like--storage-opt)The important element being the vendor name, which serves as a key for specifying options and identifiers.
I think this is easy to read since you don't have to pack everything in a single argument.
If we want per-GPU options, we can introduce some sort of indexing in
--gpus-opt:Discarded approaches
I think the approach above is the best, but here are some thoughts on other possibilities.
Single CSV argument
Similar to
--mount, add a new argument--gpuswhich expects a CSV value.This is explicit and everything is contained in one option, but it's also bizarre since we have nested equal signs, and we have to expand the list of GPU identifiers as multiple arguments, to avoid needing complicated quoting from the shell.
A follow-up question would then be: can you specify multiple times the same vendor? If yes, what if the listed options don't match?
Similar to
--deviceAdd a new argument
--gpuswhich expects 2 or 3 strings separated by:Less problematic than approach above, but hard to read.
NVIDIA specific
Same than the suggested approach, but without being generic:
It removes the need to use the vendor name as the key, and is fine for now, but is likely to be removed in the future if we add more vendors. Also, this doesn't match the approach used by the containerd PR.