Module: Ikra::Symbolic::ArrayCommand
- Includes:
- Enumerable, ParallelOperations, Types::RubyType
- Included in:
- ArrayCombineCommand, ArrayHostSectionCommand, ArrayIdentityCommand, ArrayInHostSectionCommand, ArrayIndexCommand, ArrayReduceCommand, ArraySelectCommand, ArrayStencilCommand, ArrayZipCommand, FixedSizeArrayInHostSectionCommand
- Defined in:
- lib/symbolic/symbolic.rb,
lib/types/types/array_command_type.rb
Defined Under Namespace
Modules: ClassMethods
Constant Summary collapse
- @@unique_id =
1
Instance Attribute Summary collapse
-
#block ⇒ Object
readonly
Returns the block of the parallel section or [nil] if none.
-
#block_size ⇒ Object
readonly
Returns the value of attribute block_size.
-
#generator_node ⇒ Object
readonly
A reference to the AST send node that generated this [ArrayCommand] (if inside a host section).
-
#gpu_result_pointer ⇒ Object
This field can only be used if keep is true.
-
#input ⇒ Object
readonly
An array of commands that serve as input to this command.
-
#keep ⇒ Object
readonly
Indicates if result should be kept on the GPU for further processing.
-
#unique_id ⇒ Object
readonly
- Fixnum
-
Returns a unique ID for this command.
Class Method Summary collapse
Instance Method Summary collapse
-
#==(other) ⇒ Object
Methods for equality and hash.
-
#[](index) ⇒ Object
—– ARRAY METHODS —–.
-
#block_def_node ⇒ Object
Returns the abstract syntax tree for a parallel section.
-
#block_parameter_names ⇒ Array(Symbol)
Returns a collection of the names of all block parameters.
-
#command_binding ⇒ Object
Returns the binding of this command.
-
#command_translator_class ⇒ Object
The class or subclass of [CommandTranslator] that should be used for translating this command.
- #dimensions ⇒ Object
- #each(&block) ⇒ Object
- #eql?(other) ⇒ Boolean
- #execute ⇒ Object
-
#externals ⇒ Object
Returns a collection of external objects that are accessed within a parallel section.
- #has_previous_result? ⇒ Boolean
- #hash ⇒ Object
-
#ikra_type ⇒ Object
Every [ArrayCommand] has itself as an Ikra type.
- #initialize(block: nil, block_ast: nil, block_size: nil, keep: nil, generator_node: nil, command_binding: nil) ⇒ Object
-
#lexical_externals ⇒ Hash{Symbol => Object}
Returns a collection of lexical variables that are accessed within a parallel section.
- #pack(fmt) ⇒ Object
-
#post_execute(environment) ⇒ Object
This method is executed after execution of the parallel section has finish.
- #result_type ⇒ Object
- #set_unique_id ⇒ Object
-
#size ⇒ Fixnum
Returns the size (number of elements) of the result, after executing the parallel section.
- #to_c_type ⇒ Object
- #to_command ⇒ Object
- #to_ffi_type ⇒ Object
- #to_ruby_type ⇒ Object
- #to_s ⇒ Object
- #with_index(&block) ⇒ Object
Methods included from Types::RubyType
#class_id, #inspect, #is_primitive?, #is_union_type?, #should_generate_self_arg?, #to_array_type, #to_str, #to_union_type
Methods included from ParallelOperations
#&, #*, #+, #-, #/, #<, #<=, #>, #>=, #^, #pcombine, #pmap, #preduce, #pstencil, #pzip, #|
Instance Attribute Details
#block ⇒ Object
Returns the block of the parallel section or [nil] if none.
175 176 177 |
# File 'lib/symbolic/symbolic.rb', line 175 def block @block end |
#block_size ⇒ Object (readonly)
Returns the value of attribute block_size.
158 159 160 |
# File 'lib/symbolic/symbolic.rb', line 158 def block_size @block_size end |
#generator_node ⇒ Object (readonly)
A reference to the AST send node that generated this [ArrayCommand] (if inside a host section).
179 180 181 |
# File 'lib/symbolic/symbolic.rb', line 179 def generator_node @generator_node end |
#gpu_result_pointer ⇒ Object
This field can only be used if keep is true
172 173 174 |
# File 'lib/symbolic/symbolic.rb', line 172 def gpu_result_pointer @gpu_result_pointer end |
#input ⇒ Object (readonly)
An array of commands that serve as input to this command. The number of input commands depends on the type of the command.
166 167 168 |
# File 'lib/symbolic/symbolic.rb', line 166 def input @input end |
#keep ⇒ Object (readonly)
Indicates if result should be kept on the GPU for further processing.
169 170 171 |
# File 'lib/symbolic/symbolic.rb', line 169 def keep @keep end |
#unique_id ⇒ Object (readonly)
- 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?).
162 163 164 |
# File 'lib/symbolic/symbolic.rb', line 162 def unique_id @unique_id end |
Class Method Details
.included(base) ⇒ Object
8 9 10 |
# File 'lib/types/types/array_command_type.rb', line 8 def self.included(base) base.extend(ClassMethods) end |
.reset_unique_id ⇒ Object
183 184 185 |
# File 'lib/symbolic/symbolic.rb', line 183 def self.reset_unique_id @@unique_id = 1 end |
Instance Method Details
#==(other) ⇒ Object
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.
225 226 227 228 229 230 231 232 233 234 |
# 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) ⇒ Object
—– ARRAY METHODS —–
249 250 251 252 |
# File 'lib/symbolic/symbolic.rb', line 249 def [](index) execute return @result[index] end |
#block_def_node ⇒ Object
Returns the abstract syntax tree for a parallel section.
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
# 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 ⇒ Array(Symbol)
Returns a collection of the names of all block parameters.
316 317 318 |
# File 'lib/symbolic/symbolic.rb', line 316 def block_parameter_names return block_def_node.parameters end |
#command_binding ⇒ Object
Returns the binding of this command. It is used to retrieve lexical variables that are used inside this parallel section.
361 362 363 364 365 366 367 368 369 |
# 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 ⇒ Object
The class or subclass of [CommandTranslator] that should be used for translating this command. May be overridden.
273 274 275 |
# File 'lib/symbolic/symbolic.rb', line 273 def command_translator_class return Translator::CommandTranslator end |
#dimensions ⇒ Object
327 328 329 330 331 |
# 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(&block) ⇒ Object
254 255 256 257 258 259 260 261 |
# 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) ⇒ Boolean
240 241 242 |
# File 'lib/symbolic/symbolic.rb', line 240 def eql?(other) return self == other end |
#execute ⇒ Object
277 278 279 280 281 |
# File 'lib/symbolic/symbolic.rb', line 277 def execute if @result == nil @result = command_translator_class.translate_command(self).execute end end |
#externals ⇒ Object
Returns a collection of external objects that are accessed within a parallel section.
393 394 395 |
# File 'lib/symbolic/symbolic.rb', line 393 def externals return lexical_externals.keys end |
#has_previous_result? ⇒ Boolean
310 311 312 |
# File 'lib/symbolic/symbolic.rb', line 310 def has_previous_result? return !gpu_result_pointer.nil? end |
#hash ⇒ Object
236 237 238 |
# 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 ⇒ Object
Every [ArrayCommand] has itself as an Ikra type. This integrates well with the current type inference approach and ‘ruby_core`.
109 110 111 |
# File 'lib/types/types/array_command_type.rb', line 109 def ikra_type return self end |
#initialize(block: nil, block_ast: nil, block_size: nil, keep: nil, generator_node: nil, command_binding: nil) ⇒ Object
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# 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 |
#lexical_externals ⇒ Hash{Symbol => Object}
Returns a collection of lexical variables that are accessed within a parallel section.
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 |
# 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) ⇒ Object
263 264 265 266 |
# File 'lib/symbolic/symbolic.rb', line 263 def pack(fmt) execute return @result.pack(fmt) end |
#post_execute(environment) ⇒ Object
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.
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# 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 ⇒ Object
113 114 115 116 117 118 119 120 |
# 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 ⇒ Object
397 398 399 400 401 |
# File 'lib/symbolic/symbolic.rb', line 397 def set_unique_id # Generate unique ID @unique_id = @@unique_id @@unique_id += 1 end |
#size ⇒ Fixnum
Returns the size (number of elements) of the result, after executing the parallel section.
323 324 325 |
# File 'lib/symbolic/symbolic.rb', line 323 def size raise NotImplementedError.new end |
#to_c_type ⇒ Object
94 95 96 |
# File 'lib/types/types/array_command_type.rb', line 94 def to_c_type return "#{Translator::ArrayCommandStructBuilder.struct_name(self)} *" end |
#to_command ⇒ Object
283 284 285 |
# File 'lib/symbolic/symbolic.rb', line 283 def to_command return self end |
#to_ffi_type ⇒ Object
98 99 100 101 |
# 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 ⇒ Object
103 104 105 |
# File 'lib/types/types/array_command_type.rb', line 103 def to_ruby_type return ArrayCommand end |
#to_s ⇒ Object
187 188 189 |
# File 'lib/symbolic/symbolic.rb', line 187 def to_s return "[#{self.class.to_s}, size = #{size.to_s}]" end |
#with_index(&block) ⇒ Object
403 404 405 406 407 408 409 |
# 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 |