Class: Bones::Algorithm
Overview
This class holds one algorithm, which includes a species, a name, and the source C-code.
The algorithm class holds all sorts of information on var- iables. This information is only available after calling the ‘populate’ method, which populates a lists of varia- bles of all sorts: a regular list, a specialized hash, and lists of input/output array variables.
Constant Summary collapse
- ACCELERATED =
Constant to set the name of the algorithm’s accelerated version
'_accelerated'- ORIGINAL =
Constant to set the name of the algorithm’s original version
'_original'
Instance Attribute Summary collapse
-
#arrays ⇒ Object
readonly
Returns the value of attribute arrays.
-
#code ⇒ Object
readonly
Returns the value of attribute code.
-
#function_name ⇒ Object
readonly
Returns the value of attribute function_name.
-
#hash ⇒ Object
Returns the value of attribute hash.
-
#id ⇒ Object
readonly
Returns the value of attribute id.
-
#lists ⇒ Object
readonly
Returns the value of attribute lists.
-
#merge_factor ⇒ Object
Returns the value of attribute merge_factor.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#register_caching_enabled ⇒ Object
Returns the value of attribute register_caching_enabled.
-
#species ⇒ Object
readonly
Returns the value of attribute species.
Instance Method Summary collapse
-
#generate_replacement_code(options, skeleton, verify_code, prefix, timer_start, timer_stop) ⇒ Object
This method is used to generate verification code.
-
#initialize(name, filename, id, species, code) ⇒ Algorithm
constructor
This method initializes the class.
-
#opencl_arguments(list, kernel_id) ⇒ Object
Helper function to create a the special code which is required for OpenCL function calls to be able to use kernel arguments.
-
#perform_transformations(transformation_settings) ⇒ Object
This method performs the code transformations according to the transformation settings as provided as an argument to the function.
-
#performance_model_code(model_dir) ⇒ Object
Method to generate performance modeling code.
-
#populate_hash ⇒ Object
This method creates the search-and-replace hash based on information provided by the algorithm.
-
#populate_lists ⇒ Object
Method to populate 5 lists with variable information.
-
#populate_variables(original_code, defines) ⇒ Object
Method to create a list of variables for the current algorithm.
-
#set_function(full_code) ⇒ Object
This method sets the code and name for the function in which the algorithm is found.
-
#update_hash(loop_variable) ⇒ Object
This method updates the hash after loops are removed from the code.
Methods inherited from Common
#flatten_hash, #from, #replace_defines, #search_and_replace, #search_and_replace!, #sum, #sum_and_from, #to
Constructor Details
#initialize(name, filename, id, species, code) ⇒ Algorithm
This method initializes the class. It gives the new algorithm a name, species and source code. At initiali- zation, this method checks if the name starts with a digit. This is not allowed, so an underscore is added prior to the digit.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/bones/algorithm.rb', line 25 def initialize(name, filename, id, species, code) name = '_'+name if name =~ /^\d/ @filename = filename @basename = name @name = (name+'_'+id).gsub(/\W/,'') @id = id @original_name = @name+ORIGINAL @accelerated_name = @name+ACCELERATED @species = species begin @code = C::Statement.parse(code).preprocess rescue @code = C::Statement.parse('{'+code+'}').preprocess end @hash = {} @lists = {:host_name => [],:host_definition => [], :argument_name => [], :argument_definition => [], :golden_name => []} @arrays = Variablelist.new() @constants = Variablelist.new() @merge_factor = nil @register_caching_enabled = 1 @function_code = '' @function_name = '' # Set the initial hash @hash = {:algorithm_id => @id, :algorithm_name => @name, :algorithm_basename => @basename, :algorithm_filename => @filename} end |
Instance Attribute Details
#arrays ⇒ Object (readonly)
Returns the value of attribute arrays.
12 13 14 |
# File 'lib/bones/algorithm.rb', line 12 def arrays @arrays end |
#code ⇒ Object (readonly)
Returns the value of attribute code.
12 13 14 |
# File 'lib/bones/algorithm.rb', line 12 def code @code end |
#function_name ⇒ Object (readonly)
Returns the value of attribute function_name.
12 13 14 |
# File 'lib/bones/algorithm.rb', line 12 def function_name @function_name end |
#hash ⇒ Object
Returns the value of attribute hash.
13 14 15 |
# File 'lib/bones/algorithm.rb', line 13 def hash @hash end |
#id ⇒ Object (readonly)
Returns the value of attribute id.
12 13 14 |
# File 'lib/bones/algorithm.rb', line 12 def id @id end |
#lists ⇒ Object (readonly)
Returns the value of attribute lists.
12 13 14 |
# File 'lib/bones/algorithm.rb', line 12 def lists @lists end |
#merge_factor ⇒ Object
Returns the value of attribute merge_factor.
13 14 15 |
# File 'lib/bones/algorithm.rb', line 13 def merge_factor @merge_factor end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
12 13 14 |
# File 'lib/bones/algorithm.rb', line 12 def name @name end |
#register_caching_enabled ⇒ Object
Returns the value of attribute register_caching_enabled.
13 14 15 |
# File 'lib/bones/algorithm.rb', line 13 def register_caching_enabled @register_caching_enabled end |
#species ⇒ Object (readonly)
Returns the value of attribute species.
12 13 14 |
# File 'lib/bones/algorithm.rb', line 12 def species @species end |
Instance Method Details
#generate_replacement_code(options, skeleton, verify_code, prefix, timer_start, timer_stop) ⇒ Object
This method is used to generate verification code. This verification code contains a copy of the original code. It also provides a verification which compares the output of the original code with the output of the generated code. The verification code prints warnings if the outputs are not equal, else it prints a success message.
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
# File 'lib/bones/algorithm.rb', line 497 def generate_replacement_code(, skeleton, verify_code, prefix, timer_start, timer_stop) replacement = C::NodeArray.new replacement.push(C::ExpressionStatement.parse(@accelerated_name+'('+@lists[:host_name]+');')) original_definition = '' verify_definitions = [] if [:verify] guesses = @arrays.map { |array| array.guess } if guesses.include?(true) puts WARNING+'Verification not supported for this class' else # Generate the replacement code and the original function @arrays.each do |array| replacement.insert(0,C::ExpressionStatement.parse("memcpy(#{array.golden_name},#{array.name},#{array.size.join('*')}*sizeof(#{array.type_name}));")) replacement.insert(0,C::Declaration.parse(array.definition.gsub!(/\b#{array.name}\b/,array.golden_name)+array.initialization)) end replacement.push(C::ExpressionStatement.parse(@original_name+'('+@lists[:golden_name]+');')) original_definition = "void #{@original_name}(#{@lists[:host_definition]})" body = "#{timer_start}#{NL} // Original code#{NL}#{@code}#{NL}#{timer_stop}" verify_code.push(prefix+original_definition+' {'+NL+body+'}'+NL+NL) @arrays.select(OUTPUT).each do |array| replacement.push(C::ExpressionStatement.parse(("bones_verify_results_#{array.name}_#{@id}(#{array.name}#{array.flatten},#{array.golden_name}#{array.flatten},#{@hash[:argument_name]});").remove_extras)) end @arrays.each do |array| replacement.push(C::ExpressionStatement.parse("free(#{array.golden_name});")) if array.dynamic? end # Generate the verification function itself @arrays.select(OUTPUT).each_with_index do |array,num_array| minihash = @hash["out#{num_array}".to_sym] minihash[:name] = minihash[:name]+'_'+@id minihash[:argument_definition] = @hash[:argument_definition] instantiated_skeleton = search_and_replace(minihash,skeleton) verify_definitions.push(instantiated_skeleton.scan(/#{START_DEFINITION}(.+)#{END_DEFINITION}/m).join.strip.remove_extras) verify_code.push(instantiated_skeleton.remove_extras.gsub!(/#{START_DEFINITION}(.+)#{END_DEFINITION}/m,'')) end end end return replacement, original_definition, verify_definitions.join(NL) end |
#opencl_arguments(list, kernel_id) ⇒ Object
Helper function to create a the special code which is required for OpenCL function calls to be able to use kernel arguments.
354 355 356 357 358 359 360 361 |
# File 'lib/bones/algorithm.rb', line 354 def opencl_arguments(list,kernel_id) return '' if list == '' argument_string = '' list.split(', ').each_with_index do |variable,id| argument_string += 'clSetKernelArg(bones_kernel_'+@name+'_'+kernel_id.to_s+',bones_num_args+'+id.to_s+',sizeof('+variable.strip+'),(void*)&'+variable.strip+');'+NL+INDENT end return argument_string end |
#perform_transformations(transformation_settings) ⇒ Object
This method performs the code transformations according to the transformation settings as provided as an argument to the function. It calls the various code transformation functions as implemented for the CAST class. The resulting modified code is finally stored in the search-and-replace hash. This method assumes that the populate method has already been called, such that the hash contains the dimensions needed to create the global ID definitions.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/bones/algorithm.rb', line 78 def perform_transformations(transformation_settings) complexity = 0 # Save the original code (with flattened arrays) in the hash as well new_code = @code.clone @arrays.each do |array| new_code.transform_flatten(array) end @hash[:algorithm_code0] = new_code.to_s # Loop over the number of transformation 'blocks' transformation_settings.split(' ').each_with_index do |transformation,num_transformation| new_code = @code.clone extra_indent = '' # Replace existing loops in the code (always do this) array = @arrays.representative array.species.dimensions.each_with_index do |dimension,num_dimension| index = (array.species.reverse?) ? num_dimension : array.species.dimensions.length-num_dimension-1 index_reverse = !(array.species.reverse?) ? num_dimension : array.species.dimensions.length-num_dimension-1 # Calculate the loop start and end conditions from = array.species.from_at(index) to = array.species.to_at(index) # Process the existing code and update the hash if from != to new_code, loop_variable_name = new_code.remove_loop(from,to) new_variable_name = GLOBAL_ID+'_'+index_reverse.to_s new_code.replace_variable(loop_variable_name,new_variable_name) update_hash(loop_variable_name) end end # Shuffle the indices of the first input(s) (conditionally do this) shuffle_arrays = [] if transformation[0,1] == '2' shuffle_arrays.push(@arrays.select(INPUT)[0]) elsif transformation[0,1] == '3' shuffle_arrays.push(@arrays.select(INPUT)[0]) shuffle_arrays.push(@arrays.select(INPUT)[1]) end new_code.transform_shuffle(shuffle_arrays) # Use the local on-chip memory (conditionally do this) if transformation[0,1] == '1' local_memory_arrays = [@arrays.select(INPUT)[0]] new_code.transform_use_local_memory(local_memory_arrays) end # Flatten the arrays to 1D (always do this) @arrays.each do |array| new_code.transform_flatten(array) end # Perform array substitution a.k.a. register caching (conditionally do this) if @register_caching_enabled == 1 @arrays.outputs.each do |array| if array.species.element? if @arrays.inputs.include?(array) new_code.transform_substitution(array,true) else new_code.transform_substitution(array,false) end extra_indent = INDENT end end end # Perform transformations for reduction operations (conditionally do this) if transformation[1,1].to_i >= 1 new_code = new_code.transform_reduction(@arrays.select(INPUT)[0],@arrays.select(OUTPUT)[0],transformation[1,1].to_i) end # Perform thread-merging (experimental) # TODO: Solve the problem related to constants (e.g chunk/example1.c) if @merge_factor == nil if transformation[0,1] == '4' && @hash[:parallelism].to_i >= 1024*1024 @merge_factor = 4 else @merge_factor = 1 end end if @merge_factor > 1 puts @hash[:parallelism] if new_code.has_conditional_statements? puts MESSAGE+'Not coarsening ('+@merge_factor.to_s+'x) because of conditional statements in kernel body.' # TODO: Fix this temporary hack for multiple loops with mismatching bounds elsif ((@hash[:parallelism].to_i % @merge_factor) != 0) || (@hash[:parallelism].to_i == 4192256) puts MESSAGE+'Not coarsening ('+@merge_factor.to_s+'x) because of mismatching amount of parallelism ('+@hash[:parallelism]+').' else puts MESSAGE+'Coarsening threads by a factor '+@merge_factor.to_s+'.' # Update the hash @hash[:ids] = @hash[:ids].split(NL).map { |line| C::parse(line).transform_merge_threads(@merge_factor,[GLOBAL_ID]+@constants.map{ |c| c.name }).to_s.split(NL).each_with_index.map do |id,index| id.gsub(/\b#{GLOBAL_ID}\b/,"(#{GLOBAL_ID}+gridDim.x*blockDim.x*#{index})") end }.join(NL+INDENT*2) @hash[:parallelism] = (@hash[:parallelism].to_i / @merge_factor).to_s # Transform the code excludes = (@constants+@arrays).map { |c| c.name } new_code.transform_merge_threads(@merge_factor,excludes) end end # Obtain the complexity in terms of operations for the resulting code complexity += new_code.get_complexity # Store the resulting code in the hash resulting_code = new_code.strip_brackets.to_s @hash[('algorithm_code'+(num_transformation+1).to_s).to_sym] = (transformation[1,1].to_i >= 1) ? resulting_code : extra_indent+INDENT+resulting_code.gsub!(NL,NL+INDENT) end @hash[:complexity] = complexity.to_s end |
#performance_model_code(model_dir) ⇒ Object
Method to generate performance modeling code. This method is still under construction and will not be called yet. TODO: Complete this method
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 |
# File 'lib/bones/algorithm.rb', line 541 def performance_model_code(model_dir) # Load the profile database profiles = Array.new File.read(File.join(model_dir,'profile.txt')).each do |line| profiles.push(line.split(',')) end # Iterate over all the profiles result = C::NodeArray.new profiles.each do |profile| # Fill the hash with profile information and species information mini_hash = { :name => profile[0].strip, :comp => profile[1].strip, :coal => profile[2].strip, :unco => profile[3].strip, :copy => profile[4].strip, :f => @hash[:complexity], :w => @hash[:parallelism], :c => @species.all_structures.map { |s| simplify('4*('+s.dimensions.map { |d| sum(d) }.join('*')+')') }.join(' + '), :m => '1', :u => '0', :o => '8' } # Load the skeleton for the performance model and set the values according to the hash model_skeleton = File.read(File.join(model_dir,'model.c')) search_and_replace!(mini_hash,model_skeleton) result.push(C::Block.parse(model_skeleton)) end return result end |
#populate_hash ⇒ Object
This method creates the search-and-replace hash based on information provided by the algorithm. It is called from the ‘populate’ method of this class.
List of possible hash keys:
algorithm_id
_name
_basename
_filename
_code*
(in*|out*)_type
_name
_devicename
_devicepointer
_dimensions
_dimension*_to
_from
_sum
_to
_from
_parameters
_parameter*_to
_from
_sum
_ids
_localids
_flatindex
(in|out)_names
_devicenames
_devicedefinitions
_devicedefinitionsopencl
names devicenames devicedefinitions devicedefinitionsopencl
parallelism factors ids verifyids
argument_name argument_definition kernel_argument_list
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
# File 'lib/bones/algorithm.rb', line 242 def populate_hash @hash[:argument_name] = @lists[:argument_name] @hash[:argument_definition] = @lists[:argument_definition] # Obtain the necessary data for the hash per array parallelisms = [] DIRECTIONS.each do |direction| arrays = @arrays.select(direction) arrays.each_with_index do |array,num_array| hashid = "#{direction}#{num_array}".to_sym # Gather the name and type data minihash = {:type => array.type_name, :name => array.name, :devicepointer => array.device_pointer, :devicename => array.device_name, :flatindex => array.flatindex} # Gather the dimensions data dimensions = array.species.dimensions dimensions.each_with_index do |dimension,num_dimension| minihash["dimension#{num_dimension}".to_sym] = {:sum => simplify(sum(dimension)), :from => simplify(from(dimension)), :to => simplify(to(dimension))} end minihash[:dimensions] = simplify(dimensions.map { |d| sum(d) }.join('*')) minihash[:from] = dimensions.map { |d| from(d) }.zip(array.factors.drop(1).reverse).map { |e| simplify(e.join('')) }.join('+') minihash[:to ] = dimensions.map { |d| to(d) }.zip(array.factors.drop(1).reverse).map { |e| simplify(e.join('')) }.join('+') # Gather the parameter data if array.species.has_parameter? parameters = array.species.parameters parameters.each_with_index do |parameter,num_parameter| minihash["parameter#{num_parameter}".to_sym] = {:sum => simplify(sum(parameter)), :from => simplify(from(parameter)), :to => simplify(to(parameter))} end minihash[:parameters] = simplify(parameters.map { |p| sum(p) }.join('*')) end # Store the data into the hash @hash[hashid] = minihash # Gather information regarding the parallelism if array.species.chunk? dim_div = simplify(minihash[:dimensions]+'/'+minihash[:parameters]) parallelisms.push([dim_div,hashid,0]) elsif array.species.element? || array.species.neighbourhood? parallelisms.push([minihash[:dimensions],hashid,1]) end # Populate the global ID definitions hash, create the proper indices (and store as '{in/out}*_ids' in the hash) ids, localids, verifyids, factors = [], [], [], [''] dimensions = array.species.dimensions.clone dimensions.each_with_index do |dimension,num_dimension| index = (array.species.reverse?) ? num_dimension : array.species.dimensions.length-num_dimension-1 index_reverse = !(array.species.reverse?) ? num_dimension : array.species.dimensions.length-num_dimension-1 # Generate the index expressions divider = (array.species.chunk?) ? '/'+sum(array.species.parameters[index]) : '' dimensions_hash = (index == dimensions.length-1) ? '1' : dimensions.drop(index+1).map { |d| sum(d) }.join('*') dimensions_hash = simplify(dimensions_hash) dimensions_division = (dimensions_hash == '1') ? '' : '/('+dimensions_hash+')' minihash = {:dimensions1 => "#{GLOBAL_ID}#{dimensions_division}", :dimensions2 => "#{LOCAL_ID }#{dimensions_division}", :modulo => (index_reverse != dimensions.length-1) ? '%('+simplify(sum(dimension)+divider)+')' : '', :offset => simplify(from(dimension))} expr_global = search_and_replace(minihash,"((<dimensions1>)<modulo>)+<offset>") expr_local = search_and_replace(minihash,"((<dimensions2>)<modulo>)+<offset>") # Selectively push the ID definitions to the result array from = array.species.from_at(index) to = array.species.to_at(index) verifyids.push("const int #{GLOBAL_ID}_#{index_reverse} = "+expr_global+';') if from != to ids.push("const int #{GLOBAL_ID}_#{index_reverse} = "+expr_global+';') localids.push("const int #{LOCAL_ID }_#{index_reverse} = "+expr_local+';') factors.push(array.factors[index_reverse]) end end # Store the results in the hash @hash[hashid][:ids] = ids.join(NL+INDENT*2) @hash[hashid][:localids] = localids.join(NL+INDENT*2) @hash[hashid][:verifyids] = verifyids.join(NL+INDENT*2) @hash[hashid][:factors] = factors.last end # Create lists of array names and definitions @hash["#{direction}_devicedefinitions".to_sym] = arrays.map { |a| a.device_definition }.uniq.join(', ') @hash["#{direction}_devicedefinitionsopencl".to_sym] = arrays.map { |a| '__global '+a.device_definition }.uniq.join(', ') @hash["#{direction}_devicenames".to_sym] = arrays.map { |a| a.device_name }.uniq.join(', ') @hash["#{direction}_names".to_sym] = arrays.map { |a| a.name }.uniq.join(', ') end @hash[:devicedefinitions] = @arrays.map { |a| a.device_definition }.uniq.join(', ') @hash[:devicedefinitionsopencl] = @arrays.map { |a| '__global '+a.device_definition }.uniq.join(', ') @hash[:devicenames] = @arrays.map { |a| a.device_name }.uniq.join(', ') @hash[:names] = @arrays.map { |a| a.name }.uniq.join(', ') # Set the parallelism for the complete species, first sort them according to priorities and then find the maximum # TODO: Remove the 'reverse' statement and get the 'ids' part working correctly for chunks # TODO: How to find the maximum of symbolic expressions? parallelisms = parallelisms.reverse.sort_by { |p| p[2] } parallelism = parallelisms.reverse.max_by { |p| p[0].to_i } @hash[:parallelism] = parallelism[0] @hash[:ids] = @hash[parallelism[1]][:ids] @hash[:factors] = @hash[parallelism[1]][:factors] @arrays.set_representative(parallelism[1]) end |
#populate_lists ⇒ Object
Method to populate 5 lists with variable information. Below are listed the names of the four lists with an example value:
- host_name
-
Example: ‘array’
- host_definition
-
Example: ‘int array[10]’
- argument_name
-
Example: ‘threshold’
- argument_definition
-
Example: ‘float threshold’
- golden_name
-
Example: ‘golden_array’
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 |
# File 'lib/bones/algorithm.rb', line 475 def populate_lists @constants.each do |variable| @lists[:host_name] .push(variable.name) @lists[:host_definition] .push(variable.definition) @lists[:argument_name] .push(variable.name) @lists[:argument_definition].push(variable.definition) @lists[:golden_name] .push(variable.name) end @arrays.each do |variable| @lists[:host_name] .push(variable.name) @lists[:host_definition] .push(variable.definition) @lists[:golden_name] .push(variable.golden_name) end @lists.each { |name,list| @lists[name] = list.join(', ') } end |
#populate_variables(original_code, defines) ⇒ Object
Method to create a list of variables for the current algorithm. These variables should hold two conditions: 1) they are not local to the algorithm’s code, and 2), they are used in the algorithm’s code.
The method gets a lists of undefined variables in the algorithm’s code and subsequently searches the original code for the definition of this variable.
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 |
# File 'lib/bones/algorithm.rb', line 394 def populate_variables(original_code,defines) @code.undefined_variables.each do |name| type = @function_code.variable_type(name) raise_error('Variable '+name+' not declared in original code') if !type size = original_code.size(name) direction = @code.direction(name) size.map! { |s| simplify(replace_defines(s,defines)) } variable = Variable.new(name,type,size,direction,@id,@species.shared?) (variable.dimensions > 0) ? @arrays.push(variable) : @constants.push(variable) end raise_error('No input nor output arrays detected, make sure they are properly defined') if arrays.empty? DIRECTIONS.each do |direction| species = @species.structures(direction) arrays = @arrays.select(direction) if !arrays.empty? # Check if the amount of input/ouput arrays is equal to the amount of input/output species if species.length < arrays.length array_names = arrays.map { |a| a.name }.join('","') raise_error(direction.capitalize+'put array count mismatch (expected '+species.length.to_s+', found '+arrays.length.to_s+' ["'+array_names+'"])') end # Set the species for the arrays (distinguish between arrays with and without a name) species.each do |structure| # Loop over all found arrays and match it with a species array = nil arrays.each do |free_array| if !free_array.species if structure.has_arrayname? if structure.name == free_array.name array = free_array break end else array = free_array break end end end # Still haven't found anything, assign the species to an array of equal name if !array arrays.each do |free_array| array = free_array if structure.name == free_array.name end end # Process the assignment array.species = structure raise_error("Species of '#{array.species.name}' is mismatched with array '#{array.name}'") if array.species.name != array.name # Check if the array size was set, if not, it will be set to the species' size if array.size.empty? array.size = array.species.dimensions.map { |d| sum(d) } array.guess = true puts WARNING+'Could not determine size for array "'+array.name+'" automatically, assuming: '+array.size.inspect+'.' end # Set the multiplication factors (for later) array.set_factors end end end # Sort the arrays according to the alphabet if @arrays.length > 1 @arrays.sort_by(['chunk','neighbourhood','element','shared','full']) end end |
#set_function(full_code) ⇒ Object
This method sets the code and name for the function in which the algorithm is found. This is done based on the original code, which is given as input to this method. The method does not return any value, instead, it sets two class variables (@function_code and @function_name).
60 61 62 63 64 65 66 67 |
# File 'lib/bones/algorithm.rb', line 60 def set_function(full_code) full_code.get_functions.each do |function| if function.node_exists?(@code) @function_code = function @function_name = function.name end end end |
#update_hash(loop_variable) ⇒ Object
This method updates the hash after loops are removed from the code. It takes as an argument a loop variable, which it removes from both the ‘:argument_name’ and ‘:argument_ definition’ hash entries.
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/bones/algorithm.rb', line 367 def update_hash(loop_variable) names = @hash[:argument_name].split(', ') definitions = @hash[:argument_definition].split(', ') # TODO: The following two lines give problems with correlation-k4 names.delete(loop_variable.to_s) definitions.each { |definition| definitions.delete(definition) if definition =~ /\b#{loop_variable}\b/ } @hash[:argument_name] = names.join(', ') @hash[:argument_definition] = definitions.join(', ') # Now, generate the special code which is required for OpenCL function calls to be able to use kernel arguments. @hash[:kernel_argument_list] = opencl_arguments([@hash[:devicenames],@hash[:argument_name]].join(', ').remove_extras,0) @hash[:kernel_argument_list_in] = opencl_arguments(@hash[:in_devicenames],0) @hash[:kernel_argument_list_out] = opencl_arguments(@hash[:out_devicenames],0) @hash[:kernel_argument_list_constants] = opencl_arguments(@hash[:argument_name],0) # Add declarations for the loop variables for the original code in the hash @hash[:algorithm_code0] = INDENT+"int #{loop_variable};"+NL+@hash[:algorithm_code0] end |