module Ikra::Symbolic::ArrayCommand
Attributes
Returns the block of the parallel section or [nil] if none.
A reference to the AST
send node that generated this [ArrayCommand] (if inside a host section).
This field can only be used if keep is true
An array of commands that serve as input to this command. The number of input commands depends on the type of the command.
Indicates if result should be kept on the GPU for further processing.
Fixnum
-
Returns a unique ID for this command. It is used during name mangling in
the code generator to determine the name of array identifiers (and do other stuff?).
Public Class Methods
# File lib/types/types/array_command_type.rb, line 8 def self.included(base) base.extend(ClassMethods) end
# File lib/symbolic/symbolic.rb, line 191 def initialize( block: nil, block_ast: nil, block_size: nil, keep: nil, generator_node: nil, command_binding: nil) super() set_unique_id # Set instance variables @block_size = block_size @keep = keep @generator_node = generator_node @command_binding = command_binding if block != nil and block_ast == nil @block = block elsif block == nil and block_ast != nil @ast = block_ast elsif block != nil and block_ast != nil raise ArgumentError.new("`block` and `block_ast` given. Expected at most one.") end end
# File lib/symbolic/symbolic.rb, line 183 def self.reset_unique_id @@unique_id = 1 end
Public Instance Methods
Methods for equality and hash. These methods are required for comparing array commands for equality. This is necessary because every array command can also act as a type. Types
must be comparable for equality.
# File lib/symbolic/symbolic.rb, line 225 def ==(other) # Important: ArrayCommands may be created over and over during type inference. # It is important that we compare values and not identities! return self.class == other.class && block_size == other.block_size && input == other.input && keep == other.keep && block_def_node == other.block_def_node end
—– ARRAY METHODS —–
# File lib/symbolic/symbolic.rb, line 249 def [](index) execute return @result[index] end
Returns the abstract syntax tree for a parallel section.
# File lib/symbolic/symbolic.rb, line 334 def block_def_node if @ast == nil if block == nil return nil end # Get array of block parameter names block_params = block.parameters.map do |param| param[1] end parser_local_vars = command_binding.local_variables + block_params source = Parsing.parse_block(block, parser_local_vars) @ast = AST::BlockDefNode.new( parameters: block_params, ruby_block: block, # necessary to get binding body: AST::Builder.from_parser_ast(source)) end # Ensure `return` is there @ast.accept(Translator::LastStatementReturnsVisitor.new) return @ast end
Returns a collection of the names of all block parameters. @return [Array(Symbol
)] list of block parameters
# File lib/symbolic/symbolic.rb, line 316 def block_parameter_names return block_def_node.parameters end
Returns the binding of this command. It is used to retrieve lexical variables that are used inside this parallel section.
# File lib/symbolic/symbolic.rb, line 361 def command_binding if @command_binding != nil return @command_binding elsif block != nil return block.binding else return nil end end
The class or subclass of [CommandTranslator] that should be used for translating this command. May be overridden.
# File lib/symbolic/symbolic.rb, line 273 def command_translator_class return Translator::CommandTranslator end
# File lib/symbolic/symbolic.rb, line 327 def dimensions # Dimensions are defined in a root command. First input currently determines the # dimensions (even if there are multiple root commands). return input.first.command.dimensions end
# File lib/symbolic/symbolic.rb, line 254 def each(&block) next_index = 0 while next_index < size yield(self[next_index]) next_index += 1 end end
# File lib/symbolic/symbolic.rb, line 240 def eql?(other) return self == other end
# File lib/symbolic/symbolic.rb, line 277 def execute if @result == nil @result = command_translator_class.translate_command(self).execute end end
Returns a collection of external objects that are accessed within a parallel section.
# File lib/symbolic/symbolic.rb, line 393 def externals return lexical_externals.keys end
# File lib/symbolic/symbolic.rb, line 310 def has_previous_result? return !gpu_result_pointer.nil? end
# File lib/symbolic/symbolic.rb, line 236 def hash return (block_size.hash + input.hash + keep.hash + block_def_node.hash) % 7546777 end
Every [ArrayCommand] has itself as an Ikra
type. This integrates well with the current type inference approach and `ruby_core`.
# File lib/types/types/array_command_type.rb, line 109 def ikra_type return self end
Returns a collection of lexical variables that are accessed within a parallel section. @return [Hash{Symbol => Object}]
# File lib/symbolic/symbolic.rb, line 374 def lexical_externals if block_def_node != nil && command_binding != nil all_lexical_vars = command_binding.local_variables lexical_vars_enumerator = AST::LexicalVariablesEnumerator.new(all_lexical_vars) block_def_node.accept(lexical_vars_enumerator) accessed_variables = lexical_vars_enumerator.lexical_variables result = Hash.new for var_name in accessed_variables result[var_name] = command_binding.local_variable_get(var_name) end return result else return {} end end
# File lib/symbolic/symbolic.rb, line 263 def pack(fmt) execute return @result.pack(fmt) end
This method is executed after execution of the parallel section has finish. The boolean return value indicates if a change has been registered or not.
# File lib/symbolic/symbolic.rb, line 289 def post_execute(environment) if keep # The (temporary) result of this command should be kept on the GPU. Store a # pointer to the result in global memory in an instance variable. begin @gpu_result_pointer = environment[("prev_" + unique_id.to_s).to_sym].to_i Log.info("Kept pointer for result of command #{unique_id.to_s}: #{@gpu_result_pointer}") return true rescue ArgumentError # No pointer saved for this command. This can happen if the result of this # command was already cached earlier and the cached result of a # computation based on this command was used now. Log.info("No pointer kept for result of command #{unique_id.to_s}.") return false end end return false end
# File lib/types/types/array_command_type.rb, line 113 def result_type # Result cache should be cached, just like the result itself if @result_type == nil @result_type = TypeInference::CommandInference.process_command(self) end return @result_type end
# File lib/symbolic/symbolic.rb, line 397 def set_unique_id # Generate unique ID @unique_id = @@unique_id @@unique_id += 1 end
Returns the size (number of elements) of the result, after executing the parallel section. @return [Fixnum] size
# File lib/symbolic/symbolic.rb, line 323 def size raise NotImplementedError.new end
# File lib/types/types/array_command_type.rb, line 94 def to_c_type return "#{Translator::ArrayCommandStructBuilder.struct_name(self)} *" end
# File lib/symbolic/symbolic.rb, line 283 def to_command return self end
# File lib/types/types/array_command_type.rb, line 98 def to_ffi_type # TODO: This method is probably not required? return :pointer end
# File lib/types/types/array_command_type.rb, line 103 def to_ruby_type return ArrayCommand end
# File lib/symbolic/symbolic.rb, line 187 def to_s return "[#{self.class.to_s}, size = #{size.to_s}]" end
# File lib/symbolic/symbolic.rb, line 403 def with_index(&block) self.block = block @input.push(SingleInput.new( command: ArrayIndexCommand.new(dimensions: dimensions), pattern: :tid)) return self end