|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
| Powered by Nabble | Edit this page |
