Come gestire l’affinità delle CPU in SQL Server 2008 R2 con più di 64 unità logiche

Nel precedente post http://blogs.technet.com/b/italian_premier_center_for_sql_server/archive/2011/05/13/ha-senso-avere-pi-249-di-64-cpu-per-sql-server-2008.aspx abbiamo approfondito come sfruttare pienamente la disponibilità di un numero maggiore di 64 CPU logiche con Windows Server 2008 R2 e SQL Server 2008 R2. Uno dei punti affrontati era relativo al fatto che il tradizionale meccanismo dell’ “Affinity Mask”, disponibile in SQL Server da molte versioni, non era di fatto utilizzabile.

In passato, questo meccanismo è stato raramente utilizzato, ma con la disponibilità sul mercato di server equipaggiati con i più recenti modelli di CPU multi-core, sia da Intel che da AMD, la necessità di poter stabilire un’affinità statica tra le CPU logiche ed il processo SQL Server è tornata in auge.

Come per altre “features” introdotte da SQL Server 2008 R2, lo statement “ALTER SERVER CONFIGURATION” è passato pressochè inosservato, ma è una assoluta novità di questa versione di SQL Server (non esiste in SQL Server 2008) e permette, per l’appunto, di gestire le CPU logiche usate dal database engine di SQL Server in maniera estremamente granulare, oltre il limite delle 64 unità e fino ad un massimo di 256: http://msdn.microsoft.com/en-us/library/ee210585.aspx

NOTA: Come si può vedere nella parte evidenziata, questa funzionalità è disponibile solo in SQL Server 2008 R2 e in “Denali”, cioè la prossima versione di SQL Server; Osservando con attenzione la sintassi di questo comando, ci si può subito rendere conto che, nonostante l’apparente generalità dello statement (“ALTER SERVER CONFIGURATION”), almeno nella corrente versione di SQL Server, l’unica cosa che può gestire è l’affinità delle CPU, niente altro.

Prima di analizzare più a fondo le possibilità di questo comando e le relative implicazioni a livello di Sisteam Operativo, è bene introdurre un esempio significativo in modo da rendere più chiari i concetti successivi:

  • Sistema Operativo: Windows Server 2008 R2 Enterprise (x64)
  • Versione di SQL Server: SQL Server 2008 R2 Enterprise Edition

 Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64) Apr 2 2010 15:48:46

 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.1 <X64> (Build 7600: )

  • Hardware: 4 CPU (sockets) “Westmere-EX” with Hyper-Threading (HT) abilitato.

Con una rapida verifica in Task Manager, o tramite uno dei molteplici script TSQL di diagnostica, in questo specifico caso abbiamo a disposizione ben 80 CPU “logiche”: (4 CPU) x (10 CORE) x HT = 80. Ben più interessante è la seguente porzione dell’ERRORLOG di SQL Server, nella parte iniziale dove sono tracciate tutte le informazioni relative al “bootstrap” dell’istanza:

 

Sicuramente alcune persone avranno già riconosciuto questo stralcio dell’ERRORLOG e sapranno cosa significa: questo server viene “visto”, da Windows e da SQL, come una macchina ad architettura NUMA con 4 nodi e con specifici gruppi di CPU assegnati ad ognuno; solo i più attenti, però, avranno notato una piccola ma significativa differenza con quello che normalmente appare con SQL Server 2008, e cioè la singola cifra evidenziata in rosso che appare alla fine di ogni riga. Di che cosa si tratta ? Prima di rispondere a questa domanda due importanti approfondimenti che è bene conoscere prima di proseguire nella lettura di questo post:

1) Come SQL Server (>= 2005) supporta e trae beneficio dalle architetture NUMA:

Understanding Non-uniform Memory Access http://msdn.microsoft.com/en-us/library/ms178144.aspx

How SQL Server Supports NUMA http://msdn.microsoft.com/en-us/library/ms180954.aspx

2) Come Windows Server 2008 R2 “vede” le macchine con più di 64 CPU logiche:

Running SAP Applications on SQL Server

http://blogs.msdn.com/b/saponsqlserver/archive/2010/09/28/windows-2008-r2-groups-processors-sockets-cores-threads-numa-nodes-what-is-all-this.aspx

Questo secondo punto è basilare e spiega la cifra evidenziata in rosso a cui ho fatto precedentemente riferimento: nell’estendere la capacità di Windows oltre il limite delle 64 CPU logiche, è stato introdotto il concetto di “Processor Group” (o “K-group” come a volte viene altresì chiamato), e cioè una ulteriore unità di raggruppamento delle CPU in sottoinsiemi di massimo 64 unità, come ben chiarifica il seguente diagramma:

Ebbene, quella famosa cifra evidenza proprio il “Processor Group” (PG) al quale lo specifico nodo NUMA appartiene, così come le CPU/CORE che ne fanno parte come riportato dalla relativa bitmap; con questa nuova importante informazione rileggiamo la parte di ERRORLOG già evidenziata:

  • Il nodo NUMA [0] comprende i primi 20 CORE logici del PG [1];
  • Il nodo NUMA [1] comprende anch’esso i primi 20 CORE logici ma del PG [0];
  • Il nodo NUMA [2] comprende i CORE da 21 a 40 del PG [1];
  • Il nodo NUMA [3] comprende i CORE da 41 a 60 del PG [1];

E’ evidente che qualcosa di strano c’è dato che un PG è composto da 60 CPU logiche (PG[1]) mentre l’altro (PG[0]) solo da 20 ! In realtà non c’è nulla di strano, la definizione di “Processor Group” (PG) dice che può includere fino a 64 CPU logiche e non è riportato da nessuna parte che la suddivisione debba per forza essere uniforme nel numero di CORE tra un PG e l’altro. In questo caso, infatti, su un totale di 80 CPU logiche, 20 sono assegnate al PG[0] e rappresentano di fatto una singola (la prima !) CPU (10 CORE x HT = 20) e nodo NUMA[1], mentre le altre 60 sono assegnate al PG[1] e rappresentano le altre 3 CPU (3 x 10 CORE x HT = 60) per i nodi NUMA[ 0],[2] e[3].

La seconda cosa strana è: perché al primo nodo NUMA ([0]) corrisponde un set di CPU del secondo “Processor Group” (PG[1])? La risposta a questa domanda richiederebbe un post a parte, magari scritto da un collega esperto di Sistemi Operativi, qui è sufficiente sapere che in SQL Server vengono invertite le CPU usate dai primi due nodi NUMA ([0] e [1])per evitare che alcuni dei task di sistema/default di SQL Server si trovino in esecuzione sugli stessi CORE dove girando alcuni dei task di sistema/default di Windows.

Se la cosa Vi sembra complicata, ed effettivamente ad un certo grado lo è, potete usare il tool “COREINFO” di “Sysinternals” per conoscere i dettagli delle CPU, CORE, HT, Processor Groups, etc:http://technet.microsoft.com/en-us/sysinternals/cc835722

Il tool fornisce veramente molte informazioni utili, specialmente per quanto riguarda la numerazione dei CORE, delle CPU, dei NUMA nodes e dei “Processor Group” (PG), la velocità di accesso alla memoria non locale di ogni nodo NUMA, etc; in allegato (coreinfo_result.txt) ho riportato un esempio ottenuto dalla macchina di test precedentemente citata.

Dopo questa lunga digressione, siamo infine in grado di capire come impostare l’utilizzo di CORE, CPU, PG per la nostra istanza SQL Server 2008 R2, ecco alcuni tipici esempi sul nostro hardware di riferimento:

1) Utilizzo del solo NUMA node [0]:

ALTER SERVER CONFIGURATION SET PROCESS AFFINITY NUMANODE=0

La seguente query ritorna (20) dato che utilizzeremo solo 20 CPU logiche:

select COUNT(*) from sys.dm_os_schedulers where status = 'VISIBLE ONLINE'

2) Utilizzo del primo (ed unico) NUMA nel “Processor Group” [0] e del primo NUMA node del secondo “Processor Group”:

ALTER SERVER CONFIGURATION SET PROCESS AFFINITY NUMANODE=0,1

La seguente query ritorna (40) dato che utilizzeremo 40 CPU logiche:

select COUNT(*) from sys.dm_os_schedulers where status = 'VISIBLE ONLINE'

3) Utilizzo di tutti i NUMA node in entrambi i “Processor Group” (il default !):

ALTER SERVER CONFIGURATION SET PROCESS AFFINITY CPU = AUTO

La seguente query ritorna (80) dato che utilizzeremo tutte le 80 CPU logiche:

select COUNT(*) from sys.dm_os_schedulers where status = 'VISIBLE ONLINE'

4) Utilizzo delle 20 CPU logiche del primo nodo NUMA e delle 20 del quarto nodo NUMA, tutte nel secondo “Processor Group” (PG[1]):

ALTER SERVER CONFIGURATION SET PROCESS AFFINITY CPU = 0 TO 19, 60 TO 79;

La seguente query ritorna (40):

select COUNT(*) from sys.dm_os_schedulers where status = 'VISIBLE ONLINE'

Con questi esempi spero che la trattazione dell’argomento sia completa, prima di lasciarVi però vorrei ribadire un ultimo importante concetto: oltre al supporto da parte del Sistema Operativo, anche l’applicazione/servizio deve essere capace di supportare un numero massimo di CPU logiche oltre le 64, altrimenti quello che succede è che a tale servizio/applicazione verrà assegnato un singolo “Processor Group” , con un massimo di 64 CPU logiche, ed ovviamente non sarà in grado di utilizzare le altre unità disponibili.

Buon lavoro a tutti !

- Igor Pagliai -

coreinfo_result.txt