[Rcpp-commits] r2208 - in pkg/Rcpp/inst: . examples/performance include include/Rcpp/traits include/Rcpp/vector
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Mon Sep 27 15:10:33 CEST 2010
Author: romain
Date: 2010-09-27 15:10:33 +0200 (Mon, 27 Sep 2010)
New Revision: 2208
Added:
pkg/Rcpp/inst/include/Rcpp/traits/is_sugar_expression.h
Modified:
pkg/Rcpp/inst/ChangeLog
pkg/Rcpp/inst/examples/performance/extractors.R
pkg/Rcpp/inst/include/Rcpp/traits/matrix_interface.h
pkg/Rcpp/inst/include/Rcpp/vector/Vector.h
pkg/Rcpp/inst/include/Rcpp/vector/VectorBase.h
pkg/Rcpp/inst/include/RcppCommon.h
Log:
speedup in Vector::operator=( sugar expression )
Modified: pkg/Rcpp/inst/ChangeLog
===================================================================
--- pkg/Rcpp/inst/ChangeLog 2010-09-27 10:22:26 UTC (rev 2207)
+++ pkg/Rcpp/inst/ChangeLog 2010-09-27 13:10:33 UTC (rev 2208)
@@ -1,3 +1,11 @@
+2010-09-27 Romain Francois <romain at r-enthusiasts.com>
+
+ * inst/include/Rcpp/traits/is_sugar_expression.h: new trait class
+ to recognize sugar expressions
+
+ * inst/include/Rcpp/vector/Vector.h: operator=( sugar expression)
+ no longer allocate unnecessary memory.
+
2010-09-26 Romain Francois <romain at r-enthusiasts.com>
* inst/include/Rpp/Fast.h: new helper class Rcpp::Fast that allows
Modified: pkg/Rcpp/inst/examples/performance/extractors.R
===================================================================
--- pkg/Rcpp/inst/examples/performance/extractors.R 2010-09-27 10:22:26 UTC (rev 2207)
+++ pkg/Rcpp/inst/examples/performance/extractors.R 2010-09-27 13:10:33 UTC (rev 2208)
@@ -33,7 +33,12 @@
list(
direct = signature( x_ = "numeric", y_ = "numeric" ),
extractor = signature( x_ = "numeric", y_ = "numeric" ),
- sugar_nona = signature( x_ = "numeric", y_ = "numeric" )
+ sugar_nona = signature( x_ = "numeric", y_ = "numeric" ),
+
+ assign_direct = signature( x_ = "numeric", y_ = "numeric" ),
+ assign_extractor = signature( x_ = "numeric", y_ = "numeric" ),
+ assign_sugar_nona = signature( x_ = "numeric", y_ = "numeric" )
+
) ,
list(
direct = '
@@ -53,23 +58,61 @@
for( int j=0; j<1000; j++)
res = sugar_nona__( x_, y_ ) ;
return res ;
+ ',
+
+ assign_direct = '
+ NumericVector x( x_ ), y( y_ ), z( x.size() ) ;
+ int n = x.size() ;
+ for( int j=0; j<1000; j++)
+ for( int i=0; i<n; i++)
+ z[i] = x[i] * y[i] ;
+ return z ;
+ ',
+
+ assign_extractor = '
+ NumericVector x( x_ ), y( y_ ), z( x.size() ) ;
+ Fast<NumericVector> fx(x), fy(y), fz(z) ;
+ int n = x.size() ;
+ for( int j=0; j<1000; j++)
+ for( int i=0; i<n; i++)
+ fz[i] = fx[i] * fy[i] ;
+ return z ;
+ ',
+
+ assign_sugar_nona = '
+ NumericVector x( x_ ), y( y_ ), z( x.size() ) ;
+ sugar::Nona< REALSXP, true, NumericVector > nx(x), ny(y) ;
+ for( int j=0; j<1000; j++)
+ z = nx * ny ;
+ return z ;
'
) , plugin = "Rcpp", includes = inc )
-x <- rnorm( 1000000 )
-y <- rnorm( 1000000 )
+x <- rnorm( 100000 )
+y <- rnorm( 100000 )
# resolving
-invisible( { fx$direct( 1.0, 1.0 ); fx$extractor( 1.0, 1.0 ); fx$sugar_nona(1.0, 1.0 )} )
-
+invisible( getDynLib( fx ) )
+
require( rbenchmark )
+
benchmark(
fx$direct( x, y ),
fx$extractor( x, y ),
fx$sugar_nona( x, y ),
+
replications = 1,
columns=c("test", "elapsed", "relative", "user.self", "sys.self"),
order="relative"
)
+benchmark(
+ fx$assign_direct( x, y ),
+ fx$assign_extractor( x, y ),
+ fx$assign_sugar_nona( x, y ),
+
+ replications = 1,
+ columns=c("test", "elapsed", "relative", "user.self", "sys.self"),
+ order="relative"
+)
Added: pkg/Rcpp/inst/include/Rcpp/traits/is_sugar_expression.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/traits/is_sugar_expression.h (rev 0)
+++ pkg/Rcpp/inst/include/Rcpp/traits/is_sugar_expression.h 2010-09-27 13:10:33 UTC (rev 2208)
@@ -0,0 +1,49 @@
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 4 -*-
+//
+// is_sugar_expression.h: Rcpp R/C++ interface class library --
+//
+// Copyright (C) 2010 Dirk Eddelbuettel and Romain Francois
+//
+// This file is part of Rcpp.
+//
+// Rcpp is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 2 of the License, or
+// (at your option) any later version.
+//
+// Rcpp is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef Rcpp__traits__is_sugar_expression_h
+#define Rcpp__traits__is_sugar_expression_h
+
+namespace Rcpp{
+namespace traits{
+
+ template<typename T>
+ class _is_sugar_expression_helper : __sfinae_types {
+ template<typename U> struct _Wrap_type { };
+
+ template<typename U>
+ static __one __test(_Wrap_type<typename U::rcpp_sugar_expression>*);
+
+ template<typename U>
+ static __two __test(...);
+
+ public:
+ static const bool value = sizeof(__test<T>(0)) == 1;
+ };
+
+ template<typename T> struct is_sugar_expression :
+ integral_constant<bool, _is_sugar_expression_helper<T>::value >{ };
+
+
+}
+}
+
+#endif
Modified: pkg/Rcpp/inst/include/Rcpp/traits/matrix_interface.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/traits/matrix_interface.h 2010-09-27 10:22:26 UTC (rev 2207)
+++ pkg/Rcpp/inst/include/Rcpp/traits/matrix_interface.h 2010-09-27 13:10:33 UTC (rev 2208)
@@ -29,14 +29,6 @@
namespace Rcpp{
namespace traits{
- template <int RTYPE>
- struct matrix_interface__impl{} ;
-
- template <>
- struct matrix_interface__impl<LGLSXP> {
- struct r_matrix_interface{};
- } ;
-
template<typename T>
class _has_matrix_interface_helper : __sfinae_types {
template<typename U> struct _Wrap_type { };
Modified: pkg/Rcpp/inst/include/Rcpp/vector/Vector.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/vector/Vector.h 2010-09-27 10:22:26 UTC (rev 2207)
+++ pkg/Rcpp/inst/include/Rcpp/vector/Vector.h 2010-09-27 13:10:33 UTC (rev 2208)
@@ -22,6 +22,8 @@
#ifndef Rcpp__vector__Vector_h
#define Rcpp__vector__Vector_h
+// template <int RTYPE, typename VEC, typename T> class Assigner ;
+
template <int RTYPE>
class Vector :
public RObject,
@@ -51,7 +53,7 @@
}
Vector& operator=( const Vector& other ){
- RObject::setSEXP( other.asSexp() ) ;
+ set_sexp( other.asSexp() ) ;
return *this ;
}
@@ -62,15 +64,58 @@
Vector( const RObject::AttributeProxy& proxy ) throw(not_compatible) {
RObject::setSEXP( r_cast<RTYPE>( proxy ) ) ;
}
-
+
template <typename T>
Vector& operator=( const T& x){
- // TODO: wrap will reallocate the memory. we can definitely avoid that
- // if this is of the same size as the target
- RObject::setSEXP( r_cast<RTYPE>( wrap(x) ) ) ;
- return *this ;
+ assign_object( x, typename traits::is_sugar_expression<T>::type() ) ;
+ return *this ;
}
+private:
+
+ // sugar
+ template <typename T>
+ inline void assign_object( const T& x, traits::true_type ){
+ int n = size() ;
+ if( n == x.size() ){
+
+ // just copy the data
+ iterator start = begin() ;
+
+ int __trip_count = n >> 2 ;
+ int i = 0 ;
+ for ( ; __trip_count > 0 ; --__trip_count) {
+ start[i] = x[i] ; i++ ;
+ start[i] = x[i] ; i++ ;
+ start[i] = x[i] ; i++ ;
+ start[i] = x[i] ; i++ ;
+ }
+ switch (n - i){
+ case 3:
+ start[i] = x[i] ; i++ ;
+ case 2:
+ start[i] = x[i] ; i++ ;
+ case 1:
+ start[i] = x[i] ; i++ ;
+ case 0:
+ default:
+ {}
+ }
+ } else{
+ // different size, so we change the memory
+ set_sexp( r_cast<RTYPE>( wrap(x) ) );
+ }
+ }
+
+ // anything else
+ template <typename T>
+ inline void assign_object( const T& x, traits::false_type ){
+ // TODO: maybe we already have the memory to host the results
+ set_sexp( r_cast<RTYPE>( wrap(x) ) ) ;
+ }
+
+public:
+
internal::ListInitialization<iterator,init_type> operator=( init_type x){
iterator start = begin() ; *start = x;
return internal::ListInitialization<iterator,init_type>( start + 1 ) ; ;
@@ -470,10 +515,12 @@
}
+public:
void set_sexp(SEXP x){
RObject::setSEXP( x) ;
update_vector() ;
}
+private:
void push_back__impl(const stored_type& object){
int n = size() ;
@@ -744,4 +791,69 @@
} ; /* Vector */
+// template <int RTYPE, typename VEC, typename T>
+// class Assigner{
+// public:
+//
+// Assigner( VEC& target_, const T& source_ ) : target(target_), source(source_){
+// Rprintf( "Assigner wrap ( %s )\n", DEMANGLE(Assigner) ) ;
+// }
+//
+// inline void assign(){
+// target.set_sexp( r_cast<RTYPE>( wrap(source) ) );
+// }
+//
+// private:
+// VEC& target ;
+// const T& source ;
+// } ;
+//
+// template <int RTYPE, typename VEC, bool SOURCE_NA, typename SOURCE_T>
+// class Assigner<RTYPE,VEC, VectorBase<RTYPE,SOURCE_NA,SOURCE_T> >{
+// public:
+//
+// typedef VectorBase<RTYPE,SOURCE_NA,SOURCE_T> T ;
+//
+// Assigner( VEC& target_, const T& source_ ) : target(target_), source(source_){
+// Rprintf( "Assigner sugar ( %s )\n", DEMANGLE(Assigner) ) ;
+// }
+//
+// inline void assign(){
+// int n = target.size() ;
+// if( n == source.size() ){
+//
+// const SOURCE_T& ref = source.get_ref() ;
+// // just copy the data
+// typename VEC::iterator start = target.begin() ;
+//
+// int __trip_count = n >> 2 ;
+// int i = 0 ;
+// for ( ; __trip_count > 0 ; --__trip_count) {
+// start[i] = ref[i] ; i++ ;
+// start[i] = ref[i] ; i++ ;
+// start[i] = ref[i] ; i++ ;
+// start[i] = ref[i] ; i++ ;
+// }
+// switch (n - i){
+// case 3:
+// start[i] = ref[i] ; i++ ;
+// case 2:
+// start[i] = ref[i] ; i++ ;
+// case 1:
+// start[i] = ref[i] ; i++ ;
+// case 0:
+// default:
+// {}
+// }
+// } else{
+// target.set_sexp( r_cast<RTYPE>( wrap(source) ) );
+// }
+// }
+//
+// private:
+// VEC& target ;
+// const T& source ;
+//
+// } ;
+
#endif
Modified: pkg/Rcpp/inst/include/Rcpp/vector/VectorBase.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/vector/VectorBase.h 2010-09-27 10:22:26 UTC (rev 2207)
+++ pkg/Rcpp/inst/include/Rcpp/vector/VectorBase.h 2010-09-27 13:10:33 UTC (rev 2208)
@@ -28,7 +28,8 @@
template <int RTYPE, bool na, typename VECTOR>
class VectorBase : public traits::expands_to_logical__impl<RTYPE> {
public:
- struct r_type : traits::integral_constant<int,RTYPE>{} ;
+ struct rcpp_sugar_expression{} ;
+ struct r_type : traits::integral_constant<int,RTYPE>{} ;
struct can_have_na : traits::integral_constant<bool,na>{} ;
typedef typename traits::storage_type<RTYPE>::type stored_type ;
typedef typename traits::storage_type<RTYPE>::type elem_type ;
Modified: pkg/Rcpp/inst/include/RcppCommon.h
===================================================================
--- pkg/Rcpp/inst/include/RcppCommon.h 2010-09-27 10:22:26 UTC (rev 2207)
+++ pkg/Rcpp/inst/include/RcppCommon.h 2010-09-27 13:10:33 UTC (rev 2208)
@@ -224,6 +224,7 @@
#include <Rcpp/traits/has_iterator.h>
#include <Rcpp/traits/expands_to_logical.h>
#include <Rcpp/traits/matrix_interface.h>
+#include <Rcpp/traits/is_sugar_expression.h>
#include <Rcpp/traits/has_na.h>
#include <Rcpp/traits/storage_type.h>
#include <Rcpp/traits/r_sexptype_traits.h>
More information about the Rcpp-commits
mailing list