From maechler at lynne.stat.math.ethz.ch  Tue Mar  3 09:59:28 2015
From: maechler at lynne.stat.math.ethz.ch (Martin Maechler)
Date: Tue, 3 Mar 2015 09:59:28 +0100
Subject: [Rd] R-devel does not update the C++ returned variables
In-Reply-To: <54F4CF7F.4080808@fredhutch.org>
References: <CAHyAz7TOELUyX2XW=8Abvuz2tU0_ZXVuyx-B84RBk7TQyM-mAA@mail.gmail.com>
	<54F45105.40608@gmail.com>
	<CAHyAz7QvAyL-KgKp0B6pk=RDHAQs2LHeGS48HvATqZnbuoAfww@mail.gmail.com>
	<54F46F15.3030901@gmail.com>
	<21748.30477.886575.819346@max.nulle.part>
	<21748.33727.92491.976456@stat.math.ethz.ch>
	<54F4C587.5040501@ttk.mta.hu> <54F4CF7F.4080808@fredhutch.org>
Message-ID: <21749.30704.941749.320247@stat.math.ethz.ch>

>>>>> Herv? Pag?s <hpages at fredhutch.org>
>>>>>     on Mon, 2 Mar 2015 13:00:47 -0800 writes:

    > Hi,
    > On 03/02/2015 12:18 PM, D?nes T?th wrote:
    >> 
    >> 
    >> On 03/02/2015 04:37 PM, Martin Maechler wrote:
    >>> 
    >>>> On 2 March 2015 at 09:09, Duncan Murdoch wrote:
    >>>> | I generally recommend that people use Rcpp, which hides a lot of the
    >>>> | details.  It will generate your .Call calls for you, and generate the
    >>>> | C++ code that receives them; you just need to think about the real
    >>>> | problem, not the interface.  It has its own learning curve, but I
    >>>> think
    >>>> | it is easier than using the low-level code that you need to work
    >>>> with .Call.
    >>> 
    >>>> Thanks for that vote, and I second that.
    >>> 
    >>>> And these days the learning is a lot flatter than it was a decade ago:
    >>> 
    R> Rcpp::cppFunction("NumericVector doubleThis(NumericVector x) {
    >>>> return(2*x); }")
    R> doubleThis(c(1,2,3,21,-4))
    >>>> [1]  2  4  6 42 -8
    R> 
    >>> 
    >>>> That defined, compiled, loaded and run/illustrated a simple function.
    >>> 
    >>>> Dirk
    >>> 
    >>> Indeed impressive,  ... and it also works with integer vectors
    >>> something also not 100% trivial when working with compiled code.
    >>> 
    >>> When testing that, I've went a step further:
    >>> 
    >>> ##---- now "test":
    >>> require(microbenchmark)
    >>> i <- 1:10
    >> 
    >> Note that the relative speed of the algorithms also depends on the size
    >> of the input vector. i + i becomes the winner for longer vectors (e.g. i
    >> <- 1:1e6), but a proper Rcpp version is still approximately twice as fast.

    > The difference in speed is probably due to the fact that R does safe
    > arithmetic. C or C++ do not:

    >> doubleThisInt(i)
    > [1]  2147483642  2147483644  2147483646          NA -2147483646 
    > -2147483644

    >> 2L * i
    > [1] 2147483642 2147483644 2147483646         NA         NA         NA
    > Warning message:
    > In 2L * i : NAs produced by integer overflow

    > H.

Exactly, excellent, Herv?!    

Luke also told me so in a private message.
and 'i+i' is looking up 'i' twice  which is relatively costly
for very small i  as in my example.

This ("no safe integer arithmetic in C, but in R") is another
good example {as Martin Morgan's}  why using 
Rccp -- or .Call() directly -- may be a too sharp edged sword and
maybe should be advocated for good programmers only.

Martin


    >> 
    >> Rcpp::cppFunction("NumericVector doubleThisNum(NumericVector x) {
    >> return(2*x); }")
    >> Rcpp::cppFunction("IntegerVector doubleThisInt(IntegerVector x) {
    >> return(2*x); }")
    >> i <- 1:1e6
    >> mb <- microbenchmark::microbenchmark(doubleThisNum(i), doubleThisInt(i),
    >> i*2, 2*i, i*2L, 2L*i, i+i, times=100)
    >> plot(mb, log="y", notch=TRUE)
    >> 
    >> 
    >>> (mb <- microbenchmark(doubleThis(i), i*2, 2*i, i*2L, 2L*i, i+i,
    >>> times=2^12))
    >>> ## Lynne (i7; FC 20), R Under development ... (2015-03-02 r67924):
    >>> ## Unit: nanoseconds
    >>> ##           expr min  lq      mean median   uq   max neval cld
    >>> ##  doubleThis(i) 762 985 1319.5974   1124 1338 17831  4096   b
    >>> ##          i * 2 124 151  258.4419    164  221 22224  4096  a
    >>> ##          2 * i 127 154  266.4707    169  216 20213  4096  a
    >>> ##         i * 2L 143 164  250.6057    181  234 16863  4096  a
    >>> ##         2L * i 144 177  269.5015    193  237 16119  4096  a
    >>> ##          i + i 152 183  272.6179    199  243 10434  4096  a
    >>> 
    >>> plot(mb, log="y", notch=TRUE)
    >>> ## hmm, looks like even the simple arithm. differ slightly ...
    >>> ##
    >>> ## ==> zoom in:
    >>> plot(mb, log="y", notch=TRUE, ylim = c(150,300))
    >>> 
    >>> dev.copy(png, file="mbenchm-doubling.png")
    >>> dev.off() # [ <- why do I need this here for png ??? ]
    >>> ##--> see the appended *png graphic
    >>> 
    >>> Those who've learnt EDA or otherwise about boxplot notches, will
    >>> know that they provide somewhat informal but robust pairwise tests on
    >>> approximate 5% level.
    >>> From these, one *could* - possibly wrongly - conclude that
    >>> 'i * 2' is significantly faster than both 'i * 2L' and also
    >>> 'i + i' ---- which I find astonishing, given that  i is integer here...
    >>> 
    >>> Probably no reason for deep thoughts here, but if someone is
    >>> enticed, this maybe slightly interesting to read.
    >>> 
    >>> Martin Maechler, ETH Zurich
    >>> 
    >>> 
    >>> 
    >>> ______________________________________________
    >>> R-devel at r-project.org mailing list
    >>> https://stat.ethz.ch/mailman/listinfo/r-devel
    >>> 
    >> 
    >> ______________________________________________
    >> R-devel at r-project.org mailing list
    >> https://stat.ethz.ch/mailman/listinfo/r-devel

    > -- 
    > Herv? Pag?s

    > Program in Computational Biology
    > Division of Public Health Sciences
    > Fred Hutchinson Cancer Research Center
    > 1100 Fairview Ave. N, M1-B514
    > P.O. Box 19024
    > Seattle, WA 98109-1024

    > E-mail: hpages at fredhutch.org
    > Phone:  (206) 667-5791
    > Fax:    (206) 667-1319



[Rd] R-devel does not update the C++ returned variables
Martin Maechler