Wındows için yazdığımız programda fonksiyonları parçalamak - Thread

Başlatan z, 05 Ekim 2015, 14:16:12

engerex

Zaten 30 50 fps pekte farketmez. 2d resmi döndürüp pencerede konumlandıracak. Hesap bu.

z

@sovalye

Ne demek istediğini anladım.

Fakat;

Windowsda iki program birbirlerine 32 bit datamı al - 32 bit datanı gönder mantığıyla veri takası yapacaklarsa 1ms den daha kısa sürede veri değiş tokuşu yapamazlar değilmi?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

fatih6761

Alıntı yapılan: z - 05 Ekim 2015, 23:32:40
Sorun şu. Robot simülatör bir program, robot kontroller ayrı bir program.

Bu iki program sürekli olarak veri paslaşacaklar.  Robotun gerçekteki hızında hareket edebilmesi için gerçek zamanda hesap yapmam ve ekrana basmam lazım.

Saniyede 50 kez görüntü basma ağzımdan çıkan öylesine bir söz. (TV tarama hızından)

Ancak saniyede en azından 1000 kere iki program veri paslaşması yapmak zorunda. Saniyede 25 kare basarsam 1000/25 her 40 paslaşma ardından ekrana bir kare çizdirmem gerekecek.

1 saniyede tüm hesapları yapmak  ardından 15 saniye görüntü göstermek olmaz. Programlar etkiye tepki prensibinde işlemek zorunda.

Hocam PC için fonksiyonları yazdıktan sonra ayrı bir yazılımla veya mantık yürütmeyle basit bir "profiling" yapabilirsiniz. Böylece fonksiyonlarınızın aslında nerede oyalandığını görürsünüz.
Benim son zamanlarda karşılaştığım en önemli kavram bellek erişim hızı.
İşlemcilere bağlı genelde 3 çeşit bellek oluyor. Bunlar L1 ve L2 cache ve RAM (main memory).
L1'e erişim 2-3 cycle gibi çok kısa bir süre iken işlemciye göre L2 ye erişim 10-20 cycle, RAM'e erişim ise 100-200 cycle gibi sürelere ulaşabiliyor.
Bu sıkıntıyı çözmek için tasarımcılar verileri cache'ye almak için donanımsal iyileştirme sistemleri geliştirmişler. Mesela sizin programınız bellekteki sırayla her 4. veriyi okuyup acc ile topluyorsa donanım cacheye otomatik olarak sadece bu dördüncü verileri koyarak ciddi bir perfromans artışı sağlayabiliyor. Bu aşamada üç önemli nokta var.
1) Cross Thread safety of Cache: Mesela bir işlemci düşünelim. 2 çekirdek ve L1 cache boyutu 64-bayt olsun.
RAM'de oluşturulan 64-baytlık bir dizinin birinci thread ilk 32 elemanını, ikinci thread son 32-elemanını toplayıp register'a yazıyor olsun. Bu durumda threadlerin cache'lerine 0-64. baytlar alınır(alınabilir). Birinci thread aslında ikincinin bölgesine hiç dokunmuyor olsa da cache'e yapılacak bir yazma işlemi ilgili bellek alanındaki tüm cache'lerin "dirty" olarak işaretlenmesine sebep olur. Dirty olarak işaretlenen tüm cache ler bir sonraki instruction işlenmeden yenilenir. Bu da tekrar RAMden okuma anlamına gelir ki cache hızının hiçbir anlamı kalmaz.
Mesela bir dizinin elemanlarını tek bir değişkene topyalacağız. Bu thread'lerin her birinde bu ortak değişkene doğrudan ekleme yaparsak paralel kullanılan çekirdekler tek çekirdekte sıralı imiş gibi çalışmak zorunda kalır.
Çünkü bizim değişkenimize bir çekirdek erişmek istediğinde diğerlerinin tamamının işinin bir anlığına bitmesini beklemek zorundadır.
Ama her threade ayrı bir değişken verip, değerleri bu değişkenlere toplayıp en sonda bu ara toplamları toplayarak asıl sonucu elde edersek çekirdek sayısı kadar yüksek bir performansa ulaşabiliriz.

2) Locality of Reference: Bu da genel olarak bir dizinin en çok erişilen elemanlarının yakın tutulması ve böylece caching işleminin en verimli biçimde yapılabilmesi ile ilgili.
Diyelimki bir binary search işlemi yapıyoruz. Bu işlemde her aramada ilk kontrol edilen eleman dizinin ortanca elemanıdır. Sonra duruma göre üst veya alt yarının ortanca elemanı... diye gider. Ama bir istatistik yaparsak en çok başvurulan eleman ortancadır. Dolayısıyla ortanca elemanı, üst-alt yarının ortanca elemanlarını ve sonraki en sık kullanılan elemanları bellekte yakın -hatta mümkünse art arda- koymak cache'i düzenleyen donanımım sıralamayı daha kolay anlamasını sağlar.

3) DOD (data oriented design): Bu da yine cache ile ilgili. Mesela şu iki kod parçasına bakalım:
typedef struct {
	float x;
	float vx;
	char name[30];
} s_object;

s_object space[100];

void evaluate_objects(s_object *p, float dt)
{
	int i;
	for (i = 0; i < 100; ++i)
	{
		p[i].x += p[i].vx * dt;
	}
}


float x[100];
float vx[100];
char *names[100];

void evaluate_objects(float *px, float* pvx, float dt)
{
	int i;
	for (i = 0; i < 100; ++i)
	{
		x[i] += vx[i] * dt;
	}
}


İlk kodla ikinci kod aynı şeyi yapsalar da performansları çok farklı olur.
Neden? s_object struct'ının boyutu en iyi ihtimalle 38 bayt. Dolayısıyla 64-baytlık bir cache'e yalnızca bir tane nesne sığabilir. Geri kalan 26 bayt her döngüde çöp olur ve tekrar tekrar bellekten okuma yapılır.
Halbuki ikinci örnekte bir register'da dt değeri tutulurken x-vx çiftlerinden 8 tanesi tek seferde cache'e alınabilir (en iyi durumda tabi). Ana bellekten okumaya göre 8 kata kadar hızlanma sağlar. Tabi modern işlemcilerde L3 cache de mevcut ve kullanımı (çekirdekler arası paylaşımı) daha farklı olabiliyor ama bu cache'lerin nasıl kullanılacağına programcı olarak biz doğrudan karar veremiyoruz. Derleyici+Donanım bunu belirler ama belirttiğim ve daha bilmediğim birçok yöntemi kullanarak onların işini kolaylaştırabiliriz.

Hocam bir de veri paslaşması olarak bahsettiğiniz işlemde bir taraf sadece yazacak, diğer taraf sadece okuyacak ise queue(kuyruk) yapısı kullanmak daha mantıklı olur. Siz kuyruğun süreki arkasına basarsınız verileri, alıcı fonksiyon sürekli kuyruğu başından okur. Böylelikle hiç birbirlerini rahatsız etmezler. Kendi PCscope çalışmamda (sizikinden esinlendiğim) bu yöntemi kullandım. Bir thread USB den okuyup sıfır geçişleri tesbit edip kuyruğa basıyor. Diğer thread sıfır geçişlere göre ekranın yenilenmesi gerektiğinde ekrana basılacak kadar veriyi kuyruktan alıp ekrana basılacak diziye atıyor basitçe.

z

@sovalye

Tamam tamam şimdi anladım.

Simülatörü DLL olarak verirsek windowsda iki programın paslaşması sorunu kalkar. Ok.

Bu durumda gerçek robotların 2 dakikada bitireceği yarış PC de bir kaç yüz mili saniyede biter. Bu esnada konum bilgileri depolanmış olur. Daha sonra yavaş yavaş yarışmacıya film izletirim.





mesaj birleştirme:: 06 Ekim 2015, 00:39:23

Ben sanki gerçek bir elektrik motorunu bilgisayar yazılımı ile kontrol edecekmişim gibi şartlanmışım. Motor da sanal olunca istediğim gibi hızlı simülasyon yapabilirim.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com