Skip to content

Commit 5413aa8

Browse files
authored
Update to ThreadingUtilities 0.4 and add Static.jl as a dependency. (#73)
* Update to ThreadingUtilities 0.4 and add Static.jl as a dependency. Fixes #71 * VectorizationBase 0.18 is probably fine * Start threading sooner
1 parent afd0f15 commit 5413aa8

File tree

10 files changed

+56
-175
lines changed

10 files changed

+56
-175
lines changed

Project.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ version = "0.2.10"
66
[deps]
77
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
88
LoopVectorization = "bdcacae8-1622-11e9-2a5c-532679323890"
9+
Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
910
ThreadingUtilities = "8290d209-cae3-49c0-8002-c8c24d57dab5"
1011
VectorizationBase = "3d5dd08c-fd9d-11e8-17fa-ed2836048c2f"
1112

1213
[compat]
1314
ArrayInterface = "3"
14-
LoopVectorization = "0.11.2"
15-
ThreadingUtilities = "0.2"
16-
VectorizationBase = "0.18.1"
15+
LoopVectorization = "0.11,0.12"
16+
Static = "0.2"
17+
ThreadingUtilities = "0.4"
18+
VectorizationBase = "0.18,0.19"
1719
julia = "1.5"
1820

1921
[extras]

benchmark/tilesearch.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11

22

33
using Octavian, VectorizationBase, ProgressMeter
4-
using Octavian: StaticFloat
4+
using Octavian: StaticFloat64
55
function matmul_pack_ab!(C, A, B, ::Val{W₁}, ::Val{W₂}, ::Val{R₁}, ::Val{R₂}) where {W₁, W₂, R₁, R₂}
66
M, N = size(C); K = size(B,1)
77
zc, za, zb = Octavian.zstridedpointer.((C,A,B))
88
nspawn = min(Threads.nthreads(), VectorizationBase.num_cores())
99
@elapsed(
1010
Octavian.matmul_pack_A_and_B!(
1111
zc, za, zb, StaticInt{1}(), StaticInt{0}(), M, K, N, nspawn,
12-
StaticFloat{W₁}(), StaticFloat{W₂}(), StaticFloat{R₁}(), StaticFloat{R₂}()
12+
StaticFloat64{W₁}(), StaticFloat64{W₂}(), StaticFloat64{R₁}(), StaticFloat64{R₂}()
1313
)
1414
)
1515
end

src/Octavian.jl

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ using VectorizationBase: align, AbstractStridedPointer, zstridedpointer,
66
static_sizeof, lazymul, StridedPointer, gesp, pause, pick_vector_width, has_feature,
77
num_cache_levels, cache_size, num_cores, num_cores, cache_inclusive, cache_linesize, ifelse
88
using LoopVectorization: maybestaticsize, matmul_params, preserve_buffer, CloseOpen
9-
using ArrayInterface: StaticInt, Zero, One, OptionallyStaticUnitRange, size, strides, offsets, indices,
10-
static_length, static_first, static_last, axes, dense_dims, stride_rank,
11-
StaticBool, True, False, gt, eq
9+
using ArrayInterface: OptionallyStaticUnitRange, size, strides, offsets, indices,
10+
static_length, static_first, static_last, axes, dense_dims, stride_rank
11+
12+
using Static: StaticInt, Zero, One, StaticBool, True, False, gt, eq, StaticFloat64,
13+
roundtostaticint, floortostaticint
1214

1315
using ThreadingUtilities:
14-
_atomic_add!, _atomic_umax!, _atomic_umin!,
15-
_atomic_load, _atomic_store!, _atomic_cas_cmp!,
16-
SPIN, WAIT, TASK, LOCK, STUP, taskpointer,
17-
wake_thread!, __wait, load, store!
16+
_atomic_add!, _atomic_load, _atomic_store!,
17+
launch, wait, load, store!
1818

1919
export StaticInt
2020
export matmul!
@@ -24,7 +24,6 @@ export matmul_serial
2424

2525
include("global_constants.jl")
2626
include("types.jl")
27-
include("staticfloats.jl")
2827
include("integerdivision.jl")
2928
include("memory_buffer.jl")
3029
include("block_sizes.jl")

src/funcptrs.jl

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
struct LoopMulFunc{P,TC,TA,TB,Α,Β,Md,Kd,Nd} <: Function end
44
function (::LoopMulFunc{P,TC,TA,TB,Α,Β,Md,Kd,Nd})(p::Ptr{UInt}) where {P,TC,TA,TB,Α,Β,Md,Kd,Nd}
5-
offset, C = load(p, TC, 1)
5+
offset, C = load(p, TC, 2*sizeof(UInt))
66
offset, A = load(p, TA, offset)
77
offset, B = load(p, TB, offset)
88
offset, α = load(p, Α, offset)
@@ -27,7 +27,7 @@ call_loopmul!(C, A, B, α, β, M, K, N, ::Val{P}) where {P} = _call_loopmul!(C,
2727

2828
struct SyncMulFunc{TC,TA,TB,Α,Β,Md,Kd,Nd,AP,BCP,ID,TT,W₁,W₂,R₁,R₂} <: Function end
2929
function (::SyncMulFunc{TC,TA,TB,Α,Β,Md,Kd,Nd,AP,BCP,ID,TT,W₁,W₂,R₁,R₂})(p::Ptr{UInt}) where {TC,TA,TB,Α,Β,Md,Kd,Nd,AP,BCP,ID,TT,W₁,W₂,R₁,R₂}
30-
offset, C = load(p, TC, 1)
30+
offset, C = load(p, TC, 2*sizeof(UInt))
3131
offset, A = load(p, TA, offset)
3232
offset, B = load(p, TB, offset)
3333
offset, α = load(p, Α, offset)
@@ -39,7 +39,7 @@ function (::SyncMulFunc{TC,TA,TB,Α,Β,Md,Kd,Nd,AP,BCP,ID,TT,W₁,W₂,R₁,R₂
3939
offset, bcachep = load(p, BCP, offset)
4040
offset, id = load(p, ID, offset)
4141
offset, total_ids = load(p, TT, offset)
42-
sync_mul!(C, A, B, α, β, M, K, N, atomicp, bcachep, id, total_ids, StaticFloat{W₁}(), StaticFloat{W₂}(), StaticFloat{R₁}(), StaticFloat{R₂}())
42+
sync_mul!(C, A, B, α, β, M, K, N, atomicp, bcachep, id, total_ids, StaticFloat64{W₁}(), StaticFloat64{W₂}(), StaticFloat64{R₁}(), StaticFloat64{R₂}())
4343
nothing
4444
end
4545

@@ -52,7 +52,7 @@ end
5252
end
5353

5454
@inline function setup_matmul!(p::Ptr{UInt}, C::TC, A::TA, B::TB, α::Α, β::Β, M::Md, K::Kd, N::Nd, ::Val{P}) where {P,TC,TA,TB,Α,Β,Md,Kd,Nd}
55-
offset = store!(p, cfuncpointer(LoopMulFunc{P,TC,TA,TB,Α,Β,Md,Kd,Nd}()), 0)
55+
offset = store!(p, cfuncpointer(LoopMulFunc{P,TC,TA,TB,Α,Β,Md,Kd,Nd}()), sizeof(UInt))
5656
offset = store!(p, C, offset)
5757
offset = store!(p, A, offset)
5858
offset = store!(p, B, offset)
@@ -66,9 +66,9 @@ end
6666

6767
@inline function setup_syncmul!(
6868
p::Ptr{UInt}, C::TC, A::TA, B::TB, α::Α, β::Β, M::Md, K::Kd, N::Nd,
69-
ap::AP,bcp::BCP,id::ID,tt::TT,::StaticFloat{W₁},::StaticFloat{W₂},::StaticFloat{R₁},::StaticFloat{R₂}
69+
ap::AP,bcp::BCP,id::ID,tt::TT,::StaticFloat64{W₁},::StaticFloat64{W₂},::StaticFloat64{R₁},::StaticFloat64{R₂}
7070
) where {TC,TA,TB,Α,Β,Md,Kd,Nd,AP,BCP,ID,TT,W₁,W₂,R₁,R₂}
71-
offset = store!(p, cfuncpointer(SyncMulFunc{TC,TA,TB,Α,Β,Md,Kd,Nd,AP,BCP,ID,TT,W₁,W₂,R₁,R₂}()), 0)
71+
offset = store!(p, cfuncpointer(SyncMulFunc{TC,TA,TB,Α,Β,Md,Kd,Nd,AP,BCP,ID,TT,W₁,W₂,R₁,R₂}()), sizeof(UInt))
7272
offset = store!(p, C, offset)
7373
offset = store!(p, A, offset)
7474
offset = store!(p, B, offset)
@@ -85,44 +85,18 @@ end
8585
end
8686

8787
function launch_thread_mul!(C, A, B, α, β, M, K, N, tid::Int, ::Val{P}) where {P}
88-
p = taskpointer(tid)
89-
while true
90-
if _atomic_cas_cmp!(p, SPIN, STUP)
91-
setup_matmul!(p, C, A, B, α, β, M, K, N, Val{P}())
92-
@assert _atomic_cas_cmp!(p, STUP, TASK)
93-
return
94-
elseif _atomic_cas_cmp!(p, WAIT, STUP)
95-
setup_matmul!(p, C, A, B, α, β, M, K, N, Val{P}())
96-
@assert _atomic_cas_cmp!(p, STUP, LOCK)
97-
wake_thread!(tid % UInt)
98-
return
99-
end
100-
pause()
88+
launch(tid, C, A, B, α, β, M, K, N, Val{P}()) do p, C, A, B, α, β, M, K, N, VP
89+
setup_matmul!(p, C, A, B, α, β, M, K, N, VP)
10190
end
10291
end
10392
function launch_thread_mul!(
104-
C, A, B, α, β, M, K, N, ap, bcp, tid, tt,::StaticFloat{W₁},::StaticFloat{W₂},::StaticFloat{R₁},::StaticFloat{R₂}
93+
C, A, B, α, β, M, K, N, ap, bcp, tid, tt,::StaticFloat64{W₁},::StaticFloat64{W₂},::StaticFloat64{R₁},::StaticFloat64{R₂}
10594
) where {W₁,W₂,R₁,R₂}
106-
p = taskpointer(tid+one(UInt))
107-
while true
108-
if _atomic_cas_cmp!(p, SPIN, STUP)
109-
setup_syncmul!(
110-
p, C, A, B, α, β, M, K, N, ap, bcp, tid, tt,
111-
StaticFloat{W₁}(),StaticFloat{W₂}(),StaticFloat{R₁}(),StaticFloat{R₂}()
112-
)
113-
@assert _atomic_cas_cmp!(p, STUP, TASK)
114-
return
115-
elseif _atomic_cas_cmp!(p, WAIT, STUP)
116-
# we immediately write the `atomicp, bc, tid, total_tids` part, so we can dispatch to the same code as the other methods
117-
setup_syncmul!(
118-
p, C, A, B, α, β, M, K, N, ap, bcp, tid, tt,
119-
StaticFloat{W₁}(),StaticFloat{W₂}(),StaticFloat{R₁}(),StaticFloat{R₂}()
120-
)
121-
@assert _atomic_cas_cmp!(p, STUP, LOCK)
122-
wake_thread!(tid+one(UInt))
123-
return
124-
end
125-
pause()
95+
launch(tid+one(tid), C, A, B, α, β, M, K, N, ap, bcp, tid, tt) do p, C, A, B, α, β, M, K, N, ap, bcp, tid, tt
96+
setup_syncmul!(
97+
p, C, A, B, α, β, M, K, N, ap, bcp, tid, tt,
98+
StaticFloat64{W₁}(),StaticFloat64{W₂}(),StaticFloat64{R₁}(),StaticFloat64{R₂}()
99+
)
126100
end
127101
end
128102

src/global_constants.jl

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,25 @@ MᵣW_mul_factor(::True) = StaticInt{4}()
1616
MᵣW_mul_factor(::False) = StaticInt{9}()
1717
MᵣW_mul_factor() = MᵣW_mul_factor(has_feature(Val(:x86_64_avx512f)))
1818

19-
W₁Default(::True) = StaticFloat{0.006089395198610773}()
20-
W₂Default(::True) = StaticFloat{0.7979822724696168}()
21-
R₁Default(::True) = StaticFloat{0.5900561503730485}()
22-
R₂Default(::True) = StaticFloat{0.762152930709678}()
23-
24-
W₁Default_arch(::Val{:znver1}) = StaticFloat{0.053918949422353986}()
25-
W₂Default_arch(::Val{:znver1}) = StaticFloat{0.3013238122374886}()
26-
R₁Default_arch(::Val{:znver1}) = StaticFloat{0.6077103834481342}()
27-
R₂Default_arch(::Val{:znver1}) = StaticFloat{0.8775382433240162}()
28-
29-
W₁Default_arch(::Union{Val{:znver2},Val{:znver3}}) = StaticFloat{0.1}()
30-
W₂Default_arch(::Union{Val{:znver2},Val{:znver3}}) = StaticFloat{0.993489411720157}()
31-
R₁Default_arch(::Union{Val{:znver2},Val{:znver3}}) = StaticFloat{0.6052218809954467}()
32-
R₂Default_arch(::Union{Val{:znver2},Val{:znver3}}) = StaticFloat{0.7594052633561165}()
33-
34-
W₁Default_arch(_) = StaticFloat{0.1}()
35-
W₂Default_arch(_) = StaticFloat{0.15989396641218157}()
36-
R₁Default_arch(_) = StaticFloat{0.4203583148344484}()
37-
R₂Default_arch(_) = StaticFloat{0.8775382433240162}()
19+
W₁Default(::True) = StaticFloat64{0.006089395198610773}()
20+
W₂Default(::True) = StaticFloat64{0.7979822724696168}()
21+
R₁Default(::True) = StaticFloat64{0.5900561503730485}()
22+
R₂Default(::True) = StaticFloat64{0.762152930709678}()
23+
24+
W₁Default_arch(::Val{:znver1}) = StaticFloat64{0.053918949422353986}()
25+
W₂Default_arch(::Val{:znver1}) = StaticFloat64{0.3013238122374886}()
26+
R₁Default_arch(::Val{:znver1}) = StaticFloat64{0.6077103834481342}()
27+
R₂Default_arch(::Val{:znver1}) = StaticFloat64{0.8775382433240162}()
28+
29+
W₁Default_arch(::Union{Val{:znver2},Val{:znver3}}) = StaticFloat64{0.1}()
30+
W₂Default_arch(::Union{Val{:znver2},Val{:znver3}}) = StaticFloat64{0.993489411720157}()
31+
R₁Default_arch(::Union{Val{:znver2},Val{:znver3}}) = StaticFloat64{0.6052218809954467}()
32+
R₂Default_arch(::Union{Val{:znver2},Val{:znver3}}) = StaticFloat64{0.7594052633561165}()
33+
34+
W₁Default_arch(_) = StaticFloat64{0.1}()
35+
W₂Default_arch(_) = StaticFloat64{0.15989396641218157}()
36+
R₁Default_arch(_) = StaticFloat64{0.4203583148344484}()
37+
R₂Default_arch(_) = StaticFloat64{0.8775382433240162}()
3838

3939
W₁Default(::False) = W₁Default_arch(VectorizationBase.cpu_name())
4040
W₂Default(::False) = W₂Default_arch(VectorizationBase.cpu_name())

src/matmul.jl

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ Only packs `A`. Primitively does column-major packing: it packs blocks of `A` in
33
"""
44
function matmul_st_only_pack_A!(
55
C::AbstractStridedPointer{T}, A::AbstractStridedPointer, B::AbstractStridedPointer,
6-
α, β, M, K, N, ::StaticFloat{W₁}, ::StaticFloat{W₂}, ::StaticFloat{R₁}, ::StaticFloat{R₂}
6+
α, β, M, K, N, ::StaticFloat64{W₁}, ::StaticFloat64{W₂}, ::StaticFloat64{R₁}, ::StaticFloat64{R₂}
77
) where {T, W₁, W₂, R₁, R₂}
88

99
mᵣ, nᵣ = matmul_params()
1010
((Mblock, Mblock_Mrem, Mremfinal, Mrem, Miter), (Kblock, Kblock_Krem, Krem, Kiter)) =
11-
solve_McKc(T, M, K, N, StaticFloat{W₁}(), StaticFloat{W₂}(), StaticFloat{R₁}(), StaticFloat{R₂}(), mᵣ)
11+
solve_McKc(T, M, K, N, StaticFloat64{W₁}(), StaticFloat64{W₂}(), StaticFloat64{R₁}(), StaticFloat64{R₂}(), mᵣ)
1212
for ko CloseOpen(Kiter)
1313
ksize = ifelse(ko < Krem, Kblock_Krem, Kblock)
1414
let A = A, C = C
@@ -236,7 +236,7 @@ end
236236
if maybeinline(M, N, T, ArrayInterface.is_column_major(A)) # check MUST be compile-time resolvable
237237
inlineloopmul!(pC, pA, pB, One(), Zero(), M, K, N)
238238
return
239-
elseif (nᵣ N) || (M*K*N < (StaticInt{13824}() * W))
239+
elseif (nᵣ N) || (M*K*N < (StaticInt{4096}() * W))
240240
loopmul!(pC, pA, pB, α, β, M, K, N)
241241
return
242242
else
@@ -336,14 +336,14 @@ end
336336
# If tasks is [0,1,2,3] (e.g., `CloseOpen(0,4)`), it will wait on `MULTASKS[i]` for `i = [1,2,3]`.
337337
function waitonmultasks(tasks)
338338
for tid tasks
339-
__wait(tid)
339+
wait(tid)
340340
end
341341
end
342342

343343
@inline allocref(::StaticInt{N}) where {N} = Ref{NTuple{N,UInt8}}()
344344
function matmul_pack_A_and_B!(
345345
C::AbstractStridedPointer{T}, A::AbstractStridedPointer, B::AbstractStridedPointer, α, β, M, K, N,
346-
tospawn::Int, ::StaticFloat{W₁}, ::StaticFloat{W₂}, ::StaticFloat{R₁}, ::StaticFloat{R₂}#, ::Val{1}
346+
tospawn::Int, ::StaticFloat64{W₁}, ::StaticFloat64{W₂}, ::StaticFloat64{R₁}, ::StaticFloat64{R₂}#, ::Val{1}
347347
) where {T,W₁,W₂,R₁,R₂}
348348
W = pick_vector_width(T)
349349
mᵣ, nᵣ = matmul_params()
@@ -356,8 +356,6 @@ function matmul_pack_A_and_B!(
356356
for i CloseOpen(2_to_spawn)
357357
_atomic_store!(p + i*cache_linesize(), zero(UInt))
358358
end
359-
# _atomic_umin!(p, zero(UInt)); _atomic_umin!(p + 8sizeof(UInt), zero(UInt))
360-
# Mbsize, Mrem, Mremfinal, _to_spawn = split_m(M, tospawn, mᵣW) # M is guaranteed to be > W because of `W ≥ M` condition for `jmultsplitn!`...
361359
Mblock_Mrem, Mblock_ = promote(Mbsize + W, Mbsize)
362360
u_to_spawn = _to_spawn % UInt
363361
tid = 0
@@ -366,11 +364,11 @@ function matmul_pack_A_and_B!(
366364
last_id = _to_spawn - One()
367365
for m CloseOpen(last_id) # ...thus the fact that `CloseOpen()` iterates at least once is okay.
368366
Mblock = ifelse(m < Mrem, Mblock_Mrem, Mblock_)
369-
launch_thread_mul!(C, A, B, α, β, Mblock, K, N, p, bc_ptr, m % UInt, u_to_spawn, StaticFloat{W₁}(),StaticFloat{W₂}(),StaticFloat{R₁}(),StaticFloat{R₂}())
367+
launch_thread_mul!(C, A, B, α, β, Mblock, K, N, p, bc_ptr, m % UInt, u_to_spawn, StaticFloat64{W₁}(),StaticFloat64{W₂}(),StaticFloat64{R₁}(),StaticFloat64{R₂}())
370368
A = gesp(A, (Mblock, Zero()))
371369
C = gesp(C, (Mblock, Zero()))
372370
end
373-
sync_mul!(C, A, B, α, β, Mremfinal, K, N, p, bc_ptr, last_id % UInt, u_to_spawn, StaticFloat{W₁}(), StaticFloat{W₂}(), StaticFloat{R₁}(), StaticFloat{R₂}())
371+
sync_mul!(C, A, B, α, β, Mremfinal, K, N, p, bc_ptr, last_id % UInt, u_to_spawn, StaticFloat64{W₁}(), StaticFloat64{W₂}(), StaticFloat64{R₁}(), StaticFloat64{R₂}())
374372
waitonmultasks(CloseOpen(One(), _to_spawn))
375373
end
376374
_free_bcache!(bc)
@@ -379,11 +377,11 @@ end
379377

380378
function sync_mul!(
381379
C::AbstractStridedPointer{T}, A::AbstractStridedPointer, B::AbstractStridedPointer, α, β, M, K, N, atomicp::Ptr{UInt}, bc::Ptr, id::UInt, total_ids::UInt,
382-
::StaticFloat{W₁}, ::StaticFloat{W₂}, ::StaticFloat{R₁}, ::StaticFloat{R₂}
380+
::StaticFloat64{W₁}, ::StaticFloat64{W₂}, ::StaticFloat64{R₁}, ::StaticFloat64{R₂}
383381
) where {T, W₁, W₂, R₁, R₂}
384382

385383
(Mblock, Mblock_Mrem, Mremfinal, Mrem, Miter), (Kblock, Kblock_Krem, Krem, Kiter), (Nblock, Nblock_Nrem, Nrem, Niter) =
386-
solve_block_sizes(T, M, K, N, StaticFloat{W₁}(), StaticFloat{W₂}(), StaticFloat{R₁}(), StaticFloat{R₂}(), One())
384+
solve_block_sizes(T, M, K, N, StaticFloat64{W₁}(), StaticFloat64{W₂}(), StaticFloat64{R₁}(), StaticFloat64{R₂}(), One())
387385

388386
# atomics = atomicp + 8sizeof(UInt)
389387
sync_iters = zero(UInt)
@@ -416,19 +414,12 @@ function sync_mul!(
416414
_B = default_zerobased_stridedpointer(bc, (One(), ksize))
417415
unsafe_copyto_avx!(gesp(_B, (Zero(), pack_offset)), gesp(B, (Zero(), pack_offset)), ksize, pack_len)
418416
# synchronize before starting the multiplication, to ensure `B` is packed
419-
# sync_iters += total_ids
420-
# _mv = _atomic_add!(atomicp, one(UInt))
421-
# while _mv < sync_iters
422-
# pause()
423-
# _mv = _atomic_umax!(atomicp, zero(UInt))
424-
# end
425417
_mv = _atomic_add!(myp, one(UInt))
426418
sync_iters += one(UInt)
427419
let atomp = atomicp
428420
for _ CloseOpen(total_ids)
429421
atomp += cache_linesize()
430422
atomp == myp && continue
431-
# while !_atomic_cas_cmp!(atomp, sync_iters, sync_iters)
432423
while _atomic_load(atomp) != sync_iters
433424
pause()
434425
end
@@ -450,17 +441,11 @@ function sync_mul!(
450441
A = gesp(A, (Zero(), ksize))
451442
B = gesp(B, (ksize, Zero()))
452443
# synchronize on completion so we wait until every thread is done with `Bpacked` before beginning to overwrite it
453-
# _mv = _atomic_add!(atomics, one(UInt))
454-
# while _mv < sync_iters
455-
# pause()
456-
# _mv = _atomic_umax!(atomics, zero(UInt))
457-
# end
458444
_mv = _atomic_add!(mys, one(UInt))
459445
let atoms = atomics
460446
for _ CloseOpen(total_ids)
461447
atoms += cache_linesize()
462448
atoms == mys && continue
463-
# while !_atomic_cas_cmp!(atoms, sync_iters, sync_iters)
464449
while _atomic_load(atoms) != sync_iters
465450
pause()
466451
end

src/staticfloats.jl

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

0 commit comments

Comments
 (0)