From: Cameron McBride Date: 2006-02-12T06:12:00+09:00 Subject: extending NArray ------=_Part_9477_9412626.1139692302456 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline I'm trying to make the fast extensions to NArray, yet still preserve the general nature of methods (i.e. works on all NArray types). As an example, I'll show benchmarks of a simple weighted mean: Benchmarking based: num_runs =3D 1000 data_size =3D 100000 user system total real NArray_rb 3.150000 0.660000 3.810000 ( 3.803652) NArray_mod 3.930000 0.020000 3.950000 ( 3.949027) NArray_dbl 1.040000 0.000000 1.040000 ( 1.039897) GSL 1.670000 0.000000 1.670000 ( 1.665538) (sorry, Gmail messed with the formating on paste) I did the quick NArray_dbl hack, which is fast but explicitly casts to 'double', so it's not general. When I generalized it using some internal SetFuncs of NArray, the result is slower than a ruby version that does a double loop (two #sum calls). What am I missing? As a success meter, I'd like it to be at least as fast as GSL libs. (benchmark and code attached. additionally uses inline and rb-gsl) Thanks! Cameron ------=_Part_9477_9412626.1139692302456 Content-Type: application/octet-stream; name=bench_wmean.rb Content-Transfer-Encoding: 7bit X-Attachment-Id: f_ejkf4aha Content-Disposition: attachment; filename="bench_wmean.rb" #!/usr/bin/env ruby require 'benchmark' include Benchmark require 'gsl' require 'na_wmean.rb' n = 1_000 data_size = 100_000 x = NArray.float(data_size).random! w = NArray.float(data_size).random! gx = x.to_gv gw = w.to_gv def wmean_orig(xt,wt) (xt * wt).sum / wt.sum end puts "Benchmarking based: " puts " num_runs = #{n}" puts " data_size = #{data_size}" bmbm(12) do |be| be.report("NArray_rb") { n.times { m = wmean_orig(x,w)} } be.report("NArray_mod") { n.times { m = x.wmean(w)} } be.report("NArray_dbl") { n.times { m = x.wmean_dbl(w)} } be.report("GSL") { n.times { m = gx.wmean(gw)} } end ------=_Part_9477_9412626.1139692302456 Content-Type: application/octet-stream; name=na_wmean.rb Content-Transfer-Encoding: 7bit X-Attachment-Id: f_ejkf4ll0 Content-Disposition: attachment; filename="na_wmean.rb" #!/usr/bin/env ruby require 'rubygems' require 'narray' require 'inline' class NArray inline do |builder| builder.add_compile_flags %q(-I /export/home/cameron/sys/narray-0.5.8/) builder.include '"narray.h"' builder.include '"narray_local.h"' # few local things used in linspace builder.c_raw <<-'END_CODE' VALUE wmean_dbl(int argc, VALUE *argv, VALUE self) { int i; struct NARRAY *nv, *nw; double p_sum = 0.0, w_sum = 0.0; GetNArray(self, nv); GetNArray(argv[0], nw); if(nv->total != nw->total) rb_raise( rb_eArgError, "Vector and weight must be same size!" ); for(i=0 ; i < nv->total ; i++) { p_sum += ((double *)nw->ptr)[i] * ((double *)nv->ptr)[i]; w_sum += ((double *)nw->ptr)[i]; } return rb_float_new( p_sum / w_sum); } END_CODE builder.c_raw <<-'END_CODE' VALUE wmean(int argc, VALUE *argv, VALUE self) { int i,sv,sw; struct NARRAY *nv, *nw; double wt,val; double p_sum = 0.0, w_sum = 0.0; char *v,*w; void (*na_getv)(); void (*na_getw)(); GetNArray(self, nv); GetNArray(argv[0], nw); if(nv->total != nw->total) rb_raise( rb_eArgError, "Vector and weight must be same size!" ); na_getv = SetFuncs[NA_DFLOAT][nv->type]; na_getw = SetFuncs[NA_DFLOAT][nw->type]; sv = na_sizeof[nv->type]; sw = na_sizeof[nw->type]; v = nv->ptr; w = nw->ptr; for(i=0 ; i < nv->total ; i++) { (*na_getv)( 1, &val, 0, v, 0 ); (*na_getw)( 1, &wt, 0, w, 0 ); v += sv; w += sw; p_sum += (wt) * (val); w_sum += (wt); } return rb_float_new( p_sum / w_sum); } END_CODE end end ------=_Part_9477_9412626.1139692302456--