BOAST 0.99997 → 1.0.1

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.
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: {}