module Ikra::Symbolic::ArrayCommand

Attributes

block[RW]

Returns the block of the parallel section or [nil] if none.

block_size[R]
generator_node[R]

A reference to the AST send node that generated this [ArrayCommand] (if inside a host section).

gpu_result_pointer[RW]

This field can only be used if keep is true

input[R]

An array of commands that serve as input to this command. The number of input commands depends on the type of the command.

keep[R]

Indicates if result should be kept on the GPU for further processing.

unique_id[R]
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

included(base) click to toggle source
# File lib/types/types/array_command_type.rb, line 8
def self.included(base)
    base.extend(ClassMethods)
end
new( block: nil, block_ast: nil, block_size: nil, keep: nil, generator_node: nil, command_binding: nil) click to toggle source
Calls superclass method
# 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
reset_unique_id() click to toggle source
# File lib/symbolic/symbolic.rb, line 183
def self.reset_unique_id
    @@unique_id = 1
end

Public Instance Methods

==(other) click to toggle source

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
[](index) click to toggle source

—– ARRAY METHODS —–

# File lib/symbolic/symbolic.rb, line 249
def [](index)
    execute
    return @result[index]
end
block_def_node() click to toggle source

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
block_parameter_names() click to toggle source

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
command_binding() click to toggle source

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
command_translator_class() click to toggle source

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
dimensions() click to toggle source
# 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
each() { |self| ... } click to toggle source
# 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
eql?(other) click to toggle source
# File lib/symbolic/symbolic.rb, line 240
def eql?(other)
    return self == other
end
execute() click to toggle source
# File lib/symbolic/symbolic.rb, line 277
def execute
    if @result == nil
        @result = command_translator_class.translate_command(self).execute
    end
end
externals() click to toggle source

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
has_previous_result?() click to toggle source
# File lib/symbolic/symbolic.rb, line 310
def has_previous_result?
    return !gpu_result_pointer.nil?
end
hash() click to toggle source
# File lib/symbolic/symbolic.rb, line 236
def hash
    return (block_size.hash + input.hash + keep.hash + block_def_node.hash) % 7546777
end
ikra_type() click to toggle source

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
lexical_externals() click to toggle source

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
pack(fmt) click to toggle source
# File lib/symbolic/symbolic.rb, line 263
def pack(fmt)
    execute
    return @result.pack(fmt)
end
post_execute(environment) click to toggle source

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
result_type() click to toggle source
# 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
set_unique_id() click to toggle source
# File lib/symbolic/symbolic.rb, line 397
def set_unique_id
    # Generate unique ID
    @unique_id = @@unique_id
    @@unique_id += 1
end
size() click to toggle source

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
to_c_type() click to toggle source
# File lib/types/types/array_command_type.rb, line 94
def to_c_type
    return "#{Translator::ArrayCommandStructBuilder.struct_name(self)} *"
end
to_command() click to toggle source
# File lib/symbolic/symbolic.rb, line 283
def to_command
    return self
end
to_ffi_type() click to toggle source
# File lib/types/types/array_command_type.rb, line 98
def to_ffi_type
    # TODO: This method is probably not required?
    return :pointer
end
to_ruby_type() click to toggle source
# File lib/types/types/array_command_type.rb, line 103
def to_ruby_type
    return ArrayCommand
end
to_s() click to toggle source
# File lib/symbolic/symbolic.rb, line 187
def to_s
    return "[#{self.class.to_s}, size = #{size.to_s}]"
end
with_index(&block) click to toggle source
# 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