2014-07-23 24 views
5

Jestem absolutnym Rcpp -begner, więc proszę was, ostrzeżcie, że wkrótce pojawi się pytanie początkującego.Jak zadeklarować wejście do funkcji Rcpp?

Rozważmy przykład:

#include <Rcpp.h> 
using namespace Rcpp; 
// [[Rcpp::export]] 
NumericMatrix mat_1(NumericMatrix X){ 
do.stuff.with.X 
} 

Mi się, że definiuje funkcję mat_1 w obszarze roboczym R, które ma matrycę liczbową na wejściu i zwraca matrycę numerycznej w końcu. Jednakże looking e.g. here I rozumie, że można również określić

SEXP mat_2(SEXP X){ 
Rcpp::NumericMatrix x(X);     
do.stuff.with.x 
} 

lub alternatywnie

SEXP mat_3(SEXP X){ 
NumericMatrix x(as<NumericMatrix>(X)) 
do.stuff.with.x 
} 

Mi się, że określa wyjście funkcji jako S-ekspresji, i wymaga S ekspresję jako wejście, które jest wewnętrznie przekonwertowane (?) na macierz numeryczną.

Teraz looking at this document, który był bardzo cennym źródłem do mnie, ja dowiedziałem się, że mogę również napisać

NumericMatrix mat_4(NumericMatrix X&){ 
do.stuff.with.X 
} 

Tutaj mój zrozumienia jest to, że zamiast tworzenia kopii X, tym Rcpp -function używa odwołania do obiektu R. W rzeczywistości nie jestem pewien, czy rozumiem, co to oznacza. Czy nie było sensu używać SEXP, że nie wykonano żadnej kopii, czy też coś złego? Ponadto, jeśli oszczędza pamięć, a zatem jest bardziej wydajny, dlaczego miałbym kiedykolwiek użyć czegoś innego?

Jestem pewien, że przegapiłem kilka opcji. W każdym razie, moje wielkie pytanie jest następujące: z punktu widzenia użytkownika R (ja), wywołuję każdą funkcję mat_1, mat_2, mat_3 lub mat_4 dostarczając matrycę numeryczną (która jest obiektem R w moim obszarze roboczym, a zatem SEXP), i wydaje się, że powinienem otrzymać to samo wyjście (macierz numeryczna, która będzie z perspektywy SEXP z perspektywy R, prawda?). Byłbym wdzięczny za wskazówki dotyczące względnych zalet tych pozornie identycznych sposobów definiowania funkcji. Oznacza to, że przy założeniu, że wiemy dokładnie, jaka funkcja będzie wejście i wyjście co będzie,

  1. Dlaczego i kiedy ma się opłacać używać NumericMatrix zamiast SEXP dla argumentu, lub odwrotnie?
  2. Dlaczego i kiedy używać &?
  3. Jeśli wiem, że funkcja zwróci macierz numeryczną, czy istnieją powody, aby zadeklarować funkcję jako SEXP? Czy są powody, aby trzymać się NumericMatrix?

A może zupełnie nie rozumiem?

Co więcej, czy istnieje jakaś praktyczna różnica między konwersją użytą w mat_2 i mat_3? Czy są jakieś różnice między Rcpp::NumericMatrix x(X) i NumericMatrix x(as<NumericMatrix>(X))?

Wszelkie uwagi są mile widziane.

+0

Zadajesz tutaj kilka pytań, które łączą w sobie ogólne pytania dotyczące C++ ze szczegółami na temat Rcpp. SO ma wiele wspaniałych zasobów na temat tego pierwszego; wysyłamy osiem winiet z tą ostatnią, a następnie znajduje się również [książka na Rcpp] (http://www.rcpp.org/book). –

+0

Zgadzam się. Mam jeden problem polegający na tym, że nie mogę łatwo odróżnić specyfikacji Rcpp od C++, ponieważ znam tylko C++ przez Rcpp, ale zdaję sobie sprawę, że jest to problem przy zadawaniu pytań. – coffeinjunky

+1

Jestem świadomy winiet i książki. Są to ogromne zasoby, a przykłady na tej stronie pomogły mi zacząć, ale uważam, że książka, w szczególności, wymaga dużej wiedzy w tle, co utrudnia czytanie na konkretny temat. Jest to problematyczne, jeśli naprawdę nie wiesz, czego szukasz, co moim zdaniem jest typowym problemem dla początkujących. Jeśli jednak mógłbyś wskazać mi konkretną winietę, w której znajdę odpowiedzi na powyższe pytanie (może nawet konkretna sekcja lub słowo kluczowe, którego powinienem szukać), doceniłbym to. – coffeinjunky

Odpowiedz

5

W porządku. Próbuję podać jakieś wskazówki.Po pierwsze, jeśli jesteś początkującym, dobrze się z pierwszą funkcją, użyj mat_1. Gdy twoje umiejętności się poprawią, możesz zrozumieć niektóre różnice między mat_1, a drugą, i ostatecznie przejść do ... użyć mat_1, ponieważ jest to ta, której chcesz użyć.

  1. Zawsze. Większość użytkowników nie powinna nigdy używać numeru SEXP.
  2. Nie ma to znaczenia w tym przypadku. Rcpp będzie wiedział, co zrobić z referencją, ale to, co się dzieje, jest prawie takie samo, tworzy obiekt lokalnie i daje do niego odniesienie. Rozróżnienie pomiędzy wartością przekazywaną przez wartość i przez odniesienie ma znaczenie, jeśli użytkownik zadzwonił, aby zadzwonić pod numer mat_4 z innej funkcji C++.
  3. Jeśli znasz typ, użyj tego typu. To jest cały punkt Rcpp. SEXP to typ R dla wszystkich typów, jeśli zwrócisz SEXP, może to być cokolwiek, jeśli zwrócisz NumericMatrix wiesz, że dzięki zwróceniu matrycy numerycznej masz ogromną przewagę i prawie cały powód, dla którego istnieje Rcpp.

Pozwalam ci zdecydować, czy brakowało ci punktu.

Ogólnie rzecz biorąc as<> będzie starał się trudniej, ale to nie ma znaczenia w tym przypadku.

W skrócie: użyj mat_1. Jest jeszcze wiele innych rzeczy do nauczenia się, nie martw się o to jeszcze.

+0

Dzięki Romain! Doceniam twoją opinię. Bardzo szybka odpowiedź na moje pytanie: 1. [na podstawie tej odpowiedzi] (http://stackoverflow.com/questions/24781428/how-could-i-speed-up-this-rcpp-code/24782888#24782888), Rozumiem, że użycie 'SEXP' dla argumentów funkcji pozwala uniknąć kopii w pamięci. Jeśli mam bardzo duże macierze, powiedzmy, czy powinienem więc preferować użycie 'SEXP'? 2. Do twojego punktu 2, gdybym użył wyjścia 'mat_4' w innej funkcji' C++ '(co zrobię), czy wolałbym używać' & '? – coffeinjunky

+2

Nie ma dodatkowej pamięci w NumericMatrix poza SEXP, brak, zero. niezależnie od wielkości matrycy. Nie płacisz za NumericMatrix. Dostajesz jednak coś wygodnego w użyciu. W przypadku 2 tak naprawdę przekazanie matrycy według wartości jest tanie, ponieważ dane nie są kopiowane, a jedynie wskaźnik. Nie mogę powiedzieć nic więcej, biorąc pod uwagę przykład kodu 'do.stuff.with.X'. W przypadku typów Rcpp takich jak NumericMatrix, po prostu przekazuj je według wartości. –

+0

Ok, rozumiem. Dziękuję Romain za poświęcenie czasu, aby mi pomóc. Doceniam to! – coffeinjunky

Powiązane problemy