3

R で多くの一般的な線形回帰を含む離散イベント シミュレーションを実行する必要があるため、多数の R オブジェクトをリストまたは配列に 1 つずつ追加する必要があります。これですべてが実装され、シミュレーターが実行されます。ただし、プロセス全体のパフォーマンスのボトルネックは、実際にはリストの追加にあることに気付きました (6000 イベントをシミュレートするのに約 15 分かかります)。R のリスト、ベクトル、または配列内のオブジェクトの数が多くなると、挿入が非常に遅くなることに気付きました。シミュレーション コードの多くの部分で何度も使用されるため、再利用可能なリスト データ構造が必要です。R で記述された単純な ArrayList の実装を次に示します。

ArrayListX = setRefClass(
  Class = "ArrayListX",
  fields = list(
    ol = "array",
    len = "integer",
    cap = "integer",
    expandNum = "integer"),
  methods = list(
    initialize = function(){
      len <<- 0L
      expandNum <<- 100000L
      #TODO: The preallocation here made the performance worse.
      ol <<- array(dim = expandNum)
      cap <<- expandNum
    },
    expand = function(){
      ol <<- c(ol, array(list(), dim = expandNum))
      cap <<- cap + expandNum
    },
    get = function(i){
      return(ol[i])
    },
    remove = function(i){
      ol[i] <<- NULL
      len <<- len - 1L
    },
    add = function(obj){
      if(cap <= len)
      {
        expand()
      }
      len <<- len + 1L
      ol[len] <<- obj
      return(len)
    },
    size = function(){
      return(len)
    },
    set = function(i, obj){
      ol[i] <<- obj
    },
    insert = function(before, obj){
      if(before < 1 || before > len + 1)
        throw(paste("Subscript out of bound. before = ", before))

      if(len == 0)
      {
        ol[1] <<- obj
      }  else
      {
        head = ol[1:before - 1]
        head[before] = obj
      {
        if(before <= len)
          ol <<- c(head, ol[before:len])
        else
          ol <<- head
      }
      }
      len <<- len + 1L
    }
  )
)

リストを初期化し、特定の数の行を事前に割り当てようとしたことに注意してください。これでもパフォーマンスは向上しませんでした。実際、事前に割り当てない場合よりもさらに遅くなります。(これは、私が使用している参照クラスのためかもしれません。私の経験では、事前割り当ては通常、参照クラスを使用しない場合に R でのパフォーマンスを向上させます) そのため、Java ArrayList をリストのバックエンド データ構造として使用することを考えました。rJava を試してみました。

ArrayListJ = setRefClass(
  Class = "ArrayListJ",
  contains = "ArrayList",
  fields = list(
    jal = "ANY"),
  methods = list(
    initialize = function(){
      jal <<- .jnew("java.util.ArrayList")
    },
    get = function(i){
      rObj = .jcall(jal, returnSig="Ljava/lang/Object;", method = "get", as.integer(i))
      return(rObj)
    },
    remove = function(i){
    },
    add = function(obj){
      jRef = toJava(x = obj, engine = NULL)
      .jcall(obj = jal, returnSig = "Z", method = "add", .jcast(jRef, new.class = "java/lang/Object"))
    },
    size = function(){
      s = .jcall(obj = jal, returnSig = "I", method = "size")
      return (s)
    },
set = function(i, obj){
    #Not implemented yet.
    },
insert = function(before, obj){
    #Not implemented yet.
    }    
    )
  )

「get」機能を機能させることができなかったため、現在苦労しています。R では使用できない REXPReference オブジェクトを常に返します。返してほしいのは、実際には ArrayListJ に追加された元の R オブジェクト obj です。挿入された R オブジェクトは、ArrayListJ に挿入された後に他のロジックによって更新された可能性があるため、最初に参照されたオブジェクトである必要があります。誰かが ArrayListX または ArrayListJ の実装を手伝ってくれますか? 基本的に、多数の R 参照クラス オブジェクトをリストに 1 つずつ一定の時間で追加できる必要があります (リストが大きくなってもパフォーマンスが低下しないようにする必要があります)。ArrayListJ 実装の場合、「get」メソッドを使用して元の参照された R オブジェクトを取得するにはどうすればよいですか? ありがとう。

4

0 に答える 0