Skip to content

Commit adfa0fd

Browse files
authored
Add Poplar.get_ipu_model to more easily obtain an IPU Model (#59)
1 parent 438bd84 commit adfa0fd

File tree

7 files changed

+54
-20
lines changed

7 files changed

+54
-20
lines changed

docs/src/poplar.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,21 @@ You can slice a tensor with the usual Julia notation `tensor[index1:index2]`, th
4949
5050
[`similar`](@ref) can be used to add to `graph` a tensor with the same shape and optionally element type as `tensor`, while [`copyto!`](@ref) can be used to copy elements of a CPU host array into an IPU tensor.
5151
52+
## Using `IPUToolkit.jl` without an IPU
53+
54+
While this package requires a physical IPU to use all the available features, you can still experiment with the IPU programming model even if you do not have access to a hardware IPU.
55+
The Poplar SDK provides a feature called IPU Model, which is a software emulation of the behaviour of the IPU hardware.
56+
While the IPU model comes with [some limitations](https://docs.graphcore.ai/projects/poplar-user-guide/en/latest/poplar_programs.html#programming-with-poplar), it can be useful for testing or debugging.
57+
58+
To use the IPU model in `IPUToolkit.jl`, define the device of your IPU program with `Poplar.IPUModelCreateDevice` (which calls [`IPUModel::createDevice`](https://docs.graphcore.ai/projects/poplar-api/en/3.4.0/poplar/profiling/IPUModel.html#_CPPv4NK6poplar8IPUModel12createDeviceE11OptionFlagsbj) under the hood):
59+
```julia
60+
device = Poplar.get_ipu_model()
61+
# Then the rest of the program continues as usual
62+
target = Poplar.DeviceGetTarget(device)
63+
graph = Poplar.Graph(target)
64+
# ...
65+
```
66+
5267
```@autodocs
5368
Modules = [IPUToolkit.Poplar]
5469
```

examples/main.jl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
using IPUToolkit.IPUCompiler
22
using IPUToolkit.Poplar
33

4-
device = if Poplar.SDK_VERSION < v"2.0"
5-
Poplar.IPUModelCreateDevice(Poplar.IPUModel())
6-
else
7-
Poplar.get_ipu_device()
8-
end
4+
device = Poplar.get_ipu_device()
95

106
target = Poplar.DeviceGetTarget(device)
117
graph = Poplar.Graph(target)

examples/tutorial1.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using IPUToolkit.Poplar
22

3-
# model = Poplar.IPUModel()
4-
# device = Poplar.IPUModelCreateDevice(model)
3+
# device = Poplar.get_ipu_model()
54
device = Poplar.get_ipu_device()
65

76
target = Poplar.DeviceGetTarget(device)

examples/tutorial2.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using IPUToolkit.Poplar
22

3-
# model = Poplar.IPUModel()
4-
# device = Poplar.IPUModelCreateDevice(model)
3+
# device = Poplar.get_ipu_model()
54
device = Poplar.get_ipu_device()
65

76
target = Poplar.DeviceGetTarget(device)

src/poplar.jl

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ const ATTACHED_DEVICES_LOCK = ReentrantLock()
207207

208208
# Be sure to quit all julia sessions which hold devices!!!
209209
"""
210-
Poplar.get_ipu_devices(n::Int, hint::Union{AbstractVector{<:Integer},Integer}=0)
210+
Poplar.get_ipu_devices(n::Int, hint::Union{AbstractVector{<:Integer},Integer}=0) -> Vector{Poplar.DeviceAllocated}
211211
212212
Try to attach to `n` IPU devices, returns a vector of the pointers to the devices
213213
successfully attached to. You can release them with `Poplar.DeviceDetach` (note that this
@@ -222,8 +222,8 @@ attach. It can have different types:
222222
* if of type `AbstractVector`, try to attach to `n` devices from that list of
223223
IDs.
224224
225-
See [`Poplar.get_ipu_device`](@ref) for requesting exactly one IPU device.
226-
To release all devices previously attached with `Poplar.get_ipu_devices` or [`Poplar.get_ipu_device`](@ref) use [`Poplar.detach_devices`](@ref).
225+
See [`Poplar.get_ipu_device`](@ref) for requesting exactly one IPU device, and [`Poplar.get_ipu_model`](@ref) for requesting an IPU Model.
226+
To release all devices previously attached with `Poplar.get_ipu_devices`, [`Poplar.get_ipu_device`](@ref), or [`Poplar.get_ipu_model`](@ref) use [`Poplar.detach_devices`](@ref).
227227
"""
228228
function get_ipu_devices(n::Int, hint::Union{AbstractVector{<:Integer},Integer}=0)
229229
lock(ATTACHED_DEVICES_LOCK) do
@@ -261,12 +261,16 @@ function get_ipu_devices(n::Int, hint::Union{AbstractVector{<:Integer},Integer}=
261261
end
262262

263263
"""
264-
Poplar.get_ipu_device(hint::Union{AbstractVector{<:Integer},Integer}=0)
264+
Poplar.get_ipu_device(hint::Union{AbstractVector{<:Integer},Integer}=0) -> Poplar.DeviceAllocated
265265
266266
Similar to [`Poplar.get_ipu_devices`](@ref), but request exactly one IPU device. If it can attach
267267
to a device, return that pointer only (not in a vector, like `get_ipu_devices`), otherwise
268-
return `nothing`. You can release the device with `Poplar.DeviceDetach(device)`.
269-
To release all devices previously attached with `Poplar.get_ipu_device` or [`Poplar.get_ipu_devices`](@ref) use [`Poplar.detach_devices`](@ref).
268+
return `nothing`.
269+
270+
See [`Poplar.get_ipu_model`](@ref) for requesting an IPU Model.
271+
272+
You can release the device with `Poplar.DeviceDetach(device)`.
273+
To release all devices previously attached with `Poplar.get_ipu_device`, [`Poplar.get_ipu_devices`](@ref), or [`Poplar.get_ipu_model`](@ref) use [`Poplar.detach_devices`](@ref).
270274
271275
The optional argument `hint` suggests to which device IDs to try and
272276
attach. It can have different types:
@@ -283,10 +287,33 @@ function get_ipu_device(hint::Union{AbstractVector{<:Integer},Integer}=0)
283287
return nothing
284288
end
285289

290+
"""
291+
Poplar.get_ipu_model(ipu_version::String="ipu2") -> Poplar.DeviceAllocated
292+
293+
Attach to an [IPU Model](https://docs.graphcore.ai/projects/poplar-user-guide/en/latest/poplar_programs.html#programming-with-poplar), and return the attached device.
294+
This uses [`IPUModel::createDevice`](https://docs.graphcore.ai/projects/poplar-api/en/3.4.0/poplar/profiling/IPUModel.html#_CPPv4NK6poplar8IPUModel12createDeviceE11OptionFlagsbj) under the hood.
295+
296+
The optional positional argument `ipu_version::String`, `ipu2` by default`, represents the version of the IPU to emulate.
297+
Valid values for `ipu_version` are `ipu1` and `ipu2` (for Mk1 and Mk2 IPU architectures respectively).
298+
299+
See [`Poplar.get_ipu_device`](@ref) and [`Poplar.get_ipu_devices`](@ref) for requesting one or mode hardware IPUs.
300+
301+
You can release the device with `Poplar.DeviceDetach(device)`.
302+
To release all devices previously attached with `Poplar.get_ipu_model`, [`Poplar.get_ipu_device`](@ref) or [`Poplar.get_ipu_devices`](@ref) use [`Poplar.detach_devices`](@ref).
303+
"""
304+
function get_ipu_model(ipu_version::String="ipu2")
305+
lock(ATTACHED_DEVICES_LOCK) do
306+
model = Poplar.IPUModel(ipu_version)
307+
device = Poplar.IPUModelCreateDevice(model)
308+
push!(ATTACHED_DEVICES, device)
309+
device
310+
end
311+
end
312+
286313
"""
287314
Poplar.detach_devices() -> Nothing
288315
289-
Detach all devices previously attached in the current Julia session with [`Poplar.get_ipu_devices`](@ref) or [`Poplar.get_ipu_device`](@ref).
316+
Detach all devices previously attached in the current Julia session with [`Poplar.get_ipu_devices`](@ref), [`Poplar.get_ipu_device`](@ref), or [`Poplar.get_ipu_model`](@ref).
290317
"""
291318
function detach_devices()
292319
lock(ATTACHED_DEVICES_LOCK) do

test/compiler.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,8 +347,7 @@ end
347347
match_mode=:any,
348348
Poplar.get_ipu_device())
349349
else
350-
model = @cxxtest Poplar.IPUModel()
351-
Poplar.IPUModelCreateDevice(model)
350+
Poplar.get_ipu_model()
352351
end
353352

354353
# Run a test program

test/poplar.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ end
100100

101101
# Test a simple program using a software-emulated IPU (IPU model)
102102
@testset "IPU Model" begin
103-
model = @cxxtest Poplar.IPUModel()
104-
device = @cxxtest Poplar.IPUModelCreateDevice(model)
103+
device = @cxxtest Poplar.get_ipu_model()
105104
test_poplar_program(device)
106105
end
107106

0 commit comments

Comments
 (0)