BOAST 0.99997 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bb89f1443e6a90d1e3de87c5d9d6a23987b4c18a
4
- data.tar.gz: c305d01f65fbdf595bb9a381589cd7220c67e5eb
3
+ metadata.gz: 88a3643b3adeeb4ba00c9e2531df8351c70739f0
4
+ data.tar.gz: ab54c2487d50cdd9683ce700ada7c4af6d36113c
5
5
  SHA512:
6
- metadata.gz: a3a43dac0e6441cb2b1cc646bb40953974f861d5c8fb2e199ea60c517964c08eca4e20aba5a4831932b246cb1164633ca8d53196e3b77413bac0aa6eca7176d8
7
- data.tar.gz: 94959453ffdf64b5e73429771eaaf1cc809369fd214be89668b51a27ae896554cdc053271af1877aa7ed4b42d5be1b4e3b116b9d5c9a6684f9467bffa7bfef89
6
+ metadata.gz: 898b0a5c86fde5ef320abcce81c9adb21a34ff0ce0b8d49acad2232b2f23d0e595a238140b3295070831f06f51a996280b6d5213f7e3d2dc37f3185a3ee0a515
7
+ data.tar.gz: 155796857e44a0456c4e2ae0549e69d8599d2ee5efa7803d8fc95a139d58d491eecb032dd89a4b24efaf3c76a06a66793ee9f610d0c5d20b39f882ea505e5bf3
data/BOAST.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'BOAST'
3
- s.version = "0.99997"
3
+ s.version = "1.0.1"
4
4
  s.author = "Brice Videau"
5
5
  s.email = "brice.videau@imag.fr"
6
- s.homepage = "https://forge.imag.fr/projects/boast/"
6
+ s.homepage = "https://github.com/Nanosim-LIG/boast"
7
7
  s.summary = "BOAST is a computing kernel metaprogramming tool."
8
8
  s.description = "BOAST aims at providing a framework to metaprogram, benchmark and validate computing kernels"
9
9
  s.files = %w( BOAST.gemspec
@@ -42,4 +42,5 @@ Gem::Specification.new do |s|
42
42
  s.add_dependency 'narray', '>=0.6.0.8'
43
43
  s.add_dependency 'opencl_ruby_ffi', '>=0.4'
44
44
  s.add_dependency 'systemu', '>=2.2.0'
45
+ s.add_dependency 'PAPI', '>=0.101'
45
46
  end
data/lib/BOAST/CKernel.rb CHANGED
@@ -37,9 +37,12 @@ module BOAST
37
37
 
38
38
  module PrivateStateAccessor
39
39
  private_boolean_state_accessor :verbose
40
+ private_boolean_state_accessor :ffi
40
41
  end
41
42
 
42
43
  boolean_state_accessor :verbose
44
+ boolean_state_accessor :ffi
45
+ @@ffi = false
43
46
  @@verbose = false
44
47
  FORTRAN_LINE_LENGTH = 72
45
48
 
@@ -77,6 +80,7 @@ module BOAST
77
80
  }
78
81
  @@compiler_default_options[:LD] = ENV["LD"] if ENV["LD"]
79
82
  @@verbose = ENV["VERBOSE"] if ENV["VERBOSE"]
83
+ @@ffi = ENV["FFI"] if ENV["FFI"]
80
84
  end
81
85
 
82
86
  read_boast_config
@@ -424,7 +428,18 @@ def self.run(*args)
424
428
  params.each_index{ |i|
425
429
  @kernel.set_arg(i, params[i])
426
430
  }
427
- event = @queue.enqueue_NDrange_kernel(@kernel, opts[:global_work_size], :local_work_size => opts[:local_work_size])
431
+ gws = opts[:global_work_size]
432
+ if not gws then
433
+ gws = []
434
+ opts[:block_number].each_index { |i|
435
+ gws.push(opts[:block_number][i]*opts[:block_size][i])
436
+ }
437
+ end
438
+ lws = opts[:local_work_size]
439
+ if not lws then
440
+ lws = opts[:block_size]
441
+ end
442
+ event = @queue.enqueue_NDrange_kernel(@kernel, gws, :local_work_size => lws)
428
443
  @procedure.parameters.each_index { |i|
429
444
  if @procedure.parameters[i].dimension and (@procedure.parameters[i].direction == :inout or @procedure.parameters[i].direction == :out) then
430
445
  read_opencl_param( params[i], args[i], @procedure.parameters[i] )
@@ -468,7 +483,7 @@ EOF
468
483
  set_output( module_file )
469
484
  fill_module(module_file, module_name)
470
485
  module_file.rewind
471
- #puts module_file.read
486
+ #puts module_file.read
472
487
  module_file.close
473
488
  set_lang( previous_lang )
474
489
  set_output( previous_output )
@@ -492,6 +507,83 @@ EOF
492
507
  return [source_file, path, target]
493
508
  end
494
509
 
510
+ def create_ffi_module(module_name, module_final)
511
+ s =<<EOF
512
+ require 'ffi'
513
+ require 'narray_ffi'
514
+ module #{module_name}
515
+ extend FFI::Library
516
+ ffi_lib "#{module_final}"
517
+ attach_function :#{@procedure.name}#{@lang == FORTRAN ? "_" : ""}, [ #{@procedure.parameters.collect{ |p| ":"+p.decl_ffi.to_s }.join(", ")} ], :#{@procedure.properties[:return] ? @procedure.properties[:return].type.decl_ffi : "void" }
518
+ def run(*args)
519
+ if args.length < @procedure.parameters.length or args.length > @procedure.parameters.length + 1 then
520
+ raise "Wrong number of arguments for \#{@procedure.name} (\#{args.length} for \#{@procedure.parameters.length})"
521
+ else
522
+ ev_set = nil
523
+ if args.length == @procedure.parameters.length + 1 then
524
+ options = args.last
525
+ if options[:PAPI] then
526
+ require 'PAPI'
527
+ ev_set = PAPI::EventSet::new
528
+ ev_set.add_named(options[:PAPI])
529
+ end
530
+ end
531
+ t_args = []
532
+ r_args = {}
533
+ if @lang == FORTRAN then
534
+ @procedure.parameters.each_with_index { |p, i|
535
+ if p.decl_ffi(true) != :pointer then
536
+ arg_p = FFI::MemoryPointer::new(p.decl_ffi(true))
537
+ arg_p.send("write_\#{p.decl_ffi(true)}",args[i])
538
+ t_args.push(arg_p)
539
+ r_args[p] = arg_p if p.scalar_output?
540
+ else
541
+ t_args.push( args[i] )
542
+ end
543
+ }
544
+ else
545
+ @procedure.parameters.each_with_index { |p, i|
546
+ if p.scalar_output? then
547
+ arg_p = FFI::MemoryPointer::new(p.decl_ffi(true))
548
+ arg_p.send("write_\#{p.decl_ffi(true)}",args[i])
549
+ t_args.push(arg_p)
550
+ r_args[p] = arg_p
551
+ else
552
+ t_args.push( args[i] )
553
+ end
554
+ }
555
+ end
556
+ results = {}
557
+ counters = nil
558
+ ev_set.start if ev_set
559
+ begin
560
+ start = Time::new
561
+ ret = #{@procedure.name}#{@lang == FORTRAN ? "_" : ""}(*t_args)
562
+ stop = Time::new
563
+ ensure
564
+ if ev_set then
565
+ counters = ev_set.stop
566
+ ev_set.cleanup
567
+ ev_set.destroy
568
+ end
569
+ end
570
+ results = { :start => start, :stop => stop, :duration => stop - start, :return => ret }
571
+ results[:PAPI] = Hash[[options[:PAPI]].flatten.zip(counters)] if ev_set
572
+ if r_args.length > 0 then
573
+ ref_return = {}
574
+ r_args.each { |p, p_arg|
575
+ ref_return[p.name.to_sym] = p_arg.send("read_\#{p.decl_ffi(true)}")
576
+ }
577
+ results[:reference_return] = ref_return
578
+ end
579
+ return results
580
+ end
581
+ end
582
+ end
583
+ EOF
584
+ eval s
585
+ end
586
+
495
587
  def build(options = {})
496
588
  compiler_options = BOAST::get_compiler_options
497
589
  compiler_options.update(options)
@@ -503,28 +595,45 @@ EOF
503
595
 
504
596
  source_file, path, target = create_source
505
597
 
506
- module_file_name, module_name = create_module_source(path)
507
-
508
- module_target = module_file_name.chomp(File::extname(module_file_name))+".o"
509
- module_final = module_file_name.chomp(File::extname(module_file_name))+".so"
510
-
598
+ if not ffi? then
599
+ module_file_name, module_name = create_module_source(path)
600
+ module_target = module_file_name.chomp(File::extname(module_file_name))+".o"
601
+ module_final = module_file_name.chomp(File::extname(module_file_name))+".so"
602
+ else
603
+ module_final = path.chomp(File::extname(path))+".so"
604
+ module_name = "Mod_" + File::split(path.chomp(File::extname(path)))[1].gsub("-","_")
605
+ end
511
606
 
512
607
  kernel_files = get_sub_kernels
513
608
 
514
- file module_final => [module_target, target] do
515
- #puts "#{linker} -shared -o #{module_final} #{module_target} #{target} #{kernel_files.join(" ")} -Wl,-Bsymbolic-functions -Wl,-z,relro -rdynamic -Wl,-export-dynamic #{ldflags}"
516
- sh "#{linker} -shared -o #{module_final} #{module_target} #{target} #{(kernel_files.collect {|f| f.path}).join(" ")} -Wl,-Bsymbolic-functions -Wl,-z,relro -rdynamic -Wl,-export-dynamic #{ldflags}"
517
- end
518
- Rake::Task[module_final].invoke
609
+ if not ffi? then
610
+ file module_final => [module_target, target] do
611
+ #puts "#{linker} -shared -o #{module_final} #{module_target} #{target} #{kernel_files.join(" ")} -Wl,-Bsymbolic-functions -Wl,-z,relro -rdynamic -Wl,-export-dynamic #{ldflags}"
612
+ sh "#{linker} -shared -o #{module_final} #{module_target} #{target} #{(kernel_files.collect {|f| f.path}).join(" ")} -Wl,-Bsymbolic-functions -Wl,-z,relro -rdynamic -Wl,-export-dynamic #{ldflags}"
613
+ end
614
+ Rake::Task[module_final].invoke
519
615
 
520
- require(module_final)
616
+ require(module_final)
617
+ else
618
+ file module_final => [target] do
619
+ #puts "#{linker} -shared -o #{module_final} #{target} #{kernel_files.join(" ")} -Wl,-Bsymbolic-functions -Wl,-z,relro -rdynamic -Wl,-export-dynamic #{ldflags}"
620
+ sh "#{linker} -shared -o #{module_final} #{target} #{(kernel_files.collect {|f| f.path}).join(" ")} -Wl,-Bsymbolic-functions -Wl,-z,relro -rdynamic -Wl,-export-dynamic #{ldflags}"
621
+ end
622
+ Rake::Task[module_final].invoke
623
+ create_ffi_module(module_name, module_final)
624
+ end
521
625
  eval "self.extend(#{module_name})"
522
-
523
626
  save_binary(target)
524
627
 
525
- [target, module_target, module_file_name, module_final].each { |fn|
526
- File::unlink(fn)
527
- }
628
+ if not ffi? then
629
+ [target, module_target, module_file_name, module_final].each { |fn|
630
+ File::unlink(fn)
631
+ }
632
+ else
633
+ [target, module_final].each { |fn|
634
+ File::unlink(fn)
635
+ }
636
+ end
528
637
  kernel_files.each { |f|
529
638
  f.unlink
530
639
  }
@@ -598,7 +707,7 @@ EOF
598
707
  module_file.print <<EOF
599
708
  VALUE #{module_name} = Qnil;
600
709
  void Init_#{module_name}();
601
- VALUE method_run(int argc, VALUE *argv, VALUE self);
710
+ VALUE method_run(int _boast_argc, VALUE *_boast_argv, VALUE _boast_self);
602
711
  void Init_#{module_name}() {
603
712
  #{module_name} = rb_define_module("#{module_name}");
604
713
  rb_define_method(#{module_name}, "run", method_run, -1);
@@ -607,20 +716,23 @@ EOF
607
716
  end
608
717
 
609
718
  def check_args(module_file)
610
- if @lang == CUDA then
611
- module_file.print <<EOF
612
- if( argc < #{@procedure.parameters.length} || argc > #{@procedure.parameters.length + 1} )
613
- rb_raise(rb_eArgError, "wrong number of arguments for #{@procedure.name} (%d for #{@procedure.parameters.length})", argc);
614
- EOF
615
- else
616
- module_file.print <<EOF
617
- if( argc != #{@procedure.parameters.length} )
618
- rb_raise(rb_eArgError, "wrong number of arguments for #{@procedure.name} (%d for #{@procedure.parameters.length})", argc);
719
+ module_file.print <<EOF
720
+ VALUE _boast_rb_opts;
721
+ if( _boast_argc < #{@procedure.parameters.length} || _boast_argc > #{@procedure.parameters.length + 1} )
722
+ rb_raise(rb_eArgError, "wrong number of arguments for #{@procedure.name} (%d for #{@procedure.parameters.length})", _boast_argc);
723
+ _boast_rb_opts = Qnil;
724
+ if( _boast_argc == #{@procedure.parameters.length + 1} ) {
725
+ _boast_rb_opts = _boast_argv[_boast_argc -1];
726
+ if ( _boast_rb_opts != Qnil ) {
727
+ if (TYPE(_boast_rb_opts) != T_HASH)
728
+ rb_raise(rb_eArgError, "Options should be passed as a hash");
729
+ }
730
+ }
619
731
  EOF
620
- end
621
732
  end
622
733
 
623
734
  def get_params_value(module_file, argv, rb_ptr)
735
+ set_decl_module(true)
624
736
  @procedure.parameters.each_index do |i|
625
737
  param = @procedure.parameters[i]
626
738
  if not param.dimension then
@@ -635,30 +747,31 @@ EOF
635
747
  (rb_ptr === argv[i]).pr
636
748
  if @lang == CUDA then
637
749
  module_file.print <<EOF
638
- if ( IsNArray(rb_ptr) ) {
639
- struct NARRAY *n_ary;
640
- size_t array_size;
641
- Data_Get_Struct(rb_ptr, struct NARRAY, n_ary);
642
- array_size = n_ary->total * na_sizeof[n_ary->type];
643
- cudaMalloc( (void **) &#{param.name}, array_size);
644
- cudaMemcpy(#{param.name}, (void *) n_ary->ptr, array_size, cudaMemcpyHostToDevice);
750
+ if ( IsNArray(_boast_rb_ptr) ) {
751
+ struct NARRAY *_boast_n_ary;
752
+ size_t _boast_array_size;
753
+ Data_Get_Struct(_boast_rb_ptr, struct NARRAY, _boast_n_ary);
754
+ _boast_array_size = _boast_n_ary->total * na_sizeof[_boast_n_ary->type];
755
+ cudaMalloc( (void **) &#{param.name}, _boast_array_size);
756
+ cudaMemcpy(#{param.name}, (void *) _boast_n_ary->ptr, _boast_array_size, cudaMemcpyHostToDevice);
645
757
  } else
646
758
  rb_raise(rb_eArgError, "wrong type of argument %d", #{i});
647
759
  EOF
648
760
  else
649
761
  module_file.print <<EOF
650
- if (TYPE(rb_ptr) == T_STRING) {
651
- #{param.name} = (void *) RSTRING_PTR(rb_ptr);
652
- } else if ( IsNArray(rb_ptr) ) {
653
- struct NARRAY *n_ary;
654
- Data_Get_Struct(rb_ptr, struct NARRAY, n_ary);
655
- #{param.name} = (void *) n_ary->ptr;
762
+ if (TYPE(_boast_rb_ptr) == T_STRING) {
763
+ #{param.name} = (void *) RSTRING_PTR(_boast_rb_ptr);
764
+ } else if ( IsNArray(_boast_rb_ptr) ) {
765
+ struct NARRAY *_boast_n_ary;
766
+ Data_Get_Struct(_boast_rb_ptr, struct NARRAY, _boast_n_ary);
767
+ #{param.name} = (void *) _boast_n_ary->ptr;
656
768
  } else
657
769
  rb_raise(rb_eArgError, "wrong type of argument %d", #{i});
658
770
  EOF
659
771
  end
660
772
  end
661
773
  end
774
+ set_decl_module(false)
662
775
  end
663
776
 
664
777
  def decl_module_params(module_file)
@@ -670,42 +783,60 @@ EOF
670
783
  param_copy.decl
671
784
  }
672
785
  set_decl_module(false)
673
- module_file.print " #{@procedure.properties[:return].type.decl} ret;\n" if @procedure.properties[:return]
674
- module_file.print " VALUE stats = rb_hash_new();\n"
675
- module_file.print " struct timespec start, stop;\n"
676
- module_file.print " unsigned long long int duration;\n"
786
+ module_file.print " #{@procedure.properties[:return].type.decl} _boast_ret;\n" if @procedure.properties[:return]
787
+ module_file.print " VALUE _boast_stats = rb_hash_new();\n"
788
+ module_file.print " VALUE _boast_refs = rb_hash_new();\n"
789
+ module_file.print " VALUE _boast_event_set = Qnil;\n"
790
+ module_file.print " struct timespec _boast_start, _boast_stop;\n"
791
+ module_file.print " unsigned long long int _boast_duration;\n"
677
792
  end
678
793
 
679
794
  def get_cuda_launch_bounds(module_file)
680
795
  module_file.print <<EOF
681
- VALUE rb_opts;
682
- size_t block_size[3] = {1,1,1};
683
- size_t block_number[3] = {1,1,1};
684
- if( argc == #{@procedure.parameters.length + 1} ) {
685
- rb_opts = argv[argc -1];
686
- if ( rb_opts != Qnil ) {
687
- VALUE rb_array_data = Qnil;
688
- int i;
689
- if (TYPE(rb_opts) != T_HASH)
690
- rb_raise(rb_eArgError, "Cuda options should be passed as a hash");
691
- rb_ptr = rb_hash_aref(rb_opts, ID2SYM(rb_intern("block_size")));
692
- if( rb_ptr != Qnil ) {
693
- if (TYPE(rb_ptr) != T_ARRAY)
694
- rb_raise(rb_eArgError, "Cuda option block_size should be an array");
695
- for(i=0; i<3; i++) {
696
- rb_array_data = rb_ary_entry(rb_ptr, i);
697
- if( rb_array_data != Qnil )
698
- block_size[i] = (size_t) NUM2LONG( rb_array_data );
796
+ size_t _boast_block_size[3] = {1,1,1};
797
+ size_t _boast_block_number[3] = {1,1,1};
798
+ if( _boast_rb_opts != Qnil ) {
799
+ VALUE _boast_rb_array_data = Qnil;
800
+ int _boast_i;
801
+ _boast_rb_ptr = rb_hash_aref(_boast_rb_opts, ID2SYM(rb_intern("block_size")));
802
+ if( _boast_rb_ptr != Qnil ) {
803
+ if (TYPE(_boast_rb_ptr) != T_ARRAY)
804
+ rb_raise(rb_eArgError, "Cuda option block_size should be an array");
805
+ for(_boast_i=0; _boast_i<3; _boast_i++) {
806
+ _boast_rb_array_data = rb_ary_entry(_boast_rb_ptr, _boast_i);
807
+ if( _boast_rb_array_data != Qnil )
808
+ _boast_block_size[_boast_i] = (size_t) NUM2LONG( _boast_rb_array_data );
809
+ }
810
+ } else {
811
+ _boast_rb_ptr = rb_hash_aref(_boast_rb_opts, ID2SYM(rb_intern("local_work_size")));
812
+ if( _boast_rb_ptr != Qnil ) {
813
+ if (TYPE(_boast_rb_ptr) != T_ARRAY)
814
+ rb_raise(rb_eArgError, "Cuda option local_work_size should be an array");
815
+ for(_boast_i=0; _boast_i<3; _boast_i++) {
816
+ _boast_rb_array_data = rb_ary_entry(_boast_rb_ptr, _boast_i);
817
+ if( _boast_rb_array_data != Qnil )
818
+ _boast_block_size[_boast_i] = (size_t) NUM2LONG( _boast_rb_array_data );
699
819
  }
700
820
  }
701
- rb_ptr = rb_hash_aref(rb_opts, ID2SYM(rb_intern("block_number")));
702
- if( rb_ptr != Qnil ) {
703
- if (TYPE(rb_ptr) != T_ARRAY)
704
- rb_raise(rb_eArgError, "Cuda option block_number should be an array");
705
- for(i=0; i<3; i++) {
706
- rb_array_data = rb_ary_entry(rb_ptr, i);
707
- if( rb_array_data != Qnil )
708
- block_number[i] = (size_t) NUM2LONG( rb_array_data );
821
+ }
822
+ _boast_rb_ptr = rb_hash_aref(_boast_rb_opts, ID2SYM(rb_intern("block_number")));
823
+ if( _boast_rb_ptr != Qnil ) {
824
+ if (TYPE(_boast_rb_ptr) != T_ARRAY)
825
+ rb_raise(rb_eArgError, "Cuda option block_number should be an array");
826
+ for(_boast_i=0; _boast_i<3; _boast_i++) {
827
+ _boast_rb_array_data = rb_ary_entry(_boast_rb_ptr, _boast_i);
828
+ if( _boast_rb_array_data != Qnil )
829
+ _boast_block_number[_boast_i] = (size_t) NUM2LONG( _boast_rb_array_data );
830
+ }
831
+ } else {
832
+ _boast_rb_ptr = rb_hash_aref(_boast_rb_opts, ID2SYM(rb_intern("global_work_size")));
833
+ if( _boast_rb_ptr != Qnil ) {
834
+ if (TYPE(_boast_rb_ptr) != T_ARRAY)
835
+ rb_raise(rb_eArgError, "Cuda option global_work_size should be an array");
836
+ for(_boast_i=0; _boast_i<3; _boast_i++) {
837
+ _boast_rb_array_data = rb_ary_entry(_boast_rb_ptr, _boast_i);
838
+ if( _boast_rb_array_data != Qnil )
839
+ _boast_block_number[_boast_i] = (size_t) NUM2LONG( _boast_rb_array_data ) / _boast_block_size[_boast_i];
709
840
  }
710
841
  }
711
842
  }
@@ -713,11 +844,45 @@ EOF
713
844
  EOF
714
845
  end
715
846
 
847
+ def get_PAPI_options(module_file)
848
+ module_file.print <<EOF
849
+ if( _boast_rb_opts != Qnil ) {
850
+ VALUE _boast_rb_array_data = Qnil;
851
+ _boast_rb_ptr = rb_hash_aref(_boast_rb_opts, ID2SYM(rb_intern("PAPI")));
852
+ if( _boast_rb_ptr != Qnil ) {
853
+ VALUE _boast_PAPI = Qnil;
854
+ VALUE _boast_EventSet = Qnil;
855
+ rb_require("PAPI");
856
+ _boast_PAPI = rb_const_get(rb_cObject, rb_intern("PAPI"));
857
+ _boast_EventSet = rb_const_get(_boast_PAPI, rb_intern("EventSet"));
858
+ _boast_event_set = rb_funcall(_boast_EventSet, rb_intern("new"), 0);
859
+ rb_funcall(_boast_event_set, rb_intern("add_named"), 1, _boast_rb_ptr);
860
+ rb_funcall(_boast_event_set, rb_intern("start"), 0);
861
+ }
862
+ }
863
+ EOF
864
+ end
865
+
866
+ def get_PAPI_results(module_file)
867
+ module_file.print <<EOF
868
+ if( _boast_event_set != Qnil) {
869
+ VALUE _boast_papi_results = Qnil;
870
+ VALUE _boast_papi_stats = Qnil;
871
+ _boast_papi_results = rb_funcall(_boast_event_set, rb_intern("stop"), 0);
872
+ _boast_papi_stats = rb_ary_new3(1,rb_hash_aref(_boast_rb_opts, ID2SYM(rb_intern("PAPI"))));
873
+ _boast_papi_stats = rb_funcall(_boast_papi_stats, rb_intern("flatten"), 0);
874
+ _boast_papi_stats = rb_funcall(_boast_papi_stats, rb_intern("zip"), 1, _boast_papi_results);
875
+ _boast_papi_stats = rb_funcall(rb_const_get(rb_cObject, rb_intern("Hash")), rb_intern("send"), 2, ID2SYM(rb_intern("[]")), _boast_papi_stats );
876
+ rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"PAPI\")),_boast_papi_stats);
877
+ }
878
+ EOF
879
+ end
880
+
716
881
  def create_procedure_call(module_file)
717
882
  if @lang == CUDA then
718
- module_file.print " duration = "
883
+ module_file.print " _boast_duration = "
719
884
  elsif @procedure.properties[:return] then
720
- module_file.print " ret = "
885
+ module_file.print " _boast_ret = "
721
886
  end
722
887
  module_file.print " #{@procedure.name}"
723
888
  module_file.print "_" if @lang == FORTRAN
@@ -744,28 +909,29 @@ EOF
744
909
  }
745
910
  end
746
911
  if @lang == CUDA then
747
- params.push( "block_number", "block_size" )
912
+ params.push( "_boast_block_number", "_boast_block_size" )
748
913
  end
749
914
  module_file.print params.join(", ")
750
915
  module_file.print " );\n"
751
916
  end
752
917
 
753
918
  def get_results(module_file, argv, rb_ptr)
919
+ set_decl_module(true)
754
920
  if @lang == CUDA then
755
921
  @procedure.parameters.each_index do |i|
756
922
  param = @procedure.parameters[i]
757
923
  if param.dimension then
758
924
  (rb_ptr === argv[i]).pr
759
925
  module_file.print <<EOF
760
- if ( IsNArray(rb_ptr) ) {
926
+ if ( IsNArray(_boast_rb_ptr) ) {
761
927
  EOF
762
928
  if param.direction == :out or param.direction == :inout then
763
929
  module_file.print <<EOF
764
- struct NARRAY *n_ary;
765
- size_t array_size;
766
- Data_Get_Struct(rb_ptr, struct NARRAY, n_ary);
767
- array_size = n_ary->total * na_sizeof[n_ary->type];
768
- cudaMemcpy((void *) n_ary->ptr, #{param.name}, array_size, cudaMemcpyDeviceToHost);
930
+ struct NARRAY *_boast_n_ary;
931
+ size_t _boast_array_size;
932
+ Data_Get_Struct(_boast_rb_ptr, struct NARRAY, _boast_n_ary);
933
+ _boast_array_size = _boast_n_ary->total * na_sizeof[_boast_n_ary->type];
934
+ cudaMemcpy((void *) _boast_n_ary->ptr, #{param.name}, _boast_array_size, cudaMemcpyDeviceToHost);
769
935
  EOF
770
936
  end
771
937
  module_file.print <<EOF
@@ -776,20 +942,38 @@ EOF
776
942
  EOF
777
943
  end
778
944
  end
945
+ else
946
+ first = true
947
+ @procedure.parameters.each_with_index do |param,i|
948
+ if param.scalar_output? then
949
+ if first then
950
+ module_file.print " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"reference_return\")),_boast_refs);\n"
951
+ first = false
952
+ end
953
+ case param.type
954
+ when Int
955
+ module_file.print " rb_hash_aset(_boast_refs, ID2SYM(rb_intern(\"#{param}\")),rb_int_new((long long)#{param}));\n" if param.type.signed?
956
+ module_file.print " rb_hash_aset(_boast_refs, ID2SYM(rb_intern(\"#{param}\")),rb_int_new((unsigned long long)#{param}));\n" if not param.type.signed?
957
+ when Real
958
+ module_file.print " rb_hash_aset(_boast_refs, ID2SYM(rb_intern(\"#{param}\")),rb_float_new((double)#{param}));\n"
959
+ end
960
+ end
961
+ end
779
962
  end
963
+ set_decl_module(false)
780
964
  end
781
965
 
782
966
  def store_result(module_file)
783
967
  if @lang != CUDA then
784
- module_file.print " duration = (unsigned long long int)stop.tv_sec * (unsigned long long int)1000000000 + stop.tv_nsec;\n"
785
- module_file.print " duration -= (unsigned long long int)start.tv_sec * (unsigned long long int)1000000000 + start.tv_nsec;\n"
968
+ module_file.print " _boast_duration = (unsigned long long int)_boast_stop.tv_sec * (unsigned long long int)1000000000 + _boast_stop.tv_nsec;\n"
969
+ module_file.print " _boast_duration -= (unsigned long long int)_boast_start.tv_sec * (unsigned long long int)1000000000 + _boast_start.tv_nsec;\n"
786
970
  end
787
- module_file.print " rb_hash_aset(stats,ID2SYM(rb_intern(\"duration\")),rb_float_new((double)duration*(double)1e-9));\n"
971
+ module_file.print " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"duration\")),rb_float_new((double)_boast_duration*(double)1e-9));\n"
788
972
  if @procedure.properties[:return] then
789
973
  type_ret = @procedure.properties[:return].type
790
- module_file.print " rb_hash_aset(stats,ID2SYM(rb_intern(\"return\")),rb_int_new((long long)ret));\n" if type_ret.kind_of?(Int) and type_ret.signed
791
- module_file.print " rb_hash_aset(stats,ID2SYM(rb_intern(\"return\")),rb_int_new((unsigned long long)ret));\n" if type_ret.kind_of?(Int) and not type_ret.signed
792
- module_file.print " rb_hash_aset(stats,ID2SYM(rb_intern(\"return\")),rb_float_new((double)ret));\n" if type_ret.kind_of?(Real)
974
+ module_file.print " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"return\")),rb_int_new((long long)_boast_ret));\n" if type_ret.kind_of?(Int) and type_ret.signed
975
+ module_file.print " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"return\")),rb_int_new((unsigned long long)_boast_ret));\n" if type_ret.kind_of?(Int) and not type_ret.signed
976
+ module_file.print " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"return\")),rb_float_new((double)_boast_ret));\n" if type_ret.kind_of?(Real)
793
977
  end
794
978
  end
795
979
 
@@ -798,13 +982,13 @@ EOF
798
982
  @procedure.boast_header(@lang)
799
983
  module_preamble(module_file, module_name)
800
984
 
801
- module_file.puts "VALUE method_run(int argc, VALUE *argv, VALUE self) {"
985
+ module_file.puts "VALUE method_run(int _boast_argc, VALUE *_boast_argv, VALUE _boast_self) {"
802
986
 
803
987
  check_args(module_file)
804
988
 
805
989
  argc = @procedure.parameters.length
806
- argv = Variable::new("argv", CustomType, :type_name => "VALUE", :dimension => [ Dimension::new(0,argc-1) ] )
807
- rb_ptr = Variable::new("rb_ptr", CustomType, :type_name => "VALUE")
990
+ argv = Variable::new("_boast_argv", CustomType, :type_name => "VALUE", :dimension => [ Dimension::new(0,argc-1) ] )
991
+ rb_ptr = Variable::new("_boast_rb_ptr", CustomType, :type_name => "VALUE")
808
992
  set_transition("VALUE", "VALUE", :default, CustomType::new(:type_name => "VALUE"))
809
993
  rb_ptr.decl
810
994
 
@@ -816,17 +1000,21 @@ EOF
816
1000
  module_file.print get_cuda_launch_bounds(module_file)
817
1001
  end
818
1002
 
819
- module_file.print " clock_gettime(CLOCK_REALTIME, &start);\n"
1003
+ get_PAPI_options(module_file)
1004
+
1005
+ module_file.print " clock_gettime(CLOCK_REALTIME, &_boast_start);\n"
820
1006
 
821
1007
  create_procedure_call(module_file)
822
1008
 
823
- module_file.print " clock_gettime(CLOCK_REALTIME, &stop);\n"
1009
+ module_file.print " clock_gettime(CLOCK_REALTIME, &_boast_stop);\n"
1010
+
1011
+ get_PAPI_results(module_file)
824
1012
 
825
1013
  get_results(module_file, argv, rb_ptr)
826
1014
 
827
1015
  store_result(module_file)
828
1016
 
829
- module_file.print " return stats;\n"
1017
+ module_file.print " return _boast_stats;\n"
830
1018
  module_file.print "}"
831
1019
  end
832
1020
 
@@ -45,6 +45,10 @@ module BOAST
45
45
  end
46
46
  end
47
47
 
48
+ def decl_ffi
49
+ return :size_t
50
+ end
51
+
48
52
  def signed?
49
53
  return !!signed
50
54
  end
@@ -133,6 +137,11 @@ module BOAST
133
137
  end
134
138
  end
135
139
 
140
+ def decl_ffi
141
+ return :float if @size == 4
142
+ return :double if @size == 8
143
+ end
144
+
136
145
  def suffix
137
146
  s = ""
138
147
  if [C, CL, CUDA].include?( lang ) then
@@ -176,6 +185,7 @@ module BOAST
176
185
  # @getters["s#{indx}"] = indx
177
186
  # @setters["s#{indx}="] = indx
178
187
  # }
188
+ raise "Vectors need to have their element size specified!" if not @size
179
189
  else
180
190
  @vector_length = 1
181
191
  end
@@ -199,12 +209,16 @@ module BOAST
199
209
  end
200
210
 
201
211
  def decl
202
- return "integer(kind=#{@size})" if lang == FORTRAN
212
+ if lang == FORTRAN then
213
+ return "integer(kind=#{@size})" if @size
214
+ return "integer"
215
+ end
203
216
  if lang == C then
204
217
  if @vector_length == 1 then
205
218
  s = ""
206
219
  s += "u" if not @signed
207
- return s+"int#{8*@size}_t"
220
+ return s+"int#{8*@size}_t" if @size
221
+ return s+"int"
208
222
  elsif @vector_length > 1 then
209
223
  if get_architecture == X86 then
210
224
  return "__m#{@total_size*8}#{@total_size*8>64 ? "i" : ""}"
@@ -228,6 +242,8 @@ module BOAST
228
242
  char += "int"
229
243
  when 8
230
244
  char += "long"
245
+ when nil
246
+ char += "int"
231
247
  else
232
248
  raise "Unsupported integer size!"
233
249
  end
@@ -248,6 +264,8 @@ module BOAST
248
264
  char += "int"
249
265
  when 8
250
266
  char += "longlong"
267
+ when nil
268
+ char += "int"
251
269
  else
252
270
  raise "Unsupported integer size!"
253
271
  end
@@ -255,14 +273,33 @@ module BOAST
255
273
  else
256
274
  char = ""
257
275
  char += "unsigned " if not @signed
258
- return char += "char" if @size==1
259
- return char += "short" if @size==2
260
- return char += "int" if @size==4
261
- return char += "long long" if @size==8
276
+ case @size
277
+ when 1
278
+ char += "char"
279
+ when 2
280
+ char += "short"
281
+ when 4
282
+ char += "int"
283
+ when 8
284
+ char += "longlong"
285
+ when nil
286
+ char += "int"
287
+ else
288
+ raise "Unsupported integer size!"
289
+ end
290
+ return char
262
291
  end
263
292
  end
264
293
  end
265
294
 
295
+ def decl_ffi
296
+ t = ""
297
+ t += "u" if not @signed
298
+ t += "int"
299
+ t += "#{@size*8}" if @size
300
+ return t.to_sym
301
+ end
302
+
266
303
  def suffix
267
304
  s = ""
268
305
  return s
@@ -79,6 +79,15 @@ module BOAST
79
79
  return close_c if [C, CL, CUDA].include?( lang )
80
80
  end
81
81
 
82
+ def ckernel
83
+ old_output = output
84
+ k = CKernel::new
85
+ k.procedure = self
86
+ self.pr
87
+ set_output( old_output )
88
+ return k
89
+ end
90
+
82
91
  def close_c
83
92
  decrement_indent_level
84
93
  s = ""
@@ -26,6 +26,8 @@ module BOAST
26
26
  def to_s
27
27
  if lang == FORTRAN and @val2 then
28
28
  return "#{@val1}:#{@val2}"
29
+ elsif lang == FORTRAN and get_array_start != 1 then
30
+ return "#{get_array_start}:#{@size-(1+get_array_start)}"
29
31
  else
30
32
  return @size
31
33
  end
@@ -169,6 +171,10 @@ module BOAST
169
171
  !!@dimension
170
172
  end
171
173
 
174
+ def scalar_output?
175
+ !!@scalar_output
176
+ end
177
+
172
178
  def initialize(name,type,hash={})
173
179
  @name = name.to_s
174
180
  @direction = hash[:direction] ? hash[:direction] : hash[:dir]
@@ -223,7 +229,7 @@ module BOAST
223
229
  s = @constant.to_s + @type.suffix
224
230
  return s
225
231
  end
226
- if @scalar_output and [C, CL, CUDA].include?( lang ) then
232
+ if @scalar_output and [C, CL, CUDA].include?( lang ) and not decl_module? then
227
233
  return "(*#{name})"
228
234
  end
229
235
  return @name
@@ -290,6 +296,13 @@ module BOAST
290
296
  return s
291
297
  end
292
298
 
299
+ def decl_ffi(alloc = false)
300
+ return :pointer if lang == FORTRAN and not alloc
301
+ return :pointer if dimension?
302
+ return :pointer if @direction == :out or @direction == :inout and not alloc
303
+ return @type.decl_ffi
304
+ end
305
+
293
306
  def decl
294
307
  return decl_fortran if lang == FORTRAN
295
308
  return decl_c if [C, CL, CUDA].include?( lang )
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: BOAST
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.99997'
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brice Videau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-26 00:00:00.000000000 Z
11
+ date: 2015-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: narray
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: 2.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: PAPI
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0.101'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0.101'
55
69
  description: BOAST aims at providing a framework to metaprogram, benchmark and validate
56
70
  computing kernels
57
71
  email: brice.videau@imag.fr
@@ -88,7 +102,7 @@ files:
88
102
  - lib/BOAST/Transitions.rb
89
103
  - lib/BOAST/Variable.rb
90
104
  - lib/BOAST/While.rb
91
- homepage: https://forge.imag.fr/projects/boast/
105
+ homepage: https://github.com/Nanosim-LIG/boast
92
106
  licenses:
93
107
  - BSD
94
108
  metadata: {}