質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
R

R言語は、「S言語」をオープンソースとして実装なおした、統計解析向けのプログラミング言語です。 計算がとても速くグラフィックも充実しているため、数値計算に向いています。 文法的には、統計解析部分はS言語を参考にしており、データ処理部分はSchemeの影響を受けています。 世界中の専門家が開発に関わり、日々新しい手法やアルゴリズムが追加されています。

Q&A

解決済

1回答

604閲覧

R言語でグローバル変数の参照が遅い

menshan

総合スコア54

R

R言語は、「S言語」をオープンソースとして実装なおした、統計解析向けのプログラミング言語です。 計算がとても速くグラフィックも充実しているため、数値計算に向いています。 文法的には、統計解析部分はS言語を参考にしており、データ処理部分はSchemeの影響を受けています。 世界中の専門家が開発に関わり、日々新しい手法やアルゴリズムが追加されています。

1グッド

3クリップ

投稿2017/08/04 12:57

R言語で関数内処理中にグローバル変数を参照した処理をしたいのですが assign を使うと処理が遅くなってしまいます。
以下の処理1で 700 ミリ秒、処理2で 220 ミリ秒と約3倍となります。
処理2で使っている「<<-」は非推奨ということなので使わずに速くしたいのですが、何かいい方法はありますでしょうか

処理1:

R

1count1 <- 0 2 3func1 <- function(){ 4 for(i in 1:100000){ 5 assign('count1', get("count1",env=.GlobalEnv) + 1, env=.GlobalEnv) 6 } 7} 8 9func1() 10cat('count1=') 11cat(count1)

処理2:

R

1count1 <- 0 2 3func1 <- function(){ 4 for(i in 1:100000){ 5 count1 <<- count1 + 1 6 } 7} 8 9func1() 10cat('count1=') 11cat(count1)

そもそもグローバル変数を頻繁に参照する様な処理がだめでしょう!
というツッコミもあるかも知れませんが、何か高速化方法があればと思い投稿します。

s8_chu👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

興味深い質問だったので、自分で試してみました。
以下のスクリプトにおいて
func0がassign/getを使うバージョン。
func1が<<-を使うバージョン。
そしてfunc2では、対象のグローバル変数をローカル環境にまずコピーし、処理が全部終わってから書き戻すというのを試してみました。

R

1Rprof(tmp<-tempfile(), interval=0.01) 2 3rep <- 10000000 4 5count1 <- 0 6func0 <- function(){ 7 for(i in 1:rep){ 8 assign('count1', get("count1",env=.GlobalEnv) + 1, env=.GlobalEnv) 9 } 10} 11func0() 12cat(sprintf('count1=%d\n', count1)) 13 14count1 <- 0 15func1 <- function(){ 16 for(i in 1:rep){ 17 count1 <<- count1 + 1 18 } 19} 20func1() 21cat(sprintf('count1=%d\n', count1)) 22 23count1 <- 0 24func2 <- function(){ 25 count1.local <- count1 26 for(i in 1:rep){ 27 count1.local <- count1.local + 1 28 } 29 assign('count1', count1.local, env=.GlobalEnv) 30} 31func2() 32cat(sprintf('count1=%d\n', count1)) 33 34Rprof(NULL) 35summaryRprof(tmp) 36

結果をサマライズしたものを示します。

$ R -q --slave --vanilla < ~/test.r |egrep 'count|func|total.time' count1=10000000 count1=10000000 count1=10000000 self.time self.pct total.time total.pct "func0" 4.52 26.65 15.86 93.51 "func1" 0.82 4.83 0.82 4.83 "func2" 0.27 1.59 0.28 1.65 total.time total.pct self.time self.pct "func0" 15.86 93.51 4.52 26.65 "func1" 0.82 4.83 0.82 4.83 "func2" 0.28 1.65 0.27 1.59

やはりassignとgetの繰り返しは時間を食うようです。
そして、どうやら<<-より<-の方がだいぶん高速のようです。
func2()の所要時間はfun1()の1/3。<<-を使わずに高速化が達成できたと言えそうです。いかがでしょうか。

投稿2017/08/04 17:00

KojiDoi

総合スコア13671

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

menshan

2017/08/05 13:11

ご回答有難うございます。 ローカルにコピーしておくという発想は無かったです。(何で気づかなかったのか・・・) 提示していただいたコピーして最後に書き戻す方法が良さそうです。 実際の処理は関数が10段ぐらいネストしているのですが、参照の場合は変数名をそのまま参照すれば参照でき 更新している部分は少なく、その部分のみ assign を使えば速く出来そうです。 デバッグ用の関数 Rprof の使い方とか大変ためになりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問