Matlab'da 'for' döngüleri yazmanın en etkili yolu nedir?


12

Örneğin, forbir matrisin dizinleri üzerinde çalışan bir çift döngü varsa, sonra dış döngüde sütun çalışan dizin koyarak daha verimli olduğunu okudum . Örneğin:

a=zeros(1000);
for j=1:1000
 for i=1:1000
  a(i,j)=1;
 end
end

Üç veya daha fazla fordöngüm varsa kodlamanın en etkili yolu nedir ?

Örneğin:

a=zeros(100,100,100);
for j=1:100
 for i=1:100
  for k=1:100
   a(i,j,k)=1;
  end
 end
end

4
ForMATLAB'da döngüler çok yavaş. Mümkün olduğunca MATLAB'da açık döngülerden kaçınmalısınız. Bunun yerine, genellikle bir problem matris / vektör işlemleri açısından ifade edilebilir. MATLABic yolu budur. Matrisleri başlatmak için birçok yerleşik işlev de vardır. Örneğin , bir matrisin tüm öğelerini 1'e (uzantısıyla, çarpma ile herhangi bir değere (skaler ) ayarlayacak olan bir işlevler () vardır. hepsi matris ile çarpılır)). Ayrıca 3 boyutlu dizilerde de çalışır (bence buradaki örneği kapsar).
Peter Mortensen

3
@PeterMortensen Matlab'daki döngülerin verimliliği (kabaca) C ve Python ile karşılaştırıldığında daha küçüktür? Ve neden böyle? Ayrıca, Matlab'daki döngülerin verimliliği son birkaç yılda daha iyi olmamış mı?
TensoR

3
@PeterMortensen “genellikle bir sorun matris / vektör işlemleri açısından ifade edilebilir” - belirli “genellikle” değerleri için evet. IMO, Matlab ve benzerlerinde çalışan insanların, matris / vektör işlemleri ile yapılamayan her şeyi göz ardı etme kültürünün on yıl sürdüğünü söylemek daha doğrudur, o kadar ki her şey bu çekiç için onlara bir çivi gibi görünür. . Ve sadece “Matlab'daki döngüler yavaş” dememeliyiz, “Matlab yavaş” (sadece C ve Fortran'da yazılmış hızlı bir LA ilkel kütüphanesi ile bağlantılı).
leftaroundabout

5
Döngülerin performansı tartışmalıdır: matlabtips.com/matlab-is-no-longer-slow-at-for-loops
ohreally

@leftaroundabout True. Yorumlanmış (veya yarı yorumlanmış) bir dilde hız konusunda endişe duymak, gerçek çözümün "bu dili kullanma" olduğu bir XY probleminiz olduğu konusunda oldukça açık bir göstergedir. Tabii istisna, Simulink'te kod üretme kullanıyorsanız, ancak soru, kod üretecinin ne C oluşturduğunu ve ne kadar verimli olduğudur.
Graham

Yanıtlar:


18

Kısa cevap, en içteki döngüde en soldaki dizine sahip olmak istiyorsunuz. Örneğinizde, döngü indeksleri k, j, i ve dizi indeksleri i, j, k olacaktır. Bu, MATLAB'ın farklı boyutları bellekte nasıl sakladığıyla ilgilidir. Daha fazla bilgi için bu reddit gönderisinin 13. bölümüne bakın .


2
Veya yerleşik işlev olanları () kullanın .
Peter Mortensen

5
@Peter OP'nin örneği neredeyse kesinlikle gerçek kullanım durumu değil, bir şey yapan bir for döngüsü için bir oyuncak örneğidir.
Matt

@Matt Doğru.
TensoR

11

En soldaki endeksin en hızlı şekilde değişmesinin neden daha verimli olduğunu açıklayan biraz daha uzun bir cevap. Anlamanız gereken iki anahtar şey var.

İlk olarak, MATLAB (ve Fortran, ancak C ve diğer programlama dillerinin çoğunda değil) dizileri "sütun ana düzeninde" bellekte depolar. örneğin A 2'den 3'e 10 matris ise, girişler sırayla bellekte depolanır

Bir (1,1,1)

Bir (2,1,1)

Bir (1,2,1)

Bir (2,2,1)

Bir (1,3,1)

Bir (2,3,1)

Bir (1,1,2)

Bir (2,1,2)

...

A (2,3,10)

Sütun ana düzeninin bu seçimi keyfidir - kolayca bir "satır büyük düzen" kuralı benimseyebiliriz ve aslında C ve diğer bazı programlama dillerinde yapılan budur.

Anlamanız gereken ikinci önemli şey, modern işlemcilerin belleğe tek seferde erişmemesi, daha ziyade 64 veya 128 bitişik baytlık (8 veya 16 çift kesinlikli kayar nokta sayısı) "önbellek hatlarını" yükleyip depolamasıdır. bir anda hafızadan. Bu veri parçaları geçici olarak hızlı bir bellek önbelleğinde saklanır ve gerektiğinde geri yazılır. (Uygulamada, önbellek mimarisi artık 3 veya 4 düzey önbellek seviyesi ile oldukça karmaşıktır, ancak temel fikir, bilgisayarların daha genç günlerimde sahip olduğu tek düzey bir önbellekle açıklanabilir.)

A

Döngüler, en içteki döngü satır altyazısını güncelleyecek şekilde iç içe yerleştirilmişse, dizi girişlerine A (1,1), A (2,1), A (3,1), ... sırasıyla erişilir. ilk A girişine (1,1) erişildiğinde, sistem ana bellekten önbelleğe A (1,1), A (2,1), ..., A (8,1) içeren bir önbellek satırı getirecektir. . En içteki döngünün sonraki 8 yinelemesi, ek ana bellek aktarımı olmadan bu veriler üzerinde çalışır.

Alternatif olarak, ilmekleri sütun indeksi en içteki döngüde değişecek şekilde yapılandırırsak, A girişlerine A (1,1), A (1,2), A (1,3) şeklinde erişilirdi ), ... Bu durumda, ilk erişim ana bellekten önbelleğe A (1,1), A (2,1), ..., A (8,1) getirir, ancak 7/8 bu girişler kullanılmaz. İkinci iterasyonda A (1,2) 'ye erişim daha sonra ana bellekten 8 giriş daha getirecektir, vb. Kod, matrisin 2. satırında çalışmaya başladığında, A (2,1) girişi, diğer gerekli verilere yol açmak için önbellekten temizlenebilir. Sonuç olarak, kod gerektiği kadar 8 kat daha fazla trafik üretiyor.

Bazı iyileştirme derleyicileri, bu sorunu önlemek için döngüleri otomatik olarak yeniden yapılandırabilir.

Matris çarpımı ve çarpanlarına ayırma için birçok sayısal doğrusal cebir algoritması, programlama diline bağlı olarak satır-büyük veya sütun-büyük sıralama düzeni ile verimli çalışacak şekilde optimize edilebilir. Bunu yanlış yapmak performans üzerinde önemli bir olumsuz etki yaratabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.