Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DeviceRequests to HostConfig to support NVIDIA GPUs #38828

Merged
merged 1 commit into from
Mar 19, 2019

Conversation

tiborvass
Copy link
Contributor

@tiborvass tiborvass commented Mar 5, 2019

This patch hard-codes support for NVIDIA GPUs.
In a future patch it should move out into its own Device Plugin.

Signed-off-by: Tibor Vass tibor@docker.com

Closes #37434 #37504

The CLI part is at docker/cli#1714

Notes

I tried to keep the API generic enough for devices other than GPU for the future.

In addition to "options", there's this generic notion of "capabilities" that any device can advertise a set of, and then there's a matching happening when requesting devices. This should help with @thaJeztah and @tonistiigi's concerns about mixing "constraints" and "settings" (aka "options"). This is going to be even more important for orchestration and secure setups like in buildkit, where you'll have a separation between device requesters and providers.

For instance, any GPU vendor should add the "gpu" device capability to its docker device driver. They can also advertise other caps which can be used for matching the driver (and in the future, the node in a cluster).

Currently, the nvidia driver doesn't do anything with "options", but in the future it could decide to limit how much GPU memory should be used for instance. It's all the settings that would not be used for scheduling. Device capabilities include NVIDIA capabilities (compute, utility, etc.).

I'm happy to bikeshed on names, but would love to get review on the API itself.

cc @RenaudWasTaken @cpuguy83 @crosbymichael

@thaJeztah
Copy link
Member

Some linting failures;

04:24:38 pkg/capabilities/caps.go:1::warning: file is not gofmted with -s (gofmt)
04:24:38 pkg/capabilities/caps.go:1::warning: file is not goimported (goimports)
04:24:38 daemon/nvidia_linux.go:33:29:warning: unnecessary conversion (unconvert)

@cpuguy83
Copy link
Member

cpuguy83 commented Mar 5, 2019

Why are we doing this instead of the PR from Nvidia?

@thaJeztah
Copy link
Member

linking the other PR's; #37434 and #37504

@tiborvass
Copy link
Contributor Author

@cpuguy83 Because there's nothing specific about GPUs, it's just devices with prestart hooks. It's akin to Kubernetes device plugins. On the CLI however, it's --gpu.

daemon/nvidia_linux.go Outdated Show resolved Hide resolved
daemon/nvidia_linux.go Outdated Show resolved Hide resolved
daemon/nvidia_linux.go Show resolved Hide resolved
pkg/capabilities/caps.go Show resolved Hide resolved
Copy link
Contributor

@RenaudWasTaken RenaudWasTaken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A single small comment otherwise ship it!

daemon/nvidia_linux.go Outdated Show resolved Hide resolved
api/swagger.yaml Outdated Show resolved Hide resolved
api/swagger.yaml Show resolved Hide resolved
api/swagger.yaml Outdated Show resolved Hide resolved
Driver string // Name of device driver
Count int // Number of devices to request (-1 = All)
DeviceIDs []string // List of device IDs as recognizable by the device driver
Capabilities [][]string // An OR list of AND lists of device capabilities (e.g. "gpu")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were discussing Capabilities as a name for this (as it could be confused for Capabilities on the container itself (i.e. Linux capabilities)), but I can't come up with good alternatives; perhaps Features, but not sure if that's a good match

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand it but on the other hand, it's literally a list of what the device is capable of doing, what capabilities it provides. In this case it provides "gpu" capability, as well as nvidia-specific capabilities like "compute", etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only other names I can think of is "requirements" or "constraints", but I'm unsure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It only matches if all of these are matched, correct? "constraints" could work, but possibly too generic? idk. Naming is really hard on this one

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

design LGTM

api/swagger.yaml Outdated Show resolved Hide resolved
api/swagger.yaml Outdated Show resolved Hide resolved
@tiborvass tiborvass force-pushed the nvidia-gpu branch 2 times, most recently from 6904937 to 0e85958 Compare March 13, 2019 05:16
@codecov
Copy link

codecov bot commented Mar 13, 2019

Codecov Report

❗ No coverage uploaded for pull request base (master@36d2c8b). Click here to learn what that means.
The diff coverage is 22.22%.

@@            Coverage Diff            @@
##             master   #38828   +/-   ##
=========================================
  Coverage          ?   36.41%           
=========================================
  Files             ?      617           
  Lines             ?    45950           
  Branches          ?        0           
=========================================
  Hits              ?    16732           
  Misses            ?    26929           
  Partials          ?     2289

@tiborvass
Copy link
Contributor Author

Updated

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments inline, and saw that containerd/containerd#3093 was merged (so we can use the exported list)

Also could you add code to ignore the new field on older API versions on container-create?

if hostConfig != nil && versions.LessThan(version, "1.40") {
// Ignore BindOptions.NonRecursive because it was added in API 1.40.
for _, m := range hostConfig.Mounts {
if bo := m.BindOptions; bo != nil {
bo.NonRecursive = false
}
}
// Ignore KernelMemoryTCP because it was added in API 1.40.
hostConfig.KernelMemoryTCP = 0
// Ignore Capabilities because it was added in API 1.40.
hostConfig.Capabilities = nil
// Older clients (API < 1.40) expects the default to be shareable, make them happy
if hostConfig.IpcMode.IsEmpty() {
hostConfig.IpcMode = container.IpcMode("shareable")
}
}

pkg/capabilities/caps_test.go Outdated Show resolved Hide resolved
pkg/capabilities/caps.go Show resolved Hide resolved
daemon/devices_linux.go Outdated Show resolved Hide resolved
func (daemon *Daemon) handleDevice(req container.DeviceRequest, spec *specs.Spec) error {
if req.Driver == "" {
for _, dd := range deviceDrivers {
if selected := dd.capset.Match(req.Capabilities); selected != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I'm wondering: here, we match capabilities against the driver. So if a machine has (e.g.) two GPUs, and one of them supports "capA" and one of them "capB", then the driver would register itself with all of those (so driver says: "I provide capA and capB") correct?

This could result in a situation where none of the GPUs support the requested list of capabilities, i.e.;

Request GPU-A GPU-B Driver Driver Match GPU Match
"capA,capB" "capA, capC" "capB, capC" "capA,capB,capC"

What would happen in that case? (i.e., conversion to OCI succeeds, hook is registered, but no GPU is found)? Will a proper error be produced?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could make it an OR list of ANDs as well instead of a map.

Copy link
Member

@thaJeztah thaJeztah Mar 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should if this is a concern, so in that case the driver would report itself as;

{
  "capabilities": [
    ["capA", "capB"],
    ["capB", "capC"]
  ]
}

Could even decide to make it just return a list of capabilities for each GPU (then we can even determine the number of GPUs available);

{
  "capabilities": [
    ["capA", "capB"],
    ["capA", "capB"],
    ["capA", "capB"],
    ["capA", "capB"],
    ["capB", "capC"]
  ]
}

But perhaps that breaks the abstraction

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we punt on the problem since the problem is extremely unlikely to happen at this time and the structure is that of the device driver so it's internal, we can change it. The API needs to be locked down.

daemon/devices_linux.go Outdated Show resolved Hide resolved
api/swagger.yaml Show resolved Hide resolved
api/swagger.yaml Show resolved Hide resolved
api/swagger.yaml Show resolved Hide resolved
items:
type: "string"
example:
# gpu AND nvidia AND compute
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need an example for OR here?

Suggested change
# gpu AND nvidia AND compute
# gpu AND nvidia AND compute, OR gpu AND intel
- ["gpu", "nvidia", "compute"]
- ["gpu", "intel"]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's fine, the reason I put it there is so that we can support it in the future without breaking the API.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't want to support OR yet; we should error out if len(capabilities) > 1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is that it is supported, but not from the CLI.

api/swagger.yaml Show resolved Hide resolved
@tiborvass tiborvass force-pushed the nvidia-gpu branch 2 times, most recently from 7100ebf to accc53a Compare March 15, 2019 17:13
@tiborvass
Copy link
Contributor Author

@thaJeztah thanks for your review, I updated again.

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@thaJeztah
Copy link
Member

ping @cpuguy83 @kolyshkin ptal

@@ -49,6 +49,8 @@ keywords: "API, Docker, rcli, REST, documentation"
* `GET /info` now returns information about `DataPathPort` that is currently used in swarm
* `GET /info` now returns `PidsLimit` boolean to indicate if the host kernel has
PID limit support enabled.
* `GET /containers/create` now accepts `DeviceRequests` as part of `HostConfig`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, erm,

Suggested change
* `GET /containers/create` now accepts `DeviceRequests` as part of `HostConfig`.
* `POST /containers/create` now accepts `DeviceRequests` as part of `HostConfig`.
* `GET /containers/{id}/json` now returns `DeviceRequests` as part of `HostConfig`.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

facepalm

@thaJeztah
Copy link
Member

@tiborvass vendoring is failing;

22:23:22 The result of vndr differs
22:23:22 
22:23:22  M vendor/github.com/containerd/containerd/contrib/nvidia/nvidia.go
22:23:22 
22:23:22 Please vendor your package with github.com/LK4D4/vndr.

This patch hard-codes support for NVIDIA GPUs.
In a future patch it should move out into its own Device Plugin.

Signed-off-by: Tibor Vass <tibor@docker.com>
Copy link
Member

@vdemeester vdemeester left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🐯
But @tiborvass, we need to create issues related to the TODO's in there (to track future work)

@tiborvass
Copy link
Contributor Author

I'm merging since I see those windows errors are unrelated, they are also on other PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants