• Базы данных
  • SQL Server
  • Поддержка и разрешение проблем процессорной архитектуры NUMA в SQL Server 2005

Поддержка и разрешение проблем процессорной архитектуры NUMA в SQL Server 2005 - Поддержка NUMA в Windows

ОГЛАВЛЕНИЕ

 

Поддержка NUMA в Windows

Реализующие архитектуру NUMA платформы могут быть построены по-разному. Есть две основные схемы - это NUMA в чистом виде, или многослойная схема NUMA архитектуры. NUMA в чистом виде представляется для операционной системы как набор процессорных узлов, которые иногда называют контейнерами (блоками) с локальной памятью. В зависимости от аппаратной реализации, могут быть разные по времени и производительности потери при обращении одного узла к участку локальной памяти сервера, который принадлежит другому узлу, числящемуся в другом процессорном блоке. Такая архитектура хороша для приложений, для которых характерно не большое число удаленных подключений.

Если же система имеет многослойную архитектуру, построенную на чередовании адресного пространства локальной памяти сервера между узлами, для операционной системы это будет выглядеть как большой SMP блок, в котором строки кэша разных узлов NUMA будут чередоваться в оперативной память. Такая архитектура больше подходит для приложений, которые не оптимизированы для NUMA и поэтому могут создавать проблемы для архитектуры NUMA в чистом виде. Например, если Вы работаете с SQL Server 2000, для которого не установлена вышедшая после SP3 заплатка QFE, которая включаем оптимизацию NUMA, Вам лучше не запускать SQL Server на сервере с архитектурой NUMA в чистом виде. В дистрибутиве SQL Server 2000 не реализованы многие из возможностей по оптимизации NUMA, и поэтому Вам стоит выбирать для него систему с многослойной NUMA архитектурой.

Когда Windows запускается на платформе с NUMA в чистом виде, операционная система распознает систему с множеством узлов и выбирает соответствующий тип загрузки. Из нашего опыта мы заметили, что во время загрузки, система распределяет память в основном для одного узла - имеется в виду, что это в действительности зависит от доступности памяти узлам, так же как это происходит при запуске большинства приложений операционной системы. Такая особенность распределения памяти во время загрузки операционной системы может создать проблемы для адоптированного к NUMA приложения - так как память не распределяется равномерно между узлами и не существует способов узнать о распределении памяти по узлам. После этого, когда система продолжает работать, проблема усугубляется, и свободной памяти, доступной узлам, становится всё меньше. Это может произойти из-за прожорливых по отношению к памяти приложений или из-за кэша файловой системы (SFC) при распределении значительного объема памяти и в некоторых системных конфигурациях. Кроме того, на платформе NUMA, возрастает вероятность того, что для SFC память по узлам будет использоваться неравномерно. Если адоптированное к NUMA приложение попытается распределять локальную память, оно может стать жертвой "зависания" памяти на узлах, которые работают с SFC или с памятью других, прожорливых по отношению к памяти приложений.

В Windows реализован набор API, с помощью которого приложениям могут задействовать возможности NUMA:

    GetNumaHighestNodeNumber
    GetNumaProcessorNode
    GetNumaNodeProcessorMask
    GetNumaAvailableMemoryNode

Есть несколько скользких моментов у некоторых из этих API, о которых Вам стоит знать:

  1. Нет явного способа распределения памяти от заданного узла - распределение памяти потока от выбранного узла памяти происходит за счёт изменения его привязки (афинитизации) к данному узлу, и последующего вызова VirtualAlloc (при работе с файлом подкачки, Вы вначале должны будете затронуть виртуальную адресацию, а затем установить связь с физической страницей) или другого низкоуровнего API, который осуществит физическое распределение страниц. Если у операционной системы нет памяти на этом узле, она задействует память другого узла, не приводя при этом к сбоям в распределении.
  2. Программный интерфейс GetNumaAvailableMemoryNode может возвращать 0 даже при том, что все еще может оставаться память, которую система могла бы задействовать у узла.
  3. Windows обслуживает память в следующем порядке:
    1. Для потока, привязанного к узлу.
    2. Для узла, который имеет свободную память.
    3. Для любого узла - с освобожденной памятью из зарезервированных списков, рабочих множеств или кэша файловой системы.

Последствиями пунктов A и C является то, что в адаптированных к NUMA приложениях нужно уделять больше внимания специальной обработке ситуаций, когда память может оказаться дальней по отношению к исполняющему задачу узлу. В пунктах A и C возможно такое поведение, что операционная система будет возвращать память случайным образом, то удалённую от узла память, то локальную и т.п. Имейте в виду, что если приложение решает не кэшировать отдаленную для используемого узла память, это может вызвать проблемы, т.к. когда память освобождается, она попадает в список свободной памяти и будет отдана при следующем запросе на распределение.

Последствием пункта B является то, что приложение не может принять абсолютно точное решение, возможно ли распределить память от узла. Пункт B характерен для тех случаев, когда система работает продолжительное время и особенно когда используются большие приложения.