2D boids simülasyonunu nasıl paralelleştirebilirsiniz?


16

Bir 2D, simülasyonu farklı kaynaklardan (kümeler, gpu) gelen işleme gücünü kullanabilecek şekilde nasıl programlayabilirsiniz?

Örnekler

Yukarıdaki örnekte, renkli olmayan parçacıklar kümelenene kadar (sarı) hareket etmeyi bırakana kadar hareket ederler.

Sorun, sol üstteki bir varlığın sağ altta bulunan bir varlık ile etkileşime girme olasılığı düşük olsa da, tüm varlıkların birbirleriyle potansiyel olarak etkileşimde bulunabilmesidir. Etki alanı farklı segmentlere ayrıldıysa, her şeyi hızlandırabilir, Ancak bir işletme başka bir segmente geçmek isterse sorunlar olabilir.

Şu anda bu simülasyon iyi bir kare hızına sahip 5000 objeyle çalışıyor, bunu mümkünse milyonlarla denemek istiyorum.

Bunu daha da optimize etmek için dört ağaç kullanmak mümkün müdür? Başka öneriniz var mı?


Optimizasyon mu istiyorsun yoksa nasıl paralelleştirilir? Bunlar farklı şeyler.
bummzack

@bummzack Paralel hale getirme, daha fazla açıklama ekledim, bu yardımcı olur mu?
Sycren

Yanıtlar:


7

Yüksek lisans tezinin Mattias Linde tarafından Parçacık Akışkanlarının Paralel Simülasyonu, büyük ölçekli simülasyon için veri bölümleme ve algoritmalar hakkında bir fikir verebilir.

Makalesi , naif çözüm için simülasyondaki parçacıkların çekirdek ayak izi büyüklüğünde bir kova boyutuyla Mekansal Hashing kullanma eğiliminde olan Smoothed-Particle Hydrodynamics'e yöneliktir .

Etkileşim mesafesi tipik SPH çekirdeklerinde sabit olarak sıkıştırıldığından, bu tür bölümleme optimizasyonları sistemin ölçeklendirilmesinde neredeyse gereklidir.


güzel bir kağıt, ama bu soru ile ilgili gerçek kısmı @Fxlll cevap gibi çok görünüyor.
Ali1S232

Kağıdın asıl kısmının, bir iletişim protokolü tanıtarak kenar vakalarını nasıl çözdüğünü söyleyebilirim, bu zor kısım, dört bölümleme oldukça açıktır ve kendi başına kenar durumu sorununu çözmez.
Maik Semder

4

Uzun zaman önce öğrendiğim terim, oyunun bilgi hızıydı.

Tekliflerinizin hızı 1 ise ve sadece komşularını önemsiyorlarsa, o zaman bilgi hızı 3'tür, yani sizden iki kare uzakta olan bir değer, tek bir çerçeve içinde önem verdiğiniz aralıkta olabilir:

Etkileşimde örgü başına 1 kare hareket (1 + 1) artı bir şeyler fark edebileceğiniz mesafe (1) 3'e eşittir.

Bu göz önüne alındığında, bir haritayı istediğimiz kadar küçük boyutlu olarak parçalara ayırabileceğimizi öğreniyoruz, ancak bu bilgi hızı komşu parçalarla çakışıyor.

Siparişlerinizin sadece bir kare hareket etmesine izin verdiğinizi varsayacağım, ancak üçünü görebilirler

Büyük bir paralel sim çalıştırmak istiyorsanız, 10x10 ızgaraya bölünür, ancak her kenarda 5 kare ile çakışırsınız. Her ne zaman biriniz yerel yığının kenarından bilgi uzaklığı içinde olursa, komşuyu güncellemelisiniz ve sınırı geçtikten sonra size ait değillerdir. Bir komşu kontrol ettikleri bir satın almanın yığınınıza taşındığını söylüyorsa, AI'yı ele geçirmeniz gerekir.

Bu, iletişimin komşu yığın yöneticileri için yerelleştirildiği ve trafiğin en aza indirildiği anlamına gelir. Ne kadar çok iş çalıştırırsanız, simülasyona güç vermek için o kadar çok CPU kullanabilirsiniz, ancak ne kadar çok iş çalıştırırsanız o kadar fazla çakışma olur ve bu nedenle simülasyon ilerledikçe işler / yığınlar arasında daha fazla bilgi aktarılır. Bu, AI karmaşıklığına ve hangi donanıma sahip olduğunuza bağlı olarak, ağır teslim olmanız ve yığın boyutunu ayarlamanız gereken yerdir.


dünyanın 1.000.000x1.000.000 ızgara olduğunu ve dünyada 10.000.000 teklif olduğunu ve her bir turun her turda tam olarak bir kare hareket edebileceğini hayal edin, başka bir mahallede bir teklif olup olmadığını nasıl kontrol edeceğinizi açıklayabilir misiniz?
Ali1S232

2000 500x500 kareye veya daha büyük karelere bölebileceğimizi tahmin ediyorum. her meydanda bir liste ve komşuların bir listesi bulunur. Bir kare kareden çıkarsa, kareler listesinden çıkarılır ve diğer kareye eklenir. Görebildiğim bu yöntemle ilgili sorun, kareden daha büyük bir sürü akın eklerseniz. quadtree çözümü dinamik olmak zorundaydı, ama bunun ne kadar pahalı olacağından emin değilim
Sycren

@Gajet: Sadece paketinizdeki veya komşu yönetilen sınırlardaki teklifleri kontrol etmeniz gerekir. Unutmayın, sınır tasarım tarafından herhangi bir varlığın ne kadar uzağa gidebileceğini ve varlıkların görebileceği mesafeyi dikkate alacak şekilde garanti edilir. @Sycren: akın, bize büyük bir varlık gibi görünse de, hala sadece küçük ölçekli bir etki. Bir balık okulu okulu takip etmez, gözlenebilir komşularını takip eder.
Richard Fabian

2

Quesiton'unuzu okuyarak dört ağaçtan yararlanabilir, dört ağaç oluşturabilir ve farklı bir işlem birimindeki her segment için simülasyon çalıştırabilirsiniz. Bu, yalnızca birbirine yakın nesnelere denetim yapılmasına neden olur. ancak her döngüde sizi dizileri senkronize etmeniz gerekir. Bu, bu tekliflerden bazılarının bir işleme grubundan diğerine aktarılması anlamına gelir. genel olarak her döngü 3 adımdan oluşur:

  1. Tüm teklifleri bir birim taşı. (birden fazla iş parçacığı kullanılarak kolayca işlenebilir)
  2. Her bir grubu bir gruba atama *. Bu, O (n) 'nin bir algoritmasını kullanarak, hangi modellerin bir çarpışma yapmasının en muhtemel olduğunu seçmeniz gerektiği anlamına gelir. Bu, birden fazla iş parçacığı kullanılarak da gerçekleştirilebilir.
  3. Sonunda, aynı gruptaki iki teklifin çarpışma yapıp yapmadığını kontrol etmelisiniz.

* Grup oluşturmak için aşağıdaki kalıbı kullanabilirsiniz:

resim açıklamasını buraya girin

bazı tekliflerin birden fazla grubun parçası olabileceğini unutmayın, ancak bu model size daha doğru sonuçlar verir. Ayrıca bu kalıbı kullanarak istediğiniz sayıda grup oluşturabilirsiniz, sadece kaç tane teklif ve hangi ekran boyutu için ekran bulmanız gereken bir sayıdır, oluşturmanız gereken en iyi grup sayısı nedir.

--Düzenle--

@LarsViklund'un önerdiği makalede açıklanan segmentasyon hakkında başka bir fikir daha var, bu şekilde daha az çift kontrol var ve adımlar arasında iş parçacığı sayısını artırmaya / azaltmaya gerek yok:

resim açıklamasını buraya girin

bazı alanların hala iki grubun bir parçası olduğunu unutmayın. ve alanın genişliği her iki grup tam olarak kaplıdır 2*maximum speed. Durumunuzda simülasyonlar simülasyon adımı başına bir piksel hareket ediyorsa, her 2 grup arasında yalnızca 2 piksel genişlik alanını paylaşmanız gerekir. ve 4 grubun parçası olan küçük bir alan vardır. ancak genel olarak bu yöntemin uygulanması daha kolaydır ve doğru şekilde uygulandığında çok daha hızlıdır. ve bu arada bu şekilde ters hareket olmaz, eğer bir nesne hareket edebiliyorsa hareket edebilir, başka kontrol gerekmez.


Kulağa iyi bir fikir gibi geliyor, ancak 1. adıma geçmeden önce, hareket edip edemeyeceklerini görmek için çarpışma tespiti yapmam gerekir mi?
Sycren

Onları hareket ettirebilir ve simülasyonun devam etmesine izin vermiyorsa, hareketin tersine herhangi bir çarpışma olup olmadığını kontrol edebilirsiniz (tam olarak satın almak için).
Ali1S232

Teşekkürler, bu daha mantıklı. Quadtrees dışında, iş yükünü bölmenin başka bir yolunu düşünebilir misiniz?
Sycren

Segmentasyonlarımın tamamen dörtlü bir ağaç olmadığını gördüğünüz gibi, doğruluğu artırmak için bir ekstra gruba daha sahip, dörtlü ağaç stilinin kullanımı çok daha kolay. Dünya boyutuna bağlı olarak daha fazla grup ekleyebilirsiniz, bu da her döngüde daha az kontrol anlamına gelir. anı tüketimi ve hesaplama hızı arasında bir değiş tokuş. ve her grup için mutlaka bir iş parçacığı olması gerekmez. birden fazla grubu hesaplamak için bazı evreleriniz olabilir. Ayrıca grup hesaplamalarını iki veya daha fazla iş parçacığı arasında bölebilirsiniz.
Ali1S232

@Gajet, resminizi doğru anlarsam, grupların çakışan alanları çok büyük olduğu için çok sayıda çift hesaplama olur. Sorunun milyonlarca noktaya benzetilmesini istediği göz önüne alındığında, bu çok büyük bir israf olacaktır.
Maik Semder

2

Son zamanlarda bu sorunun bazılarını başlangıç ​​noktası olarak kullanarak bu sorunu çözdüm. Akılda tutulması gereken en yararlı şey, tekliflerin bir nevi basit n-vücut simülasyonu olduğudur: her bir teklif, komşularına kuvvet uygulayan bir parçacıktır.

Linde gazetesini okumayı zor buldum; Bunun yerine SJ Plimpton'un Linde'nin referans aldığı "Kısa Menzilli Moleküler Dinamikler için Hızlı Paralel Algoritmalar" a bakmasını öneriyorum . Plimpton'un kağıdı daha iyi rakamlarla çok daha okunabilir ve ayrıntılı:

Özetle, atom ayrıştırma yöntemleri her işlemciye kalıcı olarak bir atom alt kümesi atar, kuvvet ayrıştırma yöntemleri her proc için çift kuvvet hesaplamalarının bir alt kümesini atar ve uzamsal ayrışma yöntemleri her proc için simülasyon kutusunun bir alt bölgesini atar .

AD'yi denemenizi tavsiye ederim. Anlaması ve uygulaması en kolay olanıdır. FD çok benzer. İşte nVidia'nın FD kullanarak CUDA ile n-vücut simülasyonu.

SD uygulamaları genellikle teknikleri optimize eder ve uygulanması için bir miktar koreografi gerektirir. Neredeyse her zaman daha hızlıdırlar ve daha iyi ölçeklenirler.

Bunun nedeni, AD / FD'nin her bir satınalma için bir "komşu listesi" oluşturmasını gerektirmesidir. Her bir alımın komşularının konumunu bilmesi gerekiyorsa, aralarındaki iletişim O ( n ²) 'dir. Eğer her adımın her birkaç dilimler yerine listesini yeniden olanak alanda her boid çekler, boyutunu azaltmak için Verlet komşu listelerini kullanabilirsiniz, ama yine de O (var n ²). SD'de her hücre bir komşu listesi tutarken, AD / FD'de her bir komşunun bir komşu listesi vardır. Böylece, her hücre birbiriyle iletişim kurmak yerine, her hücre birbiriyle iletişim kurar. İletişimdeki azalma hız artışının nereden kaynaklandığıdır.

Ne yazık ki, boids sorunu SD'yi biraz sabote ediyor. Her işlemcinin bir hücrenin izini sürmesi, teklifler tüm bölgeye eşit olarak dağıtıldığında en avantajlıdır. Ama tekliflerin birlikte kümelenmesini istiyorsunuz ! Sürünüz düzgün bir şekilde davranıyorsa, işlemcilerinizin büyük çoğunluğu birbiriyle boş listeler alıp değiştirecek ve küçük bir hücre grubu AD veya FD'nin yaptığı aynı hesaplamaları gerçekleştirecektir.

Bununla başa çıkmak için, herhangi bir zamanda boş hücre sayısını en aza indirmek için hücrelerin boyutunu (sabit olan) matematiksel olarak ayarlayabilir veya dört ağaçlar için Barnes-Hut algoritmasını kullanabilirsiniz. BH algoritması inanılmaz derecede güçlü. Paradoksal olarak, paralel mimarilere uygulamak son derece zordur. Bunun nedeni, bir BH ağacının düzensiz olmasıdır, bu nedenle paralel dişler, çılgınca değişen hızlarda hareket edecek ve iplik sapmasına neden olacaktır. Salmon ve Dubinski, dört paralel parçayı işlemciler arasında eşit olarak dağıtmak için dikey paralel çoğaltma algoritmaları sundular.

Gördüğünüz gibi, bu noktada açıkça optimizasyon ve kara büyü alanındayız. Yine, Plimpton'ın makalesini okumayı deneyin ve bunun mantıklı olup olmadığını görün.


1

Seninkinin toroidal bir sistem olduğunu varsayıyorum, her birimin kendi alt alanına sahip olması için uzaya bölünebilirsin.

Her adımda parçacıklar taşınır, alt alandan çıkan parçacıklar ilgili işlemciye gönderilir; bir iletişim adımı işlemcileri senkronize eder ve yabancı partiküllerin pozisyonunu (eğer varsa) detaylandırmak için son bir son adım alınır.

Burada üç sorun var:

  • 1) alt alanın şekli:

Dikdörtgenler tercih edilebilir, ancak daire ile karşılaştırıldığında küçük bir Alan / çevre oranı gösterir. Sınır ne kadar büyük olursa parçacıklar o kadar fazla kalır. Döngüler en iyi A / p oranını sergilemekle birlikte, mozaikleme için kullanılamaz, bu nedenle iyi bir ortalama A / p oranına sahip bazı (muhtemelen yarı düzenli) mozaikleme için su atmanız gerekir. Açıkça püskül indeksinin hücre koordinatı ile hesaplanması basit olmalıdır, bu yüzden çok egzotik bir tasselasyonu denemeden önce bunu düşünün.

  • 2) İletişim Protokolü:

Ne tür bir iletişim altyapısına sahip olduğunuza bağlı olarak, sınır ötesi bilgileri işlemciler arasında nasıl dağıtacağınızı düşünebilirsiniz. Yayıncılık ve eşler arası rekonstrüksiyon ve eşler arası iletişim tüm seçeneklerdir.

  • 3) Alt Alan Tahsisi:

Her adımda bir senkronizasyon olduğundan, detaylandırmanızı dengeli tutmalısınız. Alanları işlemcilere statik veya dinamik olarak ayırmayı seçebilirsiniz. Alanınız aktif olarak parçacıklar tarafından kaplanıyorsa, bu büyük bir sorun değildir, ancak çarpışmaların parçacıkları devre dışı bırakması nedeniyle bu durumda yanlış olabileceğine inanıyorum. tüm işlemciler sınır ötesi bilgileri paylaşıyorsa, ancak bu konuda biraz düşünmeniz gerekiyorsa bazı kısayollar alınabilir


@Fxlll Toroidal sistemden kastettiğinizden emin değilim, bir çörek şeklinde değil. Bir parçacık sağ taraftan çıkarsa, solda tekrar belirir mi demek istiyorsun? Eğer durum böyle değilse, eğer bir parçacık sağ tarafa çarparsa, farklı bir yöne doğru hareket etmeye çalışır.
Sycren

@Sycren ok bu durumda tasselasyon ve kenardaki alanı özel bir şekilde tedavi etme hakkında biraz düşünmelisiniz
FxIII

-1

İpuçları için simülasyonumu dene https://github.com/wahabjawed/Boids-Simulation

Bunu XNA'da geliştirdim


Tam bir projeye bağlantı vermek iyi bir cevap değildir. Okuyucu, soruyla ilgili kısmı bulana kadar kaynağınızı kazmaya zorlanır ve yine de sorunun nasıl çözüldüğünü anlaması gerekir. Lütfen soruna nasıl yaklaştığınızı ve diğer cevaplarda açıklanan çözümlere göre ne gibi avantajları olduğunu açık bir şekilde anlatabilir misiniz? Açıklamanızı anlamaya yardımcı olurlarsa, bazı kısa kod snippet'lerini cevabınıza kopyalayıp yapıştırabilirsiniz.
Philipp
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.