diff --git a/package/src/ExpressionProcessing.jl b/package/src/ExpressionProcessing.jl index a78fc4c..5ec6a8f 100644 --- a/package/src/ExpressionProcessing.jl +++ b/package/src/ExpressionProcessing.jl @@ -5,22 +5,24 @@ export replace_variables! export expr_to_postfix export SymbolTable64 export PostfixType +export Operator, Add, Subtract, Multiply, Divide, Power, Abs, Log, Exp, Sqrt +@enum Operator Add=1 Subtract=2 Multiply=3 Divide=4 Power=5 Abs=6 Log=7 Exp=8 Sqrt=9 const SymbolTable64 = Dict{Tuple{Expr, Symbol},Float64} -const PostfixType = Array{Union{Float64,String},1} +const PostfixType = Vector{Union{Float64,Operator,Symbol}} # Maybe switch from Array{String} to Array{Union{Float64, Symbol}}? function expr_to_postfix(expr::Expr)::PostfixType postfix = PostfixType() - operator = String(expr.args[1]) + operator = get_operator(expr.args[1]) # push!(postfix, expr.args[2], expr.args[3], operator) for j in 2:length(expr.args) arg = expr.args[j] if typeof(arg) === Expr append!(postfix, expr_to_postfix(arg)) - elseif typeof(arg) === Symbol - push!(postfix, String(arg)) + elseif typeof(arg) === Symbol # variables/parameters + push!(postfix, arg) else push!(postfix, convert(Float64, arg)) end @@ -76,4 +78,26 @@ function fill_symtable!(expr::Expr, symtable::SymbolTable64, values::Vector{Floa end end +function get_operator(op::Symbol)::Operator + if op == :+ + return Add + elseif op == :- + return Subtract + elseif op == :* + return Multiply + elseif op == :/ + return Divide + elseif op == :^ + return Power + elseif op == :abs + return Abs + elseif op == :log + return Log + elseif op == :exp + return Exp + elseif op == :sqrt + return Sqrt + end +end + end diff --git a/package/src/Interpreter.jl b/package/src/Interpreter.jl index 77fe650..bb70814 100644 --- a/package/src/Interpreter.jl +++ b/package/src/Interpreter.jl @@ -1,34 +1,35 @@ module Interpreter using CUDA include("ExpressionProcessing.jl") +using .ExpressionProcessing: PostfixType, Add, Subtract, Operator +export Interpret export CudaTest -@enum Operators Add=1 Subtract=2 Multiply=3 Division=4 Power=5 Abs=6 Log=7 Exp=8 Sqrt=9 - function CudaTest() N = 2^20 x = CUDA.fill(1.0f0, N) y = CUDA.fill(2.0f0, N) - kernelAdd = @cuda launch=false InterpretExplicit!(Add, x, y) + kernelAdd = @cuda launch=false InterpretExplicit!(ExpressionProcessing.Add, x, y) + # kernelAdd = @cuda launch=false InterpretExplicit!(Add, x, y, reference) config = launch_configuration(kernelAdd.fun) threads = min(length(y), config.threads) blocks = cld(length(y), threads) kernelAdd(Add, x, y; threads, blocks) - println(y[1]) + # println(y[1]) # @test all(Array(y) .== 3.0f0) - kernelSubtract = @cuda launch=false InterpretExplicit!(Subtract, x, y) + kernelSubtract = @cuda launch=false InterpretExplicit!(ExpressionProcessing.Subtract, x, y) configSub = launch_configuration(kernelSubtract.fun) threadsSub = min(length(y), configSub.threads) blocksSub = cld(length(y), threadsSub) CUDA.fill!(y, 2.0f0) - kernelSubtract(Subtract, x, y; threadsSub, blocksSub) + # kernelSubtract(Subtract, x, y; threadsSub, blocksSub) # @test all(Array(y) .== -1.0f0) - println(y[1]) + # println(y[1]) end "Interprets the given expressions with the values provided. @@ -42,22 +43,27 @@ function Interpret(expressions::Vector{ExpressionProcessing.PostfixType}, variab # create CUDA array and fill it with the expressions, variables and parameters # calculate needed number of threads, probably based off of the number of expressions, so I can ensure each warp takes the same execution path # Start the kernel + cudaExprs = Vector{CuArray{ExpressionProcessing.PostfixType}}(undef, length(expressions)) + for i in eachindex(expressions) + push!(cudaExprs, CuArray(expressions[i])) + end + # cudaExprs = CuArray(copy(expressions)) end # Kernel -function InterpretExplicit!(op::Operators, x, y) +function InterpretExplicit!(op::Operator, x, y) index = (blockIdx().x - 1) * blockDim().x + threadIdx().x stride = gridDim().x * blockDim().x if op == Add - @cuprintln("Performing Addition") # Will only be displayed when the GPU is synchronized + # @cuprintln("Performing Addition") # Will only be displayed when the GPU is synchronized for i = index:stride:length(y) @inbounds y[i] += x[i] end return elseif op == Subtract - @cuprintln("Performing Subtraction") # Will only be displayed when the GPU is synchronized + # @cuprintln("Performing Subtraction") # Will only be displayed when the GPU is synchronized for i = index:stride:length(y) @inbounds y[i] -= x[i] end diff --git a/package/test/ExpressionProcessing.jl b/package/test/ExpressionProcessingTests.jl similarity index 65% rename from package/test/ExpressionProcessing.jl rename to package/test/ExpressionProcessingTests.jl index 4c5a267..5facc36 100644 --- a/package/test/ExpressionProcessing.jl +++ b/package/test/ExpressionProcessingTests.jl @@ -1,3 +1,5 @@ +using .ExpressionProcessing + expressions = Vector{Expr}(undef, 1) variables = Matrix{Float64}(undef, 1,2) parameters = Vector{Vector{Float64}}(undef, 1) @@ -10,7 +12,7 @@ parameters[1] = Vector{Float64}(undef, 1) parameters[1][1] = 5 @testset "Test symtable construction" begin - symtable = ExpressionExecutorCuda.ExpressionProcessing.construct_symtable(expressions, variables, parameters) + symtable = construct_symtable(expressions, variables, parameters) @test haskey(symtable, (expressions[1], :x1)) @test haskey(symtable, (expressions[1], :x2)) @test haskey(symtable, (expressions[1], :p1)) @@ -21,17 +23,17 @@ parameters[1][1] = 5 end @testset "Test variable replacement in expression" begin - symtable = ExpressionExecutorCuda.ExpressionProcessing.construct_symtable(expressions, variables, parameters) + symtable = construct_symtable(expressions, variables, parameters) exprCopy = deepcopy(expressions[1]) - ExpressionExecutorCuda.ExpressionProcessing.replace_variables!(exprCopy, symtable, expressions[1]) + replace_variables!(exprCopy, symtable, expressions[1]) @test eval(exprCopy) == 10 # If it can be evaluated, it means all variables have been replaced, as there are no globally defined variables end @testset "Test conversion to postfix" begin - reference = Array{Union{Float64,String},1}() - append!(reference, ["x1", 1.0, "x2", "*", "+", "p1", "+"]) - postfix = ExpressionExecutorCuda.ExpressionProcessing.expr_to_postfix(expressions[1]) + reference = PostfixType() + append!(reference, [:x1, 1.0, :x2, Multiply, Add, :p1, Add]) + postfix = expr_to_postfix(expressions[1]) @test isequal(reference, postfix) end \ No newline at end of file diff --git a/package/test/InterpreterTests.jl b/package/test/InterpreterTests.jl new file mode 100644 index 0000000..ca3cfec --- /dev/null +++ b/package/test/InterpreterTests.jl @@ -0,0 +1,21 @@ +using .ExpressionProcessing +using .Interpreter + +expressions = Vector{Expr}(undef, 1) +variables = Matrix{Float64}(undef, 1,2) +parameters = Vector{Vector{Float64}}(undef, 1) + +# Resulting value should be 10 +expressions[1] = :(x1 + 1 * x2 + p1) +variables[1,1] = 2 +variables[1,2] = 3 +parameters[1] = Vector{Float64}(undef, 1) +parameters[1][1] = 5 + +@testset "Test interpretation" begin + postfixExpr = expr_to_postfix(expressions[1]) + postfixExprs = Vector{PostfixType}(undef, 1) + postfixExprs[1] = postfixExpr + + Interpret(postfixExprs, variables, parameters) +end \ No newline at end of file diff --git a/package/test/Project.toml b/package/test/Project.toml index 0c36332..73f75fc 100644 --- a/package/test/Project.toml +++ b/package/test/Project.toml @@ -1,2 +1,3 @@ [deps] +CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/package/test/runtests.jl b/package/test/runtests.jl index 7699656..da95594 100644 --- a/package/test/runtests.jl +++ b/package/test/runtests.jl @@ -1,6 +1,11 @@ using ExpressionExecutorCuda using Test +const baseFolder = dirname(dirname(pathof(ExpressionExecutorCuda))) +include(joinpath(baseFolder, "src", "ExpressionProcessing.jl")) +include(joinpath(baseFolder, "src", "Interpreter.jl")) + @testset "ExpressionExecutorCuda.jl" begin - include("ExpressionProcessing.jl") + include("ExpressionProcessingTests.jl") + include("InterpreterTests.jl") end