【问题标题】:Is rJava object is exportable in future(Package for Asynchronous computing in R)rJava 对象将来是否可导出(R 中的异步计算包)
【发布时间】:2018-09-12 06:19:35
【问题描述】:

我正在尝试通过在 Linux 上使用多核计划来加速我的 R 代码。在未来的定义中,我正在创建一个 java 对象并尝试将其传递给 .jcall(),但将来我会为 java 对象获得一个空值。谁能帮我解决这个问题。下面是示例代码-

    library("future")
    plan(multicore)

    library(rJava)
    .jinit()

    # preprocess is a user defined function
    my_value <- preprocess(a = value){
      # some preprocessing task here
      # time consuming statistical analysis here
      return(lreturn) # return a list of 3 components
    }
    obj=.jnew("java.custom.class")

    f <- future({
      .jcall(obj, "V", "CustomJavaMethod", my_value)
    })

基本上我正在处理大型流数据。在上面的代码中,我将流数据字符串发送到用户定义的函数进行统计分析并返回 3 个组件的列表。然后想将此列表发送到自定义 java 类 [java.custom.class] 以使用自定义 Java 方法 [CustomJavaMethod] 进行进一步处理。 不使用未来我的代码运行良好。但是我在一分钟内获得了 12 条流记录,然后我的代码变慢了,观察到处理延迟。

目前我使用的是 16 核的 Unix。使用 future 包后,我的过程很快完成。我已经追溯了我的代码,在 .jcall 中发生了错误。

希望这能澄清我的痛苦。

【问题讨论】:

    标签: r parallel-processing rjava r-future


    【解决方案1】:

    (这里是未来包的作者:)

    不幸的是,R 中有某些类型的对象无法发送到另一个 R 进程进行进一步处理。澄清一下,这是对那些类型的对象的限制——而不是并行框架的使用(这里是未来的框架)。这种对象的这个最简单的例子可能是文件连接,例如con &lt;- file("my-local-file.txt", open = "wb")。我在“解决方案的常见问题”小插图 (https://cran.r-project.org/web/packages/future/vignettes/future-4-issues.html) 的“不可导出对象”部分记录了一些示例。

    如小插图中所述,您可以设置一个选项 (*),以便未来框架在尝试启动未来(“提前停止”)之前查找这些类型的对象并给出信息性错误。这是激活此检查的示例:

    library("future")
    plan(multisession)
    
    ## Assert that global objects can be sent back and forth between
    ## the main R process and background R processes ("workers")
    options(future.globals.onReference = "error")
    
    library("rJava")
    .jinit()
    
    end <- .jnew("java/lang/String", " World!")
    
    f <- future({
      start <- .jnew("java/lang/String", "Hello")
      .jcall(start, "Ljava/lang/String;", "concat", end)
    })
    
    # Error in FALSE : 
    #  Detected a non-exportable reference ('externalptr') in one of the
    #  globals ('end' of class 'jobjRef') used in the future expression
    

    所以,是的,您的示例在使用 plan(multicore) 时确实有效。原因是“多核”使用 forked 进程(在 Unix 和 macOS 上可用,但在 Windows 上不可用)。但是,我会尽力限制您的软件仅在“可分叉”系统上并行化;如果你能找到一种替代方法,我会为此而努力。这样,您的代码也可以在一个巨大的云集群上运行。

    (*) 默认情况下未启用这些检查的原因是 (a) 它仍处于 beta 测试中,并且 (b) 它带有开销,因为我们基本上需要在所有全局变量中扫描不支持的对象。未来是否会默认启用这些检查,将在https://github.com/HenrikBengtsson/future 讨论。

    【讨论】:

    • 感谢您的帮助。仍然不清楚如何在并行处理中导出此类不可导出的对象。
    • 不幸的是,默认情况下它们不可导出。这些结构/类的作者/开发人员需要编写序列化/反序列化函数。同样的问题是,如果您保存它们(例如saveRDS()),重新启动R,然后将它们读回(例如readRDS()),它们将无法工作。在他们支持之前,您无能为力。
    • 谢谢!我已经用更多细节更新了我的问题。你能帮忙吗?
    • 在最新版本的 R 3.5.0 中,他们使用 ALTREP 框架对象的自定义序列化解决了这个问题。
    • 我认为在 R 3.5.0 中完成的与 ALTREP 相关的序列化与此处无关,但我可能错了。
    【解决方案2】:

    问题中的代码正在调用未知的Method1 方法,my_value 未定义,...很难知道您真正想要实现的目标。

    看看下面这个例子,或许你能从中得到启发:

    library(future)
    plan(multicore)
    
    library(rJava)
    .jinit()
    
    end = .jnew("java/lang/String", " World!")
    
    f <- future({
      start = .jnew("java/lang/String", "Hello")
      .jcall(start, "Ljava/lang/String;", "concat", end)
    })
    
    value(f)
    [1] "Hello World!"
    

    【讨论】:

    • 我正在使用Java中创建的自定义方法。
    猜你喜欢
    • 2012-05-14
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 2023-04-10
    • 2017-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多