I wish to use the JLD package to write an OrderedDict to file in such a way that I can subsequently read it back unchanged.
Here was my first effort:
using JLD, HDF5, DataStructures
function testjld()
res = OrderedDict("A" => 1, "B" => 2)
filename = "c:/temp/test.jld"
save(File(format"JLD", filename), "res", res)
res2 = load(filename)["res"]
#Check if round-tripping works
res == res2
end
But the "round-tripping" doesn't work - the function returns false. It also raises a warning:
julia> testjld()
┌ Warning: type JLD.AssociativeWrapper{Core.String,Core.Int64,OrderedCollections.OrderedDict{Core.String,Core.Int64}} not present in workspace; reconstructing
└ # JLD C:\Users\Philip\.julia\packages\JLD\1BoSz\src\jld_types.jl:703
false
After reading the docs, I thought that JLD does not support OrderedDict "out of the box", but does support Dict and I can use that fact to write my own custom serialisation for OrderedDict. Something like this:
struct OrderedDictSerializer
d::Dict
end
JLD.writeas(data::OrderedDict) = OrderedDictSerializer(Dict("contents" => convert(Dict, data),
"keyorder" => [k for (k, v) in data]))
function JLD.readas(serdata::OrderedDictSerializer)
unordered = serdata.d["contents"]
keyorder = serdata.d["keyorder"]
OrderedDict((k, unordered[k]) for k in keyorder)
end
Hardly an exhaustive test, but this does seem to work:
julia> testjld()
true
Am I correct in thinking I need to write my own serializer for OrderedDict, and can my serializer be improved?
EDIT
The answer to to my question "Can my serializer be improved?" seems to be "It will have to be, though I don't yet understand how."
Consider the two following test functions:
function testjld2()
res = OrderedDict("A" => [1.0,2.0],"B" => [3.0,4.0])
#check if round-tripping of readas and writeas methods works:
JLD.readas(JLD.writeas(res)) == res
end
function testjld3()
res = OrderedDict("A" => [1.0,2.0],"B" => [3.0,4.0])
filename = "c:/temp/test.jld"
save(File(format"JLD", filename), "res", res)
res2 = load(filename)["res"]
#Check if round-tripping to jld file and back works
res == res2
end
testjld2 shows that my writeas and readas methods correctly round-trip for an OrderedDict{String,Array{Float64,1}} with 2 entries
julia> testjld2()
true
and yet testjld3 doesn't work at all, but yields an error:
julia> testjld3()
HDF5-DIAG: Error detected in HDF5 (1.10.5) thread 0:
#000: E:/mingwbuild/mingw-w64-hdf5/src/hdf5-1.10.5/src/H5Tfields.c line 60 in H5Tget_nmembers(): not a datatype
major: Invalid arguments to routine
minor: Inappropriate type
HDF5-DIAG: Error detected in HDF5 (1.10.5) thread 0:
#000: E:/mingwbuild/mingw-w64-hdf5/src/hdf5-1.10.5/src/H5Tfields.c line 60 in H5Tget_nmembers(): not a datatype
major: Invalid arguments to routine
minor: Inappropriate type
ERROR: Error getting the number of members
Stacktrace:
[1] error(::String) at .\error.jl:33
[2] h5t_get_nmembers at C:\Users\Philip\.julia\packages\HDF5\rF1Fe\src\HDF5.jl:2279 [inlined]
[3] _gen_h5convert!(::Any) at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\jld_types.jl:638
[4] #s27#9(::Any, ::Any, ::Any, ::Any, ::Any, ::Any) at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\jld_types.jl:664
[5] (::Core.GeneratedFunctionStub)(::Any, ::Vararg{Any,N} where N) at .\boot.jl:524
[6] #write_compound#24(::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::typeof(JLD.write_compound), ::JLD.JldGroup, ::String, ::JLD.AssociativeWrapper{String,Any,Dict{String,Any}}, ::JLD.JldWriteSession) at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:700
[7] write_compound at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:694 [inlined]
[8] #_write#23 at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:690 [inlined]
[9] _write at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:690 [inlined]
[10] write_ref(::JLD.JldFile, ::Dict{String,Any}, ::JLD.JldWriteSession) at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:658
[11] macro expansion at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\jld_types.jl:648 [inlined]
[12] h5convert!(::Ptr{UInt8}, ::JLD.JldFile, ::OrderedDictSerializer, ::JLD.JldWriteSession) at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\jld_types.jl:664
[13] #write_compound#24(::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::typeof(JLD.write_compound), ::JLD.JldFile, ::String, ::OrderedDictSerializer, ::JLD.JldWriteSession) at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:700
[14] write_compound at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:694 [inlined]
[15] #_write#23 at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:690 [inlined]
[16] _write at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:690 [inlined]
[17] #write#17(::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::typeof(write), ::JLD.JldFile, ::String, ::OrderedDict{String,Array{Float64,1}}, ::JLD.JldWriteSession) at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:514
[18] write at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:514 [inlined]
[19] #35 at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:1223 [inlined]
[20] #jldopen#14(::Base.Iterators.Pairs{Symbol,Bool,Tuple{Symbol,Symbol},NamedTuple{(:compatible, :compress),Tuple{Bool,Bool}}}, ::typeof(jldopen), ::getfield(JLD, Symbol("##35#36")){String,OrderedDict{String,Array{Float64,1}},Tuple{}},
::String, ::Vararg{String,N} where N) at C:\Users\Philip\.julia\packages\JLD\1BoSz\src\JLD.jl:246
[21] testjld3() at .\none:0
[22] top-level scope at REPL[48]:1
Use JLD2 instead:
using JLD2, DataStructures, FileIO
function testjld2()
res = OrderedDict("A" => 1, "B" => 2)
myfilename = "c:/temp/test.jld2"
save(myfilename, "res", res)
res2 = load(myfilename)["res"]
#Check if round-tripping works
res == res2
end
Testing:
julia> testjld2()
true
Personally, whenever I can I use BJSON:
using DataStructures, BSON, OrderedCollections
function testbson()
res = OrderedDict("A" => 1, "B" => 2)
myfilename = "c:/temp/test.bjson"
BSON.bson(myfilename, Dict("res" => res))
res2 = BSON.load(myfilename)["res"]
#Check if round-tripping works
res == res2
end
julia> testbson()
true
Related
I apologize at first if it turns out that I simply overlooked something. I am very new to Julia programming and am now stuck since a week on making the model zoo examples run on GPU.
With inspiration from https://github.com/FluxML/model-zoo/blob/master/vision/mnist/conv.jl I changed https://github.com/FluxML/model-zoo/blob/master/text/lang-detection/model.jl to this:
using Flux: onehot, onehotbatch, logitcrossentropy, reset!, throttle
using Statistics: mean
using Random
using Unicode
using Parameters: #with_kw
using CUDAapi
if has_cuda()
#info "CUDA is on"
import CUDA
#CUDA.allowscalar(false)
end
#with_kw mutable struct Args
lr::Float64 = 1e-3 # learning rate
N::Int = 300 # Number of perceptrons in hidden layer
test_len::Int = 100 # length of test data
langs_len::Int = 0 # Number of different languages in Corpora
alphabet_len::Int = 0 # Total number of characters possible, in corpora
throttle::Int = 5 # throttle timeout
end
function get_processed_data(args)
corpora = Dict()
for file in readdir("corpus")
lang = Symbol(match(r"(.*)\.txt", file).captures[1])
corpus = split(String(read("corpus/$file")), ".")
corpus = strip.(Unicode.normalize.(corpus, casefold=true, stripmark=true))
corpus = filter(!isempty, corpus)
corpora[lang] = corpus
end
langs = collect(keys(corpora))
args.langs_len = length(langs)
alphabet = ['a':'z'; '0':'9'; ' '; '\n'; '_']
args.alphabet_len = length(alphabet)
# See which chars will be represented as "unknown"
unique(filter(x -> x ∉ alphabet, join(vcat(values(corpora)...))))
dataset = [(onehotbatch(s, alphabet, '_'), onehot(l, langs)) for l in langs for s in corpora[l]] |> shuffle
train, test = dataset[1:end-args.test_len], dataset[end-args.test_len+1:end]
return train, test
end
function build_model(args)
scanner = Chain(Dense(args.alphabet_len, args.N, σ), LSTM(args.N, args.N))
encoder = Dense(args.N, args.langs_len)
return scanner, encoder
end
function model(x, scanner, encoder)
state = scanner.(x.data)[end]
reset!(scanner)
encoder(state)
end
function train(; kws...)
# Initialize Hyperparameters
args = Args(; kws...)
# Load Data
train_data, test_data = get_processed_data(args)
#info("Constructing Model...")
scanner, encoder = build_model(args)
# Load model and datasets onto GPU, if enabled
train_data = gpu.(train_data)
test_data = gpu.(test_data)
scanner = gpu(scanner)
encoder = gpu(encoder)
loss(x, y) = logitcrossentropy(model(x, scanner, encoder), y)
testloss() = mean(loss(t...) for t in test_data)
opt = ADAM(args.lr)
ps = params(scanner, encoder)
evalcb = () -> #show testloss()
#info("Training...")
Flux.train!(loss, ps, train_data, opt, cb = throttle(evalcb, args.throttle))
end
cd(#__DIR__)
train()
The result is:
[ Info: CUDA is on
[ Info: Constructing Model...
[ Info: Training...
ERROR: LoadError: CuArray only supports bits types
Stacktrace:
[1] error(::String) at .\error.jl:33
[2] CUDA.CuArray{CUDA.CuArray{Float32,1},1}(::UndefInitializer, ::Tuple{Int64}) at C:\Users\Fenmore\.julia\packages\CUDA\dZvbp\src\array.jl:115
[3] CUDA.CuArray{CUDA.CuArray{Float32,1},N} where N(::UndefInitializer, ::Tuple{Int64}) at C:\Users\Fenmore\.julia\packages\CUDA\dZvbp\src\array.jl:124
[4] similar(::Type{CUDA.CuArray{CUDA.CuArray{Float32,1},N} where N}, ::Tuple{Int64}) at .\abstractarray.jl:675
[5] similar(::Type{CUDA.CuArray{CUDA.CuArray{Float32,1},N} where N}, ::Tuple{Base.OneTo{Int64}}) at .\abstractarray.jl:674
[6] similar(::Base.Broadcast.Broadcasted{CUDA.CuArrayStyle{1},Tuple{Base.OneTo{Int64}},Zygote.var"#1177#1180"{Chain{Tuple{Dense{typeof(σ),CUDA.CuArray{Float32,2},CUDA.CuArray{Float32,1}},Flux.Recur{Flux.LSTMCell{CUDA.CuArray{Float32,2},CUDA.CuArray{Float32,1}}}}}},Tuple{Base.Broadcast.Extruded{CUDA.CuArray{Flux.OneHotVector,1},Tuple{Bool},Tuple{Int64}}}}, ::Type{CUDA.CuArray{Float32,1}}) at C:\Users\Fenmore\.julia\packages\CUDA\dZvbp\src\broadcast.jl:11
[7] copy at .\broadcast.jl:877 [inlined]
[8] materialize at .\broadcast.jl:837 [inlined]
[9] broadcast_forward at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\lib\broadcast.jl:190 [inlined]
[10] adjoint at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\lib\broadcast.jl:202 [inlined]
[11] _pullback at C:\Users\Fenmore\.julia\packages\ZygoteRules\6nssF\src\adjoint.jl:47 [inlined]
[12] adjoint at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\lib\lib.jl:175 [inlined]
[13] _pullback at C:\Users\Fenmore\.julia\packages\ZygoteRules\6nssF\src\adjoint.jl:47 [inlined]
[14] broadcasted at .\broadcast.jl:1257 [inlined]
[15] model at D:\Users\Fenmore\git\Term-Project\module.jl:55 [inlined]
[16] _pullback(::Zygote.Context, ::typeof(model), ::Flux.OneHotMatrix{CUDA.CuArray{Flux.OneHotVector,1}}, ::Chain{Tuple{Dense{typeof(σ),CUDA.CuArray{Float32,2},CUDA.CuArray{Float32,1}},Flux.Recur{Flux.LSTMCell{CUDA.CuArray{Float32,2},CUDA.CuArray{Float32,1}}}}}, ::Dense{typeof(identity),CUDA.CuArray{Float32,2},CUDA.CuArray{Float32,1}}) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface2.jl:0
[17] loss at D:\Users\Fenmore\git\Term-Project\module.jl:75 [inlined]
[18] _pullback(::Zygote.Context, ::var"#loss#35", ::Flux.OneHotMatrix{CUDA.CuArray{Flux.OneHotVector,1}}, ::Flux.OneHotVector) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface2.jl:0
[19] adjoint at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\lib\lib.jl:175 [inlined]
[20] _pullback at C:\Users\Fenmore\.julia\packages\ZygoteRules\6nssF\src\adjoint.jl:47 [inlined]
[21] #14 at C:\Users\Fenmore\.julia\packages\Flux\05b38\src\optimise\train.jl:83 [inlined]
[22] _pullback(::Zygote.Context, ::Flux.Optimise.var"#14#20"{var"#loss#35",Tuple{Flux.OneHotMatrix{CUDA.CuArray{Flux.OneHotVector,1}},Flux.OneHotVector}}) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface2.jl:0
[23] pullback(::Function, ::Zygote.Params) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface.jl:172
[24] gradient(::Function, ::Zygote.Params) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface.jl:53
[25] macro expansion at C:\Users\Fenmore\.julia\packages\Flux\05b38\src\optimise\train.jl:82 [inlined]
[26] macro expansion at C:\Users\Fenmore\.julia\packages\Juno\hEPx8\src\progress.jl:119 [inlined]
[27] train!(::Function, ::Zygote.Params, ::Array{Tuple{Flux.OneHotMatrix{CUDA.CuArray{Flux.OneHotVector,1}},Flux.OneHotVector},1}, ::ADAM; cb::Flux.var"#throttled#42"{Flux.var"#throttled#38#43"{Bool,Bool,var"#34#38"{var"#testloss#36"{var"#loss#35"}},Int64}}) at C:\Users\Fenmore\.julia\packages\Flux\05b38\src\optimise\train.jl:80
[28] train(; kws::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at D:\Users\Fenmore\git\Term-Project\module.jl:82
[29] train() at D:\Users\Fenmore\git\Term-Project\module.jl:62
[30] top-level scope at D:\Users\Fenmore\git\Term-Project\module.jl:86
[31] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1088
in expression starting at D:\Users\Fenmore\git\Term-Project\module.jl:86
Another model I tried is https://github.com/FluxML/model-zoo/blob/master/text/char-rnn/char-rnn.jl which I changed to:
using Flux
using Flux: onehot, chunk, batchseq, throttle, logitcrossentropy
using StatsBase: wsample
using Base.Iterators: partition
using Parameters: #with_kw
# Hyperparameter arguments
#with_kw mutable struct Args
lr::Float64 = 1e-2 # Learning rate
seqlen::Int = 50 # Length of batchseqences
nbatch::Int = 50 # number of batches text is divided into
throttle::Int = 30 # Throttle timeout
end
function getdata(args)
# Download the data if not downloaded as 'input.txt'
isfile("input.txt") ||
download("https://cs.stanford.edu/people/karpathy/char-rnn/shakespeare_input.txt","input.txt")
text = collect(String(read("input.txt")))
# an array of all unique characters
alphabet = [unique(text)..., '_']
text = map(ch -> onehot(ch, alphabet), text)
stop = onehot('_', alphabet)
N = length(alphabet)
# Partitioning the data as sequence of batches, which are then collected as array of batches
Xs = collect(partition(batchseq(chunk(text, args.nbatch), stop), args.seqlen))
Ys = collect(partition(batchseq(chunk(text[2:end], args.nbatch), stop), args.seqlen))
return Xs, Ys, N, alphabet
end
# Function to construct model
function build_model(N)
return Chain(
LSTM(N, 128),
LSTM(128, 128),
Dense(128, N))
end
function train(; kws...)
# Initialize the parameters
args = Args(; kws...)
# Get Data
Xs, Ys, N, alphabet = getdata(args)
# Constructing Model
m = build_model(N)
Xs = gpu.(Xs)
Ys = gpu.(Ys)
m = gpu(m)
function loss(xs, ys)
l = sum(logitcrossentropy.(m.(xs), ys))
return l
end
## Training
opt = ADAM(args.lr)
tx, ty = (Xs[5], Ys[5])
evalcb = () -> #show loss(tx, ty)
Flux.train!(loss, params(m), zip(Xs, Ys), opt, cb = throttle(evalcb, args.throttle))
return m, alphabet
end
# Sampling
function sample(m, alphabet, len; seed="")
m = cpu(m)
Flux.reset!(m)
buf = IOBuffer()
if seed == ""
seed = string(rand(alphabet))
end
write(buf, seed)
c = wsample(alphabet, softmax(m.(map(c -> onehot(c, alphabet), collect(seed)))[end]))
for i = 1:len
write(buf, c)
c = wsample(alphabet, softmax(m(onehot(c, alphabet))))
end
return String(take!(buf))
end
cd(#__DIR__)
m, alphabet = train()
sample(m, alphabet, 1000) |> println
With this result:
ERROR: LoadError: Mutating arrays is not supported
Stacktrace:
[1] error(::String) at .\error.jl:33
[2] (::Zygote.var"#455#456")(::Nothing) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\lib\array.jl:68
[3] (::Zygote.var"#2384#back#457"{Zygote.var"#455#456"})(::Nothing) at C:\Users\Fenmore\.julia\packages\ZygoteRules\6nssF\src\adjoint.jl:49
[4] CuArray at C:\Users\Fenmore\.julia\packages\CUDA\dZvbp\src\array.jl:206 [inlined]
[5] CuArray at C:\Users\Fenmore\.julia\packages\CUDA\dZvbp\src\array.jl:211 [inlined]
[6] (::typeof(∂(CUDA.CuArray{Float32,N} where N)))(::CUDA.CuArray{Float32,2}) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface2.jl:0
[7] LSTMCell at C:\Users\Fenmore\.julia\packages\Flux\05b38\src\cuda\curnn.jl:45 [inlined]
[8] (::typeof(∂(λ)))(::Tuple{Nothing,CUDA.CuArray{Float32,2}}) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface2.jl:0
[9] (::Zygote.var"#177#178"{typeof(∂(λ)),Tuple{Tuple{Nothing},Tuple{Nothing}}})(::Tuple{Nothing,CUDA.CuArray{Float32,2}}) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\lib\lib.jl:178
[10] (::Zygote.var"#1730#back#179"{Zygote.var"#177#178"{typeof(∂(λ)),Tuple{Tuple{Nothing},Tuple{Nothing}}}})(::Tuple{Nothing,CUDA.CuArray{Float32,2}}) at C:\Users\Fenmore\.julia\packages\ZygoteRules\6nssF\src\adjoint.jl:49
[11] Recur at C:\Users\Fenmore\.julia\packages\Flux\05b38\src\layers\recurrent.jl:36 [inlined]
[12] (::typeof(∂(λ)))(::CUDA.CuArray{Float32,2}) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface2.jl:0
[13] applychain at C:\Users\Fenmore\.julia\packages\Flux\05b38\src\layers\basic.jl:36 [inlined]
[14] (::typeof(∂(applychain)))(::CUDA.CuArray{Float32,2}) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface2.jl:0
[15] Chain at C:\Users\Fenmore\.julia\packages\Flux\05b38\src\layers\basic.jl:38 [inlined]
[16] (::typeof(∂(λ)))(::CUDA.CuArray{Float32,2}) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface2.jl:0
[17] #1157 at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\lib\broadcast.jl:142 [inlined]
[18] (::Base.var"#3#4"{Zygote.var"#1157#1164"})(::Tuple{typeof(∂(λ)),CUDA.CuArray{Float32,2}}) at .\generator.jl:36
[19] iterate at .\generator.jl:47 [inlined]
[20] collect(::Base.Generator{Base.Iterators.Zip{Tuple{Array{typeof(∂(λ)),1},Array{CUDA.CuArray{Float32,2},1}}},Base.var"#3#4"{Zygote.var"#1157#1164"}}) at .\array.jl:686
[21] map at .\abstractarray.jl:2248 [inlined]
[22] (::Zygote.var"#1156#1163"{Tuple{Array{Flux.OneHotMatrix{CUDA.CuArray{Flux.OneHotVector,1}},1}},Val{2},Array{typeof(∂(λ)),1}})(::Array{CUDA.CuArray{Float32,2},1}) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\lib\broadcast.jl:142
[23] #3985#back at C:\Users\Fenmore\.julia\packages\ZygoteRules\6nssF\src\adjoint.jl:49 [inlined]
[24] (::Zygote.var"#177#178"{Zygote.var"#3985#back#1167"{Zygote.var"#1156#1163"{Tuple{Array{Flux.OneHotMatrix{CUDA.CuArray{Flux.OneHotVector,1}},1}},Val{2},Array{typeof(∂(λ)),1}}},Tuple{Tuple{Nothing,Nothing,Nothing},Tuple{}}})(::Array{CUDA.CuArray{Float32,2},1}) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\lib\lib.jl:178
[25] #1730#back at C:\Users\Fenmore\.julia\packages\ZygoteRules\6nssF\src\adjoint.jl:49 [inlined]
[26] broadcasted at .\broadcast.jl:1257 [inlined]
[27] (::typeof(∂(broadcasted)))(::Array{CUDA.CuArray{Float32,2},1}) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface2.jl:0
[28] loss at C:\Users\Fenmore\github\model-zoo\text\char-rnn\char-rnn.jl:60 [inlined]
[29] (::typeof(∂(λ)))(::Float32) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface2.jl:0
[30] #177 at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\lib\lib.jl:178 [inlined]
[31] #1730#back at C:\Users\Fenmore\.julia\packages\ZygoteRules\6nssF\src\adjoint.jl:49 [inlined]
[32] #14 at C:\Users\Fenmore\.julia\packages\Flux\05b38\src\optimise\train.jl:83 [inlined]
[33] (::typeof(∂(λ)))(::Float32) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface2.jl:0
[34] (::Zygote.var"#54#55"{Zygote.Params,Zygote.Context,typeof(∂(λ))})(::Float32) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface.jl:177
[35] gradient(::Function, ::Zygote.Params) at C:\Users\Fenmore\.julia\packages\Zygote\rqvFi\src\compiler\interface.jl:54
[36] macro expansion at C:\Users\Fenmore\.julia\packages\Flux\05b38\src\optimise\train.jl:82 [inlined]
[37] macro expansion at C:\Users\Fenmore\.julia\packages\Juno\hEPx8\src\progress.jl:119 [inlined]
[38] train!(::Function, ::Zygote.Params, ::Base.Iterators.Zip{Tuple{Array{Array{Flux.OneHotMatrix{CUDA.CuArray{Flux.OneHotVector,1}},1},1},Array{Array{Flux.OneHotMatrix{CUDA.CuArray{Flux.OneHotVector,1}},1},1}}}, ::ADAM; cb::Flux.var"#throttled#42"{Flux.var"#throttled#38#43"{Bool,Bool,var"#25#27"{var"#loss#26",Array{Flux.OneHotMatrix{CUDA.CuArray{Flux.OneHotVector,1}},1},Array{Flux.OneHotMatrix{CUDA.CuArray{Flux.OneHotVector,1}},1}},Int64}}) at C:\Users\Fenmore\.julia\packages\Flux\05b38\src\optimise\train.jl:80
[39] train(; kws::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at C:\Users\Fenmore\github\model-zoo\text\char-rnn\char-rnn.jl:69
[40] train() at C:\Users\Fenmore\github\model-zoo\text\char-rnn\char-rnn.jl:47
[41] top-level scope at C:\Users\Fenmore\github\model-zoo\text\char-rnn\char-rnn.jl:91
[42] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1088
in expression starting at C:\Users\Fenmore\github\model-zoo\text\char-rnn\char-rnn.jl:91
I guess I can't just simply use these gpu() operations, but I have no idea where to start to figure out what else I have to do.
I appreciate any help.
Thanks in advance. =)
Suppose I make my own custom vector type with it's own custom show method:
struct MyVector{T} <: AbstractVector{T}
v::Vector{T}
end
function Base.show(io::IO, v::MyVector{T}) where {T}
println(io, "My custom vector with eltype $T with elements")
for i in eachindex(v)
println(io, " ", v.v[i])
end
end
If I try making one of these objects at the REPL I get unexpected errors related to functions I never intended to call:
julia> MyVector([1, 2, 3])
Error showing value of type MyVector{Int64}:
ERROR: MethodError: no method matching size(::MyVector{Int64})
Closest candidates are:
size(::AbstractArray{T,N}, ::Any) where {T, N} at abstractarray.jl:38
size(::BitArray{1}) at bitarray.jl:77
size(::BitArray{1}, ::Integer) at bitarray.jl:81
...
Stacktrace:
[1] axes at ./abstractarray.jl:75 [inlined]
[2] summary(::IOContext{REPL.Terminals.TTYTerminal}, ::MyVector{Int64}) at ./show.jl:1877
[3] show(::IOContext{REPL.Terminals.TTYTerminal}, ::MIME{Symbol("text/plain")}, ::MyVector{Int64}) at ./arrayshow.jl:316
[4] display(::REPL.REPLDisplay, ::MIME{Symbol("text/plain")}, ::Any) at /Users/mason/julia/usr/share/julia/stdlib/v1.3/REPL/src/REPL.jl:132
[5] display(::REPL.REPLDisplay, ::Any) at /Users/mason/julia/usr/share/julia/stdlib/v1.3/REPL/src/REPL.jl:136
[6] display(::Any) at ./multimedia.jl:323
...
Okay, whatever so I'll implement Base.size so it'll leave me alone:
julia> Base.size(v::MyVector) = size(v.v)
julia> MyVector([1, 2, 3])
3-element MyVector{Int64}:
Error showing value of type MyVector{Int64}:
ERROR: getindex not defined for MyVector{Int64}
Stacktrace:
[1] error(::String, ::Type) at ./error.jl:42
[2] error_if_canonical_getindex(::IndexCartesian, ::MyVector{Int64}, ::Int64) at ./abstractarray.jl:991
[3] _getindex at ./abstractarray.jl:980 [inlined]
[4] getindex at ./abstractarray.jl:981 [inlined]
[5] isassigned(::MyVector{Int64}, ::Int64, ::Int64) at ./abstractarray.jl:405
[6] alignment(::IOContext{REPL.Terminals.TTYTerminal}, ::MyVector{Int64}, ::UnitRange{Int64}, ::UnitRange{Int64}, ::Int64, ::Int64, ::Int64) at ./arrayshow.jl:67
[7] print_matrix(::IOContext{REPL.Terminals.TTYTerminal}, ::MyVector{Int64}, ::String, ::String, ::String, ::String, ::String, ::String, ::Int64, ::Int64) at ./arrayshow.jl:186
[8] print_matrix at ./arrayshow.jl:159 [inlined]
[9] print_array at ./arrayshow.jl:308 [inlined]
[10] show(::IOContext{REPL.Terminals.TTYTerminal}, ::MIME{Symbol("text/plain")}, ::MyVector{Int64}) at ./arrayshow.jl:345
[11] display(::REPL.REPLDisplay, ::MIME{Symbol("text/plain")}, ::Any) at /Users/mason/julia/usr/share/julia/stdlib/v1.3/REPL/src/REPL.jl:132
[12] display(::REPL.REPLDisplay, ::Any) at /Users/mason/julia/usr/share/julia/stdlib/v1.3/REPL/src/REPL.jl:136
[13] display(::Any) at ./multimedia.jl:323
...
Hmm, now it wants getindex
julia> Base.getindex(v::MyVector, args...) = getindex(v.v, args...)
julia> MyVector([1, 2, 3])
3-element MyVector{Int64}:
1
2
3
What? That wasn't the print formatting I told it to do! what's going on here?
The problem is that in julia, Base defines a method Base.show(io::IO ::MIME"text/plain", X::AbstractArray) which is actually more specific than the Base.show(io::IO, v::MyVector) for the purposes of display. This section of the julia manual describes the sort of custom printing that AbstractArray uses. So if we want to use our custom show method, we instead need to do
julia> function Base.show(io::IO, ::MIME"text/plain", v::MyVector{T}) where {T}
println(io, "My custom vector with eltype $T and elements")
for i in eachindex(v)
println(io, " ", v.v[i])
end
end
julia> MyVector([1, 2, 3])
My custom vector with eltype Int64 and elements
1
2
3
See also: https://discourse.julialang.org/t/extending-base-show-for-array-of-types/31289
I'm trying to learn Julia via project Euler. And for the largest prime factor problem I ran into an issue with out of memory error and I don't understand why.
I have tried the same solution in Python and had no issues.
function Primes(n)
numbers = Set{Int64}(2:n)
primes = Int64[]
while length(numbers)!=0
p = pop!(numbers,minimum(numbers))
push!(primes,p)
if length(numbers)!=0
numbers = setdiff(numbers,Set{Int64}(2*p:p:maximum(numbers)))
end
end
return primes
end
function LPF(n)
primes = Primes(n//2)
for p in primes
if n%p==0
return p
end
end
end
LPF(600851475143)
this is my error message:
OutOfMemoryError()
Stacktrace:
[1] _growend! at .\array.jl:811 [inlined]
[2] resize! at .\array.jl:1003 [inlined]
[3] rehash!(::Dict{Int64,Nothing}, ::Int64) at .\dict.jl:183
[4] sizehint! at .\dict.jl:242 [inlined]
[5] sizehint! at .\set.jl:64 [inlined]
[6] union!(::Set{Int64}, ::UnitRange{Rational{Int64}}) at .\abstractset.jl:79
[7] Type at .\set.jl:10 [inlined]
[8] Primes(::Rational{Int64}) at .\In[14]:2
[9] LPF(::Int64) at .\In[24]:2
[10] top-level scope at In[25]:1
I am having trouble with pmap() throwing a BoundsError when setting the values of array elements - my code works for 1 worker but not >1. I have written a minimum working example which roughly follows the real code flow:
Get source data
Define set of points over which to iterate
Initialise array points to be calculated
Calculate each array point
The main file:
#pmapdemo.jl
using Distributed
#addprocs(length(Sys.cpu_info())) # uncomment this line for error
#everywhere include(joinpath(#__DIR__, "pmapdemo2.jl"))
function main()
# Get source data
source = Dict{String, Any}("t"=>zeros(5),
"x"=>zeros(5,6),
"y"=>zeros(5,3),
"z"=>zeros(5,3))
# Define set of points over which to iterate
iterset = Dict{String, Any}("t"=>source["t"],
"x"=>source["x"],
"y"=>fill(2, size(source["t"])[1], 1),
"z"=>fill(2, size(source["t"])[1], 1))
data = Dict{String, Any}()
# Initialise array points to be calculated
MyMod.initialisearray!(data, iterset)
# Calculate each array point
MyMod.calcarray!(data, iterset, source)
#show data
end
main()
The functionality file:
#pmapdemo2.jl
module MyMod
using Distributed
#everywhere using SharedArrays
# Initialise data array
function initialisearray!(data, fieldset)
zerofield::SharedArray{Float64, 4} = zeros(size(fieldset["t"])[1],
size(fieldset["x"])[2],
size(fieldset["y"])[2],
size(fieldset["z"])[2])
data["field"] = deepcopy(zerofield)
end
# Calculate values of array elements according to values in source
function calcpoint!((data, source, a, b, c, d))
data["field"][a,b,c,d] = rand()
end
# Set values in array
function calcarray!(data, iterset, source)
for a in eachindex(iterset["t"])
# [additional functionality f(a) here]
b = eachindex(iterset["x"][a,:])
c = eachindex(iterset["y"][a,:])
d = eachindex(iterset["z"][a,:])
pmap(calcpoint!, Iterators.product(Iterators.repeated(data,1), Iterators.repeated(source,1), Iterators.repeated(a,1), b, c, d))
end
end
end
The error output:
ERROR: LoadError: On worker 2:
BoundsError: attempt to access 0×0×0×0 Array{Float64,4} at index [1]
setindex! at ./array.jl:767 [inlined]
setindex! at /build/julia/src/julia-1.1.1/usr/share/julia/stdlib/v1.1/SharedArrays/src/SharedArrays.jl:500 [inlined]
_setindex! at ./abstractarray.jl:1043
setindex! at ./abstractarray.jl:1020
calcpoint! at /home/dave/pmapdemo2.jl:25
#112 at /build/julia/src/julia-1.1.1/usr/share/julia/stdlib/v1.1/Distributed/src/process_messages.jl:269
run_work_thunk at /build/julia/src/julia-1.1.1/usr/share/julia/stdlib/v1.1/Distributed/src/process_messages.jl:56
macro expansion at /build/julia/src/julia-1.1.1/usr/share/julia/stdlib/v1.1/Distributed/src/process_messages.jl:269 [inlined]
#111 at ./task.jl:259
Stacktrace:
[1] (::getfield(Base, Symbol("##696#698")))(::Task) at ./asyncmap.jl:178
[2] foreach(::getfield(Base, Symbol("##696#698")), ::Array{Any,1}) at ./abstractarray.jl:1866
[3] maptwice(::Function, ::Channel{Any}, ::Array{Any,1}, ::Base.Iterators.ProductIterator{Tuple{Base.Iterators.Take{Base.Iterators.Repeated{Dict{String,Any}}},Base.Iterators.Take{Base.Iterators.Repeated{Dict{String,Any}}},Base.Iterators.Take{Base.Iterators.Repeated{Int64}},Base.OneTo{Int64},Base.OneTo{Int64},Base.OneTo{Int64}}}) at ./asyncmap.jl:178
[4] #async_usemap#681 at ./asyncmap.jl:154 [inlined]
[5] #async_usemap at ./none:0 [inlined]
[6] #asyncmap#680 at ./asyncmap.jl:81 [inlined]
[7] #asyncmap at ./none:0 [inlined]
[8] #pmap#213(::Bool, ::Int64, ::Nothing, ::Array{Any,1}, ::Nothing, ::Function, ::Function, ::WorkerPool, ::Base.Iterators.ProductIterator{Tuple{Base.Iterators.Take{Base.Iterators.Repeated{Dict{String,Any}}},Base.Iterators.Take{Base.Iterators.Repeated{Dict{String,Any}}},Base.Iterators.Take{Base.Iterators.Repeated{Int64}},Base.OneTo{Int64},Base.OneTo{Int64},Base.OneTo{Int64}}}) at /build/julia/src/julia-1.1.1/usr/share/julia/stdlib/v1.1/Distributed/src/pmap.jl:126
[9] pmap(::Function, ::WorkerPool, ::Base.Iterators.ProductIterator{Tuple{Base.Iterators.Take{Base.Iterators.Repeated{Dict{String,Any}}},Base.Iterators.Take{Base.Iterators.Repeated{Dict{String,Any}}},Base.Iterators.Take{Base.Iterators.Repeated{Int64}},Base.OneTo{Int64},Base.OneTo{Int64},Base.OneTo{Int64}}}) at /build/julia/src/julia-1.1.1/usr/share/julia/stdlib/v1.1/Distributed/src/pmap.jl:101
[10] #pmap#223(::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::Function, ::Base.Iterators.ProductIterator{Tuple{Base.Iterators.Take{Base.Iterators.Repeated{Dict{String,Any}}},Base.Iterators.Take{Base.Iterators.Repeated{Dict{String,Any}}},Base.Iterators.Take{Base.Iterators.Repeated{Int64}},Base.OneTo{Int64},Base.OneTo{Int64},Base.OneTo{Int64}}}) at /build/julia/src/julia-1.1.1/usr/share/julia/stdlib/v1.1/Distributed/src/pmap.jl:156
[11] pmap(::Function, ::Base.Iterators.ProductIterator{Tuple{Base.Iterators.Take{Base.Iterators.Repeated{Dict{String,Any}}},Base.Iterators.Take{Base.Iterators.Repeated{Dict{String,Any}}},Base.Iterators.Take{Base.Iterators.Repeated{Int64}},Base.OneTo{Int64},Base.OneTo{Int64},Base.OneTo{Int64}}}) at /build/julia/src/julia-1.1.1/usr/share/julia/stdlib/v1.1/Distributed/src/pmap.jl:156
[12] calcarray!(::Dict{String,Any}, ::Dict{String,Any}, ::Dict{String,Any}) at /home/dave/pmapdemo2.jl:20
[13] main() at /home/dave/pmapdemo.jl:19
[14] top-level scope at none:0
in expression starting at /home/dave/pmapdemo.jl:23
In pmapdemo2.jl, replacing data["field"][a,b,c,d] = rand() with #show a, b, c, d demonstrates that all workers are running and have full access to the variables being passed, however instead replacing it with #show data["field"] throws the same error. Surely the entire purpose of SharedArrays is to avoid this? Or am I misunderstanding how to use it with pmap?
This is a crosspost from the Julia discourse here.
pmap will do the work of passing the data to the processes, so you don't need to use SharedArrays. Typically, the function provided to pmap (and indeed map) will be a pure function (and therefore doesn't mutate any variable) which returns one element of an output array. That function is mapped across each element of the input array, and the pmap function will construct the output array for you. For example, in your case, the code may look a bit like this
calcpoint(source, (a,b,c,d)) = rand() # Or some function of source and the indices a,b,c,d
field["data"] = pmap(calcpoint, Iterators.repeated(source), Iterators.product(a,b,c,d))
I created a UnitRange in Julia and trying to create a plot of x with respect to x and x ^ 2. I have written the following code.
x = [-10:10]
p1 = plot(x, x)
p2 = plot(x, x.^2)
I am getting the following error:
MethodError: no method matching ^(::UnitRange{Int64}, ::Int64)
Closest candidates are:
^(!Matched::Float16, ::Integer) at math.jl:795
^(!Matched::Missing, ::Integer) at missing.jl:120
^(!Matched::Missing, ::Number) at missing.jl:93
...
Stacktrace:
[1] _broadcast_getindex at ./none:0 [inlined]
[2] getindex at ./broadcast.jl:515 [inlined]
[3] copy at ./broadcast.jl:790 [inlined]
[4] materialize(::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(Base.literal_pow),Tuple{Base.RefValue{typeof(^)},Array{UnitRange{Int64},1},Base.RefValue{Val{2}}}}) at ./broadcast.jl:756
[5] top-level scope at In[18]:3
What is the mistake in my code?
You can change:
x.^2
to:
x[1].^2