metacl 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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: []