metacl 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/bin/metacl +9 -0
- data/lib/metacl.rb +14 -0
- data/lib/metacl/dsl.rb +5 -0
- data/lib/metacl/dsl/data_definitions.rb +26 -0
- data/lib/metacl/dsl/directs.rb +13 -0
- data/lib/metacl/dsl/expression.rb +30 -0
- data/lib/metacl/dsl/expression_applicator.rb +92 -0
- data/lib/metacl/dsl/root.rb +46 -0
- data/lib/metacl/logic.rb +2 -0
- data/lib/metacl/logic/node.rb +92 -0
- data/lib/metacl/logic/resource_manager.rb +53 -0
- data/lib/metacl/program.rb +19 -0
- data/lib/metacl/refinements.rb +31 -0
- data/lib/metacl/templates.rb +9 -0
- data/lib/metacl/templates/aggregator.any.template +6 -0
- data/lib/metacl/templates/aggregator.rb +13 -0
- data/lib/metacl/templates/expression_applicator_wrapper.cl.template +21 -0
- data/lib/metacl/templates/expression_applicator_wrapper.cpp.template +7 -0
- data/lib/metacl/templates/expression_applicator_wrapper.rb +90 -0
- data/lib/metacl/templates/init_array.cl.template +2 -0
- data/lib/metacl/templates/init_array.cpp.template +1 -0
- data/lib/metacl/templates/init_array.rb +12 -0
- data/lib/metacl/templates/init_matrix.cl.template +2 -0
- data/lib/metacl/templates/init_matrix.cpp.template +1 -0
- data/lib/metacl/templates/init_matrix.rb +12 -0
- data/lib/metacl/templates/init_numeric.cl.template +2 -0
- data/lib/metacl/templates/init_numeric.cpp.template +1 -0
- data/lib/metacl/templates/init_numeric.rb +12 -0
- data/lib/metacl/templates/kernel.cl.template +5 -0
- data/lib/metacl/templates/kernel.rb +13 -0
- data/lib/metacl/templates/print_matrix.any.template +8 -0
- data/lib/metacl/templates/print_matrix.rb +13 -0
- data/lib/metacl/templates/prints.any.template +1 -0
- data/lib/metacl/templates/prints.rb +12 -0
- data/lib/metacl/templates/wrapper.cl.template +39 -0
- data/lib/metacl/templates/wrapper.cpp.template +10 -0
- data/lib/metacl/templates/wrapper.rb +12 -0
- data/lib/metacl/utils.rb +15 -0
- data/lib/metacl/version.rb +3 -0
- data/metacl.gemspec +26 -0
- metadata +161 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 792d99fee2e47cc7aab8a97d71a727064b2fd081
|
4
|
+
data.tar.gz: 8ca813049935f3c77ea061d4ca45f68589c3173f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 976bf50850d7d48b7c7c198275335f9d3d60d102f069f8f8c3dfd31dd14d1faaf3be3e8cbecdd42b948de5d0380442d11cbf76ae7b0b723c9f016ada9b89c52f
|
7
|
+
data.tar.gz: 7c0a8940b4c4c4439ed1ffc6bc60b0d40d344ec2a4a9fe982fa168604b71e5f0708e6959c0c059fcff6b590f9178539e057e6f624747fb57ec163ce497f8856b
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Roman Kolesnev
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Metacl
|
2
|
+
|
3
|
+
DSL that generates C code for different computation platforms (pure C, OpenCL, Intel Phi)
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'metacl'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install metacl
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it ( http://github.com/<my-github-username>/metacl/fork )
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/metacl
ADDED
data/lib/metacl.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'mustache'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
require 'metacl/version'
|
5
|
+
|
6
|
+
require 'metacl/utils'
|
7
|
+
require 'metacl/templates'
|
8
|
+
require 'metacl/refinements'
|
9
|
+
require 'metacl/logic'
|
10
|
+
require 'metacl/dsl'
|
11
|
+
require 'metacl/program'
|
12
|
+
|
13
|
+
module MetaCL
|
14
|
+
end
|
data/lib/metacl/dsl.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module DSL
|
3
|
+
module DataDefinitions
|
4
|
+
|
5
|
+
def numeric(name, type, options = {})
|
6
|
+
value = options[:value]
|
7
|
+
@program.resources.add_numeric name, type
|
8
|
+
|
9
|
+
@inner_code << Templates::InitNumeric.render(name, type, value, @program.platform) << "\n\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
def array(name, type, length, options = {})
|
13
|
+
@program.resources.add_array name, length, type
|
14
|
+
|
15
|
+
@inner_code << Templates::InitArray.render(name, type, length, options[:fill_with], @program.platform) << "\n\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
def matrix(name, type, size_n, size_m, options = {})
|
19
|
+
@program.resources.add_matrix name, size_n, size_m, type
|
20
|
+
|
21
|
+
@inner_code << Templates::InitMatrix.render(name, type, size_n, size_m, options[:fill_with], @program.platform) << "\n\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module DSL
|
3
|
+
class Expression
|
4
|
+
attr_reader :tree
|
5
|
+
|
6
|
+
def initialize(program, &block)
|
7
|
+
@program = program
|
8
|
+
@tree = instance_eval(&block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def sum(index, from, to, expression)
|
12
|
+
Logic::Node.new :aggregator, expression, nil, index: index, from: from, to: to, type: :+
|
13
|
+
end
|
14
|
+
|
15
|
+
def mul(index, from, to, expression)
|
16
|
+
Logic::Node.new :aggregator, expression, nil, index: index, from: from, to: to, type: :*
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(name, *args)
|
20
|
+
sub_expression = @program.resources.expressions_hash[name.to_sym]
|
21
|
+
substitution = sub_expression.args.map.with_index { |param, index| [param, args[index]] }.to_h
|
22
|
+
sub_expression.root_node.get_tree_with_substitution(substitution)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.construct(program, &block)
|
26
|
+
Expression.new(program, &block).tree
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module DSL
|
3
|
+
class ExpressionApplicator
|
4
|
+
attr_reader :code
|
5
|
+
|
6
|
+
def initialize(program, expr, result_matrix, options = {})
|
7
|
+
@program, @expr = program, expr.deep_clone
|
8
|
+
@result_matrix = program.resources.matrices_hash[result_matrix]
|
9
|
+
|
10
|
+
@left_border = options[:from] || [0, 0]
|
11
|
+
@right_border = options[:to] || [@result_matrix.size_n, @result_matrix.size_m]
|
12
|
+
|
13
|
+
@var_letter = 't'
|
14
|
+
|
15
|
+
prepare_tree
|
16
|
+
code_generation
|
17
|
+
|
18
|
+
@code = Templates::ExpressionApplicatorWrapper.render(@left_border, @right_border, @expr.params.code || '', @expr.objects, @result_matrix, @program.platform)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.construct(program, expr, result_matrix, options = {})
|
22
|
+
ExpressionApplicator.new(program, expr, result_matrix, options).code
|
23
|
+
end
|
24
|
+
|
25
|
+
def prepare_tree
|
26
|
+
pt_vars_gen
|
27
|
+
end
|
28
|
+
|
29
|
+
# pt means prepare_tree
|
30
|
+
|
31
|
+
def pt_vars_gen
|
32
|
+
vars_count = 0
|
33
|
+
|
34
|
+
@expr.walk do |node|
|
35
|
+
case node.type
|
36
|
+
when :data
|
37
|
+
index_i = node.params.index_i || 'i'
|
38
|
+
index_j = node.params.index_j || 'j'
|
39
|
+
data = @program.resources[node.params.name]
|
40
|
+
node.params.object = data
|
41
|
+
case data.klass
|
42
|
+
when :matrix
|
43
|
+
node.params.var = "#{data.name}[(#{index_i})*#{data.size_m} + (#{index_j})]"
|
44
|
+
when :array
|
45
|
+
node.params.var = "#{data.name}[#{index_i}]"
|
46
|
+
when :numeric
|
47
|
+
node.params.var = data.name
|
48
|
+
end
|
49
|
+
when :operator, :aggregator
|
50
|
+
vars_count += 1
|
51
|
+
node.params.var = @var_letter + vars_count.to_s
|
52
|
+
when :const
|
53
|
+
node.params.var = node.params.data.to_s
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def code_generation
|
59
|
+
@expr.walk do |node|
|
60
|
+
case node.type
|
61
|
+
when :operator
|
62
|
+
left_var = node.left_child.params.var
|
63
|
+
right_var = node.right_child.params.var
|
64
|
+
left_code = node.left_child.params.code || ''
|
65
|
+
right_code = node.right_child.params.code || ''
|
66
|
+
node.params.code = left_code + right_code + "float #{node.params.var} = #{left_var} #{node.params.type} #{right_var};\n"
|
67
|
+
when :aggregator
|
68
|
+
code = node.left_child.params.code || ''
|
69
|
+
subresult_var = node.left_child.params.var
|
70
|
+
iterator = node.params.index
|
71
|
+
from, to = node.params.from, node.params.to
|
72
|
+
type = 'float'
|
73
|
+
var = node.params.var
|
74
|
+
operator = node.params.type
|
75
|
+
node.params.code = Templates::Aggregator.render(@program.platform,
|
76
|
+
code: code,
|
77
|
+
subresult_var: subresult_var,
|
78
|
+
iterator: iterator,
|
79
|
+
from: from,
|
80
|
+
to: to,
|
81
|
+
type: type,
|
82
|
+
var: var,
|
83
|
+
operator: operator
|
84
|
+
) + "\n"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
@expr.params.code += "#{@result_matrix.name}[i*#{@result_matrix.size_m} + j] = #{@expr.params.var};\n"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module DSL
|
3
|
+
class Root
|
4
|
+
attr_reader :code
|
5
|
+
|
6
|
+
include Directs
|
7
|
+
include DataDefinitions
|
8
|
+
|
9
|
+
using Refinements
|
10
|
+
|
11
|
+
def initialize(program, filename)
|
12
|
+
@program = program
|
13
|
+
super() # call initializers from modules
|
14
|
+
@inner_code = ""
|
15
|
+
@outer_code = ""
|
16
|
+
|
17
|
+
instance_eval IO.read(filename), filename
|
18
|
+
|
19
|
+
@code = Templates::Wrapper.render(@inner_code, @outer_code, @program.platform)
|
20
|
+
end
|
21
|
+
|
22
|
+
def platform(name)
|
23
|
+
@program.set_platform name # TODO platform check
|
24
|
+
end
|
25
|
+
|
26
|
+
def prints(string)
|
27
|
+
@inner_code << Templates::Prints.render(string, @program.platform) << "\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
def expression(name, *args, &block)
|
31
|
+
tree = Expression.construct(@program, &block)
|
32
|
+
@program.resources.add_expression(name, tree, args)
|
33
|
+
end
|
34
|
+
|
35
|
+
def apply_expression(matrix_name, options = {}, &block)
|
36
|
+
expr = Expression.construct(@program, &block)
|
37
|
+
@inner_code << ExpressionApplicator.construct(@program, expr, matrix_name, options) << "\n"
|
38
|
+
end
|
39
|
+
|
40
|
+
def print_matrix(name)
|
41
|
+
matrix = @program.resources.matrices_hash[name]
|
42
|
+
@inner_code << Templates::PrintMatrix.render(matrix.name, matrix.size_n, matrix.size_m, @program.platform)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/metacl/logic.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module Logic
|
3
|
+
class Node
|
4
|
+
using Refinements
|
5
|
+
attr_reader :type, :params, :left_child, :right_child
|
6
|
+
|
7
|
+
def initialize(type, left_child = nil, right_child = nil, params = {})
|
8
|
+
@type = type
|
9
|
+
@params = OpenStruct.new(params)
|
10
|
+
@left_child, @right_child = left_child, right_child
|
11
|
+
end
|
12
|
+
|
13
|
+
def deep_clone
|
14
|
+
Marshal.load(Marshal.dump(self)) # TODO: write a proper solution
|
15
|
+
end
|
16
|
+
|
17
|
+
def leaf?
|
18
|
+
not (left_child or right_child)
|
19
|
+
end
|
20
|
+
|
21
|
+
def nodify
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](index_i, index_j = nil)
|
26
|
+
params.index_i = index_i
|
27
|
+
params.index_j = index_j
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def walk(&block)
|
32
|
+
@left_child.walk(&block) if @left_child
|
33
|
+
@right_child.walk(&block) if @right_child
|
34
|
+
yield self
|
35
|
+
end
|
36
|
+
|
37
|
+
def nodes
|
38
|
+
result = []
|
39
|
+
walk { |node| result << node }
|
40
|
+
end
|
41
|
+
|
42
|
+
def leaves
|
43
|
+
nodes.select(&:leaf?)
|
44
|
+
end
|
45
|
+
|
46
|
+
def objects
|
47
|
+
leaves.map { |x| x.params.object }.compact.uniq
|
48
|
+
end
|
49
|
+
|
50
|
+
def +(arg)
|
51
|
+
Node.new :operator, self, arg.nodify, type: :+
|
52
|
+
end
|
53
|
+
|
54
|
+
def -(arg)
|
55
|
+
Node.new :operator, self, arg.nodify, type: :-
|
56
|
+
end
|
57
|
+
|
58
|
+
def /(arg)
|
59
|
+
Node.new :operator, self, arg.nodify, type: :/
|
60
|
+
end
|
61
|
+
|
62
|
+
def *(arg)
|
63
|
+
Node.new :operator, self, arg.nodify, type: :*
|
64
|
+
end
|
65
|
+
|
66
|
+
def debug(tab = 0)
|
67
|
+
text = ' ' * tab << @type.to_s << ' ' << "{ #{ @params.to_h.map { |k, v| "#{k}: #{v}"}.join ', ' } }" << "\n"
|
68
|
+
if @left_child
|
69
|
+
text << ' ' * tab << "left: \n"
|
70
|
+
text << @left_child.debug(tab+1)
|
71
|
+
end
|
72
|
+
if @right_child
|
73
|
+
text << ' ' * tab << "right: \n"
|
74
|
+
text << @right_child.debug(tab+1)
|
75
|
+
end
|
76
|
+
text
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_s
|
80
|
+
debug
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_tree_with_substitution(subst)
|
84
|
+
new_tree = self.deep_clone
|
85
|
+
new_tree.leaves.each do
|
86
|
+
|leaf| leaf.params.name = subst[leaf.params.name]
|
87
|
+
end
|
88
|
+
new_tree
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module Logic
|
3
|
+
class ResourceManager
|
4
|
+
def initialize
|
5
|
+
@namespace = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_numeric(name, type = nil) # name check
|
9
|
+
@namespace[name] = OpenStruct.new(name: name, klass: :numeric, type: type)
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_array(name, length, type = nil) # name check
|
13
|
+
@namespace[name] = OpenStruct.new(name: name, klass: :array, type: type, length: length)
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_matrix(name, size_n, size_m, type = nil)
|
17
|
+
@namespace[name] = OpenStruct.new(name: name, klass: :matrix, type: type, size_n: size_n, size_m: size_m)
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_expression(name, root_node, args = [])
|
21
|
+
@namespace[name] = OpenStruct.new(name: name, klass: :expression, args: args, root_node: root_node)
|
22
|
+
end
|
23
|
+
|
24
|
+
def numerics
|
25
|
+
@namespace.values.select { |e| e.klass == :numeric }
|
26
|
+
end
|
27
|
+
|
28
|
+
def arrays
|
29
|
+
@namespace.values.select { |e| e.klass == :array }
|
30
|
+
end
|
31
|
+
|
32
|
+
def matrices
|
33
|
+
@namespace.values.select { |e| e.klass == :matrix }
|
34
|
+
end
|
35
|
+
|
36
|
+
def expressions
|
37
|
+
@namespace.values.select { |e| e.klass == :expression }
|
38
|
+
end
|
39
|
+
|
40
|
+
def expressions_hash
|
41
|
+
Hash[expressions.map { |e| [e.name, e] }]
|
42
|
+
end
|
43
|
+
|
44
|
+
def matrices_hash
|
45
|
+
Hash[matrices.map { |e| [e.name, e] }]
|
46
|
+
end
|
47
|
+
|
48
|
+
def [](arg)
|
49
|
+
@namespace[arg]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module MetaCL
|
2
|
+
class Program
|
3
|
+
attr_accessor :code, :platform, :resources
|
4
|
+
|
5
|
+
def initialize(filename)
|
6
|
+
@platform = :cpp
|
7
|
+
@resources = Logic::ResourceManager.new
|
8
|
+
@code = DSL::Root.new(self, filename).code
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_platform(platform)
|
12
|
+
@platform = platform
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.create(filename)
|
16
|
+
Program.new(filename).code
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module Refinements
|
3
|
+
refine Symbol do
|
4
|
+
def nodify
|
5
|
+
Logic::Node.new :data, nil, nil, name: self
|
6
|
+
end
|
7
|
+
|
8
|
+
def +(arg)
|
9
|
+
self.nodify + arg.nodify
|
10
|
+
end
|
11
|
+
|
12
|
+
def -(arg)
|
13
|
+
self.nodify - arg.nodify
|
14
|
+
end
|
15
|
+
|
16
|
+
def *(arg)
|
17
|
+
self.nodify * arg.nodify
|
18
|
+
end
|
19
|
+
|
20
|
+
def [](*args)
|
21
|
+
self.nodify[*args]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
refine Numeric do
|
26
|
+
def nodify
|
27
|
+
Logic::Node.new :const, nil, nil, data: self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'metacl/templates/wrapper'
|
2
|
+
require 'metacl/templates/prints'
|
3
|
+
require 'metacl/templates/init_numeric'
|
4
|
+
require 'metacl/templates/init_array'
|
5
|
+
require 'metacl/templates/init_matrix'
|
6
|
+
require 'metacl/templates/kernel'
|
7
|
+
require 'metacl/templates/expression_applicator_wrapper'
|
8
|
+
require 'metacl/templates/print_matrix'
|
9
|
+
require 'metacl/templates/aggregator'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module Templates
|
3
|
+
class Aggregator < Mustache
|
4
|
+
attr_reader :type, :var, :iterator, :from, :to, :subresult_var, :operator, :code
|
5
|
+
|
6
|
+
def render(platform, options = {})
|
7
|
+
@type, @var, @iterator, @from, @to, @subresult_var, @operator, @code = options.values_at(:type, :var, :iterator, :from, :to, :subresult_var, :operator, :code)
|
8
|
+
@code = Utils.tab_text(@code)
|
9
|
+
super IO.read("#{__dir__}/aggregator.any.template")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
std::string kernel_code =
|
2
|
+
{{{kernel_code}}}
|
3
|
+
|
4
|
+
sources.push_back({kernel_code.c_str(),kernel_code.length()});
|
5
|
+
|
6
|
+
cl::Program program(context,sources);
|
7
|
+
if(program.build({default_device})!=CL_SUCCESS){
|
8
|
+
std::cout<<" Error building: "<<program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(default_device)<<"\n";
|
9
|
+
exit(1);
|
10
|
+
}
|
11
|
+
|
12
|
+
//create queue to which we will push commands for the device.
|
13
|
+
cl::CommandQueue queue(context,default_device);
|
14
|
+
|
15
|
+
{{{push_buffers}}}
|
16
|
+
|
17
|
+
auto metacl_program = cl::make_kernel<{{{template_params}}}>(program, "metacl_program");
|
18
|
+
cl::EnqueueArgs eargs(queue, cl::NullRange, cl::NDRange({{n_to}} - {{n_from}}, {{m_to}} - {{m_from}}), cl::NullRange);
|
19
|
+
metacl_program(eargs, {{{kernel_params}}}).wait();
|
20
|
+
|
21
|
+
{{{pop_buffer}}}
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module Templates
|
3
|
+
class ExpressionApplicatorWrapper < Mustache
|
4
|
+
attr_reader :n_from, :n_to, :m_from, :m_to, :code
|
5
|
+
attr_reader :kernel_code, :push_buffers, :template_params, :kernel_params, :pop_buffer
|
6
|
+
|
7
|
+
def render(from_border, to_border, code, objects, result_object, platform)
|
8
|
+
@n_from, @m_from = from_border
|
9
|
+
@n_to, @m_to = to_border
|
10
|
+
@code = Utils.tab_text(code, platform == :cl ? 1 : 2)
|
11
|
+
@objects = objects
|
12
|
+
@result_object = result_object
|
13
|
+
|
14
|
+
if platform == :cl
|
15
|
+
gen_push_buffers
|
16
|
+
gen_template_params
|
17
|
+
gen_kernel_params
|
18
|
+
gen_pop_buffer
|
19
|
+
gen_kernel_code
|
20
|
+
end
|
21
|
+
|
22
|
+
super IO.read("#{__dir__}/expression_applicator_wrapper.#{platform}.template")
|
23
|
+
end
|
24
|
+
|
25
|
+
def gen_push_buffers
|
26
|
+
@push_buffers = ""
|
27
|
+
@objects.each do |x|
|
28
|
+
case x.klass
|
29
|
+
when :matrix
|
30
|
+
@push_buffers << "queue.enqueueWriteBuffer(buffer_#{x.name},CL_TRUE,0,sizeof(#{x.type})*#{x.size_n}*#{x.size_m},#{x.name}.data());\n"
|
31
|
+
when :array
|
32
|
+
@push_buffers << "queue.enqueueWriteBuffer(buffer_#{x.name},CL_TRUE,0,sizeof(#{x.type})*#{x.length},#{x.name}.data());\n"
|
33
|
+
when :numeric
|
34
|
+
# TODO: @push_buffers << "queue.enqueueWriteBuffer(buffer_#{x.name},CL_TRUE,0,sizeof(#{x.type}),#{x.name};\n"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def gen_template_params
|
40
|
+
params = []
|
41
|
+
@objects.each do |x|
|
42
|
+
case x.klass
|
43
|
+
when :matrix, :array
|
44
|
+
params << "cl::Buffer&"
|
45
|
+
when :numeric
|
46
|
+
# TODO
|
47
|
+
end
|
48
|
+
end
|
49
|
+
params << "cl::Buffer&" # for result
|
50
|
+
@template_params = params.join(', ')
|
51
|
+
end
|
52
|
+
|
53
|
+
def gen_kernel_params
|
54
|
+
params = []
|
55
|
+
@objects.each do |x|
|
56
|
+
case x.klass
|
57
|
+
when :matrix, :array
|
58
|
+
params << "buffer_#{x.name}"
|
59
|
+
when :numeric
|
60
|
+
# TODO
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
params << "buffer_#{@result_object.name}"
|
65
|
+
@kernel_params = params.join(', ')
|
66
|
+
end
|
67
|
+
|
68
|
+
def gen_pop_buffer
|
69
|
+
x = @result_object
|
70
|
+
@pop_buffer = "queue.enqueueReadBuffer(buffer_#{x.name},CL_TRUE,0,sizeof(#{x.type})*#{x.size_n}*#{x.size_m},#{x.name}.data());\n"
|
71
|
+
end
|
72
|
+
|
73
|
+
def gen_kernel_code
|
74
|
+
params = []
|
75
|
+
@objects.each do |x|
|
76
|
+
case x.klass
|
77
|
+
when :matrix, :array
|
78
|
+
params << "global const #{x.type}* #{x.name}"
|
79
|
+
when :numeric
|
80
|
+
# TODO
|
81
|
+
end
|
82
|
+
end
|
83
|
+
params << "global #{@result_object.type}* #{@result_object.name}"
|
84
|
+
|
85
|
+
@kernel_code = Templates::Kernel.render(params.join(', '), @code, @n_from, @m_from)
|
86
|
+
@kernel_code = Utils.stringify_text(@kernel_code)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
std::vector<{{type}}> {{name}}({{length}}{{#fill_with}}, {{fill_with}}{{/fill_with}});
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module Templates
|
3
|
+
class InitArray < Mustache
|
4
|
+
attr_reader :name, :type, :length, :fill_with
|
5
|
+
|
6
|
+
def render(name, type, length, fill_with, platform)
|
7
|
+
@name, @type, @length, @fill_with = name, type, length, fill_with
|
8
|
+
super IO.read("#{__dir__}/init_array.#{platform}.template")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
std::vector<{{type}}> {{name}}({{size_n}} * {{size_m}}{{#fill_with}}, {{fill_with}}{{/fill_with}});
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module Templates
|
3
|
+
class InitMatrix < Mustache
|
4
|
+
attr_accessor :name, :type, :size_n, :size_m, :fill_with
|
5
|
+
|
6
|
+
def render(name, type, size_n, size_m, fill_with, platform)
|
7
|
+
@name, @type, @size_n, @size_m, @fill_with = name, type, size_n, size_m, fill_with
|
8
|
+
super IO.read("#{__dir__}/init_matrix.#{platform}.template")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{{type}} {{name}}{{#value}} = {{value}}{{/value}};
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module Templates
|
3
|
+
class InitNumeric < Mustache
|
4
|
+
attr_accessor :name, :type, :value
|
5
|
+
|
6
|
+
def render(name, type, value, platform)
|
7
|
+
@name, @type, @value = name, type, value
|
8
|
+
super IO.read("#{__dir__}/init_numeric.#{platform}.template")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module Templates
|
3
|
+
class Kernel < Mustache
|
4
|
+
attr_reader :params, :code, :n_from, :m_from
|
5
|
+
|
6
|
+
def render(params, code, n_from, m_from)
|
7
|
+
@params, @code = params, code
|
8
|
+
@n_from, @m_from = n_from, m_from
|
9
|
+
super IO.read("#{__dir__}/kernel.cl.template")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module Templates
|
3
|
+
class PrintMatrix < Mustache
|
4
|
+
attr_reader :size_n, :size_m, :matrix_name
|
5
|
+
|
6
|
+
def render(matrix_name, size_n, size_m, platform)
|
7
|
+
@size_n, @size_m, @matrix_name = size_n, size_m, matrix_name
|
8
|
+
|
9
|
+
super IO.read("#{__dir__}/print_matrix.any.template")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
std::cout << "{{string}}";
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#include <iostream>
|
2
|
+
|
3
|
+
#if defined(__APPLE__) || defined(__MACOSX)
|
4
|
+
#include <OpenCL/cl.hpp>
|
5
|
+
#else
|
6
|
+
#include <CL/cl.hpp>
|
7
|
+
#endif
|
8
|
+
|
9
|
+
{{{outer_code}}}
|
10
|
+
|
11
|
+
int main(){
|
12
|
+
//get all platforms (drivers)
|
13
|
+
std::vector<cl::Platform> all_platforms;
|
14
|
+
cl::Platform::get(&all_platforms);
|
15
|
+
if(all_platforms.size()==0){
|
16
|
+
std::cout<<" No platforms found. Check OpenCL installation!\n";
|
17
|
+
exit(1);
|
18
|
+
}
|
19
|
+
cl::Platform default_platform=all_platforms[0];
|
20
|
+
std::cout << "Using platform: "<<default_platform.getInfo<CL_PLATFORM_NAME>()<<"\n";
|
21
|
+
|
22
|
+
//get default device of the default platform
|
23
|
+
std::vector<cl::Device> all_devices;
|
24
|
+
default_platform.getDevices(CL_DEVICE_TYPE_GPU, &all_devices);
|
25
|
+
if(all_devices.size()==0){
|
26
|
+
std::cout<<" No devices found. Check OpenCL installation!\n";
|
27
|
+
exit(1);
|
28
|
+
}
|
29
|
+
cl::Device default_device=all_devices[0];
|
30
|
+
std::cout<< "Using device: "<<default_device.getInfo<CL_DEVICE_NAME>()<<"\n";
|
31
|
+
|
32
|
+
cl::Context context({default_device});
|
33
|
+
|
34
|
+
cl::Program::Sources sources;
|
35
|
+
|
36
|
+
{{{inner_code}}}
|
37
|
+
|
38
|
+
return 0;
|
39
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module MetaCL
|
2
|
+
module Templates
|
3
|
+
class Wrapper < Mustache
|
4
|
+
attr_accessor :inner_code, :outer_code
|
5
|
+
|
6
|
+
def render(inner_code, outer_code, platform)
|
7
|
+
@inner_code, @outer_code = Utils.tab_text(inner_code), outer_code
|
8
|
+
super IO.read("#{__dir__}/wrapper.#{platform}.template")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/metacl/utils.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module MetaCL
|
2
|
+
class Utils
|
3
|
+
class << self
|
4
|
+
def tab_text(text, tabs = 1, tab_size = 4)
|
5
|
+
text.split("\n").map{ |s| ' '*tab_size*tabs + s }.join("\n")
|
6
|
+
end
|
7
|
+
|
8
|
+
def stringify_text(text)
|
9
|
+
text.split("\n").map{ |s| '"' + s.gsub('"', '""') + '\\n"' }.tap { |t|
|
10
|
+
t[-1] = t[-1] + ";"
|
11
|
+
}.join("\n")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/metacl.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'metacl/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "metacl"
|
8
|
+
spec.version = MetaCL::VERSION
|
9
|
+
spec.authors = ["Roman Kolesnev"]
|
10
|
+
spec.email = ["rvkolesnev@gmail.com"]
|
11
|
+
spec.summary = %q{DSL for prototyping computation apps}
|
12
|
+
spec.description = %q{DSL that generates C code for different computation platforms (pure C, OpenCL, Intel Phi)}
|
13
|
+
spec.homepage = "https://github.com/ffloyd/metacl"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "mustache"
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "rspec"
|
25
|
+
spec.add_development_dependency "pry"
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: metacl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Roman Kolesnev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mustache
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: DSL that generates C code for different computation platforms (pure C,
|
84
|
+
OpenCL, Intel Phi)
|
85
|
+
email:
|
86
|
+
- rvkolesnev@gmail.com
|
87
|
+
executables:
|
88
|
+
- metacl
|
89
|
+
extensions: []
|
90
|
+
extra_rdoc_files: []
|
91
|
+
files:
|
92
|
+
- ".gitignore"
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- bin/metacl
|
98
|
+
- lib/metacl.rb
|
99
|
+
- lib/metacl/dsl.rb
|
100
|
+
- lib/metacl/dsl/data_definitions.rb
|
101
|
+
- lib/metacl/dsl/directs.rb
|
102
|
+
- lib/metacl/dsl/expression.rb
|
103
|
+
- lib/metacl/dsl/expression_applicator.rb
|
104
|
+
- lib/metacl/dsl/root.rb
|
105
|
+
- lib/metacl/logic.rb
|
106
|
+
- lib/metacl/logic/node.rb
|
107
|
+
- lib/metacl/logic/resource_manager.rb
|
108
|
+
- lib/metacl/program.rb
|
109
|
+
- lib/metacl/refinements.rb
|
110
|
+
- lib/metacl/templates.rb
|
111
|
+
- lib/metacl/templates/aggregator.any.template
|
112
|
+
- lib/metacl/templates/aggregator.rb
|
113
|
+
- lib/metacl/templates/expression_applicator_wrapper.cl.template
|
114
|
+
- lib/metacl/templates/expression_applicator_wrapper.cpp.template
|
115
|
+
- lib/metacl/templates/expression_applicator_wrapper.rb
|
116
|
+
- lib/metacl/templates/init_array.cl.template
|
117
|
+
- lib/metacl/templates/init_array.cpp.template
|
118
|
+
- lib/metacl/templates/init_array.rb
|
119
|
+
- lib/metacl/templates/init_matrix.cl.template
|
120
|
+
- lib/metacl/templates/init_matrix.cpp.template
|
121
|
+
- lib/metacl/templates/init_matrix.rb
|
122
|
+
- lib/metacl/templates/init_numeric.cl.template
|
123
|
+
- lib/metacl/templates/init_numeric.cpp.template
|
124
|
+
- lib/metacl/templates/init_numeric.rb
|
125
|
+
- lib/metacl/templates/kernel.cl.template
|
126
|
+
- lib/metacl/templates/kernel.rb
|
127
|
+
- lib/metacl/templates/print_matrix.any.template
|
128
|
+
- lib/metacl/templates/print_matrix.rb
|
129
|
+
- lib/metacl/templates/prints.any.template
|
130
|
+
- lib/metacl/templates/prints.rb
|
131
|
+
- lib/metacl/templates/wrapper.cl.template
|
132
|
+
- lib/metacl/templates/wrapper.cpp.template
|
133
|
+
- lib/metacl/templates/wrapper.rb
|
134
|
+
- lib/metacl/utils.rb
|
135
|
+
- lib/metacl/version.rb
|
136
|
+
- metacl.gemspec
|
137
|
+
homepage: https://github.com/ffloyd/metacl
|
138
|
+
licenses:
|
139
|
+
- MIT
|
140
|
+
metadata: {}
|
141
|
+
post_install_message:
|
142
|
+
rdoc_options: []
|
143
|
+
require_paths:
|
144
|
+
- lib
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
requirements: []
|
156
|
+
rubyforge_project:
|
157
|
+
rubygems_version: 2.2.2
|
158
|
+
signing_key:
|
159
|
+
specification_version: 4
|
160
|
+
summary: DSL for prototyping computation apps
|
161
|
+
test_files: []
|