2013-10-10 5 views
4

У меня есть программа, написанная на C++, которая вычисляет значения для функции правдоподобия, которая опирается на количество данных. Я хочу, чтобы иметь возможность вызывать функцию из R для запроса значений функции (расчеты потребовали бы много времени в R, а программа на C++ уже давно должна была его изменить, это примерно 150K строк кода).Связь между R и C++

Я могу сделать это, чтобы запросить одно значение, но тогда приложение C++ завершается, и я должен перезапустить его и снова загрузить все данные (это сделало это с помощью .c()). Загрузка занимает от 10 до 30 секунд, в зависимости от модели для функции правдоподобия и данных, и я думал, есть ли способ сохранить приложение C++ в ожидании запросов значений функций, поэтому у меня нет для чтения всех данных в память. Уже вычисление одного значения функции в приложении C++ занимает около полусекунды, что очень долго для C++.

Я думал об использовании pipe(), чтобы спросить вас, является ли это возможным вариантом, или я должен использовать какой-либо другой метод? Можно ли это сделать с помощью rcpp?

Я делаю это, чтобы проверить алгоритмы минимизации для R для этой функции.

+6

Может быть, посмотрите на Rcpp? http://cran.r-project.org/web/packages/Rcpp/index.html – juba

+0

Не может быть просто система («R Stuff»); от C++? Он похож на этот: [C вызов команды cmd] (http://stackoverflow.com/questions/5007268/call-linux-command-from-c-program) [Пример R] (http://stackoverflow.com/ вопросы/18306362/run-r-script-from-command-line) – alap

+0

трубы выглядят как вероятное решение, или, может быть, tcp-сервер? – 4pie0

ответ

7

Забудьте о .C. Это неуклюже. Возможно, использование .C над .Call или .External имело смысл перед Rcpp. Но теперь с работой, которую мы поставили в Rcpp, я больше не вижу смысла использовать .C. Просто используйте .Call.

еще лучше, с атрибутами (sourceCpp и compileAttributes), вы не должны даже больше, чтобы увидеть .Call, он просто чувствует, как вы используете функцию C++.

Теперь, если бы я хотел сделать что-то, что сохраняет состояния, я бы использовал модуль. Например, ваша заявка - это класс Test. Он имеет методы do_something и do_something_else и подсчитывает количество раз используются эти методы:

#include <Rcpp.h> 
using namespace Rcpp ; 

class Test { 
public: 
    Test(): count(0){} 

    void do_something(){ 
     // do whatever 
     count++ ; 
    } 
    void do_something_else(){ 
     // do whatever 
     count++ ; 
    } 

    int get_count(){ 
     return count ; 
    } 

private: 
    int count ; 
} ; 

Это довольно стандартный C++ до сих пор.Теперь, чтобы сделать его доступным для R, необходимо создать модуль, как это:

RCPP_MODULE(test){ 
    class_<Test>("Test") 
     .constructor() 
     .method("do_something", &Test::do_something) 
     .method("do_something_else", &Test::do_something_else) 

     .property("count", &Test::get_count) 
    ; 
} 

И тогда вы можете просто использовать:

app <- new(Test) 
app$count 
app$do_something() 
app$do_something() 
app$do_something_else() 
app$count 
+0

Большое спасибо за ваш ответ, я думаю, что могу определенно с этим справиться, создав такой модуль! – Gumeo

1

Здесь есть несколько вопросов.

Каков наилучший способ вызова кода на C++ из R?

Как отмечают другие комментаторы, пакет Rcpp обеспечивает удобный интерфейс. Использование функции .Call из базы R также возможно, но не рекомендуется так же хорошо, как Rcpp.

Как остановить многократное пересылку данных между R и C++?

Вы просто хотите немного изменить структуру своего кода. Перепишите процедуру оболочки в C++, которая вызывает все существующие подпрограммы C++, и назовите это из R.

+1

Функция '.Call()' требуется *, поскольку интерфейс '.C()' ограничен, подвержен ошибкам и не должен использоваться - см. Например, Саймон Урбанек на r-devel несколько месяцев назад. –

+0

@DirkEddelbuettel Можете ли вы объяснить, почему '.C()' подвержен ошибкам, или опубликовать ссылку на сообщение r-devel от Саймона Урбанека? – mrip

+2

@mrip: Здесь вы идете. [R Основной член Саймон Урбанек на r-devel] (http://article.gmane.org/gmane.comp.lang.r.devel/31175): _ «Как обычно, могу только сказать, не используйте .C() «_ Я получил неверную дату: это было уже в 2012 году - время летит, но некоторые люди все же думают, что они должны использовать' .C() '. Это достаточно плохо, но, к сожалению, ухудшается, когда они наносят такие плохие идеи другим. –