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 +4 -4
- data/BOAST.gemspec +3 -2
- data/lib/BOAST/CKernel.rb +280 -92
- data/lib/BOAST/DataTypes.rb +43 -6
- data/lib/BOAST/Procedure.rb +9 -0
- data/lib/BOAST/Variable.rb +14 -1
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88a3643b3adeeb4ba00c9e2531df8351c70739f0
|
4
|
+
data.tar.gz: ab54c2487d50cdd9683ce700ada7c4af6d36113c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
3
|
+
s.version = "1.0.1"
|
4
4
|
s.author = "Brice Videau"
|
5
5
|
s.email = "brice.videau@imag.fr"
|
6
|
-
s.homepage = "https://
|
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
|
-
|
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
|
-
|
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
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
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
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
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
|
-
|
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
|
-
|
526
|
-
|
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
|
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
|
-
|
611
|
-
|
612
|
-
if(
|
613
|
-
rb_raise(rb_eArgError, "wrong number of arguments for #{@procedure.name} (%d for #{@procedure.parameters.length})",
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
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(
|
639
|
-
struct NARRAY *
|
640
|
-
size_t
|
641
|
-
Data_Get_Struct(
|
642
|
-
|
643
|
-
cudaMalloc( (void **) &#{param.name},
|
644
|
-
cudaMemcpy(#{param.name}, (void *)
|
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(
|
651
|
-
#{param.name} = (void *) RSTRING_PTR(
|
652
|
-
} else if ( IsNArray(
|
653
|
-
struct NARRAY *
|
654
|
-
Data_Get_Struct(
|
655
|
-
#{param.name} = (void *)
|
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}
|
674
|
-
module_file.print " VALUE
|
675
|
-
module_file.print "
|
676
|
-
module_file.print "
|
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
|
-
|
682
|
-
size_t
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
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
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
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 "
|
883
|
+
module_file.print " _boast_duration = "
|
719
884
|
elsif @procedure.properties[:return] then
|
720
|
-
module_file.print "
|
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( "
|
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(
|
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 *
|
765
|
-
size_t
|
766
|
-
Data_Get_Struct(
|
767
|
-
|
768
|
-
cudaMemcpy((void *)
|
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 "
|
785
|
-
module_file.print "
|
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(
|
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(
|
791
|
-
module_file.print " rb_hash_aset(
|
792
|
-
module_file.print " rb_hash_aset(
|
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
|
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("
|
807
|
-
rb_ptr = Variable::new("
|
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
|
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, &
|
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
|
1017
|
+
module_file.print " return _boast_stats;\n"
|
830
1018
|
module_file.print "}"
|
831
1019
|
end
|
832
1020
|
|
data/lib/BOAST/DataTypes.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
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
|
data/lib/BOAST/Procedure.rb
CHANGED
@@ -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 = ""
|
data/lib/BOAST/Variable.rb
CHANGED
@@ -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:
|
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-
|
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://
|
105
|
+
homepage: https://github.com/Nanosim-LIG/boast
|
92
106
|
licenses:
|
93
107
|
- BSD
|
94
108
|
metadata: {}
|