R: Преимущества использования подпрограммы Fortran с .Call и C/С++-оболочкой вместо .Fortran?
У меня есть R-пакет, который использует множество подпрограмм Fortran для вложенных циклов рекурсивных вычислений линейной алгебры (в зависимости от BLAS и LAPACK-подпрограмм). В качестве интерфейса с Fortran я использую функцию .Fortran
. Я просто прочитал сообщение Джонатана Каллахана об использовании .Call
вместо .C
в случае подпрограмм, написанных на C/С++, и это заставило меня думать, что это будет лучше использовать интерфейс .Call
также при использовании подпрограмм Fortran, написав простую оболочку в C, которая затем вызывает подпрограммы Fortran?
Как сказано, мои коды Fortran довольно просты в том смысле, что я просто играю с многомерными массивами типа double или integer. Но я узнал, что я должен написать довольно много проверок на стороне R, чтобы гарантировать, что все не сбой из-за того, что я случайно забыл изменить режим хранения какой-либо матрицы на целое число или размеры какой-либо матрицы были изменены и т.д.
Подпрограммы записываются как F90/95.
Ответы
Ответ 1
Если вы работаете с большим набором данных, может быть преимущество..Call может быть намного быстрее, потому что вы не копируете данные каждый раз, когда вызываете функцию. В случае, описанном в этом вопросе, такого преимущества не будет, поскольку в примечаниях к выпуску R 2.15.1 указано
.C() и .Fortran() делают меньше копий: аргументы, которые являются необработанными, логическими, целочисленными, реальными или сложными векторами и являются неназванными, не копируются перед вызовом и (именованные или нет) не копируются после вызов. Списки больше не копируются (они должны использоваться только для чтения в коде C).
Переключение на .Call означает, что вы отказываетесь от удобства интерфейса .Fortran. Вы передавали бы SEXP в код C, делали какие-либо проверки/манипулирования данными с помощью (пугающего и плохо документированного) R API, а затем вызывали функцию Fortran из C. Любой, кто работает с вашим кодом, должен будет понять R API и C/Fortran.
Ответ 2
R пакет dotCall64 может быть интересной альтернативой. Он предоставляет .C64()
который является расширенной версией интерфейса внешних функций, то есть .C()
и .Fortran()
.
Интерфейс .C64()
может использоваться для взаимодействия как кода Fortran, так и кода C/C++. Это
- имеет аналогичное использование как
.C()
и .Fortran()
- предоставляет механизм, позволяющий избежать ненужных копий аргументов только для чтения и только для записи
- поддерживает длинные векторы (векторы с более чем 2 ^ 31-1 элементов)
- поддерживает аргументы 64-битного целого типа
Следовательно, можно избежать ненужных копий аргументов только для чтения, избегая интерфейса .Call()
в сочетании с функцией-оболочкой C.
Некоторые ссылки:
Я один из авторов dotCall64 и спама.