Quantcast

suggest that as.double( something double ) not make a copy

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

suggest that as.double( something double ) not make a copy

Tim Hesterberg-2
I've been playing with passing arguments to .C(), and found that replacing
    as.double(x)
with
    if(is.double(x)) x else as.double(x)
saves time and avoids one copy, in the case that x is already double.

I suggest modifying as.double to avoid the extra copy and just
return x, when x is already double. Similarly for as.integer, etc.

        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: suggest that as.double( something double ) not make a copy

Simon Urbanek
On Jun 6, 2012, at 6:53 PM, Tim Hesterberg wrote:

> I've been playing with passing arguments to .C(), and found that replacing
>    as.double(x)
> with
>    if(is.double(x)) x else as.double(x)
> saves time and avoids one copy, in the case that x is already double.
>

No, it doesn't:

> x=rnorm(10)
> tracemem(x)
[1] "<0x100c59cb0>"
> invisible(.C("foo",x))
tracemem[0x100c59cb0 -> 0x100c59c30]: .C
tracemem[0x100c59c30 -> 0x100ca4298]: .C
> x=rnorm(10)
> tracemem(x)
[1] "<0x100ca41f0>"
> invisible(.C("foo",as.double(x)))
tracemem[0x100ca41f0 -> 0x102cdc980]: .C
tracemem[0x102cdc980 -> 0x102cdca00]: .C

or rather more easily:

> x=rnorm(10)
> tracemem(x)
[1] "<0x102ae0ff0>"
> as.double(x)
 [1] -0.1027767  0.4018732 -1.3412045  0.8153615  1.8245356 -0.2147280
 [7]  1.1298404  1.1026897 -1.1340612 -0.2346464


as.double(x) is not stupid and doesn't copy if not needed.

However, it is a very common mistake to forget about the fact that as.double() has to strip attributes, so if you pass a matrix, you are always forcing a copy:

> x=matrix(0,2,2)
> tracemem(x)
[1] "<0x100b0f098>"
> as.double(x)
tracemem[0x100b0f098 -> 0x1008b52c8]:
[1] 0 0 0 0

That is not the fault of as.double() but rather of the user since you don't really need to strip attributes when calling .C as it doesn't care.

As usual, I can only say don't use .C() ... ;)

Cheers,
Simon


> I suggest modifying as.double to avoid the extra copy and just
> return x, when x is already double. Similarly for as.integer, etc.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: suggest that as.double( something double ) not make a copy

Matthew Dowle
In reply to this post by Tim Hesterberg-2
Tim Hesterberg <timhesterberg <at> gmail.com> writes:

> I've been playing with passing arguments to .C(), and found that replacing
>     as.double(x)
> with
>     if(is.double(x)) x else as.double(x)
> saves time and avoids one copy, in the case that x is already double.
>
> I suggest modifying as.double to avoid the extra copy and just
> return x, when x is already double. Similarly for as.integer, etc.
>

But as.double() already doesn't copy if its argument is already double. Unless,
your double has attributes?

>From coerce.c :

if(TYPEOF(x) == type) {
    if(ATTRIB(x) == R_NilValue) return x;
    ans = NAMED(x) ? duplicate(x) : x;
    CLEAR_ATTRIB(ans);
    return ans;
}

quick test :

> x=1
> .Internal(inspect(x))
@0000000003E23620 14 REALSXP g0c1 [NAM(2)] (len=1, tl=0) 1
> .Internal(inspect(as.double(x)))   # no copy
@0000000003E23620 14 REALSXP g0c1 [NAM(2)] (len=1, tl=0) 1
> x=c(foo=1)   # give x some attributes, say names
> x
foo
  1
> .Internal(inspect(x))
@0000000003E234D0 14 REALSXP g0c1 [NAM(1),ATT] (len=1, tl=0) 1
ATTRIB:
  @0000000003D54910 02 LISTSXP g0c0 []
    TAG: @0000000000380088 01 SYMSXP g0c0 [MARK,gp=0x4000] "names"
    @0000000003E234A0 16 STRSXP g0c1 [NAM(2)] (len=1, tl=0)
      @0000000003E23560 09 CHARSXP g0c1 [gp=0x21] "foo"
> .Internal(inspect(as.double(x)))   # strips attribs returning new obj
@0000000003E233B0 14 REALSXP g0c1 [] (len=1, tl=0) 1
> as.double(x)
[1] 1
>

Attribute stripping is documented in ?as.double. Rather than as.double() on the
R side, you could use coerceVector() on the C side, which might be easier to
use via .Call than .C since it takes an SEXP. Looking at coerceVector in
coerce.c its first line returns immediately if type is already the desired
type, with no attribute stripping, so that seems like the way to go?

If your double has no attributes then I'm barking up the wrong tree.

Matthew

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: suggest that as.double( something double ) not make a copy

Henrik Bengtsson-3
Check if this is the same as what was done in R v2.6.0 (2007) - from
http://cran.r-project.org/bin/windows/base/old/2.6.0/NEWS.R-2.6.0:

    o as.vector() and the default methods of as.character(),
        as.complex(), as.double(), as.expression(), as.integer(),
        as.logical() and as.raw() no longer duplicate in most cases
        where the object is unchanged.  (Beware: some code has been
        written that invalidly assumes that they do duplicate, often
        when using .C/.Fortran(DUP=FALSE).)

See also R-devel '[Rd] Suggestion for memory optimization and
as.double() with friends', March 28-29 2007
[https://stat.ethz.ch/pipermail/r-devel/2007-March/045109.html].

/Henrik


On Wed, Jun 6, 2012 at 6:12 PM, Matthew Dowle <[hidden email]> wrote:

> Tim Hesterberg <timhesterberg <at> gmail.com> writes:
>
>> I've been playing with passing arguments to .C(), and found that replacing
>>     as.double(x)
>> with
>>     if(is.double(x)) x else as.double(x)
>> saves time and avoids one copy, in the case that x is already double.
>>
>> I suggest modifying as.double to avoid the extra copy and just
>> return x, when x is already double. Similarly for as.integer, etc.
>>
>
> But as.double() already doesn't copy if its argument is already double. Unless,
> your double has attributes?
>
> >From coerce.c :
>
> if(TYPEOF(x) == type) {
>    if(ATTRIB(x) == R_NilValue) return x;
>    ans = NAMED(x) ? duplicate(x) : x;
>    CLEAR_ATTRIB(ans);
>    return ans;
> }
>
> quick test :
>
>> x=1
>> .Internal(inspect(x))
> @0000000003E23620 14 REALSXP g0c1 [NAM(2)] (len=1, tl=0) 1
>> .Internal(inspect(as.double(x)))   # no copy
> @0000000003E23620 14 REALSXP g0c1 [NAM(2)] (len=1, tl=0) 1
>> x=c(foo=1)   # give x some attributes, say names
>> x
> foo
>  1
>> .Internal(inspect(x))
> @0000000003E234D0 14 REALSXP g0c1 [NAM(1),ATT] (len=1, tl=0) 1
> ATTRIB:
>  @0000000003D54910 02 LISTSXP g0c0 []
>    TAG: @0000000000380088 01 SYMSXP g0c0 [MARK,gp=0x4000] "names"
>    @0000000003E234A0 16 STRSXP g0c1 [NAM(2)] (len=1, tl=0)
>      @0000000003E23560 09 CHARSXP g0c1 [gp=0x21] "foo"
>> .Internal(inspect(as.double(x)))   # strips attribs returning new obj
> @0000000003E233B0 14 REALSXP g0c1 [] (len=1, tl=0) 1
>> as.double(x)
> [1] 1
>>
>
> Attribute stripping is documented in ?as.double. Rather than as.double() on the
> R side, you could use coerceVector() on the C side, which might be easier to
> use via .Call than .C since it takes an SEXP. Looking at coerceVector in
> coerce.c its first line returns immediately if type is already the desired
> type, with no attribute stripping, so that seems like the way to go?
>
> If your double has no attributes then I'm barking up the wrong tree.
>
> Matthew
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: suggest that as.double( something double ) not make a copy

Matthew Dowle
Henrik Bengtsson <hb <at> biostat.ucsf.edu> writes:

> See also R-devel '[Rd] Suggestion for memory optimization and
> as.double() with friends', March 28-29 2007
> [https://stat.ethz.ch/pipermail/r-devel/2007-March/045109.html].
>
> /Henrik

Interesting thread. So we have you to thank for instigating that 5 years ago:
thanks!

Matthew

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Loading...