Recentemente ho sperimentato con Rcpp (inline) per generare DLL che eseguono varie attività sugli ingressi R forniti. Mi piacerebbe essere in grado di eseguire il debug del codice in queste DLL riga per riga, dato un set specifico di input R. (sto lavorando in ambiente Windows.)Debug (riga per riga) della DLL generata da Rcpp in Windows
Per illustrare, prendiamo in considerazione un esempio specifico che chiunque dovrebbe essere in grado di eseguire ...
Il codice qui sotto è davvero semplice cxxfunction che raddoppia semplicemente il vettore di input . Si noti tuttavia che esiste una variabile aggiuntiva myvar
che modifica il valore alcune volte ma non influisce sull'output: è stato aggiunto in modo che sia possibile vedere quando il processo di debug è in esecuzione correttamente.
library(inline)
library(Rcpp)
f0 <- cxxfunction(signature(a="numeric"), plugin="Rcpp", body='
Rcpp::NumericVector xa(a);
int myvar = 19;
int na = xa.size();
myvar = 27;
Rcpp::NumericVector out1(na);
for(int i=0; i < na; i++) {
out1[i] = 2*xa[i];
myvar++;
}
myvar = 101;
return(Rcpp::List::create(_["out1"] = out1));
')
Dopo corriamo quanto sopra, digitando il comando
getLoadedDLLs()
viene visualizzato un elenco di DLL nella sessione R. L'ultimo elencato dovrebbe essere la DLL creata dal processo di cui sopra - ha un nome temporaneo casuale, che nel mio caso è
file7e61645c
La colonna "Nome file" mostra che cxxfunction ha messo questa DLL nella posizione tempdir()
, che per me è attualmente
C:/Users/TimP/AppData/Local/Temp/RtmpXuxtpa/file7e61645c.dll
Ora, il modo più ovvio per chiamare la DLL è via f0
, come segue
> f0(c(-7,0.7,77))
$out1
[1] -14.0 1.4 154.0
Ma possiamo naturalmente anche chiamare la DLL direttamente in base al nome utilizzando il comando .Call
:
> .Call("file7e61645c",c(-7,0.7,77))
$out1
[1] -14.0 1.4 154.0
Così ho raggiunto il punto in cui sto chiamando una DLL standalone direttamente con ingresso R (qui, il vettore c(-7,0.7,77)
), e di averlo ritorno la risposta corretta a R.
quello che ho veramente bisogno, però, è una struttura per la linea per linea il debugging (usando gdb, presumo) che mi permetterà di osservare il valore di myvar
essere impostato su 19, 27, 28, 29, 30 e infine 101 mentre il codice progredisce. L'esempio sopra è impostato deliberatamente in modo che la chiamata alla DLL non ci dica nulla su myvar.
Per chiarire, la "condizione di vincita" qui è in grado di osservare il cambiamento di myvar (vedere il valore myvar = 19 sarebbe il primo passo!) Senza aggiungere altro al corpo del codice. Questo ovviamente potrebbe richiedere delle modifiche al modo in cui il codice è compilato (ci sono le impostazioni della modalità di debug per attivare?), O il modo in cui viene chiamato R - ma non so da dove cominciare. Come notato sopra, tutto questo è basato su Windows.
Nota finale: Nei miei esperimenti, in realtà ho fatto alcune piccole modifiche a una copia di cxxfunction modo che l'uscita DLL - e il codice al suo interno - riceve un nome definito dall'utente e si siede in una directory definita dall'utente, piuttosto di un nome e una posizione temporanei. Ma questo non influisce sull'essenza della domanda.Lo dico solo per sottolineare che dovrebbe essere abbastanza semplice modificare le impostazioni della compilation se qualcuno mi dà una spinta :)
Per completezza, l'impostazione verbose = TRUE nella chiamata cxxfunction originale sopra mostra l'argomento della compilazione per essere del seguente modulo:
C:/R/R-2.13.2/bin/i386/R CMD SHLIB file7e61645c.cpp 2> file7e61645c.cpp.err.txt
g++ -I"C:/R/R-213~1.2/include" -I"C:/R/R-2.13.2/library/Rcpp/include" -O2 -Wall -c file7e61645c.cpp -o file7e61645c.o
g++ -shared -s -static-libgcc -o file7e61645c.dll tmp.def file7e61645c.o C:/R/R-2.13.2/library/Rcpp/lib/i386/libRcpp.a -LC:/R/R-213~1.2/bin/i386 -lR
la mia versione adattata ha un argomento compilation identico al precedente, tranne che la stringa "file7e61645c" è sostituito ovunque dalla scelta dell'utente di nome (ad esempio "testdll") i file e le relative copiati in una posizione più permanente.
Grazie in anticipo per il vostro aiuto ragazzi :)
Non posso aiutare direttamente, ma so che Dirk ecc. È sempre utile. Tuttavia generalmente fanno affari sulla [lista email di Rcpp] (http://lists.r-forge.r-project.org/mailman/listinfo/rcpp-devel) –
hanno fatto alcuni lievi progressi su questo, quindi un breve aggiornamento . Giocando con inline ::: compileCode, che viene chiamato all'interno di cxxfunction, ho scoperto che l'aggiunta di '--debug' alla fine di' R CMD SHLIB' mi ha permesso di esaminare cosa succede all'interno della DLL combinando gdb e R. HOWEVER , questa non è una soluzione completa in quanto alcune variabili erano inaccessibili (come 'i', durante il ciclo su' i'); è arrivato il messaggio che erano stati "ottimizzati". Penso quindi di dover sostituire "-O2" con "-O0" nell'argomento della compilation ... ma non ho idea di come farlo accadere ... –
Ho raccolto un bel po 'di prove che tutto quello che devo fare è cambiare i flag del compilatore R CMD SHLIB da -O2 a qualcosa come -g -O0 ... ad es. vedere il post su https://stat.ethz.ch/pipermail/r-devel/2008-November/051390.html - ma mi manca una dichiarazione precisa su cosa è necessario specificare e come. Alcune fonti online menzionano la creazione di un file a '/.R/Makevars.win' ma non descrivono il file, e questa non è una posizione valida in Windows a causa del punto prima della lettera R ... –