I’m trying to view the same memory region as a vector of different types of the same size. The goal is to view a (large) vector of integers as a vector of atomic integers (counts), to allow parallel threads to perform atomic operations to collect the value of these integers (loop on some very large data and increment the relevant counts - this is sparse enough that using atomics should make sense), then once the collection is done, use the result (total counts) as a normal vector of integers for further processing. Here is sample code which segfaults using Julia 1.6.1 - what am I doing wrong?
using Base.Threads
size = 10 # The value doesn't matter to the behavior below as long as it is positive.
# Start with a vector of integers (Int32).
vector_of_int = zeros(Int32, size)
println("vector_of_int = $(vector_of_int)")
flush(stdout)
# Obtain a pointer to the first element.
pointer_to_int = pointer(vector_of_int)
println("pointer_to_int = $(pointer_to_int)")
flush(stdout)
# Sanity test - viewing integers as floats.
# Reinterpret the pointer to an integer as a pointer to a float (Float32).
pointer_to_float = reinterpret(Ptr{Float32}, pointer_to_int)
println("pointer_to_float = $(pointer_to_float)")
flush(stdout)
# Wrap the pointer in a vector of floats.
wrap_of_float = unsafe_wrap(Vector{Float32}, pointer_to_float, (size,))
println("wrap_of_float = $(wrap_of_float)")
flush(stdout)
# Demonstrates this works by setting a value through the floats view.
wrap_of_float[1] = 1.0
println("set! wrap_of_float = $(wrap_of_float)")
flush(stdout)
# Show that this modified the original integers vector.
println("vector_of_int = $(vector_of_int)")
flush(stdout)
# So far, so good. Now for what doesn't work...
# Obtain a pointer to an atomic integer.
pointer_to_atomic_int = reinterpret(Ptr{Atomic{Int32}}, pointer_to_int)
println("pointer_to_atomic_int = $(pointer_to_atomic_int)")
flush(stdout)
# Wrap the pointer in a vector of atomic integers: SEGFAULT - WHY?
wrap_of_atomic_int = unsafe_wrap(Vector{Atomic{Int32}}, pointer_to_atomic_int, (size,))
println("wrap_of_atomic_int = $(wrap_of_atomic_int)")
flush(stdout)
# Goal of the exercise - be able to perform atomic operations (in parallel threads).
atomic_add!(wrap_of_atomic_int[1], 1)
println("atomic_add!")
flush(stdout)
# Show that this modified the original integers vector.
println("vector_of_int = $(vector_of_int)")
flush(stdout)
This produces the output:
vector_of_int = Int32[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
pointer_to_int = Ptr{Int32} @0x00007f916ec5a5d0
pointer_to_float = Ptr{Float32} @0x00007f916ec5a5d0
wrap_of_float = Float32[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
set! wrap_of_float = Float32[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
vector_of_int = Int32[1065353216, 0, 0, 0, 0, 0, 0, 0, 0, 0]
pointer_to_atomic_int = Ptr{Atomic{Int32}} @0x00007f916ec5a5d0
signal (11): Segmentation fault
in expression starting at /home/obk/Test.jl:48
unknown function (ip: 0x7f9172e4f2b2)
show_default at ./show.jl:395 [inlined]
show at ./show.jl:390 [inlined]
show_delim_array at ./show.jl:1092
show_delim_array at ./show.jl:1081 [inlined]
show_vector at ./arrayshow.jl:490
show_vector at ./arrayshow.jl:475 [inlined]
show at ./arrayshow.jl:446 [inlined]
print at ./strings/io.jl:35
unknown function (ip: 0x7f917304a3de)
string at ./strings/io.jl:174
unknown function (ip: 0x7f9184a6ee15)
unknown function (ip: 0x7f9184a6e9d5)
unknown function (ip: 0x7f9184a6f41b)
unknown function (ip: 0x7f9184a700d0)
unknown function (ip: 0x7f9184a8b457)
unknown function (ip: 0x7f9184a8c0fc)
jl_toplevel_eval_in at /usr/bin/../lib/julia/libjulia-internal.so.1 (unknown line)
unknown function (ip: 0x7f9172fdd9f7)
unknown function (ip: 0x7f9173035338)
unknown function (ip: 0x7f9173034db2)
unknown function (ip: 0x7f9172d686cc)
unknown function (ip: 0x7f9172d6adec)
unknown function (ip: 0x7f9172d6af55)
unknown function (ip: 0x7f9184aae76e)
repl_entrypoint at /usr/bin/../lib/julia/libjulia-internal.so.1 (unknown line)
main at julia (unknown line)
__libc_start_main at /usr/bin/../lib/libc.so.6 (unknown line)
_start at julia (unknown line)
Allocations: 1498826 (Pool: 1498247; Big: 579); GC: 2