Boş matris çarpımı üzerinden diziler başlatmak için hızlı yolu? (Matlab)
Matlab empty matrices ile uğraşıyor garip tökezledi ettik (benim görüşüme göre). Eğer iki boş matrisleri çarpılır, örneğin, bir sonucu olarak ortaya
zeros(3,0)*zeros(0,3)
ans =
0 0 0
0 0 0
0 0 0
Şimdi, bu zaten benim için de sürpriz oldu, ancak, hızlı bir ara bağlantı bana yukarıda var, ve bu neden oluyor biraz çarpık mantık bir açıklaması var.
Ancakhiçbir şey, aşağıdaki gözlem için beni hazırladı. Kendimi, nasıl verimli çarpma bu tür olduğunu sordum vs sadece zeros(n)
işlevi kullanarak, başlatma amaçlı demek? timeit
bu cevap için kullandım:
f=@() zeros(1000)
timeit(f)
ans =
0.0033
vs:
g=@() zeros(1000,0)*zeros(0,1000)
timeit(g)
ans =
9.2048e-06
Her iki sınıf double
ama boş matris çarpma bir ~350 kat daha hızlı olduğu sıfır 1000x1000 matris aynı sonuç! (benzer bir sonuç tic
toc
ve bir döngü) kullanarak olur
Bu nasıl olabilir? timeit
tic,toc
matris veya başlatmak için daha hızlı bir yol buldum demedim.
(bu Windows 7-64 makine, ıntel ı5 650 3.2 üzerinde 2012a, Ghz matlab...) ile yapıldı
DÜZENLEME:
Okuduktan sonra görüşlerinizi, ben baktım daha dikkatli içine bu özelliği, ve test için 2 farklı bilgisayar (aynı matlab ver ama 2012a) bir kod inceleyecek çalışma süresi, vs boyutu matris n. Bu da nedir:
Bu oluşturmak için bu kodu daha önce olduğu gibi timeit
kullanılan, ama tic
toc
ile bir döngü aynı görünüyor. Bu yüzden, küçük boyutları için zeros(n)
karşılaştırılabilir. Ancak, n=400
etrafta boş matris çarpma için performansta bir sıçrama var. Bu arsa oluşturmak için kullandığım kod:
n=unique(round(logspace(0,4,200)));
for k=1:length(n)
f=@() zeros(n(k));
t1(k)=timeit(f);
g=@() zeros(n(k),0)*zeros(0,n(k));
t2(k)=timeit(g);
end
loglog(n,t1,'b',n,t2,'r');
legend('zeros(n)','zeros(n,0)*zeros(0,n)',2);
xlabel('matrix size (n)'); ylabel('time [sec]');
İçinizde bu deneyimi çok?
EDİT #2:
Bu arada, boş matris çarpımı bu etkiyi elde etmek için gerekli değildir. Sadece birini yapabilirim:
z(n,n)=0;
nerede^ n . bazı eşik matris büyüklüğü bir önceki grafikte görüldüğü ve almakkesinmatris çarpımı (tekrar timeit kullanarak) ile boş olarak verimlilik profili.
Burada bir kod verimliliği artırır bir örnek:
n = 1e4;
clear z1
tic
z1 = zeros( n );
for cc = 1 : n
z1(:,cc)=cc;
end
toc % Elapsed time is 0.445780 seconds.
%%
clear z0
tic
z0 = zeros(n,0)*zeros(0,n);
for cc = 1 : n
z0(:,cc)=cc;
end
toc % Elapsed time is 0.297953 seconds.
Ancak, z(n,n)=0;
yerine zeros(n)
davaya benzer sonuçlar verir.
CEVAP
Bu garip, f g ne görüyorsanız daha yavaş olurken, daha hızlı olmayı görüyorum. Ama ikisi de benim için aynıdır. * * * * Farklı bir versiyonu olabilir mi ?
>> g = @() zeros(1000, 0) * zeros(0, 1000);
>> f = @() zeros(1000)
f =
@()zeros(1000)
>> timeit(f)
ans =
8.5019e-04
>> timeit(f)
ans =
8.4627e-04
>> timeit(g)
ans =
8.4627e-04
EDİTf ve g sonuna 1 ekleyin, ve kez bakın alıyorsanız.
Jan 6, 2013 7:42 EST DÜZENLEYİN
Makine uzaktan, düşük kalite grafikler için çok üzgünüm (onları kör oluşturmak için) kullanıyorum.
Makine yapılandırma:
i7 920. 2.653 GHz. Linux. 12 GB RAM. 8 MB önbellek.
Bu davranış, daha büyük bir boyut (1979 ve 2073 arasında bir yerde) dışında gösterir erişim hakkım var hatta makine gibi görünüyor. Daha büyük boyutlarda daha hızlı olması için boş matris çarpma için şu an aklıma bir sebep yok.
Biraz daha geri gelmeden önce araştırıyorum.
Jan 11, 2013 DÜZENLEYİN
@EitanT sonrası sonra, ufak bir araştırma daha yapmak istedim. Matlab sıfır bir matris yaratmak olabilir nasıl görmek için bazı C kodu yazdım. O nedenle c kodu.
int main(int argc, char **argv)
{
for (int i = 1975; i <= 2100; i =25) {
timer::start();
double *foo = (double *)malloc(i * i * sizeof(double));
for (int k = 0; k < i * i; k ) foo[k] = 0;
double mftime = timer::stop();
free(foo);
timer::start();
double *bar = (double *)malloc(i * i * sizeof(double));
memset(bar, 0, i * i * sizeof(double));
double mmtime = timer::stop();
free(bar);
timer::start();
double *baz = (double *)calloc(i * i, sizeof(double));
double catime = timer::stop();
free(baz);
printf("%d, %lf, %lf, %lf\n", i, mftime, mmtime, catime);
}
}
İşte sonuçlar.
$ ./test
1975, 0.013812, 0.013578, 0.003321
2000, 0.014144, 0.013879, 0.003408
2025, 0.014396, 0.014219, 0.003490
2050, 0.014732, 0.013784, 0.000043
2075, 0.015022, 0.014122, 0.000045
2100, 0.014606, 0.014480, 0.000045
Gördüğünüz gibi calloc
(4. sütun) hızlı bir yöntem gibi görünüyor. Ayrıca 2025 ve 2050 (2048? civarında olacağını tahmin ediyorum) arasında önemli ölçüde daha hızlı oluyor.
Şimdi tekrar aynı kontrol etmek için matlab gittim. İşte sonuçlar.
>> test
1975, 0.003296, 0.003297
2000, 0.003377, 0.003385
2025, 0.003465, 0.003464
2050, 0.015987, 0.000019
2075, 0.016373, 0.000019
2100, 0.016762, 0.000020
Hem görünüşe göre f() ve g() daha küçük boyutlarda calloc
(<2048 ?) kullanarak. Ama en büyük boyutları f() (sıfır(m, n)) başlar kullanın malloc
memset
iken g() (sıfır(m, 0) * sıfır(0, n)) tutar kullanarak calloc
.
Ayrışmanın aşağıdaki açıklanmıştır
- sıfır bir farklı kullanmaya başlar yavaş (?) daha büyük boyutlarda düzeni.
calloc
biraz da beklenmedik bir şekilde performans artışı giden davranır.
Bu Linux üzerinde davranıştır. Biri farklı bir makine (ve belki de farklı bir işletim sistemi) aynı deney yapmak ve deney tutar.
Neden MATLAB matris çarpımı kadar hızl...
Bir tamsayı'in kare kökü belirlem...
Hızlı eğer bir tam sayı iki tamsayı (d...
Bir std başlatmak için en kolay yolu n...
Hızlı dize PHP bir tamsayı dönüştürmek...