Şimdi Ara

C# Threading

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
1 Misafir - 1 Masaüstü
5 sn
14
Cevap
1
Favori
2.241
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
Öne Çıkar
0 oy
Sayfa: 1
Giriş
Mesaj
  • Merhabalar,
    C# ile bir takım oyunlar, grafik programları vb. geliştiriyordum. Bunları yaparken şimdiye kadar programı & oyunu güncel tutmak için hep Timer kullandım (Veya XNA'in kendi güncelleme sistemi var). Ama Timer performans olarak çok düşüktü, bu yüzden forumdakilerin tavsiyesiyle Threading kullandım. Saf bir formda benim bilgisayarımda 6000 fps gördüm :), oyunun içine gömünce muhtemelen benim kodlamamdan dolayı fps yine düşük oldu tabi. Sonuç olarak ne kadar güvenilir, ne kadar iyi bir yol bilmiyorum ama bundan sonra Threading kullanacağım, bununla ilgili bilgisi olan varsa yorumlarınızı bekliyorum. (Mesela Thread'i direk olarak çalıştırdığımda ve içine sonsuz while döngüsü koyduğumda Windows bir takım işlemleri yapamadı, bunun için döngünün her adımında Sleep yaptım, bunu da internetten gördüm bu şekilde fps kontrol altında tutulabiliyor, hem de arkadaki işlemler de gerçekleşebiliyor.)



    _____________________________




  • Timer'ın ile çağırdığın fonksiyonların içinde çok oyalanma. Mesela döngüye falan girme. Başka şekillerde halletmeye çalış.
    Thread kullanabilirsin. Ama onunda bi sınırı var ve thread kullanırken dikkatli yazman gerekiyor. Yoksa zırt pırt çöker programın. Burda bişeyler anlatmış :http://www.csharptr.com/cta-thread-kullanimi
    Detaylı bir google aramasıyla bolca kaynağa ulaşabilirsin. Bu arada tam olarak ne yaptığını yazarsan daha fazla şey söyleyebilirim sana. Mesela timer'la oyununda tam olarak ne yapıyosun.
    _____________________________
  • Bu amaçla kanal kullanmak yanlış olur. Kanal içinde sonsuz döngü %100 cpu kullanımına ve oyunun çok hızlı güncellenmesine yol açar. Kanalı uyutmakta çözüm değil, ne kadar uyutacaksın? sleep(20) yapsan 50 kare zamanı sadece uykuda geçecek! Ayrıca kanal değişimi de belli miktarda zaman alır.

    Performans düşüklüğü timer veya thread ile değil, senin kodunla alakalı. Bildiğime göre windows sistemlerde max 15ms timer hassaslığı var. 20 ms ye ayarlarsan 50 fps alırsın, bu çoğu uygulama için yeterlidir. Fakat 50 kare yi tutturabilmek için timer event içinde en fazla 20ms oyalanman lazım (bir sonraki periyot ateşlenene kadar) yoksa fps düşer.
  • yanlış düşünüyosun thread olayı bu şekilde kullanılamaz. her işlemcinin bir thread kapasitesi var fazlasını kullabilirmisin ? evet kullanırsın ama performans sıkıntısı olur. her programda bi sonsuz while döngüsü olduğunu düşün sen görmüyosun ama açtıgın form app dede bi while döngüsü var herşey o şekilde çalışıyor zaten timerda öyle thread den aldığın performansı timerlada alabilirsin yeterki nerde nasıl kullanıcağını bil.
    _____________________________
  • Peki yanlış bir kullanım olduğunu öğrendim, ama dediğiniz gibi timerla bu performansı alamıyorum, tamam kodlamam kirli olabilir, ama bir rectangle boyarken bile düşer mi fps, daha oyun aşamasına gelmeden düşmeye başlarsa fps, zor iş. O zaman ben nasıl çizdireceğim oyunumu? Timer'la mı? Yoksa hazır bir update sınıfı var mı, performanslı ve güvenli bir şekilde güncelleme yapabilen?
    _____________________________
  • Hepinize birden alinti yapamadigimdan ortaya yaziyorum, umarim okursunuz.

    Simdiye kadar oyunu en cok yoran kismin cizdirme oldugunu dusunerek, hep cizdirmeyle ilgili performansi nasil yukseltirim diye dusundum. Ornegin bu son oyunda 50x50 2500 tane kare var, her biri 30x30 pixel buyuklugunde. İste karelere bina, adam yapiliyor vesaire. Simdi bir framede 2500 tane kare cizmek sacmalik olacagindan, oyun baslarken butun kareleri bir bitmape cizdirip, her framede ekrana o bitmapi cizdiriyordum. İste karelerin ustundeki nesneleri cizerken, kameranin gorus alanini kontrol ediyordum vesaire.

    Ama simdi geldi aklima, mesela oyun 25 fps ile cizim mi yapiyor, o zaman saniyede 25 kere de update yapiyor. Yani her framede oyun 2500 tane kareyi, her karenin varsa icerdigi nesneyi guncelliyor. Bir de formun kendi gorevleri var tabii, mouse move, click, keypress gibi. Mesela hic bu update konusunda nasil performanstan kazanirim diye dusunmemistim. Sizce nasil kazanirim, mesela saniyede bir update, 20 kere draw nasil olur? ( bu arada draein yavaslamasina bir neden de sanirim matematiksel hesaplarimin uzunlugu, kendi 2 b kamera sinifim var, ve bir nesne cizilmeden once her framede, kameradaki yeri, kameranin zoomuna gore yeni pozisyonu hesaplaniyor)

    sordugum sey aslinda, nasil hileler yapabilirim? Update ile drawi ayni

    tutmamdaki neden "uyumsuzluk olurmu?" kuskusuydu hep.

    < Bu ileti mobil sürüm kullanılarak atıldı >
    _____________________________




  • welrocken
    Kullandığın draw metodları directx veya opengl hızlandırma destekliyorsa (kesin öyledir) çizim olayını hiç kafana takma. En zayıf ekran kartları bile o kadar sürede milyonlarca çokgen çizer. Söylediğin matematiksel hesaplar ise ortalama bir cpu için en fazla 1 ms lik iş.

    Bu kadar basit işlemlerde fps düşüşü yaşıyorsan sorunu daha derinlerde aramalısın. Daha önceden bir tavsiye vermiştim, uygulamayı profiling ile analiz et. Bunu yapmak için önce cpu harcayan kısımları ayrı metodlar içine al. Mesela draw metodunu ciz() diye bir metodun içine al. Run ayarlarında profile diye birşey vardır onları kurcala. Visual studio falan kullanmadığım için tam bilemiyorum.

    Uygulama çalışıp sonlandıktan sonra sana metodların çalışma sürelerini, %kaç program zamanı harcadıklarını falan gösterir. Oradan sorunu bulabilirsin bence. Tabi başka çözümlerde olabilir mesela draw ın başına bir tick count koyup bitince kaç tick olduğunu (çalışma süresini) bulmak gibi.




  • Yapay Zeka’dan İlgili Konular
    Asus RTX 3070 Dual O.C
    5 yıl önce açıldı
    Daha Fazla Göster
  • Saniyede 1 Update, 20 Draw için şöyle bir şey yapabilirsin; ancak elektro_gadget'in söylediği gibi sorun başka bir yerlerden kaynaklanıyor olsa gerek:

    static DWORD lastUpdate = 0; 
    Update()
    {
    if (GetTickCount() - lastUpdate > 1000)
    {
    // kodlarin
    lastUpdate = GetTickCount();
    }
    }


    C++ örneği bu, C# konusunda kafadan yazacak kadar bilgili değilim; ancak çok benzer olduklarına eminim. Kolay gelsin. :)



    < Bu mesaj bu kişi tarafından değiştirildi qamyoncu -- 31 Ağustos 2012; 9:33:02 >
    _____________________________
    Yanmışsam, külümden doğacak bir hisar vardır.
  • timer la yaptığın örneğin kodunu ve aldığın performansı buraya yaz bakalım nerde yanlış yapıyosun.
    _____________________________
  • Grafik kartını kullanmayı dene. Çizimleri GL yada directX ile ekran kartı hafızasına at. Nesneleştirme program başında yapıldığında geri kalanı ekran kartı yapacağı için hız problemin olmaz. Tek yapacağın nesnenin kordinatlarını ve açılarını değiştirmek olur. birkaç double değiştirmek işlemciyi yormaz.
    _____________________________
  • Merhabalar,

    Eğer bir oyun geliştiriyorsan bunu forms üzerinde yapmanın pek bir mantığı yok eğer istediğin güzel bir framerate de çizimler gerçekleştirmekse sana bir kaç tavsiye verebilirim;

    1-) Eğer 2D bir oyun üzerine gideceksen platform odaklı çalışman (Örneğin mobil platformda çalışacaksan zaten 30 (Teorik 24) fps'den fazlasını istemezsin, bunu XNA da şu şekilde sağlarsın: TargetElapsedTime = TimeSpan.FromSeconds(1.0f / 30.0f);

    2-) Bir diğer yapacağın iş ise, Her draw çağrısından önce update çağsını yapmamasını istemendir(Saniyede 30 kere değil, draw dan önce). Default olarak bu açıktır bunu kapatmak için XNA da yapacağın iş: IsFixedTimeStep = false;

    3-) Bazı zamanlarda GPU kendi yaptığı işlemleri bitirip hemen Draw çağrısını yapmak ister, ancak Update CPU da yapıldığı için CPU daha işini bitirmemiş olabilir, GPU nun yaptığı her çağrıyı işlemesi için kullanacağın kod: graphics.SynchronizeWithVerticalRetrace = false;

    Yani şu şekilde toparlamam gerekirse;

    30 FPS de Sadece kendi kontrolünde bir çalışma prensibi istiyorsan (Update() <-> Draw()) şeklinde, yapman gereken şey;

    Initiliaze() Methodu içine;

    TargetElapsedTime = TimeSpan.FromSeconds(1.0f / 30.0f); 
    IsFixedTimeStep = false;
    graphics.SynchronizeWithVerticalRetrace = true;


    Gelelim 3D çizim işlemlerine; Sanılanın aksine triangle (şekilleri (model) oluşturan üçgenler) çizimi grafik kartını en az yoran işlemdir, ortalama bir grafik kartı aynı sahneden milyonlarca poligon çizebilme kapasitesine sahiptir, grafik kartlarını yoran üç işlem vardır,

    1-) Texture çizimi; texture çizimi ve UV yerleştirilmesi bir grafik kartı için yorucu işlemlerden biridir.
    2-) Shader processing; grafik kartına bir poligon topluluğunun piksellerini ekrana ne şekilde/renkte/ışıkta v.b. koşullarda çizileceğini/ışıklandırılacağını hesaplatmak.
    3-) Post Processing; Shader processing içine girsede ayrı yorumlamak gerekir, çünkü zaten çizilmiş hesaplanmış bir GBuffer üzerinde her piksel için ayrı işlem yapmak gerekeceğinden ekran kartını (GPU) yoran bir diğer işlem de budur.

    Umarım yardımcı olmuştur.



    < Bu mesaj bu kişi tarafından değiştirildi sehlor -- 31 Ağustos 2012; 11:08:09 >
    _____________________________




  • Hepinize cok cok tesekkur ederim, bilmedigim konularda aydinlattiginiz icin. Aksam mesajlari tek tek sindirip, soylediklerinizi bir deneyeyim, kolay gelsin.

    < Bu ileti mobil sürüm kullanılarak atıldı >
    _____________________________
  • elektro_gadget, dediğiniz profiling olayı benim express'te yokmuş malesef. Öğrenciyim diğer versiyonları almam şuan için pek mümkün değil, o yüzden onu yapamadım.

    qamyoncu, elektro_gadget'ın dediği yerde (Metodların çalışma süresi) bunu kullanacağım sanırım, teşekkürler.

    aLiM KaFKeF Örnek değil de bir oyun, bütün kodu buraya yazmam pek mümkün olmaz ama kısaca şu şekilde çalışıyor;
    Timer'ın tick olayında; Game'in Update'i çağırılıyor, game update edildiğinde, kullanıcıların sıralarını hesaplıyor (Rome Total War tarzı sıralı bir oyun), sıralar hesaplandıktan sonra, şuan oynayan oyuncunun update'i çağrılıyor. Daha sonra Game sınıfının Draw'ı çağrılıyor, Game sınıfımda, ilk önce Map sınıfın çizdirmesini çağırıyorum (O da 10bin x 10bin pixellik bir bitmapi arkaplana harita olarak çizdiriyor, bir de 100x100 toplamda 10bin tane de "line" çiziyor ,Aslında onu da bitmapa atsam daha iyi olur), daha sonra kullanıcıların çizdirilmesi yapılıyor, en son menüler (Üst bar, alt bar vb.). Oyun döngüsü bu kadar. Tabii bir de formun mouse olaylarında da Game'e gönderme yapıyorum, MouseClick MouseMove gibi. Özellikle hata yapabileceğim bir yer olduğunu düşünüyorsanız o kısmı yazabilirim, genel olarak uzun bir kod çünkü.

    goçhisar C# ile DirectX kullanmayı denedim, olmadı izin sorunları mıdır nedir bilemedim, C++ ile o işe başlayınca öğreneceğim inş. bu olayları, teşekkürler.

    sehlor Zaten sayenizde XNA öğrenmiştim, şimdiye kadar birkaç ufak şey yapmaya çalıştım ama XNA'in Drawing.Graphics'ten farklı olması hep delirtti beni. Bir rectangle çizdirmek falan çok zordu. Şimdi (dün) bir şekilde Line çizdirmeyi öğrendim, dolayısıyla artık Polygon çizdirebilirim, Bir sitede de Vertex Shader kullanarak, polygon boyamayı anlatmış, onu da öğrendimmi zaten boşu boşuna kasmam Forms'da. Çok teşekkür ederim.

    Herkese kolay gelsin.

    + Bir soru daha sorayım yeni konu açmadan, belki gören olur;

    Konu Geometri,
    Yapmak istediğim şey ise çokgenleri üçgenlere bölmek.
    Dışbükey çokgenlerde bu epey kolay oluyor, bir noktadan başlıyorsunuz, iki komşu köşesi ve kendisi hariç tüm noktalara birer çizgi çektinizmi, n kenarlı çokgen n-2 tane üçgene ayrılmış oluyor.
    Ama içbükey çokgenlerde bu kural işlemiyor,
    Bunun için bir algoritma kurdum, henüz test edemedim dershane falan filan. Test edeceğim ama önce bu konuda bilginiz var mı diye sormak istedim, Amerikayı yeniden keşfetmeye gerek yok.
    Algoritmam (Normal algoritma değil sadece sıralı söz dizimi) şu şekilde ilerliyor; (Bu arada, parametre olarak Nokta dizisi alıyoruz,
    1-Bir dizi kenar (İki nokta içeren bir sınıf) tanımlanır.
    2-kenar dizisine şeklin bütün kenarları atılır (n tane nokta için n tane kenar, for döngüsü ile oluşturulur)
    3-Şeklin köşe nokta sayısı - 2 kere 4'e git;
    4- 3'ten gelen index'e ait nokta için;
    index-1 (index 0 ise burası şeklin köşe sayısı, yani son noktası olacak) ,index ve index+1(index sonda ise burası 0, yani ilk nokta olacak) hariç, şeklin tüm noktaları için 5'e git (index2);
    5-Gelen iki nokta (index, index2) 'dan bir doğru parçası oluştur, Bu doğru parçası, ilk adımda oluşturduğumuz kenar dizisinden herhangi birinin İÇİNDEN GEÇİYORSA (uç uca olmaması gerek) İPTAL, Hiçbirinin içinden geçmiyorsa;
    Yeni doğru parçasını, sanki şeklin bir kenarıymış gibi yukarıdaki diziye ekle. Bu nokta için iş bitti.

    Bu adımlar sonlandığında elimizde;
    -Bir tane ana şekil, n kenarlı.
    -İçinde n-2 tane üçgen.
    -Dışta n tane kenar, içinde ise n-3 tane üçgen oluşturmak için kullanılan doğru parçaları.
    -Yani toplamda n-2 üçgen, (n+n-3) 2n - 3 tane doğru parçası var.

    Yapmadığım şey ise;
    Bu kenarlardan üçgen oluşturmak, onun için de ayrı bir algoritma yazdım ama boşu boşuna uzattığımı düşünüyorum.
    Sorduğum şey ise, yukarıdaki algoritmada, bir kenar çizildiğinde MÜMKÜNSE hemen üçgeni oluşturup bir kenara (yine bir dizi olabilir), atmak.

    Sizce yukarıdaki algoritma da bunu nasıl yaparım? Herkese kolay gelsin, şimdiden teşekkür ediyorum.
    _____________________________




  • Birilerinin görmesi umuduyla yeni konu açmadan sorumu soracağım. Ama öncelikle herkese tekrardan teşekkür ediyorum. Timerla threadin yaptığını yapabileceğimi söylemiştiniz. Ama acemilik iste dinlemedim sizi :). Ama sanırım performans düşüşüne neden olan şeyi buldum. Bitmapler, ozellikle benim yaptığım bir projede çok saçma şeyler yaptım. Oncelikle bir spritebatch sınıfı yazdım, XNAyi taklit ederekten. İki graphics nesnesi tutuyordu bu sınıf. Birisi ana kaynak(form) birisi de gecici grafik. Gecici olana butun cizdirmeleri (bitmap, polygon, string) yapip, butun cizimleri ana bitmape atiyordum. En son End() metoduyla ana bitmapi de kaynak graphicse cizdiyordum. Bu aslinda bildigim kadariyla double buffering mantigi. Asil sacmaladigim nokta ise bana gore oyun icerigi. Harita buyuklugunde bir bitmap 10000x10000 pixel, minimap diye baska bir bitmap. Herseyi birebir ayni olan binalar, adamlara bile birer bitmap atmışım, sanırım asıl sorunu bunlar çıkarıyor. Bunun yerine image sınıfını kullansam ve ortak resmi paylasan nesnelere tek tek resim degiskeni tanimlayacagima, hepsini bir static degiskenden ceksem daha mantikli olur diye dusundum. Baska neler yapabilirim? Veya bu yaptiklarim da hata var mi?

    < Bu ileti mobil sürüm kullanılarak atıldı >
    _____________________________




  • 
Sayfa: 1
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.