Skip to content

Commit 3cc38a1

Browse files
committed
incorporating Julian's suggested changes
1 parent ed49e36 commit 3cc38a1

File tree

4 files changed

+195
-95
lines changed

4 files changed

+195
-95
lines changed

example/mixed_precision.jl

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
1+
"""
2+
This example shows how to compute kernel matrix and infer the precision per tile.
3+
It import KernelFunctions and Distances Julia packages
4+
to compute distance matrix based by using Euclidean distance
5+
and then it calls GammaExponentialKernel for each resulted distance
6+
"""
17
using Dagger
28
using LinearAlgebra
39
using KernelFunctions
410
using Distances
511

12+
#Define Gamma value and distance matric to be used when computing kernel matrix
613
k = GammaExponentialKernel(; γ=0.5, metric=Euclidean());
7-
x = randn(4000, 2000);
14+
15+
#It generates matrix of normally-distributed random numbers
16+
x = randn(1000, 1000);
17+
18+
#This function will compute the distance between all points of x then it will apply Exponential Kernel
819
A = kernelmatrix(k, x);
9-
DA = view(A, Blocks(400, 400));
10-
MP = fill("FP64", 5, 5);
11-
DMP = view(MP, Blocks(1, 1));
1220

13-
Dagger.adaptive_mp!(DA, DMP, 10^-4);
14-
collect(DMP)
21+
#Create DA of the kernel matrix
22+
DA = view(A, Blocks(200, 200));
23+
24+
MP = Dagger.adapt_precision(DA, 10^-4)
25+

src/Dagger.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ include("array/sort.jl")
7474
include("array/linalg.jl")
7575
include("array/mul.jl")
7676
include("array/cholesky.jl")
77-
include("array/adaptive_mp.jl")
77+
include("array/adapt_precision.jl")
7878
# Visualization
7979
include("visualization.jl")
8080
include("ui/gantt-common.jl")

src/array/adapt_precision.jl

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
"""
2+
tile_precision(uplo, global_norm, scalar_factor, tolerance, A)
3+
4+
it receives tile and it compute required precision per tile
5+
6+
### Input
7+
- `A` -- tile of size m x n
8+
- `global_norm` -- global norm of the whole matrix
9+
- `scalar_factor` -- scale tile by this value which is the number of tiles
10+
- `tolerance` -- user defined tolerance as required aby the application
11+
12+
### Output
13+
The required precision of the tile
14+
15+
"""
16+
function tile_precision(A, global_norm, scalar_factor, tolerance)
17+
18+
tile_sqr = mapreduce(LinearAlgebra.norm_sqr, +, A)
19+
20+
tile_norm = sqrt(tile_sqr)
21+
22+
cal = tile_norm * scalar_factor / global_norm
23+
decision_hp = tile_norm * scalar_factor / global_norm < tolerance / eps(Float16)
24+
decision_sp = tile_norm * scalar_factor / global_norm < tolerance / eps(Float32)
25+
26+
#We are planning in near future to support fp8 E4M3 and E5M2
27+
#decision_fp8 = tile_norm * scalar_factor / global_norm < tolerance / 0.0625
28+
#if decision_fp8
29+
# return Float8
30+
if decision_hp
31+
return Float16
32+
elseif decision_sp
33+
return Float32
34+
else
35+
return Float64
36+
end
37+
end
38+
39+
"""
40+
function adapt_precision( A::UpperTriangular{T,<:DArray{T,2}},
41+
MP::UpperTriangular{String,<:DArray{String,2}}, tolerance::Float64) where {T}
42+
43+
it iterates over all tiles and calculates the required precision per tile based on formulation from Nicholas J. Higham
44+
45+
### Input
46+
- `A` -- Dagger UpperTriangular array of tiles with real values
47+
- `MP` -- Dagger UpperTriangular array to associate precision with each tile
48+
- `tolerance` -- User defined tolerance as required aby the application
49+
50+
### Output
51+
The Dagger array shows the required precision of each tile
52+
53+
"""
54+
55+
function adapt_precision(A::UpperTriangular{T,<:DArray{T,2}}, tolerance::Float64) where {T}
56+
57+
Ac = parent(A).chunks
58+
mt, nt = size(Ac)
59+
60+
global_norm = LinearAlgebra.norm2(A)
61+
62+
MP = fill(T, mt, nt)
63+
DMP = view(MP, Blocks(1, 1))
64+
MPc = parent(DMP).chunks
65+
66+
for n in range(1, nt)
67+
for m in range(1, n)
68+
if m == n
69+
MPc[m, n] = Dagger.@spawn tile_precision(
70+
UpperTriangular(Ac[m, n]),
71+
global_norm,
72+
max(mt, nt),
73+
tolerance)
74+
else
75+
MPc[m, n] = Dagger.@spawn tile_precision(
76+
Ac[m, n],
77+
global_norm,
78+
max(mt, nt),
79+
tolerance)
80+
end
81+
82+
end
83+
end
84+
85+
return UpperTriangular(collect(DMP))
86+
end
87+
88+
"""
89+
adapt_precision( A::LowerTriangular{T,<:DArray{T,2}},
90+
MP::LowerTriangular{String,<:DArray{String,2}}, tolerance::Float64) where {T}
91+
92+
it iterates over all tiles and calculates the required precision per tile based on formulation from Nicholas J. Higham
93+
94+
### Input
95+
- `A` -- Dagger LowerTriangular array of tiles with real values
96+
- `MP` -- Dagger LowerTriangular array to associate precision with each tile
97+
- `tolerance` -- User defined tolerance as required aby the application
98+
99+
### Output
100+
The Dagger array shows the required precision of each tile
101+
102+
"""
103+
104+
function adapt_precision(A::LowerTriangular{T,<:DArray{T,2}}, tolerance::T) where {T}
105+
106+
Ac = parent(A).chunks
107+
mt, nt = size(Ac)
108+
109+
global_norm = LinearAlgebra.norm2(A)
110+
111+
MP = fill(T, mt, nt)
112+
DMP = view(MP, Blocks(1, 1))
113+
MPc = parent(DMP).chunks
114+
115+
116+
for m in range(1, mt)
117+
for n in range(1, m)
118+
if m == n
119+
MPc[m, n] = Dagger.@spawn tile_precision(
120+
LowerTriangular(Ac[m, n]),
121+
global_norm,
122+
max(mt, nt),
123+
tolerance)
124+
else
125+
MPc[m, n] = Dagger.@spawn tile_precision(
126+
Ac[m, n],
127+
global_norm,
128+
max(mt, nt),
129+
tolerance)
130+
end
131+
132+
end
133+
end
134+
135+
return LowerTriangular(collect(DMP))
136+
end
137+
138+
"""
139+
adapt_precision(A::DArray{T,2}, MP::DArray{String,2}, tolerance::T) where {T}
140+
141+
it iterates over all tiles and calculates the required precision per tile based on formulation from Nicholas J. Higham
142+
143+
### Input
144+
- `A` -- Dagger array of tiles with real values
145+
- `MP` -- Dagger array to associate precision with each tile
146+
- `tolerance` -- User defined tolerance as required aby the application
147+
148+
### Output
149+
The Dagger array shows the required precision of each tile
150+
151+
"""
152+
153+
function adapt_precision(A::DArray{T,2}, tolerance::T) where {T}
154+
155+
Ac = parent(A).chunks
156+
mt, nt = size(Ac)
157+
158+
global_norm = LinearAlgebra.norm2(A)
159+
160+
MP = fill("Float64", mt, nt)
161+
DMP = view(MP, Blocks(1, 1))
162+
MPc = DMP.chunks
163+
164+
165+
for m in range(1, mt)
166+
for n in range(1, nt)
167+
MPc[m, n] =
168+
Dagger.@spawn tile_precision(
169+
Ac[m, n],
170+
global_norm,
171+
max(mt, nt),
172+
tolerance)
173+
end
174+
end
175+
176+
return collect(DMP)
177+
end

src/array/adaptive_mp.jl

Lines changed: 0 additions & 88 deletions
This file was deleted.

0 commit comments

Comments
 (0)