Picproje Elektronik Sitesi

SERBEST BÖLGE => Programlama ve Algoritma => Konuyu başlatan: z - 05 Ekim 2015, 14:16:12

Başlık: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: z - 05 Ekim 2015, 14:16:12
Yazdığımız program A ve B adındaki iki fonksiyondan oluşsun.

Bir döngü içerisinde A-B-A-B şeklinde fonksiyonları ard arda çağırıyor olalım.

A ve B 1 ms de işletiliyor olsun. Bu durumda bir döngü 2 ms de tamamlanacak demektir.

Eğer A ve B yi iki ayrı thread olarak yazarsam ve B ve A arasında veri aktarımı olmayacaksa

A ve B nin her ikisinin birden işletilme süresi 2 ms nin altına inebilirmi?

Eğer B, A nın çıktılarına ihtiyaç duyuyorsa bu durumda fonksiyonları threadlere ayırma herhangi bir avntaj getirirmi?


Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: vsalma - 05 Ekim 2015, 15:09:36
Alıntı Yap
A ve B nin her ikisinin birden işletilme süresi 2 ms nin altına inebilirmi?

Bu biraz threadlerin kullandigi kaynaklara bagli. Mesela A bir okuma yazma isi(veya memory allocation, database transaction vs.) bekliyosa, o beklerken B nin farkli threadde kosmasi toplam isletilme suresini kisaltir.

Ozellikle islemsel yuku agir A ve B icin farkli cekirdekte calistirma toplam performansi cok etkiler. (Tabi bu multithreading değil multicore)

Alıntı Yap
Eğer B, A nın çıktılarına ihtiyaç duyuyorsa bu durumda fonksiyonları threadlere ayırma herhangi bir avntaj getirirmi?
Birbirlerinden data bekliyorlarsa her halukarda hizli olan yavas olani bekleyecek. Threadlere bolmek veya multicore yapmak fayda getirmez gibi duruyor. Threading, haberlesme overheadleri gelecek...




Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: engerex - 05 Ekim 2015, 16:38:33
 Delphi'de multithread için omnithread oldukça kullanılıyor. Bunda mi veya hangisinde tam hatırlamıyorum ("ExThreads"dı): İşlemci kaç çekirdek görüyorsun. İstediğin thread istediğin çekirdeğe atayabiliyorsun. İstediğini thread istediğin zaman başlatıp durdurabiliyorsun. Hepsine ayrı ayrı öncelik atayabiliyorsun. (Yüksek öncelik verirsen diğer açık uygulamalardan daha az etkilenirler.) Kaç thread aktif görebiliyorsun. Normalde de yapılan şeylerdir ancak bu bileşenle oldukça kolay şekilde yapmıştım.
Bir ara test etmiştik. İşlemci 4 çekirdek. Her birine 1'er thread atıyordum. Hepsi aynı işlemi yapıyor. Tamamlanma süreleri t1: 5150ms, 5010ms, 5051ms, 5020ms gibi aralarında farklar oluyor. Buda açık diğer uygulamalardan kaynaklanıyor.

Eğer threadlar durmaksızın peş peşe çalışacaksa ayrı ayrı olarak ayrı çekirdekte çalışmaları daha hızlı sonuç verecektir. Ancak arada bekleme zamanı varsa ayrı ayrı çalışmalarına gerek yok. Asenkron thread olursa çalışma anında birbirleriyle haberleşemezler.
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: z - 05 Ekim 2015, 17:03:23
omnithread için basit bir kod örneği verebilirmisin?
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: Icarus - 05 Ekim 2015, 18:14:43
A ve B'nin algoritmalarının bu işe uygun olarak tasarlanması lazım.
A ve B ortak veri kullanmalarına rağmen asla birbirlerini beklemeyecek şekilde dizayn edilebilirler. Aynı veriyi kullanmalarına rağmen seknronizasyon araçlarını kullanmazlar (Evet bu yazdıklarım konvensiyonel fikirlerle çelişiyor gibi gözüküebilir ama değil sadece modern)
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: z - 05 Ekim 2015, 19:52:05
Eeee.

Devamı getir. Nasıl yani?
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: Yuunus - 05 Ekim 2015, 20:27:15
Ben de meraklandım şimdi!!! Thread lari durdurma devam ettirme oncellik bunlari biliyordum ama core bazli yazilabiliyorsa super.
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: engerex - 05 Ekim 2015, 20:38:29
 Eğer B A'nın sonucunu beklemeye mecbursa
Alıntı Yap
Burada olduğu gibi
A1
B1
A2
B2
...
An
Bn

Alıntı Yap
Bizde 2 kat hız sağlayan bu yolu izleriz
A1
B1 A2
B2 A3
...
Bn-1 An
Bn

Sadece ilk ve son işlem tek.

Teknikte yeri var mı? Şimdi aklıma geldi.
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: z - 05 Ekim 2015, 20:54:40
Şu anda kağıda yaptığım karalamaları ne zaman gördün.

Motorun akımını hesapla, akımdan torku hesapla, torkdan motor milinin yeni konumunu hesapla ardından motorun mil açısından yararlanarak arabanın tekerini döndür ve arabanın konumlandığı yeni koordinatı hesapla

Şeklinde iki fonksiyonu arka arkaya işletmek yerine

Threadlere ayırırsak

1. Thread: Motorun mil açısından yararlanarak arabanın tekerini döndür ve arabanın konumlandığı yeni koordinatı hesapla
2. Thread: Motorun akımını hesapla, akımdan torku hesapla, torkdan motor milinin yeni konumunu hesapla

Şekline dönüştürebiliriz.

Bu durumda

Bir fonksiyon diğer fonksiyonun sadece 1 önce ürettiği sonuçları kullanabilir.

Threadlerin 1 ms de bir çalışmasına izin verirsem 1ms lik  gecikme elemanı koymuş gibi oluruz.



Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: sovalye - 05 Ekim 2015, 22:50:09
hocam, bu tarz fonksiyonları niye thread lara ayırmak istiyorsunuz? Hesaplanmaları zaten ne kadar sürebilir ki. Ayrıca thread lara ayırmak core seçiminde pek etkili değil, olay yine işletim sisteminin kararı. İlla farklı core larda paralel çalışsın istiyorsanız ya kodunuz işletim sistemininden daha alt seviyede çalışacak yada profesyonelce yazılmış multi thread uygulamalarından faydalanmalısınız veya kodu önceden kararlaştırdığınız bir core un içinde çalışmaya zorlayacaksınız (pek önerilen bir yöntem değilmiş daha önce okuduğuma göre )
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: z - 05 Ekim 2015, 23:00:48
Saniyede 1000 kere hesap yapıp robot koordinatlarını hesaplamayı fakat ekrana saniyede 50 tane hareketli robot görüntüsü  basmayı deneyeceğim.

Ekrana görüntü basan fonksiyonla hesap yapan fonksiyonu thread yapmam daha mantıklı.
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: sovalye - 05 Ekim 2015, 23:20:11
niye saniyede 1000 kere diye bir sınır koyuyorsunuz? Bırakın program bulabildiği tüm kaynakla çalışssın. Bir saniyeyi 1000 parçaya ayrılmış halde modellemeniz bu şekilde hesaplamak zorunda olduğunuzu göstermiyor. programın hesap kısmı 1 sn de işini bitirsin sonra 15 saniye o görüntüyü gösterebilirsiniz.
aynısı görüntü içinde geçerli bırakın çalışsın. Kaynak tasarrufu yapmak istiyorsanız 50 fps hesaplamak biraz israf gibi geldi. Eğer büyük baskı altındak bir pro oyuncu veya jet pilotu falan değilse , tüm insan gözleri 24 fps(standart sinema) yada en en kötü 30fps ' nin üzerindeki görüntüleri devamlı olarak görür.

// bu örnek için yazmıyorum ama ilginç gelmişti. 50 fps üzerindeki sürekli harekete sahip görüntü insan gözünü yorup, arada çok fazla frame kaçırmasına sebep olarak, görüntünün donduğu hissine sebep oluyormuş.
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: 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.

Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: engerex - 05 Ekim 2015, 23:53:54
 Saniyede 1000 kez hesaplayacaksan multithread gerek var mı? Saniyede kaç hesap yapıyor? Motorun akımını hesapla, akımdan torku hesapla, torkdan motor milinin yeni konumunu hesapla ardından motorun mil açısından yararlanarak arabanın tekerini döndür ve arabanın konumlandığı yeni koordinatı hesapla Bu döngüyü 1 milyon kez çağırsan kaç saniye sürüyor? PIC/Atmel 16Mhz veya STM32 168 Mhz'ye yakın sabit bir performans baz alınabilir.

@sovalye fps olayı dediğin kadar kesin olsaydı oyuncular 50 yerine 100 fps için veya 60 hz yerine 120 hz yerine fazladan nede para veriyor? Evet olayın büyük kısmı hastalık ama 50 ile 100 fps arasındaki akışkanlığı farkedebiliyorsun.
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: sovalye - 05 Ekim 2015, 23:56:45
"Robot simülatör bir program, robot kontroller ayrı bir program." anlamadım. hazır bir kütüphane mi kullanıyorsunuz? Eğer ikisinide siz yazıyorsanız niye böyle bir düzenlemeye gittiniz ? Yarışmacıdan gelen kodu bir program test eder, diğeri sonucu ekrana video şeklinde basar.
"Robotun gerçekteki hızında hareket edebilmesi için gerçek zamanda hesap yapmam ve ekrana basmam lazım." niye ?
"1 saniyede tüm hesapları yapmak  ardından 15 saniye görüntü göstermek olmaz. Programlar etkiye tepki prensibinde işlemek zorunda. " Ekrana resim çizecek bir programcık nasıl bir tepki verecek ?

programın hızlı kısmı matematik işlemleri yapan kısım. yavaş kısmı ekrana basan kısım. Siz bunları hızlı çalışsınlar diye thread lere ayırmak istiyorsunuz ama o kadar da hızlı çalışmasınlar mı istiyorsunuz?
Smülatörün içini bilmiyorum ama istediğiniz kadar kompleks yazın matematiksel işlemleri yapması çok çok kısa bir süre alacaktır. Ama ekrana basması normal yarışma zamanı sürecek yani niye bunları aynı zamanda bitirmek için boş yere hızlı olan kısmı boşta bekletmek istiyorsunuz?
Sadece her saniye için 24 tane konum verisine ihtiyaç duyan bir fonksiyonla niye saniyede 1000 kez iletişime geçip bir de bundan karşı veri almak istiyorsunuz anlamadım.

Demek istediğim bütün matematiksel işlemleri bir yere toplayın, bunların en genel sonucu arabanın hangi 24'te 1 lik saniye aralığında nerede olacağı değil mi? bu küçücük veriyi program kendi içinde saklasın daha sonra her ekrana basma döngüsünde çizim yapan fonksiyonunuz bu veriyi alsın. Bu veriye göre arabayı konumlandırıp, kullanıcıya göstersin.


mesaj birleştirme:: 06 Ekim 2015, 00:05:58

@engerex hocam, anlık olarak veya beyin kendini tehlikede hisstettiğinde algılayabildiğimiz fps çok daha yükseliyor(oyunlarda bunun içinde tabiki bir anlık heyecanla) ama burada gösterilecek şey en nihayetinde bir video olduğu(izleyen kişi aktif olmayak sadece sonucu izleyecek) 24-30 fps yeterlidir dedim. Yani oyun anında ne kadar 100 fps gerekiyor desede dvd görüntüsü için bu şey takılarak geçiyor diyen kişi görmedim.
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: engerex - 06 Ekim 2015, 00:13:36
Zaten 30 50 fps pekte farketmez. 2d resmi döndürüp pencerede konumlandıracak. Hesap bu.
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: z - 06 Ekim 2015, 00:29:57
@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?
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: fatih6761 - 06 Ekim 2015, 00:33:55
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.
Başlık: Ynt: Wındows için yazdığımız programda fonksiyonları parçalamak - Thread
Gönderen: z - 06 Ekim 2015, 00:34:48
@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.