#c #r #rcpp #futhark
#c #r #rcpp #футарк
Вопрос:
Я хотел бы вызывать функции, написанные на небольшом функциональном языке программирования Futhark на R через Rcpp. Это работает, потому что компилятор Futhark может генерировать код C, а библиотеки C могут быть доступны в R через Rcpp.
Мне удалось создать рабочий прототип здесь: https://github.com/nevrome/R.futhark.example
Теперь мне интересно, смогу ли я упростить цикл разработки и уменьшить количество шаблонного / оберточного кода, который я должен вручную писать для отдельных функций.
Вот мой общий рабочий процесс (Futhark -> C -> C -> R) с примером:
futhark_test.fut: файл кода Futhark, написанный вручную. Он компилируется в C (futhark_test.h и futhark_test.c) с помощью компилятора Futhark ( futhark c --library ...
)
let main (x: i32) (y: i32): i32 =
x * 2 y * 3
futhark_bridge_c_cpp.c: код C для переноса функции C в futhark_test.c, созданный компилятором Futhark
#include <R.h>
#include <Rinternals.h>
#include "futhark_test.h"
int32_t futhark_entry_main_c(int32_t a, int32_t b) {
struct futhark_context_config *cfg = futhark_context_config_new();
struct futhark_context *ctx = futhark_context_new(cfg);
int32_t res;
futhark_entry_main(ctx, amp;res, a, b);
return res;
}
futhark_bridge_rcpp.cpp : C код для переноса функции C и управления взаимодействием с R
#include "Rcpp.h"
using namespace Rcpp;
extern "C" int32_t futhark_entry_main_c(int32_t a, int32_t b);
//' Call C function
//' @export
// [[Rcpp::export]]
SEXP futhark_entry_main_cpp(SEXP a, SEXP b) {
int32_t a_mod = Rcpp::as<int32_t>(a);
int32_t b_mod = Rcpp::as<int32_t>(b);
int32_t ab = futhark_entry_main_c(a_mod, b_mod);
return Rcpp::wrap(ab);
}
Rcpp автоматически ( Rcpp::compileAttributes()
) создает RcppExports.cpp и RcppExports.R из futhark_bridge_rcpp.cpp и я могу вызвать функцию, первоначально написанную на Футарке, через futhark_entry_main_cpp(1, 2)
in R.
Чтобы автоматизировать процесс разработки, я создал сборку R-скрипта.R со следующей последовательностью команд
devtools::document()
Rcpp::compileAttributes()
system("cd src amp;amp; futhark c --library futhark_test.fut")
devtools::install()
Это позволяет мне изменять код Futhark, запускать эти команды, а затем проверять результат в R. Конечно, только если я не изменяю интерфейс функции Futhark. Если я это сделаю, мне придется редактировать как код C, так и код-оболочку C .
Есть ли способ уменьшить сложность этого процесса и есть ли у моего решения какие-либо очевидные недостатки?
Комментарии:
1. Я думаю, что это разумный вопрос. Я также думаю, что разумно задать вопрос «почему вы это делаете?». Кажется маловероятным, что эффективность, о которой говорится на домашней странице futhark, переживет поездку через C transpiler и компилятор c . Я готов поспорить, что компилятор C умнее, чем futhark -> C transpiler при оптимизации кода. То, что вы делаете, довольно сложно, и я думаю, что ваш рабочий процесс просто соответствует этому. Я не думаю, что существует простой способ разрешить изменение интерфейса вашей функции futhark без изменения вашего кода на C . Для меня это выглядит нормально.
2. Хорошо — большое вам спасибо за эту оценку! Приятно знать, что я не упустил из виду никаких очевидных вещей и могу продолжать экспериментировать! Я делаю это в основном для того, чтобы немного лучше ознакомиться с функциональным программированием, а интеграция с R помогает мне использовать Futhark в других побочных проектах. Конечно, я надеялся, что смогу получить доступ к его функциям распараллеливания, но я понимаю ваш аргумент о том, что я, скорее всего, потеряю эффективность. Это нормально — скорость не была моей главной заботой.
3. R также имеет интерфейс к OpenCL , поэтому вы также можете использовать компилятор Futhark -> OpenCL.
4. Круто! Это может сделать это усилие действительно полезным с точки зрения производительности, или?