Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

logbook interface, min max #18

Merged
merged 4 commits into from
Jul 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Sherlogs"
uuid = "d4954a42-a18b-4f81-bb79-24f1192c93d8"
authors = ["Milan Kloewer"]
version = "0.1.1"
version = "0.2.0"

[deps]
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
Expand Down
3 changes: 2 additions & 1 deletion src/Sherlog16.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
struct Sherlog16{T<:AbstractFloat,i} <: AbstractSherlog # T is the bitpattern type for logging, i is the logbook #
# T is the bitpattern type for logging, i is the logbook number
struct Sherlog16{T<:AbstractFloat,i} <: AbstractSherlog
val::T
end

Expand Down
4 changes: 2 additions & 2 deletions src/Sherlog64.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
abstract type AbstractSherlog <: AbstractFloat end

struct Sherlog64{T<:AbstractFloat,i} <: AbstractSherlog # T is the bitpattern type for logging
val::Float64 # the value is always Float64
struct Sherlog64{T<:AbstractFloat,i} <: AbstractSherlog # T is the bitpattern type for logging, i the logbook id
val::Float64 # the value is always Float64
end

# conversions back from Sherlog64
Expand Down
46 changes: 34 additions & 12 deletions src/logbook.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
struct LogBook
struct LogBook{T<:AbstractFloat} # provide the number format as T
logbook::Array{UInt64,1}
end

# in case no type T is provided use Float16
LogBook(lb::Array{UInt64,1}) = LogBook{Float16}(lb)

const n16 = 2^16
const nlogbooks = 32
const logbooks = [LogBook(zeros(UInt64,n16)) for _ in 1:nlogbooks]
Expand All @@ -19,7 +22,8 @@ end
"""Change the type T of logbook #id. Must be a 16bit type."""
function set_logbook(T::DataType,id::Int=1)
if sizeof(T) == 2 # must be a 16bit type
logbook_types[id] = T
# copy over the logbook but change type to T
logbooks[id] = LogBook{T}(logbooks[id].logbook)
else
error("$(sizeof(T)*8)bit type $T was provided but must be a 16bit type.")
end
Expand All @@ -41,32 +45,50 @@ Base.sum(lb::LogBook)::Int64 = sum(lb.logbook)
entropy(lb::LogBook,b::Real) = entropy(lb.logbook/sum(lb),b)
entropy(lb::LogBook) = entropy(lb.logbook/sum(lb))
Base.length(lb::LogBook) = length(lb.logbook)
Base.getindex(lb::LogBook,i) = Int(getindex(lb.logbook,i))
Base.getindex(lb::LogBook,i::Integer) = Int(getindex(lb.logbook,i))
Base.getindex(lb::LogBook,u::UnitRange) = Int.(getindex(lb.logbook,u))
Base.getindex(lb::LogBook,s::StepRange) = Int.(getindex(lb.logbook,s))
Base.lastindex(lb::LogBook) = Int(lb.logbook[end])

function Base.show(io::IO,lb::LogBook)
function Base.show(io::IO,lb::LogBook{T}) where T
n = length(lb)
if n > 10
print(io,"$n-element LogBook(")
print(io,"$n-element LogBook{$T}(")
[print(io,string(Int(i)),", ") for i in lb.logbook[1:5]]
print(io,"… , ")
[print(io,string(Int(i)),", ") for i in lb.logbook[end-5:end-1]]
print(io,string(Int(lb.logbook[end])),")")
else
print(io,"$n-element LogBook(")
print(io,"$n-element LogBook{$T}(")
[print(io,string(Int(i)),", ") for i in lb.logbook[1:end-1]]
print(io,string(Int(lb.logbook[end])),")")
end
end

function Base.maximum(lb::LogBook,T::DataType)
"""Find the largest number that was logged into the logbook `lb`."""
function Base.maximum(lb::LogBook{T}) where T
n_half = length(lb)÷2
i = n_half - findfirst(x->x>0,lb.logbook[n_half:-1:1]) + 1
return reinterpret(Float16,UInt16(i))
i = n_half - findfirst(x->x>0,lb[n_half:-1:1])
return reinterpret(T,UInt16(i))
end

function Base.minimum(lb::LogBook,T::DataType)
"""Find the smallest number that was logged into the logbook `lb`."""
function Base.minimum(lb::LogBook{T}) where T
n = length(lb)
i = n - findfirst(x->x>0,lb.logbook[n:-1:1]) + 1
return reinterpret(Float16,UInt16(i))
i = n - findfirst(x->x>0,lb[n:-1:1])
return reinterpret(T,UInt16(i))
end

"""Sort a logbook as [-NaNs,-∞,...,-0,0,...,∞,NaNs]"""
function Base.sort(lb::LogBook)
@views positives = lb.logbook[1:2^15]
@views negatives = lb.logbook[2^15+1:end]
lb_sorted = vcat(reverse(negatives),positives)
return LogBook(lb_sorted)
end

"""Convert a Float16/BFloat16 value to the corresponding UInt16 in a sorted logbook"""
function uint16_sort(x::AbstractFloat)
ui = reinterpret(UInt16,x) # will trigger an error for non-16bit floats
return signbit(x) ? 0x8000 - (ui - 0x7fff) : ui + 0x8000
end
7 changes: 4 additions & 3 deletions src/stacktraces.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function scent(f,r::Real)
function scent(f::Function,r::Real)
if f(r)
i = st_index[1]
if i <= nstackframes
Expand All @@ -13,14 +13,15 @@ function scent(f,r::Real)
end
end

const empty_sym = Symbol("")
const unknown_st = Base.StackTraces.StackFrame(empty_sym,empty_sym,-1,nothing,true,false,0)
empty_symbol = Symbol("")
const unknown_st = Base.StackTraces.StackFrame(empty_symbol,empty_symbol,-1,nothing,true,false,0)

const nstackframes = 10000 # quite arbitrary for the moment
const stackframe_depth = 3

const ST = [unknown_st for _ in 1:stackframe_depth, _ in 1:nstackframes]
const st_index = [1]

get_stacktrace(i::Int=1) = ST[:,i]
get_stacktraces() = ST[:,1:st_index[1]-1]
get_st_index() = st_index[1]
87 changes: 87 additions & 0 deletions test/logbook.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
@testset "Logbook count 64" begin

n = 100

# A SINGLE ENTRY IN THE LOGBOOK
reset_logbook()
Sherlog64(0)+Sherlog64(0)
lb = get_logbook()
@test 1 == sum(lb)

# N ENTRIES IN THE LOGBOOK
reset_logbook()
a = Sherlog64(1.0)
for i in 1:n
a + randn(Float64) # promotion included
end
lb = get_logbook()
@test n == sum(lb)
end

@testset "Logbook count 32" begin

n = 100

# A SINGLE ENTRY IN THE LOGBOOK
reset_logbook()
Sherlog32(0)+Sherlog32(0)
lb = get_logbook()
@test 1 == sum(lb)

# N ENTRIES IN THE LOGBOOK
reset_logbook()
a = Sherlog32(1.0)
for i in 1:n
a + randn(Float32) # promotion included
end
lb = get_logbook()
@test n == sum(lb)
end

@testset "Logbook count 16" begin

n = 100

# A SINGLE ENTRY IN THE LOGBOOK
reset_logbook()
Sherlog16(0)+Sherlog16(0)
lb = get_logbook()
@test 1 == sum(lb)

# N ENTRIES IN THE LOGBOOK
reset_logbook()
a = Sherlog16(1.0)
for i in 1:n
a + randn(Float16) # promotion included
end
lb = get_logbook()
@test n == sum(lb)
end

@testset "Minimum, maximum logbook Float16" begin

n = 100

for T in [Float16,Float32,Float64]

# MAXIMUM
for _ in 1:n
i = rand(1:32) # pick a random logbook
reset_logbook(i) # set it to zero
x = rand(T)
Sherlogs.log_it(Float16,x,i) # log a random Float16
logbook = get_logbook(i)
@test Float16(x) == maximum(logbook)
end

# MINIMUM
for _ in 1:n
i = rand(1:32) # pick a random logbook
reset_logbook(i) # set it to zero
x = -rand(Float16)
Sherlogs.log_it(Float16,x,i) # log a random Float16
logbook = get_logbook(i)
@test Float16(x) == minimum(logbook)
end
end
end
Loading