Seyrek matris çarpımında sıfır olmayanların sayısını belirlemenin en iyi yolu nedir?


17

Her iki matrisin CSC veya CSR formatında olduğu varsayılarak seyrek matris çarpma işlemi için sıfır olmayanların sayısını bulmak için hızlı ve etkili bir yöntem olup olmadığını merak ediyordum.

Smmp paketinde biri olduğunu biliyorum ama zaten C veya C ++ uygulanan bir şeye ihtiyacım var.

Herhangi bir yardım takdir edilecektir. Şimdiden teşekkürler.


matrislerinizin sıfır olmayan girişlerinin bulunduğu yerde bir simetri veya bir yapı var mı?
Godric Seer

@GodricSeer ... hayır Sadece genel seyrek matrislerden bahsediyorum.Matlab, nnz (A) 'a sahiptir, burada A, sıfır olmayanların sayısını bulmak için seyrek matris yöntemidir.
Recker

Ben şahsen bazı matetri veya yapıyı sömürmeden gerçek matris çarpımını yapmaktan daha düşük bir sıra olan sayıyı hesaplamanın herhangi bir yolunu düşünemiyorum. Bu çarpma işleminden önce bellek ayırma için istediğinizi varsayalım?
Godric Seer

Ayrıca, bir boole matris ürünündeki sayının nasıl tahmin edileceğini açıklayan bu makaleyi buldum (herhangi bir matris ürünündeki elemanları saymakla aynıdır).
Godric Seer

@ GodricSeer .. Evet haklısın Sadece sonuçtaki matrisin bellek tahsisi için tam sayıya ihtiyacım var.
Recker

Yanıtlar:


14

Matris-matris ürününü, iki sparite paterninin çarpımını oluşturarak simüle edebilirsiniz - yani, sparlık paternini (CSR formatında ayrı dizilerde saklanan), içinde sıfır veya bir içeren bir matris olarak kabul edersiniz. her giriş. Bu simüle edilmiş ürünü gerçekleştirmek için yalnızca veBu sıfırlar ve olanlar üzerinde işlem yapar ve bu nedenle gerçek matris-matris ürününden çok daha hızlıdır - aslında, yapmanız gereken tek şey iki matrisin satırlarından ve sütunlarından geçmek ve bir satırda en az bir giriş olduğunu doğrulamaktır. satır ve her iki matrisin de sıfır olmadığı yerlerde çarptığınız sütun. Bu ucuz bir işlemdir - her durumda, gerçek üründe sadece kayan nokta aritmetiği (pahalı) yapmanızı değil, aynı zamanda bellekten gerçek kayan nokta numaralarını da okumanızı gerektiren gerçek kayan nokta çarpma işlemini yapmaktan çok daha ucuzdur ( daha pahalı, ancak buna ihtiyaç duymazsınız çünkü matrisin sıfır olmayan değerleri CSR'de ayrı olarak saklanır).


6
Buna sembolik çarpma denir. Özellikle paralel olarak, sayısal çarpma işleminden daha az pahalı olmak zorunda değildir, ancak her sparite modeli için sadece bir kez yapılması gerekir. Birçok algoritma işlemi farklı sayısal değerlerle aynı kez birkaç kez yapacaktır, ancak aynı sparite paterni, bu durumda sembolik çarpma tekrar kullanılabilir.
Jed Brown

Bu güzel bir fikir, ancak şamandıra * şamandırasını paralel olarak yapan milyonlarca transistör göz önüne alındığında, burada sadece% 50 veya yaklaşık bir hız tasarrufu hakkında konuşuyoruz.
Evgeni Sergeev

1
@EvgeniSergeev - mesele hesaplamalarda tasarruf değil, bellek transferinde tasarruf. Bugün seyrek bir matris çarpımı için bellek aktarımı için% 80 veya daha fazla zaman harcadığınızdan, kayan nokta verilerini bellekten / belleğe okumak / yazmak zorunda kalmamanız durumunda önemli ölçüde kazanç elde edersiniz.
Wolfgang Bangerth

Yöntemin karmaşıklığını açıkça belirtir misiniz? Eğer olan m tarafından k sizin yöntem gerektirdiğini bana görünen Ç ( m k ) doğru, çalışmak? CmkÖ(mk)
Carl Christian

O(mk)pm=kO(mplogp)O(m2)

13

Matlab'da orijinal kodu A * B için yazdım, hem A hem de B seyrek. Sonuç için alanın ön tahsisi gerçekten ilginçti. Godric'in neyi işaret ettiğini gözlemledik - AB'deki sıfır olmayanların sayısını bilmek, AB'nin hesaplanması kadar maliyetli.

AB'nin boyutunu doğru bir şekilde tahmin etmek için ilk pratik, hızlı yolu veren Edith Cohen gazetesinden önce, seyrek Matlab'ın ilk uygulamasını 1990'da yaptık. Daha düşük bir boyut tahmincisi bir araya getirdik ve eğer hesaplamanın ortasında yer kalmadıysa, tahsisi ikiye katladı ve kısmen hesaplanan sonucu kopyaladı.

Şimdi Matlab'da ne olduğunu bilmiyorum.

Başka bir olasılık AB'yi bir kerede bir sütun hesaplamak olacaktır. Her sütun geçici olarak seyrek bir akümülatörde saklanabilir (bunların açıklaması için seyrek Matlab kağıdına bakınız) ve sonuç sütununun tam olarak bilinen boyutunu tutmak için ayrılan alan. Sonuç, dağınık sıkıştırılmış seyrek sütun formunda olacaktır - CSC'deki her sütun, ancak kolonlar arası bitişiklik yok - meta veri olarak bir yerine 2 uzunluk numokolünü (col start, col length) kullanarak. Bir göz atmaya değer bir depolama formu; başka bir gücü daha var - tüm matrisi yeniden tahsis etmeden bir sütun büyütebilirsiniz.


Eh benim GPU uygulanması için, ilk sigara sıfır yapısını bulma ve expected.I onlar açıklanan yöntemi kullanmak düşünüyorum sonra gerçek matrix.Performance korkunçtu bulma sona erdi bu MATLAB verimli çarpın iki seyrek matrisler için kitabın.
Recker

2
Gerçekten harika, tarihsel bakış açısı için teşekkürler ve scicomp'a hoş geldiniz :)
Aron Ahmadia

4

Bu makale, iki seyrek matrisin matris ürününden elde edilen bir maddenin boyutuna yaklaşık bir algoritma tarif etmektedir.

Bir seyrek matris çarpımında tam sayı olmayan sıfır girişleri bulma problemi, sonuçtaki her elemanın, her ikisi de en az birkaç sıfır olmayan eleman içermesi muhtemel iki vektörün etkileşimine bağlı olmasıdır. Bu nedenle, sayıyı hesaplamak için, sonuçtaki her eleman için bir çift vektör üzerinde mantıksal işlemleri değerlendirmeniz gerekir. Buradaki sorun, matris ürününün kendisini hesaplamak için gereken işlem sayısına benzer bir dizi işlem gerektirmesidir. Yorumlarımda, orijinal matrislerin sıfır olmayan elemanlarındaki belirli yapılardan yararlanma olasılığından bahsettim, ancak aynı istismarlar matris çarpımında yapılan işi azaltmak için de kullanılabilir.

Bellek gereksinimlerini aşırı tahmin etmek, çarpma işlemini yapmak ve sonra ayrılan belleği kısaltmak veya sonuçtaki matrisi daha uygun boyutlu bir diziye taşımak için yukarıdaki kağıdı kullanmak daha iyi olur. Ayrıca, seyrek matris ürünleri nadir bir durum değildir ve bu sorunun daha önce çözüldüğünü neredeyse garanti ederim. Açık kaynak kodlu, seyrek matris kütüphanelerinin biraz kazılması sizi hafızayı önceden konumlandırmak için kullandıkları algoritmalara yönlendirmelidir.


0

CSR veya CSC için, matris öğeleri dizinizin sıfır olmadığından emin misiniz? Bu durumda, kaç tane sıfır olmayan elemanın olduğunu, aşağıdakine benzer bir şey kullanarak anlamak kolaydır:

int nnz = sizeof(My_Array)/sizeof(long int);

Ancak durum böyle değilse (biraz fazla kolay görünüyor) deneyebileceğiniz bir azalmadır . Matris öğeleri diziniz çok büyükse, sıfır olmayan öğe sayısını hesaplamanın en etkili yolu bu olabilir. Thrust (bir CUDA kütüphanesi) veya OpenCL (kullanmak için GPU'ya ihtiyacınız yoktur) gibi birçok paralel C / C ++ kütüphanesi, koşullu azaltmalar için desteğe sahiptir - her öğe için sonucu ekleyin Condition(Element). Koşulu şu şekilde ayarlarsanız Element != 0sıfır olmayan öğe sayısını toplarsınız. Ayrıca, sıfır değerli öğeleri öğe dizinizden, satır / sütun dizinleri dizisinden kaldırmak ve sütun / satır işaretçilerinizi ayarlamak isteyebilirsiniz.


Cevabınız için teşekkürler ... ama A * B'de sıfır olmayanlardan bahsediyordum, burada A ve B seyrek matrisler. Sonuçtaki matris depolamak için bellek tam miktarını tahsis böylece önceden sıfır olmayan sayısı gerekir.
Recker

0

KSS'yi uygulamanın en basit yolu denemektir

std::vector< std::map<int, complex<float>> > 

matrisinizi temsil etmek için. Bu durumda, sıfır olmayan elemanların sayısı hakkında gerçekten endişelenmeyeceksiniz, hepsine erişilir

std::map< int, complex<float> >::iterator

her satırda. En iyi ..


2
STL, seyrek matris rutinlerinizin daha yavaş yapılamayacağını düşündüğünüzde.
Jed Brown
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.