Email: [email protected] Blog: http://blogs.ugidotnet.org/raffaele Profilo: https://mvp.support.microsoft.com/profile/raffaele Blog http://blogs.ugidotne.org/raffaele Su singolo processore il multithreading è stato prevalentemente usato per rendere più fluide le operazioni per simulare la contemporaneità di più processi Tipicamente le architetture di oggi ci offrono due, massimo 4 processori fisici/logici Problemi a due/tre variabili dominabili dalla mente umana Hyperthreading non forniva sufficienti vantaggi da indurre i developer a modificare i sorgenti Blog http://blogs.ugidotne.org/raffaele http://www.gotw.ca/publications/concurrency-ddj.htm Autore dell’articolo: Herb Sutter Secretary , ISO/ANSI C++ Standards Committee Architect, C++ language design group Free Lunch = performance gratis Fino ad ora le applicazioni sono andate sempre più veloci senza cambiare una riga di codice I produttori hardware dicono che: non è più possibile produrre CPU con velocità superiori come è avvenuto fin’ora. è possibile aumentare invece il numero di “core” di una CPU. Per sfruttarle le applicazioni dovranno essere scritte con tecniche multithreading Blog http://blogs.ugidotne.org/raffaele Perché un algoritmo parallelo e ben scritto non è ancora abbastanza performante Blog http://blogs.ugidotne.org/raffaele Avviene fondalmentalmente in tre casi Quando il codice eseguito nel thread chiede di sospendersi chiamando Thread.Sleep oppure chiamando WaitOne, WaitAny, WaitAll Win32 ==> (WaitForSingle/MultipleObject/s, MsgWaitForxxx) Quando dal thread viene chiamata Win32 SwitchToThread() oppure Thread.Sleep(0) (identico) Quando il quantum a disposizione del thread è terminato. Thread Thread Processo Blog http://blogs.ugidotne.org/raffaele Thread Processo Thread Processo Thread Ogni context switch richiede circa 5000 istruzioni. Gli step tipici sono: 1. Entrare in Kernel Mode 2. Salvare i registri relativi al thread precedente 3. Acquisire il dispatch spinlock oggetto kernel che permette di gestire la concorrenza tra più CPU 4. Determinare il thread successivo da eseguire (se appartiene ad un 5. 6. 7. 8. altro processo, può essere ancora più costoso) Lasciare il dispatch spinlock. Scambiare in kernel mode lo stato dei thread precedente e successivo Riprisitnare i registri relativi al nuovo thread Uscire dal Kernel Mode Azioni non eseguite in caso di Fibers Blog http://blogs.ugidotne.org/raffaele Problema: lo scheduler di Windows gestisce due stati stati (running / waiting) nell'accedere agli oggetti. A questo scopo acquisisce un lock globale: il dispatcher lock In presenza di un alto numero di CPU logiche ci sono molti più thread che contemporaneamente girano nel sistema Con molti thread il dispatcher lock diventa l'imbuto più importante del sistema Soluzione: in Windows 7 è stata di introdurre un nuovo stato nel modo in cui lo Scheduler accede agli oggetti kernel: pre-waiting, waiting, running. Nello stato di pre-waiting il lock viene acquisito solo sullo specifico oggetto su cui si vuole operare e non più il dispatcher lock globale Blog http://blogs.ugidotne.org/raffaele Problema: quando il memory manager assegna una pagina fisica di memoria al working set di un processo esegue un lock al PFN Database PFN = Page Frame Number PFN Database = la lista di pagine fisiche di memoria In presenza di un alto numero di CPU logiche, questo è il secondo lock globale per impatto sulle performance Soluzione: Windows 7 ha introdotto una serie di lock minori che permettono di non tenere bloccato tutto il database Blog http://blogs.ugidotne.org/raffaele Problema: un alto numero di thread implica un grande numero di transizioni user/kernel mode Le transizioni in kernel mode sono necessarie perché lo Scheduler di Windows gira Soluzione: Windows 7 introduce il nuovo User Mode Scheduler che evita le transizioni in kernel mode per distribuire un carico di lavoro su più thread Lo User Mode Scheduler (UMS) gestisce in una sorta di loop infinito le richieste di gestione del carico Diminuisce le extra transizioni in kernel mode dovute al fatto che il carico di lavoro in user mode è tipicamente inferiore al quantum dedicato al thread dallo scheduler di Windows Blog http://blogs.ugidotne.org/raffaele In Windows erano già presente i Fibers Una sorta di "thread leggeri" che non coinvolgono il kernel mode Perché i fibers non sono una soluzione ottimale? I fibers non hanno garanzia di tornare ad essere eseguiti nello stesso thread I fibers non sono gestiti dallo scheduler di Windows che è in kernel mode ma l'applicazione ne deve provvedere uno È altamente probabile che lo stesso SQL Server (che attualmente usa i fibers) passi a UMS. Blog http://blogs.ugidotne.org/raffaele Problema: la gestione diretta di Thread, ThreadPool, Event, Mutex, Semaphore è sempre più complessa al crescere delle CPU logiche Soluzione: il Parallel Computing Team usa lo UMS in Windows 7 per le nuove librerie in Visual Studio 2010: Developer di codice nativo C++ Parallel Pattern Library (PPL) che è basato su: Concurrency Runtime (Concurs) Developer di codice managed Task Parallel Library (TPL) che fa parte della: Parallel Extensions al Framework.NET (PFX) In Windows XP/2003 queste librerie hanno un loro scheduler User Mode Per ovvi motivi le performance di UMS sono migliori Blog http://blogs.ugidotne.org/raffaele Informazioni su Windows 7 http://www.microsoft.com/windows/windows-7 Provate Windows 7 beta 1 http://msdn.microsoft.com/en-us/dd353271.aspx Windows Developer Center http://msdn.microsoft.com/windows Windows 7 Developer Guide http://msdn.microsoft.com/en-us/library/dd371748(VS.85).aspx Download di Windows SDK 7.0 beta 1 http://www.microsoft.com/downloadS/details.aspx?familyid=A91D C12A-FC94-4027-B67E-46BAB7C5226C&displaylang=en Parallel Development Libraries (parte di VS2010) http://msdn.microsoft.com/en-us/concurrency Blog http://blogs.ugidotne.org/raffaele © 2009 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.