Skip to content

Commit eb29277

Browse files
committed
docs: added first draft of common gpu workflows in the GPU Support page
1 parent f4991e5 commit eb29277

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

docs/src/gpu.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# GPU Support
22

3-
NVIDIA GPU support should work out of the box on systems with CUDA and CUDNN installed. For more details see the [CUDA](https://github.com/JuliaGPU/CUDA.jl) readme.
3+
NVIDIA GPU support should work out of the box on systems with CUDA and CUDNN installed. For more details see the [CUDA.jl](https://github.com/JuliaGPU/CUDA.jl) readme.
44

55
## Checking GPU Availability
66

@@ -86,6 +86,64 @@ julia> x |> cpu
8686
0.7766742
8787
```
8888

89+
## Common GPU Workflows
90+
91+
Some of the common workflows involving the use of GPUs are presented below.
92+
93+
### Transferring Training Data
94+
95+
In order to train the model using the GPU both model and the training data have be transferred to GPU memory. This process can be done with the `gpu` function in two different ways:
96+
97+
1. Iterating over the batches in a [DataLoader](@ref) object transfering each one of the training batches at a time to the GPU.
98+
```julia
99+
train_loader = Flux.DataLoader((xtrain, ytrain), batchsize = 64, shuffle = true)
100+
# ... model, optimizer and loss definitions
101+
for epoch in 1:nepochs
102+
for (xtrain_batch, ytrain_batch) in train_loader
103+
x, y = gpu(xtrain_batch), gpu(ytrain_batch)
104+
gradients = gradient(() -> loss(x, y), parameters)
105+
Flux.Optimise.update!(optimizer, parameters, gradients)
106+
end
107+
end
108+
```
109+
110+
1. Transferring all training data to the GPU at once before creating the [DataLoader](@ref) object. This is usually performed for smaller datasets which are sure to fit in the available GPU memory. Some possitilities are:
111+
```julia
112+
gpu_x = gpu(xtrain)
113+
gpu_y = gpu(ytrain)
114+
115+
gpu_train_loader = Flux.DataLoader((gpu_x, gpu_y), batchsize = 32)
116+
```
117+
```julia
118+
gpu_train_loader = Flux.DataLoader((xtrain |> gpu, ytrain |> gpu), batchsize = 32)
119+
```
120+
```julia
121+
gpu_train_loader = Flux.DataLoader(gpu.(collect.((xtrain, ytrain))), batchsize = 32)
122+
```
123+
124+
### Saving GPU-Trained Models
125+
126+
After the training process is done one must always transfer the trained model back to the `cpu` memory scope before saving it to secundary memory. This can be done, as described in the previous section, with:
127+
```julia
128+
model = cpu(model) # or model = model |> cpu
129+
```
130+
and then
131+
```julia
132+
using BSON
133+
# ...
134+
BSON.@save "./path/to/trained_model.bson" model
135+
136+
# in this approach the cpu-transferred model (referenced by the variable `model`)
137+
# only exists inside the `let` statement
138+
let model = cpu(model)
139+
BSON.@save "./path/to/trained_model.bson" model
140+
end
141+
```
142+
The reason behind this is that models trained in the GPU but not transferred to the CPU memory scope will expect `CuArray`s as input. In other words, Flux models expect input data coming from the same kind device in which they were trained on.
143+
144+
In controlled scenarios in which the data fed to the loaded models is garanteed to be in the GPU there's no need to transfer them back to CPU memory scope, however in production environments, where artifacts are shared among different processes, equipments or configurations, there is no garantee that the CUDA.jl package will be available for the process performing inference on the model loaded from the disk.
145+
146+
89147
## Disabling CUDA or choosing which GPUs are visible to Flux
90148

91149
Sometimes it is required to control which GPUs are visible to `julia` on a system with multiple GPUs or disable GPUs entirely. This can be achieved with an environment variable `CUDA_VISIBLE_DEVICES`.

0 commit comments

Comments
 (0)