Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Copyright (c) NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

MODULE := github.com/nvidia/go-gpuallocator

DOCKER ?= docker

GOLANG_VERSION := 1.15

ifeq ($(IMAGE),)
REGISTRY ?= nvidia
IMAGE=$(REGISTRY)/go-gpuallocator
endif
IMAGE_TAG ?= $(GOLANG_VERSION)
BUILDIMAGE ?= $(IMAGE):$(IMAGE_TAG)-devel

TARGETS := binary build all check fmt assert-fmt generate lint vet test coverage
DOCKER_TARGETS := $(patsubst %, docker-%, $(TARGETS))
.PHONY: $(TARGETS) $(DOCKER_TARGETS)

GOOS := linux

build:
GOOS=$(GOOS) go build ./...

all: check build binary
check: assert-fmt lint vet

# Apply go fmt to the codebase
fmt:
go list -f '{{.Dir}}' $(MODULE)/... \
| xargs gofmt -s -l -w

assert-fmt:
go list -f '{{.Dir}}' $(MODULE)/... \
| xargs gofmt -s -l > fmt.out
@if [ -s fmt.out ]; then \
echo "\nERROR: The following files are not formatted:\n"; \
cat fmt.out; \
rm fmt.out; \
exit 1; \
else \
rm fmt.out; \
fi

generate:
go generate $(MODULE)/...

lint:
# We use `go list -f '{{.Dir}}' $(MODULE)/...` to skip the `vendor` folder.
go list -f '{{.Dir}}' $(MODULE)/... | grep -v pkg/nvml | xargs golint -set_exit_status

vet:
go vet $(MODULE)/...

COVERAGE_FILE := coverage.out
test: build
go test -v -coverprofile=$(COVERAGE_FILE) $(MODULE)/...

coverage: test
cat $(COVERAGE_FILE) | grep -v "_mock.go" > $(COVERAGE_FILE).no-mocks
go tool cover -func=$(COVERAGE_FILE).no-mocks

# Generate an image for containerized builds
# Note: This image is local only
.PHONY: .build-image .pull-build-image .push-build-image
.build-image: docker/Dockerfile.devel
if [ "$(SKIP_IMAGE_BUILD)" = "" ]; then \
$(DOCKER) build \
--progress=plain \
--build-arg GOLANG_VERSION="$(GOLANG_VERSION)" \
--tag $(BUILDIMAGE) \
-f $(^) \
docker; \
fi

.pull-build-image:
$(DOCKER) pull $(BUILDIMAGE)

.push-build-image:
$(DOCKER) push $(BUILDIMAGE)

$(DOCKER_TARGETS): docker-%: .build-image
@echo "Running 'make $(*)' in docker container $(BUILDIMAGE)"
$(DOCKER) run \
--rm \
-e GOCACHE=/tmp/.cache \
-v $(PWD):$(PWD) \
-w $(PWD) \
--user $$(id -u):$$(id -g) \
$(BUILDIMAGE) \
make $(*)

# Start an interactive shell using the development image.
PHONY: .shell
.shell:
$(DOCKER) run \
--rm \
-ti \
-e GOCACHE=/tmp/.cache \
-v $(PWD):$(PWD) \
-w $(PWD) \
--user $$(id -u):$$(id -g) \
$(BUILDIMAGE)
17 changes: 17 additions & 0 deletions docker/Dockerfile.devel
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright (c) NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
ARG GOLANG_VERSION=1.15
FROM golang:${GOLANG_VERSION}

RUN go get -u golang.org/x/lint/golint
30 changes: 15 additions & 15 deletions gpuallocator/besteffort_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ func NewBestEffortPolicy() Policy {
return &bestEffortPolicy{}
}

// Allocate finds the best set of 'size' GPUs to allocate from a list of
// available GPU devices and returns them. The algorithm is designed to
// ensure that a list of 'required' GPU devices is present in the final
// allocation.
// Allocate finds the best set of 'size' GPUs to allocate from a list of
// available GPU devices and returns them. The algorithm is designed to
// ensure that a list of 'required' GPU devices is present in the final
// allocation.
//
// This algorithm considers all possible sets of GPUs of size 'size'.
// However, it does not settle for the greedy solution of looking for the
// single set of size 'size' with the highest score. Instead, it looks for a
// solution that maximizes the total score when dividing up all available
// GPUs on the node into sets of size 'size' and then summing their
// individual scores. It then returns the set of GPUs from that grouping
// with the highest individual score.
// This algorithm considers all possible sets of GPUs of size 'size'.
// However, it does not settle for the greedy solution of looking for the
// single set of size 'size' with the highest score. Instead, it looks for a
// solution that maximizes the total score when dividing up all available
// GPUs on the node into sets of size 'size' and then summing their
// individual scores. It then returns the set of GPUs from that grouping
// with the highest individual score.
//
// Such a solution is necessary in the general case because of the
// non-hierarchical nature of the various links that influence the score
// calculated for each pair of GPUs.
// Such a solution is necessary in the general case because of the
// non-hierarchical nature of the various links that influence the score
// calculated for each pair of GPUs.
func (p *bestEffortPolicy) Allocate(available []*Device, required []*Device, size int) []*Device {
if size <= 0 {
return []*Device{}
Expand Down Expand Up @@ -218,7 +218,7 @@ func iterateGPUPartitions(devices []*Device, size int, callback func([][]*Device
// Optimize for the case when size == 1.
if size == 1 {
for _, device := range devices {
callback([][]*Device{[]*Device{device}})
callback([][]*Device{{device}})
}
return
}
Expand Down
4 changes: 2 additions & 2 deletions gpuallocator/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type P2PLink struct {
// DeviceSet is used to hold and manipulate a set of unique GPU devices.
type DeviceSet map[string]*Device

// Create a list of Devices from all available nvml.Devices.
// NewDevices creates a list of Devices from all available nvml.Devices.
func NewDevices() ([]*Device, error) {
count, err := nvml.GetDeviceCount()
if err != nil {
Expand Down Expand Up @@ -71,7 +71,7 @@ func NewDevices() ([]*Device, error) {
return devices, nil
}

// Create a list of Devices from the specific set of GPU uuids passed in.
// NewDevicesFrom creates a list of Devices from the specific set of GPU uuids passed in.
func NewDevicesFrom(uuids []string) ([]*Device, error) {
devices, err := NewDevices()
if err != nil {
Expand Down