SORU
31 Aralık 2013, Salı


Neden Monitör yok.PulseAll bir "merdiven çıkma" sinyal iş parçacığı, desen gecikme neden?

Kitaplığı kullanan bir Monitör.PulseAll() için iş parçacığı eşitleme, fark ettim ki gecikme zamanı PulseAll(...) denir zaman bir iş parçacığı uyanmış gibi takip bir "merdiven çıkma" dağıtımı ile son derece büyük bir adım. Uyandı konuları neredeyse hiç çalışma yapıyoruz; ve hemen geri monitörde bekliyor. Örneğin, bir kutu ile 12 çekirdek ile 24 iş parçacığı bekleyen bir İzleyici (2x Xeon5680/Gulftown; 6 fiziksel çekirdek başına işlemci; HT Devre dışı), gecikme arasındaki Darbe ve İplik uyanıyor gibi:

Latency using Monitor.PulseAll(); 3rd party library

İlk 12 konu (not 12 çekirdek var) 30 ila 60 mikrosaniye cevap verebilirler. O zaman çok büyük sıçramalar elde etmeye başlıyoruz; yaylaları ile 700,, 1900 1300 ve 2600 mikrosaniye.

Başarılı bir şekilde bu davranış, 3. parti kütüphane aşağıdaki kodu kullanarak bağımsız canlandırabildim. Ne bu kod mu piyasaya çok sayıda iş parçacığı (değişiklik numThreads parametre) Bekle bir Monitör, bir okuma zaman damgası, günlük bir ConcurrentSet, sonra hemen geri dönmek için Bekliyor. İkinci bir PulseAll() bir kez uyanır bütün konuları. Bu 20 kez yapar ve 10 yineleme için gecikmeleri konsola raporları.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Diagnostics;

namespace PulseAllTest
{
    class Program
    {
        static long LastTimestamp;
        static long Iteration;
        static object SyncObj = new object();
        static Stopwatch s = new Stopwatch();
        static ConcurrentBag<Tuple<long, long>> IterationToTicks = new ConcurrentBag<Tuple<long, long>>();

        static void Main(string[] args)
        {
            long numThreads = 32;

            for (int i = 0; i < numThreads;   i)
            {
                Task.Factory.StartNew(ReadLastTimestampAndPublish, TaskCreationOptions.LongRunning);
            }

            s.Start();
            for (int i = 0; i < 20;   i)
            {
                lock (SyncObj)
                {
                      Iteration;
                    LastTimestamp = s.Elapsed.Ticks;
                    Monitor.PulseAll(SyncObj);
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }

            Console.WriteLine(String.Join("\n",
                from n in IterationToTicks where n.Item1 == 10 orderby n.Item2 
                    select ((decimal)n.Item2)/TimeSpan.TicksPerMillisecond));
            Console.Read();
        }

        static void ReadLastTimestampAndPublish()
        {
            while(true)
            {
                lock(SyncObj)
                {
                    Monitor.Wait(SyncObj);
                }
                IterationToTicks.Add(Tuple.Create(Iteration, s.Elapsed.Ticks - LastTimestamp));
            }
        }
    }
}

Kullanarak kod yukarıda, işte bir örnek gecikmeleri bir kutu ile 8 çekirdek /w hiper iş parçacığı etkin (yani 16 çekirdek Görev Yöneticisi) ve 32 iş parçacığı (*2x Xeon5550/Gainestown; 4 fiziksel çekirdek başına işlemci; HT Etkin):

Latency using Monitor.PulseAll(), sample code

EDİT: denemek için NUMA dışarı denklemi, aşağıda bir grafik çalışan örnek program ile 16 iş parçacığı üzerinde bir Core i7-3770 (Ivy Bridge); 4 Fiziksel Çekirdek; HT Etkin:

Latency using Monitor.PulseAll(), sample code, no NUMA

Herkes neden İzlemek açıklayabilir.() PulseAll bu şekilde davranır?

EDİT2:

Denemek ve göstermek gibi bir davranış değil içsel uyanma bir sürü iş parçacığı aynı anda, ben yinelenen davranış testi programı kullanarak Olayları; ve yerine ölçüm gecikmesi PulseAll() ben ölçüm gecikmesi ManualResetEvent.() Ayarlayın. Kod çalışan iş parçacığı sonra bir ManualResetEvent bekleyen bir dizi yaratıyor.() Set aynı ManualResetEvent olay nesnesi. Olay tetiklendiğinde, gecikme ölçümü hemen sonra başına iş parçacığı AutoResetEvent kendi bireysel beklesinler. Peki bir sonraki yineleme önce (500ms önce), ManualResetEvent Sıfırlanır() ve daha sonra her AutoResetEvent Ayarlanır() iş parçacığı paylaşılan ManualResetEvent bekleyen geri dönebilir.

Tereddüt ettim çünkü bu nakil olabilir bir kırmızı dev işitme (ben hiçbir iddiası Olaylar ve İzler davranmasına benzer şekilde) artı kullanarak bazı uygulamalar için kesinlikle korkunç bir Olay davranmak gibi bir Monitör (aşk/nefret etmek için bakın ne iş yapardın eğer sundum bu bir kod Gözden Geçirme); ama bence sonuçları aydınlatıcı.

Bu test orjinal test; 2xXeon5680/Gulftown olarak aynı makine üzerinde yapıldı; 6 işlemci başına çekirdek (12 çekirdek toplam); hiper iş parçacığı devre dışı.

ManualResetEventLatency

Eğer bu tamamen farklı olduğu apaçık ortada olmasa daha İzlemek.PulseAll; işte ilk grafik son grafik üzerine kaplanmış:

ManualResetEventLatency vs. Monitor Latency

Kodu bu Ölçümler oluşturmak için kullanılan aşağıdaki gibidir:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Diagnostics;

namespace MRETest
{
    class Program
    {
        static long LastTimestamp;
        static long Iteration;
        static ManualResetEventSlim MRES = new ManualResetEventSlim(false);
        static List<ReadLastTimestampAndPublish> Publishers = 
            new List<ReadLastTimestampAndPublish>();
        static Stopwatch s = new Stopwatch();
        static ConcurrentBag<Tuple<long, long>> IterationToTicks = 
            new ConcurrentBag<Tuple<long, long>>();

        static void Main(string[] args)
        {
            long numThreads = 24;
            s.Start();

            for (int i = 0; i < numThreads;   i)
            {
                AutoResetEvent ares = new AutoResetEvent(false);
                ReadLastTimestampAndPublish spinner = new ReadLastTimestampAndPublish(
                    new AutoResetEvent(false));
                Task.Factory.StartNew(spinner.Spin, TaskCreationOptions.LongRunning);
                Publishers.Add(spinner);
            }

            for (int i = 0; i < 20;   i)
            {
                  Iteration;
                LastTimestamp = s.Elapsed.Ticks;
                MRES.Set();
                Thread.Sleep(500);
                MRES.Reset();
                foreach (ReadLastTimestampAndPublish publisher in Publishers)
                {
                    publisher.ARES.Set();
                }
                Thread.Sleep(500);
            }

            Console.WriteLine(String.Join("\n",
                from n in IterationToTicks where n.Item1 == 10 orderby n.Item2
                    select ((decimal)n.Item2) / TimeSpan.TicksPerMillisecond));
            Console.Read();
        }

        class ReadLastTimestampAndPublish
        {
            public AutoResetEvent ARES { get; private set; }

            public ReadLastTimestampAndPublish(AutoResetEvent ares)
            {
                this.ARES = ares;
            }

            public void Spin()
            {
                while (true)
                {
                    MRES.Wait();
                    IterationToTicks.Add(Tuple.Create(Iteration, s.Elapsed.Ticks - LastTimestamp));
                    ARES.WaitOne();
                }
            }
        }
    }
}

CEVAP
14 NİSAN 2013, Pazar


Kısmi bir çözüm keşfettim önce senin sorunu buldum.

Bugün itibariyle, ben bulmak Güncellemelerinden 4.6.1 GUI köpek yavaş bana göre, özellikle göz önünde bulundurarak ben bir bir yaşında, mac, SSD, derlemek için bir 2 GB RAM disk ve 6 GB RAM kaldı. Hatta Eclipse yıldırım hızlı Güncellemelerinden göre çalışır

4.5.1 bir şey düzelmedi, ama uzun bir süre böyle büyük mükafat kullandıktan sonra onun bazı sorunları çözülecek olmak için herhangi bir umut yok.

Bu varlık fark var dedi, Bu "Canlı konular" ana araç çubuğu ve panelleri aynı derecede sekme geçiş yavaş. En büyük suçlu şu ana kadar navigator panelleri.

Bir zamanlar bende eskiden bir minimalist Güncellemelerinden pencere, düzeni bazı özel görev sekmeleri tutmak ayrı bir pencere için xibs ve öğrendim kısayollarını Etkinleştir/devre dışı bırak panelleri, ben artık acı öyle böyle büyük mükafat yanıt, ama yine de biraz gecikme olabilir açıkça hissettim.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Austin Evans

    Austin Evans

    5 AĞUSTOS 2007
  • Break

    Break

    10 Aralık 2005
  • buttheadgsxr1000

    buttheadgsxr

    24 Ocak 2008