Skip to content

Commit 174d67d

Browse files
authored
move Info to C interface (#268)
1 parent 761d672 commit 174d67d

File tree

4 files changed

+76
-54
lines changed

4 files changed

+76
-54
lines changed

src/MPI.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ end
1111
isfile(depfile) || error("MPI not properly installed. Please run Pkg.build(\"MPI\")")
1212
end
1313

14+
macro mpichk(expr)
15+
esc(expr)
16+
end
17+
18+
1419
include(depfile)
1520

1621
include("mpi-base.jl")

src/mpi-base.jl

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ function Init()
206206
end
207207
ccall(MPI_INIT, Nothing, (Ref{Cint},), 0)
208208
atexit(refcount_dec)
209+
210+
# initialise constants
211+
INFO_NULL.cinfo = CInfo(MPI_INFO_NULL)
209212
end
210213

211214
"""
@@ -1728,11 +1731,11 @@ function Comm_get_parent()
17281731
end
17291732

17301733
function Comm_spawn(command::String, argv::Vector{String}, nprocs::Integer,
1731-
comm::Comm, errors = Vector{Cint}(undef, nprocs))
1734+
comm::Comm, errors = Vector{Cint}(undef, nprocs); kwargs...)
17321735
c_intercomm = Ref{CComm}()
17331736
ccall((:MPI_Comm_spawn, libmpi), Nothing,
17341737
(Cstring, Ptr{Ptr{Cchar}}, Cint, CInfo, Cint, CComm, Ref{CComm}, Ptr{Cint}),
1735-
command, argv, nprocs, CInfo(INFO_NULL), 0, CComm(comm), c_intercomm, errors)
1738+
command, argv, nprocs, Info(kwargs...), 0, CComm(comm), c_intercomm, errors)
17361739
return Comm(c_intercomm[])
17371740
end
17381741

@@ -1829,13 +1832,6 @@ if HAVE_MPI_COMM_C2F
18291832
function Comm(ccomm::CComm)
18301833
Comm(ccall((:MPI_Comm_c2f, libmpi), Cint, (CComm,), ccomm))
18311834
end
1832-
# Assume info is treated the same way
1833-
function CInfo(info::Info)
1834-
ccall((:MPI_Info_f2c, libmpi), CInfo, (Cint,), info.val)
1835-
end
1836-
function Info(cinfo::CInfo)
1837-
Info(ccall((:MPI_Info_c2f, libmpi), Cint, (CInfo,), cinfo))
1838-
end
18391835
elseif sizeof(CComm) == sizeof(Cint)
18401836
# in MPICH, both C and Fortran use identical Cint comm handles
18411837
# and MPI_Comm_c2f is not provided.
@@ -1845,12 +1841,6 @@ elseif sizeof(CComm) == sizeof(Cint)
18451841
function Comm(ccomm::CComm)
18461842
Comm(reinterpret(Cint, ccomm))
18471843
end
1848-
function CInfo(info::Info)
1849-
reinterpret(CInfo, info.val)
1850-
end
1851-
function Info(cinfo::CInfo)
1852-
Info(reinterpret(Cint, cinfo))
1853-
end
18541844
else
18551845
@warn("No MPI_Comm_c2f found - conversion to/from MPI.CComm will not work")
18561846
end

src/mpi-info.jl

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -26,41 +26,67 @@ If `init=false` is used in the costructor (the default), a "null" `Info` object
2626
returned: no keys can be added to such an object.
2727
"""
2828
mutable struct Info <: AbstractDict{Symbol,String}
29-
val::Cint
29+
cinfo::CInfo
30+
31+
function Info(cinfo::CInfo)
32+
new(cinfo)
33+
end
3034
function Info(;init=false)
31-
info = new(MPI_INFO_NULL)
35+
info = Info(INFO_NULL.cinfo)
3236
if init
33-
ccall(MPI_INFO_CREATE, Nothing, (Ptr{Cint}, Ref{Cint}), info, 0)
37+
@mpichk ccall((:MPI_Info_create, libmpi), Cint, (Ptr{CInfo},), info)
3438
refcount_inc()
3539
finalizer(free, info)
3640
end
3741
return info
3842
end
3943
end
4044

41-
# allows us to pass Info objects directly into Ptr{Cint} ccall signatures
42-
function Base.unsafe_convert(::Type{Ptr{Cint}}, info::Info)
43-
convert(Ptr{Cint}, pointer_from_objref(info))
45+
# allows us to pass Info objects directly into CInfo ccall signatures
46+
function Base.cconvert(::Type{CInfo}, info::Info)
47+
info.cinfo
48+
end
49+
# allows us to pass Info objects directly into Ptr{CInfo} ccall signatures
50+
function Base.unsafe_convert(::Type{Ptr{CInfo}}, info::Info)
51+
convert(Ptr{CInfo}, pointer_from_objref(info))
4452
end
4553

54+
if HAVE_MPI_COMM_C2F
55+
# Assume info is treated the same way
56+
function CInfo(finfo::Cint)
57+
ccall((:MPI_Info_f2c, libmpi), CInfo, (Cint,), finfo)
58+
end
59+
60+
# only used for use with Fortran API
61+
# can be removed once we have switched to C API
62+
function Base.cconvert(::Type{Ptr{Cint}}, info::Info)
63+
Ref(ccall((:MPI_Info_c2f, libmpi), Cint, (CInfo,), info.cinfo))
64+
end
65+
else
66+
function CInfo(finfo::Cint)
67+
reinterpret(CInfo, finfo)
68+
end
69+
function Base.cconvert(::Type{Ptr{Cint}}, info::Info)
70+
Ref(reinterpret(Cint, info.cinfo))
71+
end
72+
end
73+
74+
const INFO_NULL = Info(Ref{CInfo}()[]) # get an arbitrary bit-pattern: this will be set correctly at Init time
75+
4676
function free(info::Info)
47-
if info.val != MPI_INFO_NULL
48-
ccall(MPI_INFO_FREE, Nothing, (Ptr{Cint}, Ref{Cint}), info, 0)
77+
if info.cinfo != INFO_NULL.cinfo
78+
@mpichk ccall((:MPI_Info_free, libmpi), Cint, (Ptr{CInfo},), info)
4979
refcount_dec()
5080
end
5181
return nothing
5282
end
5383

54-
const INFO_NULL = Info(init=false)
55-
56-
# the info functions assume that Fortran hidden arguments are placed at the end of the argument list
5784
function Base.setindex!(info::Info, value::AbstractString, key::Symbol)
5885
skey = String(key)
5986
@assert isascii(skey) && isascii(value) &&
6087
length(skey) <= MPI_MAX_INFO_KEY && length(value) <= MPI_MAX_INFO_VAL
61-
ccall(MPI_INFO_SET, Nothing,
62-
(Ptr{Cint}, Ptr{UInt8}, Ptr{UInt8}, Ref{Cint}, Csize_t, Csize_t),
63-
info, skey, value, 0, sizeof(skey), sizeof(value))
88+
@mpichk ccall((:MPI_Info_set, libmpi), Cint,
89+
(CInfo, Cstring, Cstring), info, skey, value)
6490
end
6591

6692
Base.setindex!(info::Info, value::Any, key::Symbol) = info[key] = infoval(value)
@@ -90,49 +116,49 @@ end
90116
function Base.getindex(info::Info, key::Symbol)
91117
skey = String(key)
92118
@assert isascii(skey) && length(skey) <= MPI_MAX_INFO_KEY
93-
keyexists = Ref{Cint}()
94-
len = Ref{Cint}()
95-
ccall(MPI_INFO_GET_VALUELEN, Nothing,
96-
(Ptr{Cint}, Ptr{UInt8}, Ptr{Cint}, Ptr{Cint}, Ref{Cint}, Csize_t),
97-
info, skey, len, keyexists, 0, sizeof(skey))
119+
valuelen = Ref{Cint}()
120+
flag = Ref{Cint}()
121+
@mpichk ccall((:MPI_Info_get_valuelen, libmpi), Cint,
122+
(CInfo, Cstring, Ptr{Cint}, Ptr{Cint}),
123+
info, skey, valuelen, flag)
98124

99-
if keyexists[] == 0
125+
if flag[] == 0
100126
throw(KeyError(key))
101127
end
102128

103-
buffer = Vector{UInt8}(undef, len[])
104-
ccall(MPI_INFO_GET, Nothing,
105-
(Ptr{Cint}, Ptr{UInt8}, Ptr{Cint}, Ptr{UInt8}, Ptr{Cint}, Ref{Cint}, Csize_t, Csize_t),
106-
info, skey, len, buffer, keyexists, 0, sizeof(skey), sizeof(buffer))
129+
n = valuelen[]
130+
buffer = Vector{UInt8}(undef, n)
131+
@mpichk ccall((:MPI_Info_get, libmpi), Cint,
132+
(CInfo, Cstring, Cint, Ptr{UInt8}, Ptr{Cint}),
133+
info, skey, n, buffer, flag)
107134
return String(buffer)
108135
end
109136

110137
function Base.delete!(info::Info,key::Symbol)
111138
skey = String(key)
112139
@assert isascii(skey) && length(skey) <= MPI_MAX_INFO_KEY
113-
ccall(MPI_INFO_DELETE, Nothing,
114-
(Ptr{Cint}, Ptr{UInt8}, Ref{Cint}, Csize_t),
115-
info, skey, 0, sizeof(skey))
140+
@mpichk ccall((:MPI_Info_delete, libmpi), Cint,
141+
(CInfo, Cstring), info, skey)
116142
end
117143

118144
function Base.length(info::Info)
119-
if info.val == MPI_INFO_NULL
145+
if info.cinfo == INFO_NULL.cinfo
120146
return 0
121147
end
122148
nkeys = Ref{Cint}()
123-
ccall(MPI_INFO_GET_NKEYS, Nothing,
124-
(Ptr{Cint}, Ptr{Cint}, Ref{Cint}),
125-
info, nkeys, 0)
149+
@mpichk ccall((:MPI_Info_get_nkeys, libmpi), Cint,
150+
(CInfo, Ptr{Cint}), info, nkeys)
126151
return Int(nkeys[])
127152
end
128153

129154
function nthkey(info::Info, n::Integer)
130155
buffer = Vector{UInt8}(undef, MPI_MAX_INFO_KEY)
131-
ccall(MPI_INFO_GET_NTHKEY, Nothing,
132-
(Ptr{Cint}, Ref{Cint}, Ptr{UInt8}, Ref{Cint}, Csize_t),
133-
info, n, buffer, 0, length(buffer))
134-
i = findlast(!isequal(UInt8(' ')), buffer)
135-
resize!(buffer, i)
156+
@mpichk ccall((:MPI_Info_get_nthkey, libmpi), Cint,
157+
(CInfo, Cint, Ptr{UInt8}), info, n, buffer)
158+
i = findfirst(isequal(UInt8(0)), buffer)
159+
if i !== nothing
160+
resize!(buffer, i-1)
161+
end
136162
Symbol(buffer)
137163
end
138164

test/test_info.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ MPI.Init()
55

66
info = MPI.Info()
77
@test typeof(info) == MPI.Info
8-
@test info.val == MPI.MPI_INFO_NULL
8+
@test info.cinfo == MPI.CInfo(MPI.MPI_INFO_NULL)
99

1010
testinfo(;kwargs...) = MPI.Info(kwargs...)
1111

1212
info = testinfo(foo="fast", bar=true, baz=[10, -2])
13-
@test info.val != MPI.MPI_INFO_NULL
13+
@test info.cinfo != MPI.CInfo(MPI.MPI_INFO_NULL)
1414

1515
@test length(info) == 3
1616
@test info[:foo] == "fast"
@@ -22,6 +22,7 @@ delete!(info, :bar)
2222
@test_throws KeyError info[:bar]
2323

2424
MPI.free(info)
25-
@test info.val == MPI.MPI_INFO_NULL
25+
@test info.cinfo == MPI.CInfo(MPI.MPI_INFO_NULL)
2626

2727
MPI.Finalize()
28+
@test MPI.Finalized()

0 commit comments

Comments
 (0)