Julia

2016-07-18 20 views
5

içinde sabit boyutlu dizinin en uygun boyutlarını geçirme Giriş olarak matris alan bir işlev yazmak istiyorum. Bu, karmaşık bir projede sıkça görülen düşük seviyeli bir çağrıdır, bu nedenle bu işlevi olabildiğince hızlı hale getirmek, potansiyel olarak ciddi performans sonuçları doğurur. Hız benim için çok önemli olduğu için, bu tür bellek kullanımını kaydedeceğini bildiğim gibi FixedSizeArrays türlerini kullanıyorum. Ancak çoğu zaman giriş matrisinin belirli özelliklerini bilirim ve bunun en iyi şekilde kullanıldığından emin değilim.Julia

İşte basit bir örnek. İstediğim fonksiyonu mümkün olduğunca hızlı aşağıdaki yapmak düşünün:

using FixedSizeArrays 

function foo(input::Mat) 
# NB: Mat is the FixedSizeArrays matrix type 
    return 2 * input 
end 

Açıkçası bu önemsiz bir örnektir, ama önemli olan bu değil. Önemli olan, input matrisinin boyutları hakkında bir şey bildiğim: her zaman yalnızca iki sütun var ve her zaman çalışma zamanında satır sayısını belirtebilirim. Bu, kodumu daha hızlı hale getirmek için derleyiciye iletilebilecek bilgiler gibi görünüyor. Bir şekilde input boyutunu tanımlayan bir argüman olarak geçebilir miyim? İşte işe yaramayan bir örnek, ama yapmaya çalıştığım şey hakkında bir fikir vermelisin.

function bar(int::N, thismat::Mat{N,2,Float64}) 
    return 2 * thismat 
end 

Yapabileceğim bir şey var mı? Yapabilirsem, bu işe yarar mı? Belki FixedSizeArrays zaten yapılabilir her şeyi yapar. Düşüncelerin için teşekkürler!

cevap

7

Sabit boyutlu diziler zaten boyutlarda uzmanlaşmıştır. Bu diziler sizin durumunuzdaki satır sayısı, N, değişebilir olduğunda uygun değildir. Fark ettiğiniz herhangi bir performans sorunu büyük olasılıkla aşırı özelleştirme.

Biraz daha spesifik olalım.

Julia derleyicisi, argüman türleri üzerinde agresif uzmanlaşma yoluyla sıfır maliyetli soyutlama elde edebilir. Yani genel olarak (yani, uzmanlığın çok pahalı olduğu ya da açıkça devre dışı bırakıldığı birkaç durumda hariç), iki farklı tip imza ile bir işlev çağrılırsa, bu işlevin iki sürümü derlenir.

Mat'un boyutu, türünün bir parçası olduğundan, bu, Mat'un olası her boyutu için bir sürümün derlenmesi anlamına gelir. Yani aradığınız uzmanlık zaten yapıldı. Bununla birlikte, uzmanlık, ancak, ücretsiz değildir. Bununla ilişkili iki maliyet vardır:

  • Belli bir imzada ilk kez bir işlev çağrıldığında, bellek ayrılacak ve derleyicinin çalışması gerekecektir.
  • Türü türetilemeyen bir parametre bir işleve iletildiğinde, "tür dengesizliği" vardır ve dinamik gönderim gerekir. Dinamik gönderim, çalışma zamanı aramalarını içerir. senin matrisleri N değişir ve derleme zamanında bilinmemektedir büyüklüğü (2, N) ait olup olmadığını

Böylece dinamik sevk performans maliyeti tahakkuk edilecektir. Bu performans maliyeti, fonksiyon bariyeri tekniği kullanılarak sınırlandırılabilir: sadece bu tür bir kararsız çağrı için bir kez maliyete katlanırız, bu nedenle bu tür çağrıların sayısını sınırlandırmak performansı artırır.

Ama tamamen bu dinamik sevk edilmesini önlemek olacaktır daha da performansını artırmak ne.Yalnızca türdeki sütun sayısını kodlayan ve çalışma zamanında satır sayısı olan bir dizi türü oluşturmak mümkündür. Yani, performans probleminizin aşırı uzmanlıktan kaynaklanması mümkündür ve uzmanlık miktarını azaltmak için türlerinizi oluşturmanız gerekir.

Doğru dengeyi bulmak, bir uygulamadan olabildiğince fazla performans sıkmak için merkezi bir noktadır. Bir dizinin büyüklüğü üzerinde uzmanlaşmak aslında oldukça nadiren yararlıdır - örneğin C ve C++ kodu bile, belirli bir dizi boyutunda uzmanlaşmak yerine dizi boyutlarını çalışma zamanı parametreleri olarak geçirme eğilimindedir. Bu pahalı değil. Daha fazla vakada, FixedSizeArrays.jl, performansı artırmayacak, daha ziyade zarar vermeyecektir. Kesinlikle yardım edeceği durumlar vardır, ama sizinkilerden biri olmayabilir. Senin durumunda


, maksimal performans için, böyle bir tür hızlı olacağını sanıyorum:

immutable TwoColumnMatrix{T, BaseType} <: AbstractArray{T, 2} 
    height::Int 
    base::BaseType 
end 

function TwoColumnMatrix(A::Matrix) 
    size(A, 2) == 2 || throw(ArgumentError("must be two columns")) 
    TwoColumnMatrix{eltype(A), typeof(A)}(size(A, 1), A) 
end 

[email protected]_inbounds function getindex(M::TwoColumnMatrix, n::Int) 
    M.base[n] 
end 

size(M::TwoColumnMatrix) = (M.height, 2) 

Sen, kriter olarak her zaman ek maksimum performans için yöntemler ve tanımlamak gerekebilir. Sargının yükü, derleyicileri boyutlar hakkında bilerek değmez.

+0

@squipbar Örnekle ilgili bazı ikinci düşüncelerim vardı. Ekstra işaretçi yokluğu ve iyi olmayan bir şube var (hiç de iyi değil). Bu sıkıntıları önleyen yeni bir göz atın; Bunu bir kıyaslamadım. –

+0

@squipbar Eğer görmediyseniz, Tim Holy'in bu video ve dizilerinden oluşan sunumuna bir göz atın: https://www.youtube.com/watch?v=fl0g9tHeghA –

+0

Her zaman cevaplarınızdan çok şey öğreniyorum. Soruyu soran kişi ben değilim! –