Skip to content

Commit

Permalink
all kind of fixes + better build (#16)
Browse files Browse the repository at this point in the history
* use BinDeps for build
* properly initialize library
* use Primes
* fix double free
* fix macro hygiene on 0.6 + remove depwarn
* misc fixes
  • Loading branch information
SimonDanisch authored and vchuravy committed Mar 27, 2017
1 parent 80ef8c7 commit 46d4e7a
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 69 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/deps/deps.jl
3 changes: 2 additions & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
julia 0.5-
julia 0.5
OpenCL
Primes
BinDeps
40 changes: 40 additions & 0 deletions deps/build.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using BinDeps
@BinDeps.setup
libnames = ["libCLFFT", "clFFT", "libclFFT"]
libCLFFT = library_dependency("libCLFFT", aliases = libnames)
archive = "package"
libpath = "package/bin"
baseurl = "https://github.com/clMathLibraries/clFFT/releases/download/v2.12.2/clFFT-2.12.2-"
# download a pre-compiled binary (built by GLFW)
if is_windows()
if Sys.ARCH == :x86_64
uri = URI(baseurl * "Windows-x64.zip")
provides(
Binaries, uri,
libCLFFT, unpacked_dir = archive,
installed_libpath = libpath, os = :Windows
)
else
error("Only 64 bits windows supported with automatic build")
end
end

if is_linux()
provides(AptGet, "libclfft-dev", libCLFFT)
if Sys.ARCH == :x86_64
uri = URI(baseurl * "Linux-x64.tar.gz")
provides(
Binaries, uri,
libCLFFT, unpacked_dir = archive,
installed_libpath = libpath, os = :Linux
)
end
end
if is_apple()
error("""
OSX not oficially supported.
Find manual build instructions on: https://github.com/clMathLibraries/clBLAS/wiki/Build
""")
end

@BinDeps.install Dict("libCLFFT" => "libCLFFT")
91 changes: 53 additions & 38 deletions src/CLFFT.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module CLFFT

import OpenCL.cl

using Primes
include("api.jl")
include("error.jl")

Expand All @@ -17,44 +17,38 @@ immutable CLFFTError
end
end

Base.show(io::IO, err::CLFFTError) =
Base.print(io, "CLFFTError(code=$(err.code), :$(err.desc))")
function Base.show(io::IO, err::CLFFTError)
Base.print(io, "CLFFTError(code=$(err.code), :$(err.desc))")
end

macro check(clfftFunc)
quote
local err::Cint
err = $clfftFunc
err = $(esc(clfftFunc))
if err != api.CLFFT_SUCCESS
throw(CLFFTError(err))
end
err
end
end

version() = begin
major = cl.CL_uint[0]
minor = cl.CL_uint[0]
patch = cl.CL_uint[0]
function version()
major = Ref{cl.CL_uint}(0)
minor = Ref{cl.CL_uint}(0)
patch = Ref{cl.CL_uint}(0)
api.clfftGetVersion(major, minor, patch)
return VersionNumber(Int(major[1]), Int(minor[1]), Int(patch[1]))
return VersionNumber(Int(major[]), Int(minor[]), Int(patch[]))
end

function supported_radices()
v = version()
radices = [2,3,5]
v v"2.8.0" && push!(radices, 7)
v v"2.12.0" && push!(radices, 11, 13)
v = version()
radices = [2,3,5]
v v"2.8.0" && push!(radices, 7)
v v"2.12.0" && push!(radices, 11, 13)

radices
radices
end

# Module level library handle,
# when module is GC'd, the finalizer for SetupData is
# called to teardown the library state
const __handle = begin
v = version()
api.SetupData(v.major, v.minor, v.patch, 0)
end

# clFFT floating-point types:
typealias clfftNumber Union{Float64,Float32,Complex128,Complex64}
Expand All @@ -67,23 +61,25 @@ typealias clfftTypeSingle Union{Type{Float32},Type{Complex64}}

typealias PlanHandle Csize_t


type Plan{T<:clfftNumber}
function free(x) end
type Plan{T <: clfftNumber}
# boxed handle (most api functions need address, setup/teardown need pointer)
id::Array{PlanHandle,1}

function Plan(plan::Array{PlanHandle,1})
function Plan(plan::Array{PlanHandle, 1})
p = new(plan)
finalizer(p, x -> begin
if x.id[1] != C_NULL
@check api.clfftDestroyPlan(x.id)
end
x.id[1] = C_NULL
end)
finalizer(p, free)
return p
end
end
const global is_initialized = Ref(false)

function free(x::Plan)
if x.id[1] != 0 && is_initialized[]
@check api.clfftDestroyPlan(x.id)
end
x.id[1] = 0
end

function Plan{T<:clfftNumber}(::Type{T}, ctx::cl.Context, sz::Dims)
if length(sz) > 3
Expand Down Expand Up @@ -366,7 +362,7 @@ end
set_lengths!(p::Plan, dims::Dims) = begin
ndim = length(dims)
@assert ndim <= 3
nd = Array(Csize_t, ndim)
nd = Vector{Csize_t}(ndim)
for (i, d) in enumerate(dims)
nd[i] = d
end
Expand All @@ -377,15 +373,15 @@ end

lengths(p::Plan) = begin
d = dim(p)
res = Array(Csize_t, d)
res = Vector{Csize_t}(d)
@check api.clfftGetPlanLength(p.id[1], Int32(d), res)
return map(Int, res)
end


instride(p::Plan) = begin
d = dim(p)
res = Array(Csize_t, d)
res = Vector{Csize_t}(d)
@check api.clfftGetPlanInStride(p.id[1], Int32(d), res)
return map(Int, res)
end
Expand All @@ -402,7 +398,7 @@ end

outstride(p::Plan) = begin
d = dim(p)
res = Array(Csize_t, d)
res = Vector{Csize_t}(d)
@check api.clfftGetPlanOutStride(p.id[1], Int32(d), res)
return map(Int, res)
end
Expand Down Expand Up @@ -478,16 +474,19 @@ bake!(p::Plan, qs::Vector{cl.CmdQueue}) = begin
@check api.clfftBakePlan(p.id[1], nqueues, q_ids, C_NULL, C_NULL)
return p
end
bake!(p::Plan, q::cl.CmdQueue) = bake!(p, [q])
function bake!(p::Plan, q::cl.CmdQueue)
qref = [q]
bake!(p, qref)
end


function enqueue_transform{T<:clfftNumber}(p::Plan,
dir::Symbol,
qs::Vector{cl.CmdQueue},
input::cl.Buffer{T},
output::Union{Void,cl.Buffer{T}};
wait_for::Union{Void,Vector{cl.Event}}=nothing,
tmp::Union{Void,cl.Buffer{T}}=nothing)
wait_for::Union{Void,Vector{cl.Event}} = nothing,
tmp::Union{Void,cl.Buffer{T}} = nothing)
if dir != :forward && dir != :backward
throw(ArgumentError("Unknown direction $dir"))
end
Expand All @@ -504,7 +503,7 @@ function enqueue_transform{T<:clfftNumber}(p::Plan,
evt_ids = [evt.id for evt in wait_for]
end
nqueues = length(q_ids)
out_evts = Array(cl.CL_event, nqueues)
out_evts = Vector{cl.CL_event}(nqueues)
tmp_buffer = C_NULL
if tmp != nothing
tmp_buff_id = [tmp.id]
Expand All @@ -523,4 +522,20 @@ function enqueue_transform{T<:clfftNumber}(p::Plan,
return [cl.Event(e_id) for e_id in out_evts]
end



function __init__()
v = version()
d = api.SetupData(v.major, v.minor, v.patch, 0)
setup = Ref(d)
error = api.clfftSetup(setup)
if error != api.CLFFT_SUCCESS
error("Failed to setup CLFFT Library")
end
is_initialized[] = true
atexit() do
api.clfftTeardown()
is_initialized[] = false
end
end
end # module
36 changes: 8 additions & 28 deletions src/api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,30 @@ module api

import OpenCL.cl

@static if is_unix() const libclfft = "libclFFT" end
@static if is_windows() const libclfft = "clFFT" end

depsfile = joinpath(dirname(@__FILE__), "..", "deps", "deps.jl")
if isfile(depsfile)
include(depsfile)
else
error("CLFFT not properly installed. Please run Pkg.build(\"CLFFT\") then restart Julia.")
end

macro clfft(func, arg_types)
local args_in = Symbol[Symbol("arg$i::$T")
for (i, T) in enumerate(arg_types.args)]
local funcname = Symbol("clfft$func")
@eval begin
$(funcname)($(args_in...)) = ccall(($(string(funcname)), libclfft),
$(funcname)($(args_in...)) = ccall(($(string(funcname)), libCLFFT),
cl.CL_int, #clfftStatus
$arg_types,
$(args_in...))
end
end

type SetupData
immutable SetupData
major::cl.CL_uint
minor::cl.CL_uint
patch::cl.CL_uint
debug_flags::cl.CL_ulong

function SetupData(major::Integer,
minor::Integer,
patch::Integer,
debug_flags::Integer)
d = new(cl.cl_uint(major),
cl.cl_uint(minor),
cl.cl_uint(patch),
cl.cl_ulong(debug_flags))
setup = [d]
error = clfftSetup(setup)
if error != CLFFT_SUCCESS
error("Failed to setup CLFFT Library")
end
finalizer(d, x -> begin
# gc'ing before teardown
# helps prevent a double-free event for Plan objects
# A kludge to enforce gc order.
Base.gc()
clfftTeardown()
end)
return d
end
end


Expand Down
4 changes: 2 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ facts("Version") do
end

## NOTE: the following 2 tests FAIL, testing/fixing is highly welcome
##
##
## facts("Plan") do
## context("Constructor") do
## ctx = cl.create_some_context()
Expand Down Expand Up @@ -169,7 +169,7 @@ facts("Example FFT Double") do
end

facts("2D FFT Inplace") do
transform_sizes = [2^6,]#3^4, 5^3]
transform_sizes = (2^6,)#3^4, 5^3
for N in transform_sizes
for M in transform_sizes
@show (N, M)
Expand Down

0 comments on commit 46d4e7a

Please sign in to comment.