Module: BOAST::CompiledRuntime

Included in:
CRuntime, FORTRANRuntime
Defined in:
lib/BOAST/Runtime/MAQAO.rb,
lib/BOAST/Runtime/CompiledRuntime.rb

Constant Summary collapse

@@extensions =
{
  C => ".c",
  CUDA => ".cu",
  FORTRAN => ".f90"
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#binaryObject

Returns the value of attribute binary.



34
35
36
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 34

def binary
  @binary
end

#sourceObject

Returns the value of attribute source.



35
36
37
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 35

def source
  @source
end

Instance Method Details

#base_nameObject



43
44
45
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 43

def base_name
  return File::split(@marker.path)[1]
end

#base_pathObject



75
76
77
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 75

def base_path
  return "#{directory}/#{base_name}"
end

#build(options = {}) ⇒ Object



379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 379

def build(options={})
  compiler_options = BOAST::get_compiler_options
  compiler_options.update(options)
  linker, ldshared, ldflags = setup_compilers(compiler_options)
  @compiler_options = compiler_options

  @marker = Tempfile::new([@procedure.name,""])

  kernel_files = get_sub_kernels

  create_sources

  save_source

  create_targets(linker, ldshared, ldflags, kernel_files)

  save_binary

  load_module

  cleanup(kernel_files)

  eval "self.extend(#{module_name})"

  return self
end

#cleanup(kernel_files) ⇒ Object



370
371
372
373
374
375
376
377
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 370

def cleanup(kernel_files)
  ([target] + target_depends + target_sources).each { |fn|
    File::unlink(fn)
  }
  kernel_files.each { |f|
    f.unlink
  }
end

#copy_array_param_from_ruby(param, ruby_param) ⇒ Object



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 225

def copy_array_param_from_ruby( param, ruby_param )
  rb_ptr = Variable::new("_boast_rb_ptr", CustomType, :type_name => "VALUE")
  (rb_ptr === ruby_param).pr
  get_output.print <<EOF
  if (TYPE(_boast_rb_ptr) == T_STRING) {
#{param} = (void *) RSTRING_PTR(_boast_rb_ptr);
  } else if ( IsNArray(_boast_rb_ptr) ) {
struct NARRAY *_boast_n_ary;
Data_Get_Struct(_boast_rb_ptr, struct NARRAY, _boast_n_ary);
#{param} = (void *) _boast_n_ary->ptr;
  } else {
rb_raise(rb_eArgError, "Wrong type of argument for %s, expecting array!", "#{param}");
  }
EOF
end

#copy_array_param_to_ruby(param, ruby_param) ⇒ Object



276
277
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 276

def copy_array_param_to_ruby(param, ruby_param)
end

#copy_scalar_param_from_ruby(param, ruby_param) ⇒ Object



215
216
217
218
219
220
221
222
223
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 215

def copy_scalar_param_from_ruby( param, ruby_param )
  case param.type
  when Int
    (param === FuncCall::new("NUM2INT", ruby_param)).pr if param.type.size == 4
    (param === FuncCall::new("NUM2LONG", ruby_param)).pr if param.type.size == 8
  when Real
    (param === FuncCall::new("NUM2DBL", ruby_param)).pr
  end
end

#copy_scalar_param_to_ruby(param, ruby_param) ⇒ Object



264
265
266
267
268
269
270
271
272
273
274
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 264

def copy_scalar_param_to_ruby(param, ruby_param)
  if param.scalar_output? then
    case param.type
    when Int
      get_output.puts "  rb_hash_aset(_boast_refs, ID2SYM(rb_intern(\"#{param}\")),rb_int_new((long long)#{param}));" if param.type.signed?
      get_output.puts "  rb_hash_aset(_boast_refs, ID2SYM(rb_intern(\"#{param}\")),rb_int_new((unsigned long long)#{param}));" if not param.type.signed?
    when Real
      get_output.puts "  rb_hash_aset(_boast_refs, ID2SYM(rb_intern(\"#{param}\")),rb_float_new((double)#{param}));"
    end
  end
end

#create_library_sourceObject



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 137

def create_library_source
  f = File::open(library_source,"w+")
  previous_lang = get_lang
  previous_output = get_output
  set_output(f)
  set_lang(@lang)

  fill_library_source

  if debug_source? then
    f.rewind
    puts f.read
  end
  set_output(previous_output)
  set_lang(previous_lang)
  f.close
end

#create_module_file_sourceObject



342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 342

def create_module_file_source
  f = File::open(module_file_source, "w+")
  push_env(:lang => C)
  push_env(:output => f)

  fill_module_file_source

  if debug_source? then
    f.rewind
    puts f.read
  end
  pop_env(:lang, :output)
  f.close
end

#create_procedure_callObject



257
258
259
260
261
262
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 257

def create_procedure_call
  get_output.print "  _boast_ret = " if @procedure.properties[:return]
  get_output.print " #{method_name}( "
  get_output.print create_procedure_call_parameters.join(", ")
  get_output.puts " );"
end

#create_sourcesObject



357
358
359
360
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 357

def create_sources
  create_library_source
  create_module_file_source
end

#create_targets(linker, ldshared, ldflags, kernel_files) ⇒ Object



113
114
115
116
117
118
119
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 113

def create_targets( linker, ldshared, ldflags, kernel_files)
  file target => target_depends do
    #puts "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldflags}"
    sh "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldflags}"
  end
  Rake::Task[target].invoke
end

#directoryObject



51
52
53
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 51

def directory
  return File::split(@marker.path)[0]
end

#dump_binaryObject



406
407
408
409
410
411
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 406

def dump_binary
  f = File::open(library_object,"wb")
  @binary.rewind
  f.write( @binary.read )
  f.close
end

#dump_sourceObject



413
414
415
416
417
418
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 413

def dump_source
  f = File::open(library_source,"wb")
  @source.rewind
  f.write( @source.read )
  f.close
end

#fill_check_argsObject



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 177

def fill_check_args
  get_output.print <<EOF
  VALUE _boast_rb_opts;
  if( _boast_argc < #{@procedure.parameters.length} || _boast_argc > #{@procedure.parameters.length + 1} )
rb_raise(rb_eArgError, "Wrong number of arguments for #{@procedure.name} (%d for #{@procedure.parameters.length})!", _boast_argc);
  _boast_rb_opts = Qnil;
  if( _boast_argc == #{@procedure.parameters.length + 1} ) {
_boast_rb_opts = _boast_argv[_boast_argc -1];
if ( _boast_rb_opts != Qnil ) {
  if (TYPE(_boast_rb_opts) != T_HASH)
    rb_raise(rb_eArgError, "Options should be passed as a hash");
}
  }
EOF
end

#fill_decl_module_paramsObject



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 193

def fill_decl_module_params
  push_env(:decl_module => true)
  @procedure.parameters.each { |param|
    param_copy = param.copy
    param_copy.constant = nil
    param_copy.direction = nil
    param_copy.decl
  }
  get_output.puts "  #{@procedure.properties[:return].type.decl} _boast_ret;" if @procedure.properties[:return]
  get_output.puts "  VALUE _boast_stats = rb_hash_new();"
  get_output.puts "  VALUE _boast_rb_ptr = Qnil;"
  refs = false
  @procedure.parameters.each_with_index do |param,i|
    refs = true if param.scalar_output?
  end
  if refs then
    get_output.puts "  VALUE _boast_refs = rb_hash_new();"
    get_output.puts "  rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"reference_return\")),_boast_refs);"
  end
  pop_env(:decl_module)
end

#fill_module_file_sourceObject



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
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 304

def fill_module_file_source
  fill_module_header
  @probes.map(&:header)
  @procedure.boast_header(@lang)

  fill_module_preamble

  set_transition("VALUE", "VALUE", :default,  CustomType::new(:type_name => "VALUE"))
  get_output.puts "VALUE method_run(int _boast_argc, VALUE *_boast_argv, VALUE _boast_self) {"
  increment_indent_level

  fill_check_args

  fill_decl_module_params

  @probes.reverse.map(&:decl)

  get_params_value

  @probes.map(&:configure)

  @probes.reverse.map(&:start)

  create_procedure_call

  @probes.map(&:stop)

  get_results

  @probes.map(&:compute)

  store_results

  get_output.puts "  return _boast_stats;"
  decrement_indent_level
  get_output.puts "}"
end

#fill_module_headerObject



155
156
157
158
159
160
161
162
163
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 155

def fill_module_header
  get_output.print <<EOF
#include "ruby.h"
#include <inttypes.h>
#ifdef HAVE_NARRAY_H
#include "narray.h"
#endif
EOF
end

#fill_module_preambleObject



165
166
167
168
169
170
171
172
173
174
175
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 165

def fill_module_preamble
  get_output.print <<EOF
VALUE #{module_name} = Qnil;
void Init_#{module_name}();
VALUE method_run(int _boast_argc, VALUE *_boast_argv, VALUE _boast_self);
void Init_#{module_name}() {
  #{module_name} = rb_define_module("#{module_name}");
  rb_define_method(#{module_name}, "run", method_run, -1);
}
EOF
end

#get_params_valueObject



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 241

def get_params_value
  argc = @procedure.parameters.length
  argv = Variable::new("_boast_argv", CustomType, :type_name => "VALUE", :dimension => [ Dimension::new(0,argc-1) ] )
  rb_ptr = Variable::new("_boast_rb_ptr", CustomType, :type_name => "VALUE")
  push_env(:decl_module => true)
  @procedure.parameters.each_index do |i|
    param = @procedure.parameters[i]
    if not param.dimension then
      copy_scalar_param_from_ruby(param, argv[i])
    else
      copy_array_param_from_ruby(param, argv[i])
    end
  end
  pop_env(:decl_module)
end

#get_resultsObject



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 279

def get_results
  argc = @procedure.parameters.length
  argv = Variable::new("_boast_argv", CustomType, :type_name => "VALUE", :dimension => [ Dimension::new(0,argc-1) ] )
  rb_ptr = Variable::new("_boast_rb_ptr", CustomType, :type_name => "VALUE")
  push_env(:decl_module => true)
  @procedure.parameters.each_index do |i|
    param = @procedure.parameters[i]
    if not param.dimension then
      copy_scalar_param_to_ruby(param, argv[i])
    else
      copy_array_param_to_ruby(param, argv[i])
    end
  end
  pop_env(:decl_module)
end

#get_sub_kernelsObject



125
126
127
128
129
130
131
132
133
134
135
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 125

def get_sub_kernels
  kernel_files = []
  @kernels.each { |kernel|
    kernel_file = Tempfile::new([kernel.procedure.name,".#{RbConfig::CONFIG["OBJEXT"]}"])
    kernel.binary.rewind
    kernel_file.write( kernel.binary.read )
    kernel_file.close
    kernel_files.push(kernel_file)
  }
  return kernel_files
end

#library_objectObject



83
84
85
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 83

def library_object
  return "#{base_path}.#{RbConfig::CONFIG["OBJEXT"]}"
end

#library_pathObject



87
88
89
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 87

def library_path
  return "#{base_path}.#{RbConfig::CONFIG["DLEXT"]}"
end

#library_sourceObject



79
80
81
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 79

def library_source
  return base_path + @@extensions[@lang]
end

#load_moduleObject



362
363
364
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 362

def load_module
  require module_file_path
end

#maqao_analysis(options = {}) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/BOAST/Runtime/MAQAO.rb', line 4

def maqao_analysis(options={})
  maqao_models = {
    "core2" => "CORE2_45", 
    "nehalem" => "NEHALEM",
    "sandybridge" => "SANDY_BRIDGE",
    "ivybridge" => "IVY_BRIDGE",
    "haswell" => "HASWELL"
  }
  compiler_options = BOAST::get_compiler_options
  compiler_options.update(options)

  f1 = File::open(library_object,"wb")
  @binary.rewind
  f1.write( @binary.read )
  f1.close

  f2 = File::open(library_source,"wb")
  @source.rewind
  f2.write( @source.read )
  f2.close
  maqao_model = maqao_models[get_model]
  if verbose? then
    puts "#{compiler_options[:MAQAO]} cqa #{maqao_model ? "--uarch=#{maqao_model} " : ""}#{f1.path} --fct=#{@procedure.name} #{compiler_options[:MAQAO_FLAGS]}"
  end
  result = `#{compiler_options[:MAQAO]} cqa #{maqao_model ? "--uarch=#{maqao_model} " : ""}#{f1.path} --fct=#{@procedure.name} #{compiler_options[:MAQAO_FLAGS]}`
  File::unlink(library_object)
  File::unlink(library_source)
  return result
end

#method_nameObject



121
122
123
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 121

def method_name
  return @procedure.name
end

#module_file_base_nameObject



55
56
57
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 55

def module_file_base_name
  return "Mod_" + base_name
end

#module_file_base_pathObject



59
60
61
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 59

def module_file_base_path
  return "#{directory}/#{module_file_base_name}"
end

#module_file_objectObject



71
72
73
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 71

def module_file_object
  return "#{module_file_base_path}.#{RbConfig::CONFIG["OBJEXT"]}"
end

#module_file_pathObject



63
64
65
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 63

def module_file_path
  return "#{module_file_base_path}.#{RbConfig::CONFIG["DLEXT"]}"
end

#module_file_sourceObject



67
68
69
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 67

def module_file_source
  return module_file_base_path + ".c"
end

#module_nameObject



47
48
49
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 47

def module_name
  return "Mod_" + base_name#.gsub("-","_")
end

#save_binaryObject



99
100
101
102
103
104
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 99

def save_binary
  f = File::open(library_object,"rb")
  @binary = StringIO::new
  @binary.write( f.read )
  f.close
end

#save_sourceObject



106
107
108
109
110
111
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 106

def save_source
  f = File::open(library_source,"r")
  @source = StringIO::new
  @source.write( f.read )
  f.close
end

#store_resultsObject



295
296
297
298
299
300
301
302
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 295

def store_results
  if @procedure.properties[:return] then
    type_ret = @procedure.properties[:return].type
    get_output.puts "  rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"return\")),rb_int_new((long long)_boast_ret));" if type_ret.kind_of?(Int) and type_ret.signed
    get_output.puts "  rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"return\")),rb_int_new((unsigned long long)_boast_ret));" if type_ret.kind_of?(Int) and not type_ret.signed
    get_output.puts "  rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"return\")),rb_float_new((double)_boast_ret));" if type_ret.kind_of?(Real)
  end
end

#targetObject



91
92
93
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 91

def target
  return module_file_path
end

#target_dependsObject



95
96
97
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 95

def target_depends
  return [ module_file_object, library_object ]
end

#target_sourcesObject



366
367
368
# File 'lib/BOAST/Runtime/CompiledRuntime.rb', line 366

def target_sources
  return [ module_file_source, library_source ]
end