metacl 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|