2013-08-26 19 views
5

Bazı kodları pencerelere yüklüyorum ve iş parçacığının son derece yavaş olduğunu buldum. Görev, pencereler üzerinde 300 saniye (iki xeon E5-2670 8 çekirdekli 2.6 ghz = 16 çekirdekli) ve 3,5 saniye (linux üzerinde xeon E5-1607 4 çekirdekli 3 ghz) alır. Vs2012 ekspresinin kullanılması.Pencereleri bağlama konuları. Kritik bölümler çok yavaştır

Tüm Std :: stack, SignCriticalSection ve bazı çalışma (toplamda 250k iş) bir 80 byte işi haşhaş, tüm EnterCriticalSection() çağıran 32 iş parçacığı var.

Her önemli bölümden önce ve sonra çağrı, iş parçacığı kimliğini ve geçerli saati yazdırırım.

  • tek parçacığının kilit bekleme süresi yığını alır kapalı ~ iş alır ~ 3ms
  • çağrılması izni alır ~ 3ms
  • işi pop için ~
  • 160ms olan 1 ms

dışarı yorumlarında:

(. P Debug/Release için kabaca aynı, ayıklama biraz daha uzun sürer düzgün kod profil edebilmek isteriz) İş görüşmesi tüm işlemin 2 saniye sürmesini sağlar (yine de linux'den daha fazla).

Her iki sorgusu da trydeTimeTime denedim, her ikisi de aynı sonucu veriyor.

AFAIK, bu iş hiçbir zaman hiçbir eşzamanlama yapmaz, ancak yavaşlatma işlemini açıklayamaz.

Niçin bir yığından kopyalanıp pop çağırmanın bu kadar uzun sürdüğü konusunda hiçbir fikrim yok. Başka bir kafa karıştırıcı şey ise,() beklemenin çok uzun sürmesidir.

Neden herkes bu kadar yavaş koştuğunu açıklayabilir mi?

İşlemcideki farkın 100x'lik bir performans farkı vereceğini düşünmezdim, ancak ikili CPU'larla ilgili olabilir mi? (iç çekirdekten daha farklı CPU'lar arasında senkronizasyona sahip olmak).

Bu arada, std :: thread'in farkındayım ancak kitaplık kodumun C++ 11 ile çalışmasını istiyorum. windows ipler süper çekişme karşı karşıya gibi

düzenlemek

//in a while(hasJobs) loop... 

EVENT qwe1 = {"lock", timeGetTime(), id}; 
events.push_back(qwe1); 

scene->jobMutex.lock(); 

EVENT qwe2 = {"getjob", timeGetTime(), id}; 
events.push_back(qwe2); 

hasJobs = !scene->jobs.empty(); 
if (hasJobs) 
{ 
    job = scene->jobs.front(); 
    scene->jobs.pop(); 
} 

EVENT qwe3 = {"gotjob", timeGetTime(), id}; 
events.push_back(qwe3); 

scene->jobMutex.unlock(); 

EVENT qwe4 = {"unlock", timeGetTime(), id}; 
events.push_back(qwe4); 

if (hasJobs) 
    scene->performJob(job); 

ve kaldırılan Linux #Ifdef şeylerle muteks sınıfı ...

CRITICAL_SECTION mutex; 

... 

Mutex::Mutex() 
{ 
    InitializeCriticalSection(&mutex); 
} 
Mutex::~Mutex() 
{ 
    DeleteCriticalSection(&mutex); 
} 
void Mutex::lock() 
{ 
    EnterCriticalSection(&mutex); 
} 
void Mutex::unlock() 
{ 
    LeaveCriticalSection(&mutex); 
} 
+0

Linux'ta ne kullanıyordunuz? Sadece std :: stack'a kritik bölümlerle erişimi mi koruyorsunuz? – xanatos

+2

İş parçacığı kimliğini ve geçerli saati nereye yazdırırsınız? – avakar

+0

Dil seçin. Ve bu tuhaf görünüyor. Kesinlikle * sesler * [SSCCE] (http://www.sscce.org) çalışılabilir olması için yeterince basit. Windows'taki deneyimim, karşılaştırmalı olarak donanmış bir Linux dağıtımıyla karşılaştırıldığında biraz daha cılız oldu, ancak bu gerçekten oldukça geniş bir uçurum gibi görünüyor. – WhozCraig

cevap

0

görünüyor. Tamamen serileşmiş gibi görünüyorlar. Kritik bölümünüzde toplam işlem süreniz 7ms ve 32 iş parçacığınız var. Tüm iş parçacıkları kilit üzerinde sıraya alındıysa, sıradaki son iş parçacığı 217 ms uyuyana kadar çalışmayacaktı. Bu 160ms gözlemlenen bekleme sürenizde çok uzakta değil.

Dolayısıyla, iş parçacığı kritik bir bölüme girmek yerine yapacak başka bir şeye sahip değilse, iş yapın, sonra kritik bölümü bırakın, beklediğim davranış budur.

Linux profil davranışını karakterize etmeye çalışın ve program davranışının gerçekten olup olmadığını ve elmalar karşılaştırması için elma olup olmadığını görün.

+0

Katılıyorum ki, gevşek bir şekilde ardışık olarak çalışıyor gibi görünüyorlar (bazen yürütme düzeninde küçük bir fark var). Bunları serileştirecek bir kod yoktur ve 80 baytlık bir kopya ve pop, işten daha hızlı bir şekilde WAY WAY olmalıdır. Gerçekten anlamlı olmayan şey, LeaveCriticalSection'u aramak için geçen zamandır. Serileştirmenin kritik bölümlerle ilgili bir sorunun bir belirtisi olduğuna inanıyorum. Yine de çekişmeyi linux üzerinde kontrol edeceğim. – jozxyqk

1

Pencerenin CRITICAL_SECTION, ilk girdiğinizde sıkı bir döngüde döner. Spin döngüsünde önemli bir süre geçmediği sürece EnterCriticalSection adı verilen iş parçacığını askıya almaz. Aynı kritik bölüm için yarışan 32 parçacığa sahip olmak, çok fazla CPU döngüsü yakacak ve harcayacaktır. Bunun yerine bir mutex deneyin (bkz. CreateMutex).

+3

[Aynısından şüpheleniyorum] (http://stackoverflow.com/questions/18442574/porting-threads-to-windows-critical-sections-are-very-slow#comment27103010_18442574), ancak dönüş sayısını ayarlamaz Bir mutex kullanmaktan daha uygun/hızlı mı? – dyp

İlgili konular