Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.ruby > #3557 > unrolled thread
| Started by | Ville Sipola <ville_sipola@hotmail.com> |
|---|---|
| First post | 2011-04-27 05:46 -0500 |
| Last post | 2011-04-27 11:15 -0500 |
| Articles | 7 — 4 participants |
Back to article view | Back to comp.lang.ruby
Fast way to move C array to ruby (rb_ary_new4)? Ville Sipola <ville_sipola@hotmail.com> - 2011-04-27 05:46 -0500
Re: Fast way to move C array to ruby (rb_ary_new4)? Robert Klemme <shortcutter@googlemail.com> - 2011-04-27 07:08 -0500
Re: Fast way to move C array to ruby (rb_ary_new4)? Robert Klemme <shortcutter@googlemail.com> - 2011-04-27 08:06 -0500
Re: Fast way to move C array to ruby (rb_ary_new4)? Cameron McBride <cameron.mcbride@gmail.com> - 2011-04-27 15:02 -0500
Re: Fast way to move C array to ruby (rb_ary_new4)? Ville Sipola <ville_sipola@hotmail.com> - 2011-04-27 17:01 -0500
Re: Fast way to move C array to ruby (rb_ary_new4)? Ville Sipola <ville_sipola@hotmail.com> - 2011-05-06 14:47 -0500
Re: Fast way to move C array to ruby (rb_ary_new4)? Brian Candler <b.candler@pobox.com> - 2011-04-27 11:15 -0500
| From | Ville Sipola <ville_sipola@hotmail.com> |
|---|---|
| Date | 2011-04-27 05:46 -0500 |
| Subject | Fast way to move C array to ruby (rb_ary_new4)? |
| Message-ID | <7bb00dec91cd520ed45220d7d899f294@ruby-forum.com> |
Good day
I have a number of large arrays in a C module, and I'd need to move them
to ruby as quickly as possible.
Currently I use the following type of an approach:
instance_array_in_ruby = rb_iv_get(calling_class, "@x");
double c_array[1000000];
for(i=0;i<1000000;i++)
{
rb_ary_store(instance_array_in_ruby, i, rb_float_new(c_array[i]));
}
But that's slow, apparently due to the large number of rb_float_new:s.
There is a function called rb_ary_new4 that would seem to fit
the purpose of quickly moving an entire C array to ruby. Only I'm unable
to get it work, as it, too requires VALUE:s.
I've tried many things including mumbo-jumbo like
rb_iv_set(calling_class,"@x",rb_ary_new4(1000000, (VALUE)c_array));, but
I'm only managing to get segfaults or solutions that still need a
million rb_something_new:s.
Would you know an efficient way of moving a large data from C array to
ruby array?
--
Posted via http://www.ruby-forum.com/.
[toc] | [next] | [standalone]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2011-04-27 07:08 -0500 |
| Message-ID | <BANLkTimkAt-43cdMX+ZEETjJ-K7X=kSPnw@mail.gmail.com> |
| In reply to | #3557 |
On Wed, Apr 27, 2011 at 12:46 PM, Ville Sipola <ville_sipola@hotmail.com> wrote:
> Good day
>
> I have a number of large arrays in a C module, and I'd need to move them
> to ruby as quickly as possible.
>
> Currently I use the following type of an approach:
>
> instance_array_in_ruby = rb_iv_get(calling_class, "@x");
> double c_array[1000000];
>
> for(i=0;i<1000000;i++)
> {
> rb_ary_store(instance_array_in_ruby, i, rb_float_new(c_array[i]));
> }
>
> But that's slow, apparently due to the large number of rb_float_new:s.
>
> There is a function called rb_ary_new4 that would seem to fit
> the purpose of quickly moving an entire C array to ruby. Only I'm unable
> to get it work, as it, too requires VALUE:s.
> I've tried many things including mumbo-jumbo like
> rb_iv_set(calling_class,"@x",rb_ary_new4(1000000, (VALUE)c_array));, but
> I'm only managing to get segfaults or solutions that still need a
> million rb_something_new:s.
>
> Would you know an efficient way of moving a large data from C array to
> ruby array?
What about leaving it in C, i.e. wrapping in a specific type which
presents an Array (or Enumerable) like API and uses your C array
internally? A similar approach is taken by ENV (you can find the code
in hash.c).
Kind regards
robert
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
[toc] | [prev] | [next] | [standalone]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2011-04-27 08:06 -0500 |
| Message-ID | <BANLkTinmauNPb+vZ8Tv5Fw_OSx=Xc_oT3Q@mail.gmail.com> |
| In reply to | #3559 |
On Wed, Apr 27, 2011 at 2:08 PM, Robert Klemme <shortcutter@googlemail.com> wrote: > On Wed, Apr 27, 2011 at 12:46 PM, Ville Sipola <ville_sipola@hotmail.com> wrote: >> Would you know an efficient way of moving a large data from C array to >> ruby array? > > What about leaving it in C, i.e. wrapping in a specific type which > presents an Array (or Enumerable) like API and uses your C array > internally? A similar approach is taken by ENV (you can find the code > in hash.c). PS: Of course whether that is more or less efficient than your approach totally depends on the usage pattern. If only few items in those arrays are accessed from Ruby land the wrapping approach is likely cheaper. If all items are accessed in the majority of cases then probably your original approach is better. I'd also look into NArray which might help you here. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/
[toc] | [prev] | [next] | [standalone]
| From | Cameron McBride <cameron.mcbride@gmail.com> |
|---|---|
| Date | 2011-04-27 15:02 -0500 |
| Message-ID | <BANLkTi=F7J=Fg52aFeSOqtqL1XsS4VuVtg@mail.gmail.com> |
| In reply to | #3560 |
On Wed, Apr 27, 2011 at 08:06, Robert Klemme <shortcutter@googlemail.com> wrote: > On Wed, Apr 27, 2011 at 2:08 PM, Robert Klemme > <shortcutter@googlemail.com> wrote: >> On Wed, Apr 27, 2011 at 12:46 PM, Ville Sipola <ville_sipola@hotmail.com> wrote: >>> Would you know an efficient way of moving a large data from C array to >>> ruby array? > I'd also look into NArray which might help you here. I second this suggestion. If you don't mind the NArray dependence, this is extremely easy using NArray as it keeps it in the C array structure. Cameron
[toc] | [prev] | [next] | [standalone]
| From | Ville Sipola <ville_sipola@hotmail.com> |
|---|---|
| Date | 2011-04-27 17:01 -0500 |
| Message-ID | <104a6c52e34d44d0b57874ca7d51a4c3@ruby-forum.com> |
| In reply to | #3573 |
That's a lot of answers in a short time. Thank you all! The kind of hack that Brian Candler mentioned (writing directly to struct RFloat) was one of the ways that I already tried to accomplish, but if it's likely to get broken in future, then I guess it's not a solution to fight for. And for Robert's second answer: yes, I need the whole data back, I'm sending it all to other functions. I guess I'll try them all, starting with the NArray. Now I only have to figure out how to use that. From narray.c I get the impression that they can be read into C by creating a struct NARRAY and then using the command GetNArray, right? But how would you write into it in C? Thank you for the help. Ville -- Posted via http://www.ruby-forum.com/.
[toc] | [prev] | [next] | [standalone]
| From | Ville Sipola <ville_sipola@hotmail.com> |
|---|---|
| Date | 2011-05-06 14:47 -0500 |
| Message-ID | <28d39b6f96e5111235f7b9aa93869a9e@ruby-forum.com> |
| In reply to | #3585 |
Ville Sipola wrote:
> Now I only have to figure out how to use that.
Now that I have, I thought it a good idea to describe how it was done,
so that others reading the post might be able to use the information.
So this was my method.
The writing part is a bit of a hack. Masahiro Tanaka himself advices
against this approach in here: https://www.ruby-forum.com/topic/83484,
but I'm yiet to find a better solution. If there is a function for
writing c data in an narray in a safe way, I'd like to hear about it.
First, in Ruby I did something like
@x=NArray.float(@number_of_samples).fill(some_value)
to make sure that the narray is of correct size.
Then in C:
static VALUE writingfunction(VALUE class,VALUE x)
{
struct NARRAY *xarray;
GetNArray(x, xarray);
double *floatpointerx = xarray->ptr;
double c_value;
for (counter = 0; counter < number_of_samples; counter++)
{
(do the actual calculation)
floatpointerx[samplecounter] = c_value; (This is the illegal
hack)
}
}
To read in C (this I believe is completely ok, please correct if I'm
wrong.)
static VALUE readingfunction(VALUE class, VALUE x)
{
struct NARRAY *xarray;
GetNArray(x, xarray);
double *floatpointerx = xarray->ptr;
for (counter = 0; counter < xarray->total; counter++)
{
a_function_that_takes_c_double(floatpointerx[counter1]);
}
}
--
Posted via http://www.ruby-forum.com/.
[toc] | [prev] | [next] | [standalone]
| From | Brian Candler <b.candler@pobox.com> |
|---|---|
| Date | 2011-04-27 11:15 -0500 |
| Message-ID | <46abaf7c3f9c2e4618f00dca4c370ba6@ruby-forum.com> |
| In reply to | #3557 |
Ville Sipola wrote in post #995293:
> instance_array_in_ruby = rb_iv_get(calling_class, "@x");
> double c_array[1000000];
>
> for(i=0;i<1000000;i++)
> {
> rb_ary_store(instance_array_in_ruby, i, rb_float_new(c_array[i]));
> }
>
> But that's slow, apparently due to the large number of rb_float_new:s.
I'm afraid that's bound to be the case, given that Floats are not
immediate values and therefore each one has to be allocated on the heap
(unless your data happens to have many instances of identical floats,
and could share the references)
Robert's wrapping sounds like the best way forward, perhaps with some
memoizing (i.e. lazy creation of Float objects)
It might also help a little if you pre-allocate the array:
a = Array.new(1000000)
For more of a hack, try:
a = Array.new(1000000) { 0.0+0.0 }
Then maybe you could walk the array and overwrite the RFloat structures
directly (ugh). Note that the 0.0+0.0 frig was required so that the same
object_id doesn't get used in each element, and that's not guaranteed to
work in future (e.g. if Ruby did more aggressive constant folding)
--
Posted via http://www.ruby-forum.com/.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.ruby
csiph-web