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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +1 -0
  7. data/bin/metacl +9 -0
  8. data/lib/metacl.rb +14 -0
  9. data/lib/metacl/dsl.rb +5 -0
  10. data/lib/metacl/dsl/data_definitions.rb +26 -0
  11. data/lib/metacl/dsl/directs.rb +13 -0
  12. data/lib/metacl/dsl/expression.rb +30 -0
  13. data/lib/metacl/dsl/expression_applicator.rb +92 -0
  14. data/lib/metacl/dsl/root.rb +46 -0
  15. data/lib/metacl/logic.rb +2 -0
  16. data/lib/metacl/logic/node.rb +92 -0
  17. data/lib/metacl/logic/resource_manager.rb +53 -0
  18. data/lib/metacl/program.rb +19 -0
  19. data/lib/metacl/refinements.rb +31 -0
  20. data/lib/metacl/templates.rb +9 -0
  21. data/lib/metacl/templates/aggregator.any.template +6 -0
  22. data/lib/metacl/templates/aggregator.rb +13 -0
  23. data/lib/metacl/templates/expression_applicator_wrapper.cl.template +21 -0
  24. data/lib/metacl/templates/expression_applicator_wrapper.cpp.template +7 -0
  25. data/lib/metacl/templates/expression_applicator_wrapper.rb +90 -0
  26. data/lib/metacl/templates/init_array.cl.template +2 -0
  27. data/lib/metacl/templates/init_array.cpp.template +1 -0
  28. data/lib/metacl/templates/init_array.rb +12 -0
  29. data/lib/metacl/templates/init_matrix.cl.template +2 -0
  30. data/lib/metacl/templates/init_matrix.cpp.template +1 -0
  31. data/lib/metacl/templates/init_matrix.rb +12 -0
  32. data/lib/metacl/templates/init_numeric.cl.template +2 -0
  33. data/lib/metacl/templates/init_numeric.cpp.template +1 -0
  34. data/lib/metacl/templates/init_numeric.rb +12 -0
  35. data/lib/metacl/templates/kernel.cl.template +5 -0
  36. data/lib/metacl/templates/kernel.rb +13 -0
  37. data/lib/metacl/templates/print_matrix.any.template +8 -0
  38. data/lib/metacl/templates/print_matrix.rb +13 -0
  39. data/lib/metacl/templates/prints.any.template +1 -0
  40. data/lib/metacl/templates/prints.rb +12 -0
  41. data/lib/metacl/templates/wrapper.cl.template +39 -0
  42. data/lib/metacl/templates/wrapper.cpp.template +10 -0
  43. data/lib/metacl/templates/wrapper.rb +12 -0
  44. data/lib/metacl/utils.rb +15 -0
  45. data/lib/metacl/version.rb +3 -0
  46. data/metacl.gemspec +26 -0
  47. 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
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea
19
+ bin/test*.rb
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in metacl.gemspec
4
+ gemspec
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
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ require 'metacl'
3
+
4
+ source = ARGV[0]
5
+ dest = ARGV[1] || source.gsub('mcl', 'cpp')
6
+
7
+ code = MetaCL::Program.create source
8
+
9
+ File.open(dest, 'w') { |file| file.write(code) }
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,5 @@
1
+ require 'metacl/dsl/expression'
2
+ require 'metacl/dsl/data_definitions'
3
+ require 'metacl/dsl/directs'
4
+ require 'metacl/dsl/expression_applicator'
5
+ require 'metacl/dsl/root'
@@ -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,13 @@
1
+ module MetaCL
2
+ module DSL
3
+ module Directs
4
+ def direct(string)
5
+ @inner_code << string << "\n"
6
+ end
7
+
8
+ def direct_pre(string)
9
+ @outer_code << string << "\n"
10
+ end
11
+ end
12
+ end
13
+ 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
@@ -0,0 +1,2 @@
1
+ require 'metacl/logic/resource_manager'
2
+ require 'metacl/logic/node'
@@ -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,6 @@
1
+ {{type}} {{var}} = 0;
2
+ for (int {{iterator}} = {{from}}; {{iterator}} < {{to}}; ++{{iterator}})
3
+ {
4
+ {{{code}}}
5
+ {{var}} {{operator}}= {{subresult_var}};
6
+ }
@@ -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,7 @@
1
+ for (int i = {{n_from}}; i < {{n_to}}; ++i)
2
+ {
3
+ for (int j = {{m_from}}; j < {{m_to}}; ++j)
4
+ {
5
+ {{{code}}}
6
+ }
7
+ }
@@ -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,2 @@
1
+ std::vector<{{type}}> {{name}}({{length}}{{#fill_with}}, {{fill_with}}{{/fill_with}});
2
+ cl::Buffer buffer_{{name}}(context,CL_MEM_READ_WRITE,sizeof({{type}})*{{length}});
@@ -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,2 @@
1
+ std::vector<{{type}}> {{name}}({{size_n}} * {{size_m}}{{#fill_with}}, {{fill_with}}{{/fill_with}});
2
+ cl::Buffer buffer_{{name}}(context,CL_MEM_READ_WRITE,sizeof({{type}})*{{size_n}}*{{size_m}});
@@ -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,2 @@
1
+ {{type}} {{name}}{{#value}} = {{value}}{{/value}};
2
+ cl::Buffer buffer_{{name}}(context, CL_MEM_READ_WRITE, sizeof({{type}}));
@@ -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,5 @@
1
+ void kernel metacl_program({{{params}}}) {
2
+ int i = get_global_id(0) + {{n_from}};
3
+ int j = get_global_id(1) + {{m_from}};
4
+ {{{code}}}
5
+ }
@@ -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,8 @@
1
+ for (int i = 0; i < {{size_n}}; ++i)
2
+ {
3
+ for (int j = 0; j < {{size_m}}; ++j)
4
+ {
5
+ std::cout << {{matrix_name}}[i*{{size_m}} + j] << " ";
6
+ }
7
+ std::cout << std::endl;
8
+ }
@@ -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,12 @@
1
+ module MetaCL
2
+ module Templates
3
+ class Prints < Mustache
4
+ attr_accessor :string
5
+
6
+ def render(string, platform)
7
+ @string = string
8
+ super IO.read("#{__dir__}/prints.any.template")
9
+ end
10
+ end
11
+ end
12
+ end
@@ -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,10 @@
1
+ #include <iostream>
2
+ #include <vector>
3
+
4
+ {{{outer_code}}}
5
+
6
+ int main()
7
+ {
8
+ {{{inner_code}}}
9
+ return 0;
10
+ }
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module MetaCL
2
+ VERSION = "0.2.0"
3
+ 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: []