Write Ruby methods using C ++ (Part 2) Benchmark

table of contents

Write a Ruby method using C ++ (Part 1) Writing Ruby Methods Using C ++ (Part 2) Benchmark <-Here

benchmark

A simple program that calculates the sum of arrays. With the method (1) written in Part 1 above I compared the speed of Write Ruby method using C (Part 2) Numo :: NArray (2). In addition, when passing Numo :: SFloat type data (3) (calculated after casting to Numo :: DFloat), After converting NArray to Array, the same method as (1) (4), After converting Array to Numo :: DFloat, the same method as (2) (5), How to use Ruby's built-in function Array # sum (6), How to use Ruby's built-in function Array # inject (7), How to use the Numo :: DFloat function sum (8) Are comparing speeds.

The result is written at the end.

Method 1 (1) is fast enough, but method (2) is the fastest. Array # sum of (6) is quite fast, and Ruby functions written in binary can be expected at speed. I feel that Numo :: DFloat # sum is unexpectedly slow and the conversion from Array to Numo :: DFloat is also slow.

Program used

test.cpp


#include "test.hpp"

double sum(const std::vector<double>& ary){
    double sum=0.0;
    for (int i=0; i<ary.size(); i++){
        sum+=ary[i];
    }
    return(sum);
}

double sum_nd(int n, double *ary){
    double sum=0.0;
    for (int i=0; i<n; i++){
        sum+=ary[i];
    }
    return(sum);
}

test.hpp


#include <vector>
double sum(const std::vector<double>& ary);
double sum_nd(int n, double *ary);

test.i


%module testF
%{
#include "numo/narray.h"
#include "test.hpp"
%}

%include <std_vector.i>
%template(DoubleVector) std::vector<double>;
extern double sum(std::vector<double> ary);

%typemap(in) (int LENGTH, double *NARRAY_in){
  narray_t *nary;
  if (rb_obj_class($input)!=numo_cDFloat){
      $input = rb_funcall(numo_cDFloat, rb_intern("cast"), 1, $input);
  }
  GetNArray($input, nary);
  if (NA_TYPE(nary)==NARRAY_VIEW_T){
    $input = rb_funcall($input, rb_intern("dup"), 0);
    GetNArray($input, nary);
  }
  $2 = ($2_ltype)na_get_pointer_for_read($input);
  $1 = NA_SIZE(nary);
}
extern double sum_nd(int LENGTH, double *NARRAY_in);

extconf.rb


require 'mkmf'
dir_config("numo/narray")
have_header("numo/narray.h")
create_makefile("testF")
swig -c++ -ruby test.i
ruby extconf.rb  -- --with-numo/narray-include=/opt/lib/ruby/gems/2.6.0/gems/numo-narray-0.9.1.8/lib/numo/
make

Benchmark program

benchmark.rb


require "benchmark"
require "numo/narray"
require "./testF"

data=[*1..100].map(&:to_f)
data_na=Numo::DFloat.cast(data)
data_naf=Numo::SFloat.cast(data)

puts Benchmark::CAPTION
puts Benchmark.measure{
	1000000.times{
		TestF::sum(data) # (1)
	}
}
=begin
Less than
TestF::sum_nd(data_na)   # (2)
TestF::sum_nd(data_naf)  # (3)
TestF::sum(data_na.to_a) # (4)
TestF::sum_nd(Numo::DFloat.cast(data)) # (5)
data.sum                 # (6)
data.inject(:+)          # (7)
data_na.sum              # (8)
=end

result

Data flow Execution time(μs)
(1) Array => vector 2.44
(2) Numo::DFloat => double [] 0.14
(3) Numo::SFloat => cast -> double [] 1.59
(4) Numo::DFloat -> Array => vector 4.77
(5) Array -> Numo::DFloat => double [] 10.11
(6) Array#sum 0.60
(7) Array#inject(:+) 3.42
(8) Numo::DFloat#sum 1.30

(Execution time is converted to one loop)

Recommended Posts

Write Ruby methods using C ++ (Part 2) Benchmark
Write Ruby methods using C (Part 1)
Write Ruby methods using C (Numo :: NArray)
Write code using Ruby classes and instances
Ruby Learning # 15 Methods
About Ruby methods
Try using java.lang.Math methods
Try using Talend Part 2
Ruby Learning # 31 Object Methods
About Ruby instance methods
Ruby variables and methods
Try using Talend Part 1
[Ruby] methods, instance methods, etc ...
What you write in C # is written in Ruby like this
I wrote a C parser (like) using PEG in Ruby
Solving with Ruby, Perl and Java AtCoder ABC 129 C (Part 1)