如何从R调用一个rust函数返回Vec〈Vec< f64>>?

zwghvu4y  于 2023-03-10  发布在  其他
关注(0)|答案(1)|浏览(181)

我在Rust中实现了一个从M个不同的正态分布中采样N次的函数,因为我的R代码太慢了。它也是并行的。下面是纯Rust代码:

use rand_distr::{Normal, Distribution};
    use rayon::prelude::*;

    fn rust_rprednorm(n: i32, means: Vec<f64>, sds: Vec<f64>) -> Vec<Vec<f64>> {

        let mut preds = vec![vec![0.0; n as usize]; means.len()];

        preds.par_iter_mut().enumerate().for_each(|(i, e)| {
            let mut rng = rand::thread_rng();
            (0..n).into_iter().for_each(|j| {
                let normal = Normal::new(means[i], sds[i]).unwrap();
                e[j as usize] = normal.sample(&mut rng);
            })
        });

        preds
    }

我正尝试使用rextendr库从R调用它,代码在我使用source()导入的utils.R文件中:

code <- r"(
    use rand_distr::{Normal, Distribution};
    use rayon::prelude::*;

    #[extendr]
    fn rust_rprednorm(n: i32, means: Vec<f64>, sds: Vec<f64>) -> Vec<Vec<f64>> {

        let mut preds = vec![vec![0.0; n as usize]; means.len()];

        preds.par_iter_mut().enumerate().for_each(|(i, e)| {
            let mut rng = rand::thread_rng();
            (0..n).into_iter().for_each(|j| {
                let normal = Normal::new(means[i], sds[i]).unwrap();
                e[j as usize] = normal.sample(&mut rng);
            })
        });

        preds
    }
)"

rust_source(code = code, dependencies = list(`rand` = "0.8.5", `rand_distr` ="0.4.3", `rayon` = "1.6.1"))

错误为:

Error in `invoke_cargo()`:
! Rust code could not be compiled successfully. Aborting.
✖ error[E0277]: the trait bound `Robj: From<Vec<Vec<f64>>>` is not satisfied
 --> src\lib.rs:6:5
  |
6 |     #[extendr]
  |     ^^^^^^^^^^ the trait `From<Vec<Vec<f64>>>` is not implemented for `Robj`
  |
  = help: the following other types implement trait `From<T>`:
            <Robj as From<&'a [T]>>
            <Robj as From<&Altrep>>
            <Robj as From<&Primitive>>
            <Robj as From<&Robj>>
            <Robj as From<&Vec<T>>>
            <Robj as From<&extendr_api::Complexes>>
            <Robj as From<&extendr_api::Doubles>>
            <Robj as From<&extendr_api::Environment>>
          and 71 others
  = note: this error originates in the attribute macro `extendr` (in Nightly builds, run with -Z macro-backtrace for more info)
✖ error: aborting due to previous error
Traceback:

1. source("inla_predictive_distribution_utils.R")
2. withVisible(eval(ei, envir))
3. eval(ei, envir)
4. eval(ei, envir)
5. rust_source(code = code, dependencies = list(rand = "0.8.5", 
 .     rand_distr = "0.4.3", rayon = "1.6.1"))
6. invoke_cargo(toolchain = toolchain, specific_target = specific_target, 
 .     dir = dir, profile = profile, quiet = quiet, use_rtools = use_rtools)
7. check_cargo_output(compilation_result, message_buffer, tty_has_colors(), 
 .     quiet)
8. ui_throw("Rust code could not be compiled successfully. Aborting.", 
 .     error_messages, call = call, glue_open = "{<{", glue_close = "}>}")
9. withr::with_options(list(warning.length = message_limit_bytes), 
 .     rlang::abort(message, class = "rextendr_error", call = call))
10. force(code)
11. rlang::abort(message, class = "rextendr_error", call = call)
12. signal_abort(cnd, .file)

我认为嵌套向量会被支持,因为常规向量是,但它似乎不是,我需要为Robj实现这个特性吗,或者有其他方法吗?我也不确定这是否是从R调用Rust代码的推荐方法。

ljsrvy3e

ljsrvy3e1#

您不能返回类似Vec<Vec<T>>的内容,因为R并不真正理解这些内容。

  • 如果输出为矩形,则为某种2d矩阵
  • 有一个Rmatrix类型就是用于此目的的
  • ndarray的支持有限,ndarray也转换为R矩阵
  • 如果输出为交错数组,则为包含Vec<T>元素的List

相关问题