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