以下は、配列内のセルへの代入によって生じる可能性がある追加のコピー (この場合はfor
ループを使用) を調査するコードです。
# populate a vector with a million random numbers
n = 10^6
v=runif(n)
# vectorized version: fast
vv<-v*v;
m<-mean(vv); m
# for loop: slow
tracemem(vv)
for(i in 1:length(v)) { vv[i]<-v[i]*v[i] };
m<-mean(vv); m
出力
> vv<-v*v;
> m<-mean(vv); m
[1] 0.3329162
> # for loop: slow
> tracemem(vv)
[1] "<0x000007ffff560010"
> for(i in 1:length(v)) { vv[i]<-v[i]*v[i] };
tracemem[0x000007ffff560010 -> 0x000007fffe570010]:
> m<-mean(vv); m
[1] 0.3329162
これは、ループの最初の反復でベクトルのコピーがあることを示しているようです。
注: これは、私の以前の質問Why is vectorization faster、この回答に対する回答、および回答に関するこのコメントのフォローアップです。
コピーを確認するために、ループ本体の外側で最初の反復を行いました
v=runif(n)
# vectorized version: fast
vv<-v*v;
m<-mean(vv); m
# for loop: slow
tracemem(vv)
vv[1]<-v[1]*v[1]
tracemem(vv)
for(i in 2:length(v)) { vv[i]<-v[i]*v[i] };
m<-mean(vv); m
この出力を与える
> vv<-v*v;
> m<-mean(vv); m
[1] 0.33385
> # for loop: slow
> tracemem(vv)
[1] "<0x000007fffef80010"
> vv[1]<-v[1]*v[1]
tracemem[0x000007fffef80010 -> 0x000007fffddc0010]:
> tracemem(vv)
[1] "<0x000007fffddc0010"
> for(i in 2:length(v)) { vv[i]<-v[i]*v[i] };
> m<-mean(vv); m
[1] 0.33385 # (different as I generated the random nos again)
ジョランの答えとこの厄介な議論スレッドを読んだ後、たとえば、以下のように型を変更した場合など、Rがベクトルをコピーする可能性があるという考えに慣れ始めました
> x = 1:10
> tracemem(x)
[1] "<0x00000000118ba4e0"
> x[5] = 6
tracemem[0x00000000118ba4e0 -> 0x0000000010d03568]:
> x = 1:10 # starts off as integer
> tracemem(x)
[1] "<0x00000000118ba538"
> x[5] = 6L # setting integer ok
> x[5] = 6 # setting floating point changes type
tracemem[0x00000000118ba538 -> 0x0000000010d03568]:
> x[6] = 7 # it's now floating point, setting floating point again ok
> x[7] = "asdf" # setting string changes type once more, this tanks on a large array
tracemem[0x0000000010d03568 -> 0x0000000010d03610]:
だから私は何が起こっているのかについて大まかな考えを持っていますが、なぜ私の最初の例ではvv
(または私が解釈で犯した間違い)のコピーがあるのvv
ですか?