Skip to content

Commit 2b502b5

Browse files
authored
Support drawing normally distributed random numbers with randn (#39)
1 parent 6344b15 commit 2b502b5

File tree

5 files changed

+20
-2
lines changed

5 files changed

+20
-2
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "IPUToolkit"
22
uuid = "92e0b95a-4011-435a-96f4-10064551ddbe"
33
authors = ["Emily Dietrich <jakibaki@live.com>", "Luk Burchard <luk.burchard@gmail.com>", "Mosè Giordano <mose@gnu.org>"]
4-
version = "1.2.0"
4+
version = "1.3.0"
55

66
[deps]
77
Clang = "40e3b903-d033-50b4-a0cc-940c62c95e31"

docs/src/compiler.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,15 @@ IPUCompiler.PROGRESS_SPINNER
2929

3030
Inside codelets defined with [`@codelet`](@ref) all calls to random functions
3131

32+
* `rand(Float16)`
3233
* `rand(Float32)`
3334
* `rand(UInt32)`
3435
* `rand(UInt64)`
36+
* `randn(Float16)`
37+
* `randn(Float32)`
3538

36-
result to call to corresponding IPU builtins for [random number generation](https://docs.graphcore.ai/projects/poplar-api/en/latest/ipu_intrinsics/ipu_builtins.html#random-number-generation), but with the general semantic of the Julia function `rand` (numbers uniformely distributed in the $[0, 1)$ range).
39+
result to call to corresponding IPU builtins for [random number generation](https://docs.graphcore.ai/projects/poplar-api/en/latest/ipu_intrinsics/ipu_builtins.html#random-number-generation).
40+
The uniformly distributed numbers follow the general semantic of the Julia function `rand` (numbers uniformely distributed in the $[0, 1)$ range), while the normally distributed numbers have the properties described in the Poplar SDK documentation (numbers are in the range $[-5-13/16, 5+13/16]$).
3741

3842
Additionally, you can use the [IPU builtins](https://docs.graphcore.ai/projects/poplar-api/en/latest/ipu_intrinsics/ipu_builtins.html) listed below.
3943

src/compiler/codelet.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ function __build_codelet(graph::Poplar.GraphAllocated, kernel, name::String, ori
235235
"_llvm_colossus_urand_f32" => "llvm.colossus.urand.f32",
236236
"_llvm_colossus_urand32" => "llvm.colossus.urand32",
237237
"_llvm_colossus_urand64" => "llvm.colossus.urand64",
238+
"_llvm_colossus_f16v2grand" => "llvm.colossus.f16v2grand",
239+
"_llvm_colossus_f32v2grand" => "llvm.colossus.f32v2grand",
238240
)
239241

240242
method = methods(origKernel)[end]

src/compiler/runtime.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ Base.rand(T::Type{Float16}) = ccall("extern _llvm_colossus_urand_f16", llvmcall
4949
Base.rand(T::Type{Float32}) = ccall("extern _llvm_colossus_urand_f32", llvmcall, Float32, ()) + T(0.5)
5050
Base.rand(T::Type{UInt32}) = ccall("extern _llvm_colossus_urand32", llvmcall, UInt32, ()) + T(0.5)
5151
Base.rand(T::Type{UInt64}) = ccall("extern _llvm_colossus_urand64", llvmcall, UInt64, ()) + T(0.5)
52+
Base.randn(T::Type{Float16}) = @inbounds ccall("extern _llvm_colossus_f16v2grand", llvmcall, NTuple{2, VecElement{Float16}}, ())[1].value
53+
Base.randn(T::Type{Float32}) = @inbounds ccall("extern _llvm_colossus_f32v2grand", llvmcall, NTuple{2, VecElement{Float32}}, ())[1].value
5254

5355
## Math functions.
5456
# There are different reasons why we prefer LLVM intrinsics on the IPU: implementations in

test/compiler.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ function test_ipubuiltins(device)
198198
outvec1 = PoplarVector{Float16}(undef, N)
199199
outvec2 = PoplarVector{Float16}(undef, N)
200200
outvec3 = PoplarVector{Float16}(undef, N)
201+
outvec4 = PoplarVector{Float16}(undef, N)
201202

202203
@ipuprogram device begin
203204
function Random(out::VertexVector{Float16, Out})
@@ -214,14 +215,21 @@ function test_ipubuiltins(device)
214215
copyto!(out, in)
215216
sort!(out; rev=true)
216217
end
218+
function RandomNorm(out::VertexVector{Float16, Out})
219+
for idx in eachindex(out)
220+
out[idx] = randn(Float16)
221+
end
222+
end
217223

218224
Random(outvec1)
219225
TimesTwoSin(outvec1, outvec2)
220226
Sort16(outvec2, outvec3)
227+
RandomNorm(outvec4)
221228

222229
jl_outvec1 = outvec1
223230
jl_outvec2 = outvec2
224231
jl_outvec3 = outvec3
232+
jl_outvec4 = outvec4
225233
end
226234
Poplar.detach_devices()
227235
# There's a non-zero probability that this test may fail, but assuming an
@@ -230,6 +238,8 @@ function test_ipubuiltins(device)
230238
@test mean(jl_outvec1) 0.5 rtol=(pi * sqrt(N) / N)
231239
@test jl_outvec2 sin.(2 .* jl_outvec1)
232240
@test jl_outvec3 sort(jl_outvec2; rev=true)
241+
@test mean(jl_outvec4) 0 atol=0.02
242+
@test std(jl_outvec4) 1 rtol=0.02
233243
end
234244

235245
rosenbrock(x, y=4) = (1 - x) ^ 2 + 100 * (y - x ^ 2) ^ 2

0 commit comments

Comments
 (0)