5

関数内のループ内に関数があります。内部関数は、データの大きなベクトルを取得してメモリに保存します(グローバル変数として...「S-Plus」のような「R」を使用しています)。ループは、取得するデータの長いリストをループします。外側の関数がプロセスを開始し、取得するデータセットのリストを渡します。

for (dataset in list_of_datasets) {
  for (datachunk in dataset) {
    <process datachunk>
    <store result? as vector? where?>
  }
}

次のデータセットに移動する前に各データセットを格納するように内部関数をプログラムしたため、外部関数のすべての作業はグローバル変数の副作用として発生します...大きな問題はありません。これは、メモリを大量に消費するベクトルのベクトルを収集して返すよりも良いですか、悪いですか? 優れた第 3 のアプローチはありますか?

データ ベクトルをメモリではなくデータベースに格納すると、答えは変わりますか? 理想的には、終了前に処理されたすべての情報を失うことなく、関数を終了できるようにする (またはネットワーク タイムアウトのために失敗する) ようにしたいと考えています。

4

7 に答える 7

9

グローバル変数の代わりに外部関数で変数を使用します。これにより、両方のアプローチの利点が得られます。グローバルな状態を変更することも、大量のデータをコピーすることもありません。早期に終了する必要がある場合は、部分的な結果を返すだけです。

(R マニュアルの「スコープ」セクションを参照してください: http://cran.r-project.org/doc/manuals/R-intro.html#Scope )

于 2008-09-17T03:48:29.900 に答える
6

あなたのクヌートを思い出してください。「時期尚早の最適化は、すべてのプログラミング悪の根源です。」

副作用のないバージョンをお試しください。パフォーマンスの目標を満たしているかどうかを確認してください。そうであれば、そもそも問題はありません。そうでない場合は、副作用を使用して、次のプログラマーにあなたの手が強制されたことをメモしてください。

于 2008-09-17T04:11:08.660 に答える
4

メモリの使用に大きな違いはないので、コードをきれいにすることもできます。

R には変数のコピー オン モディファイがあるため、グローバル オブジェクトを変更すると、戻り値で何かを渡すのと同じメモリへの影響があります。

出力をデータベース (またはファイル) に保存すると、メモリ使用の問題は発生せず、データは最後ではなく、作成時に段階的に利用可能になります。データベースの方が速いかどうかは、主に使用しているメモリの量に依存します。削減は、ガベージ コレクションがディスクへの書き込みコストを支払うことになるかどうかです。

R には時間プロファイラーとメモリ プロファイラーの両方があるため、その影響を経験的に確認できます。

于 2008-09-17T03:51:30.190 に答える
1

質問を理解できるかどうかはわかりませんが、いくつかの解決策があります。

  1. 関数内で、ベクトルのリストを作成し、それを返します。

  2. 関数内で環境を作成し、その中にすべてのベクトルを格納します。エラーが発生した場合は、必ず環境を返却してください。

Rで:

help(environment)

# You might do something like this:

outer <- function(datasets) {
  # create the return environment
  ret.env <- new.env()
  for(set in dataset) {
    tmp <- inner(set)
    # check for errors however you like here.  You might have inner return a list, and
    # have the list contain an error component
    assign(set, tmp, envir=ret.env)
  }
  return(ret.env)
}

#The inner function might be defined like this

inner <- function(dataset) {
  # I don't know what you are doing here, but lets pretend you are reading a data file
  # that is named by dataset
  filedata <- read.table(dataset, header=T)
  return(filedata)
}

レイフ

于 2008-09-17T03:58:26.367 に答える
1

参考までに、副作用を回避する完全なサンプル玩具ソリューションは次のとおりです。

outerfunc <- function(names) {
  templist <- list()
  for (aname in names) {
    templist[[aname]] <- innerfunc(aname)
  }
  templist
}

innerfunc <- function(aname) {
  retval <- NULL
  if ("one" %in% aname) retval <- c(1)
  if ("two" %in% aname) retval <- c(1,2)
  if ("three" %in% aname) retval <- c(1,2,3)
  retval
}

names <- c("one","two","three")

name_vals <- outerfunc(names)

for (name in names) assign(name, name_vals[[name]])
于 2008-09-17T19:39:37.370 に答える
0

3 番目のアプローチ: 内部関数は大きな配列への参照を返します。これは、ループ内の次のステートメントで逆参照され、必要な場所に保存されます (理想的には、単一のポインター ストアを使用し、配列全体を memcopy する必要はありません)。

これにより、副作用と大きなデータ構造の受け渡しの両方が取り除かれます。

于 2008-09-17T03:49:36.560 に答える
-1

使用されている言語/コンパイラを知らずに断言するのは困難です。ただし、作成しているオブジェクトへのポインタ/参照を単純に渡すことができる場合、オブジェクト自体のサイズは関数呼び出しの速度とは関係ありません。今後このデータを操作することは、別の話になる可能性があります。

于 2008-09-17T03:43:22.923 に答える