BOAST 1.3.5 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/BOAST.gemspec +1 -1
  3. data/LICENSE +13 -1
  4. data/README.md +62 -13
  5. data/lib/BOAST.rb +3 -1
  6. data/lib/BOAST/Language/ARMCPUID_by_name.rb +3752 -0
  7. data/lib/BOAST/Language/Algorithm.rb +4 -24
  8. data/lib/BOAST/Language/Architectures.rb +5 -0
  9. data/lib/BOAST/Language/Arithmetic.rb +38 -5
  10. data/lib/BOAST/Language/BOAST_OpenCL.rb +7 -8
  11. data/lib/BOAST/Language/Case.rb +10 -3
  12. data/lib/BOAST/Language/Config.rb +36 -12
  13. data/lib/BOAST/Language/ControlStructure.rb +7 -3
  14. data/lib/BOAST/Language/DataTypes.rb +6 -0
  15. data/lib/BOAST/Language/Expression.rb +26 -2
  16. data/lib/BOAST/Language/For.rb +59 -30
  17. data/lib/BOAST/Language/FuncCall.rb +9 -5
  18. data/lib/BOAST/Language/Functors.rb +1 -1
  19. data/lib/BOAST/Language/HighLevelOperators.rb +172 -0
  20. data/lib/BOAST/Language/If.rb +25 -9
  21. data/lib/BOAST/Language/Index.rb +5 -5
  22. data/lib/BOAST/Language/Intrinsics.rb +40 -27
  23. data/lib/BOAST/Language/OpenMP.rb +1 -0
  24. data/lib/BOAST/Language/Operators.rb +221 -34
  25. data/lib/BOAST/Language/Parens.rb +3 -2
  26. data/lib/BOAST/Language/Procedure.rb +18 -5
  27. data/lib/BOAST/Language/Slice.rb +176 -44
  28. data/lib/BOAST/Language/Variable.rb +99 -56
  29. data/lib/BOAST/Language/While.rb +18 -3
  30. data/lib/BOAST/Language/{CPUID_by_name.rb → X86CPUID_by_name.rb} +0 -0
  31. data/lib/BOAST/Optimization/Optimization.rb +2 -0
  32. data/lib/BOAST/Runtime/AffinityProbe.rb +7 -3
  33. data/lib/BOAST/Runtime/CKernel.rb +3 -0
  34. data/lib/BOAST/Runtime/CRuntime.rb +4 -0
  35. data/lib/BOAST/Runtime/CompiledRuntime.rb +404 -77
  36. data/lib/BOAST/Runtime/Compilers.rb +44 -18
  37. data/lib/BOAST/Runtime/Config.rb +9 -0
  38. data/lib/BOAST/Runtime/EnergyProbe.rb +19 -3
  39. data/lib/BOAST/Runtime/FFIRuntime.rb +23 -0
  40. data/lib/BOAST/Runtime/FORTRANRuntime.rb +1 -1
  41. data/lib/BOAST/Runtime/MAQAO.rb +29 -0
  42. data/lib/BOAST/Runtime/NonRegression.rb +64 -3
  43. data/lib/BOAST/Runtime/OpenCLRuntime.rb +16 -6
  44. data/lib/BOAST/Runtime/Probe.rb +21 -1
  45. metadata +5 -3
@@ -7,7 +7,11 @@ module BOAST
7
7
 
8
8
  attr_reader :condition
9
9
 
10
+ # Creates a new instance of the While construct.
11
+ # @param [Expression] condition
12
+ # @param [Proc,nil] block if given, will be evaluated when {pr} is called
10
13
  def initialize(condition, &block)
14
+ super()
11
15
  @condition = condition
12
16
  @block = block
13
17
  end
@@ -30,10 +34,13 @@ module BOAST
30
34
  eval token_string_generator( * %w{while cond} )
31
35
  eval token_string_generator( * %w{end} )
32
36
 
37
+ # Returns a string representation of the While construct.
33
38
  def to_s
34
39
  return while_string(@condition)
35
40
  end
36
41
 
42
+ # Opens the While construct (keyword, condition, opening bracket in C like languages). The result is printed to the BOAST output.
43
+ # @return [self]
37
44
  def open
38
45
  s=""
39
46
  s += indent
@@ -43,16 +50,24 @@ module BOAST
43
50
  return self
44
51
  end
45
52
 
46
- def pr(*args)
53
+ # Prints the While construct to the BOAST output (see {open}).
54
+ # If a block is provided during initialization, it will be printed and the construct will be closed (see {close}).
55
+ # @param [Array<Object>] args any number of arguments to pass to the block
56
+ # @param [Proc] block an optional block to be evaluated. Supersede the one given at initialization
57
+ # @return [self]
58
+ def pr(*args, &block)
47
59
  args = @args if args.length == 0 and @args
60
+ block = @block unless block
48
61
  open
49
- if @block then
50
- @block.call(*args)
62
+ if block then
63
+ block.call(*args)
51
64
  close
52
65
  end
53
66
  return self
54
67
  end
55
68
 
69
+ # Closes the While construct (keyword, closing bracket in C like languages). The result is printed to the BOAST output.
70
+ # @return [self]
56
71
  def close
57
72
  decrement_indent_level
58
73
  s = ""
@@ -25,6 +25,8 @@ module BOAST
25
25
  HASH_NAME = "options"
26
26
 
27
27
  def initialize( *parameters )
28
+ @rules = nil
29
+ @checkers = nil
28
30
  if parameters.length == 1 and parameters[0].is_a?(Hash) then
29
31
  @parameters = []
30
32
  parameters[0].each { |key, value|
@@ -6,10 +6,11 @@ module BOAST
6
6
 
7
7
  module_function
8
8
 
9
+ def cflags
10
+ return "-D_GNU_SOURCE"
11
+ end
12
+
9
13
  def header
10
- get_output.puts "#ifndef _GNU_SOURCE"
11
- get_output.puts "#define _GNU_SOURCE"
12
- get_output.puts "#endif"
13
14
  get_output.puts "#include <sched.h>"
14
15
  end
15
16
 
@@ -60,6 +61,9 @@ EOF
60
61
  EOF
61
62
  end
62
63
 
64
+ def store
65
+ end
66
+
63
67
  end
64
68
 
65
69
  end
@@ -23,6 +23,7 @@ module BOAST
23
23
  attr_accessor :architecture
24
24
  attr_accessor :kernels
25
25
  attr_accessor :cost_function
26
+ attr_accessor :includes
26
27
 
27
28
  # Creates a new CKernel object. BOAST output is redirected to the CKernel. If the chain_code state is set the current BOAST output, as returned by {BOAST.get_output}, is used.
28
29
  # @param [Hash] options contains named options
@@ -55,6 +56,8 @@ module BOAST
55
56
  else
56
57
  @architecture = get_architecture
57
58
  end
59
+ @includes = []
60
+ @includes = [options[:includes]].flatten if options[:includes]
58
61
 
59
62
  case @lang
60
63
  when CL
@@ -9,6 +9,10 @@ module BOAST
9
9
  def fill_library_header
10
10
  get_output.puts "#include <stdlib.h>"
11
11
  get_output.puts "#include <inttypes.h>"
12
+ get_output.puts "#include <math.h>"
13
+ @includes.each { |inc|
14
+ get_output.puts "#include \"#{inc}\""
15
+ }
12
16
  get_output.puts "#define __assume_aligned(lvalueptr, align) lvalueptr = __builtin_assume_aligned (lvalueptr, align)" if @compiler_options[:CC].match("gcc")
13
17
  end
14
18
 
@@ -8,7 +8,12 @@ require 'os'
8
8
 
9
9
  class Dir
10
10
  module Tmpname
11
- module_function
11
+ class << self
12
+ undef_method :make_tmpname
13
+ end
14
+
15
+ undef_method :make_tmpname
16
+
12
17
  def make_tmpname(prefix_suffix, n)
13
18
  case prefix_suffix
14
19
  when String
@@ -25,6 +30,9 @@ class Dir
25
30
  path << "_#{n}" if n
26
31
  path << suffix
27
32
  end
33
+
34
+ module_function :make_tmpname
35
+
28
36
  end
29
37
  end
30
38
 
@@ -86,6 +94,10 @@ module BOAST
86
94
  return "#{base_path}.#{RbConfig::CONFIG["OBJEXT"]}"
87
95
  end
88
96
 
97
+ def library_nofpic_object
98
+ return "#{base_path}.nofpic#{RbConfig::CONFIG["OBJEXT"]}"
99
+ end
100
+
89
101
  def library_path
90
102
  return "#{base_path}.#{RbConfig::CONFIG["DLEXT"]}"
91
103
  end
@@ -94,10 +106,26 @@ module BOAST
94
106
  return module_file_path
95
107
  end
96
108
 
109
+ def executable_source
110
+ return "#{base_path}_executable.c"
111
+ end
112
+
113
+ def executable_object
114
+ return "#{base_path}_executable.nofpic#{RbConfig::CONFIG["OBJEXT"]}"
115
+ end
116
+
117
+ def target_executable
118
+ return "#{base_path}_executable"
119
+ end
120
+
97
121
  def target_depends
98
122
  return [ module_file_object, library_object ]
99
123
  end
100
124
 
125
+ def target_executable_depends
126
+ return [ library_nofpic_object, executable_object ]
127
+ end
128
+
101
129
  def save_binary
102
130
  f = File::open(library_object,"rb")
103
131
  @binary = StringIO::new
@@ -112,14 +140,35 @@ module BOAST
112
140
  f.close
113
141
  end
114
142
 
115
- def create_targets( linker, ldshared, ldflags, kernel_files)
143
+ def save_module
144
+ f = File::open(module_file_path, "rb")
145
+ @module_binary = StringIO::new
146
+ @module_binary.write( f.read )
147
+ f.close
148
+ end
149
+
150
+ def save_executable
151
+ f = File::open(target_executable, "rb")
152
+ @executable = StringIO::new
153
+ @executable.write( f.read )
154
+ f.close
155
+ end
156
+
157
+ def create_targets( linker, ldshared, ldshared_flags, ldflags, kernel_files)
116
158
  file target => target_depends do
117
- #puts "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldflags}"
118
- sh "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldflags}"
159
+ #puts "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldshared_flags} #{ldflags}"
160
+ sh "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldshared_flags} #{ldflags}"
119
161
  end
120
162
  Rake::Task[target].invoke
121
163
  end
122
164
 
165
+ def create_executable_target( linker, ldflags, kernel_files)
166
+ file target_executable => target_executable_depends do
167
+ sh "#{linker} -o #{target_executable} #{target_executable_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldflags}"
168
+ end
169
+ Rake::Task[target_executable].invoke
170
+ end
171
+
123
172
  def method_name
124
173
  return @procedure.name
125
174
  end
@@ -138,19 +187,14 @@ module BOAST
138
187
 
139
188
  def create_library_source
140
189
  f = File::open(library_source,"w+")
141
- previous_lang = get_lang
142
- previous_output = get_output
143
- set_output(f)
144
- set_lang(@lang)
145
-
146
- fill_library_source
190
+ push_env( :output => f, :lang => @lang ) {
191
+ fill_library_source
147
192
 
148
- if debug_source? then
149
- f.rewind
150
- puts f.read
151
- end
152
- set_output(previous_output)
153
- set_lang(previous_lang)
193
+ if debug_source? or debug_kernel_source? then
194
+ f.rewind
195
+ puts f.read
196
+ end
197
+ }
154
198
  f.close
155
199
  end
156
200
 
@@ -162,6 +206,9 @@ module BOAST
162
206
  #include "narray.h"
163
207
  #endif
164
208
  EOF
209
+ @includes.each { |inc|
210
+ get_output.puts "#include \"#{inc}\""
211
+ }
165
212
  end
166
213
 
167
214
  def fill_module_preamble
@@ -215,26 +262,26 @@ EOF
215
262
  end
216
263
 
217
264
  def fill_decl_module_params
218
- push_env(:decl_module => true)
219
- @procedure.parameters.each { |param|
220
- param_copy = param.copy
221
- param_copy.constant = nil
222
- param_copy.direction = nil
223
- param_copy.reference = nil
224
- param_copy.decl
265
+ push_env(:decl_module => true) {
266
+ @procedure.parameters.each { |param|
267
+ param_copy = param.copy
268
+ param_copy.constant = nil
269
+ param_copy.direction = nil
270
+ param_copy.reference = nil
271
+ param_copy.decl
272
+ }
273
+ get_output.puts " #{@procedure.properties[:return].type.decl} _boast_ret;" if @procedure.properties[:return]
274
+ get_output.puts " VALUE _boast_stats = rb_hash_new();"
275
+ get_output.puts " VALUE _boast_rb_ptr = Qnil;"
276
+ refs = false
277
+ @procedure.parameters.each_with_index do |param,i|
278
+ refs = true if param.scalar_output?
279
+ end
280
+ if refs then
281
+ get_output.puts " VALUE _boast_refs = rb_hash_new();"
282
+ get_output.puts " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"reference_return\")),_boast_refs);"
283
+ end
225
284
  }
226
- get_output.puts " #{@procedure.properties[:return].type.decl} _boast_ret;" if @procedure.properties[:return]
227
- get_output.puts " VALUE _boast_stats = rb_hash_new();"
228
- get_output.puts " VALUE _boast_rb_ptr = Qnil;"
229
- refs = false
230
- @procedure.parameters.each_with_index do |param,i|
231
- refs = true if param.scalar_output?
232
- end
233
- if refs then
234
- get_output.puts " VALUE _boast_refs = rb_hash_new();"
235
- get_output.puts " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"reference_return\")),_boast_refs);"
236
- end
237
- pop_env(:decl_module)
238
285
  end
239
286
 
240
287
  def copy_scalar_param_from_ruby( param, ruby_param )
@@ -252,11 +299,23 @@ EOF
252
299
  (rb_ptr === ruby_param).pr
253
300
  get_output.print <<EOF
254
301
  if (TYPE(_boast_rb_ptr) == T_STRING) {
255
- #{param} = (void *) RSTRING_PTR(_boast_rb_ptr);
302
+ #{
303
+ if param.dimension then
304
+ "#{param} = (void *)RSTRING_PTR(_boast_rb_ptr)"
305
+ else
306
+ (param === param.copy("*(void *)RSTRING_PTR(_boast_rb_ptr)", :dimension => Dim(), :vector_length => 1)).to_s
307
+ end
308
+ };
256
309
  } else if ( IsNArray(_boast_rb_ptr) ) {
257
310
  struct NARRAY *_boast_n_ary;
258
311
  Data_Get_Struct(_boast_rb_ptr, struct NARRAY, _boast_n_ary);
259
- #{param} = (void *) _boast_n_ary->ptr;
312
+ #{
313
+ if param.dimension then
314
+ "#{param} = (void *) _boast_n_ary->ptr"
315
+ else
316
+ (param === param.copy("*(void *) _boast_n_ary->ptr", :dimension => Dim(), :vector_length => 1)).to_s
317
+ end
318
+ };
260
319
  } else {
261
320
  rb_raise(rb_eArgError, "Wrong type of argument for %s, expecting array!", "#{param}");
262
321
  }
@@ -266,17 +325,16 @@ EOF
266
325
  def get_params_value
267
326
  argc = @procedure.parameters.length
268
327
  argv = Variable::new("_boast_argv", CustomType, :type_name => "VALUE", :dimension => [ Dimension::new(0,argc-1) ] )
269
- rb_ptr = Variable::new("_boast_rb_ptr", CustomType, :type_name => "VALUE")
270
- push_env(:decl_module => true)
271
- @procedure.parameters.each_index do |i|
272
- param = @procedure.parameters[i]
273
- if not param.dimension then
274
- copy_scalar_param_from_ruby(param, argv[i])
275
- else
276
- copy_array_param_from_ruby(param, argv[i])
328
+ push_env(:decl_module => true) {
329
+ @procedure.parameters.each_index do |i|
330
+ param = @procedure.parameters[i]
331
+ if not param.dimension? and not param.vector? then
332
+ copy_scalar_param_from_ruby(param, argv[i])
333
+ else
334
+ copy_array_param_from_ruby(param, argv[i])
335
+ end
277
336
  end
278
- end
279
- pop_env(:decl_module)
337
+ }
280
338
  end
281
339
 
282
340
  def create_procedure_call
@@ -301,23 +359,67 @@ EOF
301
359
  end
302
360
  end
303
361
 
362
+ def copy_scalar_param_to_file(param, base_path)
363
+ if param.scalar_output? then
364
+ get_output.puts <<EOF
365
+ __boast_f = fopen("#{base_path}/#{param}.out", "wb");
366
+ fwrite(&#{param}, sizeof(#{param}), 1, __boast_f);
367
+ fclose(__boast_f);
368
+ EOF
369
+ end
370
+ end
371
+
372
+ def copy_scalar_param_from_file(param, base_path)
373
+ get_output.puts <<EOF
374
+ __boast_f = fopen("#{base_path}/#{param}.in", "rb");
375
+ fread(&#{param}, sizeof(#{param}), 1, __boast_f);
376
+ fclose(__boast_f);
377
+ EOF
378
+ end
379
+
304
380
  def copy_array_param_to_ruby(param, ruby_param)
305
381
  end
306
382
 
383
+ def copy_array_param_to_file(param, base_path)
384
+ if param.direction == :out or param.direction == :inout then
385
+ get_output.puts <<EOF
386
+ __boast_f = fopen("#{base_path}/#{param}.out", "wb");
387
+ fwrite(#{param}, 1, __boast_sizeof_#{param}, __boast_f);
388
+ fclose(__boast_f);
389
+ free(#{param});
390
+ EOF
391
+ else
392
+ get_output.puts <<EOF
393
+ free(#{param});
394
+ EOF
395
+ end
396
+ end
397
+
398
+ def copy_array_param_from_file(param, base_path)
399
+ get_output.puts <<EOF
400
+ __boast_f = fopen("#{base_path}/#{param}.in", "rb");
401
+ fseek(__boast_f, 0L, SEEK_END);
402
+ __boast_sizeof_#{param} = ftell(__boast_f);
403
+ rewind(__boast_f);
404
+ #{param} = malloc(__boast_sizeof_#{param});
405
+ fread(#{param}, 1, __boast_sizeof_#{param}, __boast_f);
406
+ fclose(__boast_f);
407
+ EOF
408
+ end
409
+
307
410
  def get_results
308
411
  argc = @procedure.parameters.length
309
412
  argv = Variable::new("_boast_argv", CustomType, :type_name => "VALUE", :dimension => [ Dimension::new(0,argc-1) ] )
310
- rb_ptr = Variable::new("_boast_rb_ptr", CustomType, :type_name => "VALUE")
311
- push_env(:decl_module => true)
312
- @procedure.parameters.each_index do |i|
313
- param = @procedure.parameters[i]
314
- if not param.dimension then
315
- copy_scalar_param_to_ruby(param, argv[i])
316
- else
317
- copy_array_param_to_ruby(param, argv[i])
413
+ push_env(:decl_module => true) {
414
+ @procedure.parameters.each_index do |i|
415
+ param = @procedure.parameters[i]
416
+ if not param.dimension then
417
+ copy_scalar_param_to_ruby(param, argv[i])
418
+ else
419
+ copy_array_param_to_ruby(param, argv[i])
420
+ end
318
421
  end
319
- end
320
- pop_env(:decl_module)
422
+ }
321
423
  end
322
424
 
323
425
  def store_results
@@ -329,6 +431,118 @@ EOF
329
431
  end
330
432
  end
331
433
 
434
+ def get_executable_params_value( base_path )
435
+ push_env(:decl_module => true) {
436
+ @procedure.parameters.each do |param|
437
+ if not param.dimension? then
438
+ copy_scalar_param_from_file(param, base_path)
439
+ else
440
+ copy_array_param_from_file(param, base_path)
441
+ end
442
+ end
443
+ }
444
+ end
445
+
446
+ def get_executable_params_return_value( base_path )
447
+ push_env(:decl_module => true) {
448
+ @procedure.parameters.each do |param|
449
+ if not param.dimension then
450
+ copy_scalar_param_to_file(param, base_path)
451
+ else
452
+ copy_array_param_to_file(param, base_path)
453
+ end
454
+ end
455
+ }
456
+ end
457
+
458
+ def fill_executable_source
459
+ get_output.puts "#include <inttypes.h>"
460
+ get_output.puts "#include <stdlib.h>"
461
+ get_output.puts "#include <stdio.h>"
462
+ @includes.each { |inc|
463
+ get_output.puts "#include \"#{inc}\""
464
+ }
465
+ @probes.map(&:header)
466
+ @procedure.boast_header(@lang)
467
+
468
+ get_output.print <<EOF
469
+ void Init_#{base_name}( void );
470
+ int _boast_repeat;
471
+ void Init_#{base_name}( void ) {
472
+ EOF
473
+ increment_indent_level
474
+ output.puts " FILE * __boast_f;"
475
+ push_env(:decl_module => true) {
476
+ @procedure.parameters.each { |param|
477
+ if param.dimension? then
478
+ output.puts " size_t __boast_sizeof_#{param};"
479
+ end
480
+ param_copy = param.copy
481
+ param_copy.constant = nil
482
+ param_copy.direction = nil
483
+ param_copy.reference = nil
484
+ param_copy.decl
485
+ }
486
+ get_output.puts " #{@procedure.properties[:return].type.decl} _boast_ret;" if @procedure.properties[:return]
487
+ }
488
+ @probes.reverse.map(&:decl)
489
+ @probes.map(&:configure)
490
+
491
+ get_executable_params_value( "#{@tmp_dir}/#{@procedure.name}/#{base_name}" )
492
+
493
+ @probes.reverse.map(&:start)
494
+
495
+ get_output.puts " int _boast_i;"
496
+ get_output.puts " for(_boast_i = 0; _boast_i < _boast_repeat; ++_boast_i){"
497
+ get_output.print " "
498
+ get_output.print "_boast_ret = " if @procedure.properties[:return]
499
+ get_output.print "#{method_name}( "
500
+ get_output.print create_procedure_call_parameters.join(", ")
501
+ get_output.puts " );"
502
+ get_output.puts " }"
503
+
504
+ @probes.map(&:stop)
505
+
506
+ get_output.puts ' printf("---\n");'
507
+ if @procedure.properties[:return] then
508
+ type_ret = @procedure.properties[:return].type
509
+ get_output.puts ' printf(":return: %lld\n", (long long)_boast_ret);' if type_ret.kind_of?(Int) and type_ret.signed
510
+ get_output.puts ' printf(":return: %ulld\n", (unsigned long long)_boast_ret);' if type_ret.kind_of?(Int) and not type_ret.signed
511
+ get_output.puts ' printf(":return: %lf\n", (double)_boast_ret);' if type_ret.kind_of?(Real)
512
+
513
+ end
514
+
515
+ get_executable_params_return_value( "#{@tmp_dir}/#{@procedure.name}/#{base_name}" )
516
+
517
+ @probes.map(&:compute)
518
+
519
+ @probes.map(&:to_yaml)
520
+
521
+ decrement_indent_level
522
+ get_output.print <<EOF
523
+ }
524
+ int main(int argc, char * argv[]) {
525
+ _boast_repeat=atoi(argv[1]);
526
+ Init_#{base_name}();
527
+ return 0;
528
+ }
529
+ EOF
530
+
531
+ end
532
+
533
+ def create_executable_source
534
+ f = File::open(executable_source, "w+")
535
+ push_env(:output => f, :lang => C) {
536
+ fill_executable_source
537
+
538
+ if debug_source? then
539
+ f.rewind
540
+ puts f.read
541
+ end
542
+ }
543
+ f.close
544
+ end
545
+
332
546
  def fill_module_file_source
333
547
  fill_module_header
334
548
  @probes.map(&:header)
@@ -360,7 +574,10 @@ EOF
360
574
 
361
575
  get_results
362
576
 
363
- @probes.map(&:compute)
577
+ @probes.each { |p|
578
+ p.compute
579
+ p.store
580
+ }
364
581
 
365
582
  store_results
366
583
 
@@ -371,16 +588,14 @@ EOF
371
588
 
372
589
  def create_module_file_source
373
590
  f = File::open(module_file_source, "w+")
374
- push_env(:lang => C)
375
- push_env(:output => f)
376
-
377
- fill_module_file_source
591
+ push_env(:output => f, :lang => C) {
592
+ fill_module_file_source
378
593
 
379
- if debug_source? then
380
- f.rewind
381
- puts f.read
382
- end
383
- pop_env(:lang, :output)
594
+ if debug_source? then
595
+ f.rewind
596
+ puts f.read
597
+ end
598
+ }
384
599
  f.close
385
600
  end
386
601
 
@@ -397,6 +612,10 @@ EOF
397
612
  return [ module_file_source, library_source ]
398
613
  end
399
614
 
615
+ def target_executable_sources
616
+ return [ executable_source, library_source ]
617
+ end
618
+
400
619
  def cleanup(kernel_files)
401
620
  ([target] + target_depends + target_sources).each { |fn|
402
621
  File::unlink(fn)
@@ -406,35 +625,123 @@ EOF
406
625
  }
407
626
  end
408
627
 
628
+ def cleanup_executable(kernel_files)
629
+ ( [target_executable] + target_executable_depends + target_executable_sources ).each { |fn|
630
+ File::unlink(fn)
631
+ }
632
+ kernel_files.each { |f|
633
+ f.unlink
634
+ }
635
+ end
636
+
637
+ def run_executable(*params)
638
+ options = {:repeat => 1}
639
+ if params.last.kind_of?(Hash) then
640
+ options.update(params.last)
641
+ ps = params[0..-2]
642
+ else
643
+ ps = params[0..-1]
644
+ end
645
+
646
+ Dir::mkdir(@tmp_dir, 0700) unless Dir::exist?(@tmp_dir)
647
+
648
+ dump_executable
649
+ dump_ref_inputs( { base_name => ps }, @tmp_dir )
650
+ boast_ret = YAML::load `#{target_executable} #{options[:repeat]}`
651
+ File::unlink(target_executable) unless keep_temp
652
+
653
+ res = load_ref_outputs(@tmp_dir)["#{@tmp_dir}/#{@procedure.name}/#{base_name}"]
654
+ @procedure.parameters.each_with_index { |param, indx|
655
+ if param.direction == :in or param.constant then
656
+ next
657
+ end
658
+ if param.dimension then
659
+ ps[indx][0..-1] = res[indx][0..-1]
660
+ else
661
+ boast_ret[:reference_return] = {} unless boast_ret[:reference_return]
662
+ boast_ret[:reference_return][param.name.to_sym] = res[indx]
663
+ end
664
+ }
665
+ p = Pathname::new("#{@tmp_dir}/#{@procedure.name}/#{base_name}")
666
+ p.children.each { |f| File::unlink f }
667
+ unless keep_temp then
668
+ Dir::rmdir("#{@tmp_dir}/#{@procedure.name}/#{base_name}")
669
+ Dir::rmdir("#{@tmp_dir}/#{@procedure.name}")
670
+ Dir::rmdir("#{@tmp_dir}")
671
+ end
672
+ return boast_ret
673
+ end
674
+
675
+ def build_executable(options={})
676
+ compiler_options = BOAST::get_compiler_options
677
+ compiler_options.update(options)
678
+ @probes = [TimerProbe]
679
+ linker, _, _, ldflags = setup_compilers(@probes, compiler_options)
680
+ @compiler_options = compiler_options
681
+
682
+ @marker = Tempfile::new([@procedure.name,""])
683
+ Dir::mktmpdir { |dir|
684
+ @tmp_dir = "#{dir}"
685
+ }
686
+
687
+ kernel_files = get_sub_kernels
688
+
689
+ create_library_source
690
+
691
+ create_executable_source
692
+
693
+ save_source
694
+
695
+ create_executable_target(linker, ldflags, kernel_files)
696
+
697
+ save_executable
698
+
699
+ instance_eval <<EOF
700
+ def run(*args, &block)
701
+ run_executable(*args, &block)
702
+ end
703
+ EOF
704
+
705
+ cleanup_executable(kernel_files) unless keep_temp
706
+
707
+ return self
708
+
709
+ end
710
+
409
711
  public
410
712
 
411
713
  def build(options={})
714
+ return build_executable(options) if executable? and (@lang == C or @lang == FORTRAN)
412
715
  compiler_options = BOAST::get_compiler_options
413
716
  compiler_options.update(options)
414
- linker, ldshared, ldflags = setup_compilers(compiler_options)
415
- @compiler_options = compiler_options
416
717
  @probes = []
417
- if @compiler_options[:probes] then
418
- @probes = @compiler_options[:probes]
419
- elsif get_lang != CUDA
718
+ if compiler_options[:probes] then
719
+ @probes = compiler_options[:probes]
720
+ elsif get_lang != CUDA then
420
721
  @probes = [TimerProbe, PAPIProbe]
421
722
  @probes.push EnergyProbe if EnergyProbe
422
723
  @probes.push AffinityProbe unless OS.mac?
423
724
  end
424
725
  @probes = [MPPAProbe] if @architecture == MPPA
726
+ linker, ldshared, ldshared_flags, ldflags = setup_compilers(@probes, compiler_options)
727
+ @compiler_options = compiler_options
425
728
 
426
729
  @marker = Tempfile::new([@procedure.name,""])
427
730
 
731
+ extend MAQAO if @compiler_options[:MAQAO_PASS]
732
+
428
733
  kernel_files = get_sub_kernels
429
734
 
430
735
  create_sources
431
736
 
432
737
  save_source
433
738
 
434
- create_targets(linker, ldshared, ldflags, kernel_files)
739
+ create_targets(linker, ldshared, ldshared_flags, ldflags, kernel_files)
435
740
 
436
741
  save_binary
437
742
 
743
+ save_module
744
+
438
745
  load_module
439
746
 
440
747
  cleanup(kernel_files) unless keep_temp
@@ -444,20 +751,40 @@ EOF
444
751
  return self
445
752
  end
446
753
 
447
- def dump_binary
448
- f = File::open(library_object,"wb")
754
+ def dump_binary(path = nil)
755
+ f = path ? File::open(path,"wb") : File::open(library_object,"wb")
449
756
  @binary.rewind
450
757
  f.write( @binary.read )
451
758
  f.close
452
759
  end
453
760
 
454
- def dump_source
455
- f = File::open(library_source,"wb")
761
+ def dump_source(path = nil)
762
+ f = path ? File::open(path,"wb") : File::open(library_source,"wb")
456
763
  @source.rewind
457
764
  f.write( @source.read )
458
765
  f.close
459
766
  end
460
767
 
768
+ def dump_module(path = nil)
769
+ f = path ? File::open(path,"wb") : File::open(module_file_path,"wb")
770
+ @module_binary.rewind
771
+ f.write( @module_binary.read )
772
+ f.close
773
+ end
774
+
775
+ def dump_executable(path = nil)
776
+ f = path ? File::open(path,"wb",0700) : File::open(target_executable,"wb",0700)
777
+ @executable.rewind
778
+ f.write( @executable.read )
779
+ f.close
780
+ end
781
+
782
+ def reload_module
783
+ raise "Missing binary library data!" unless @module_binary
784
+ $LOADED_FEATURES.delete(module_file_path)
785
+ require module_file_path
786
+ end
787
+
461
788
  end
462
789
 
463
790
  end