През последните три години Nvidia създаде графични чипове, в които освен обикновени ядра за шейдърите има и друг вид ядра. Това са така наречените тензорни ядра, които вече са налични в хиляди десктоп компютри, лаптопи, работни станции и дата центрове от целия свят. Но какво точно вършат тези ядра и за какво се използват? Необходими ли са изобщо във видеокартите?
Нека да разберем какво е тензорът и по какъв начин се използват тензорните ядра в света на графиката и машинното обучение.
Малко математика
За да разберем какво вършат тензорните ядра и за какво се използват, нека в началото изясним какво са тензорите. В основата на всичко е, че процесорите, какъвто и алгоритъм да следват, извършат математически операции с числа – събиране, умножение и т.н.
Понякога тези числа е необходимо да бъдат групирани. Така например, когато чипът обработва данните за рендиране на изображение, то той работи с положителни цели числа (примерно +2 или +115) за задаване на коефициента на мащабиране или с група числа с плаваща запетая (+0,1, -0,5, +0,6) за задаване координатите на точките в триизмерното пространство. Във втория случай е необходимо използването и на трите елемента на данните.
Тензорът е математически обект, описващ съотношенията между други математически обекти, свързани по някакъв начин един с друг. Обикновено те се представят във вид на масиви от числа с различни размерности:
Най-опростеният тензор е с нулева размерност (ранг 0) и се състои от един единствен елемент – скалар.
При увеличаване бора на размерността вече се сблъскваме с други разпространени математически структури – вектор и матрица.
Строго казано, скаларът е тензор 0х0, векторът – 1х0 и матрицата – 1х1. Но поради характера на работата на тензорните ядра на графичния процесор, ние ще разглеждаме единствено тензорите, които са във вид на матрици. Именно оттук идва понятието ‘тензорни ядра‘.
Една от най-важните и най-често извършваните операции с матрици е тяхното умножение (произведение). Нека да погледнем как става умножението на две матрици, които имат по четири реда и четири колони данни:
Окончателният резултат от умножението на две матрици винаги ще бъде същият брой редове и същият брой колони, каквито има първата матрица. Ето как става умножението на тези два масива:
Това не може да се сметне ‘на пръсти’, понеже пръстите няма да достигнат за да се реши това нещо.
Веднага се вижда, че едно обикновено умножение на матрици се състои от голям брой малки умножения и суми. И тъй като всеки съвременен централен процесор може да извършва всички тези операции, най-опростените тензори може да пресмята всеки десктоп компютър, лаптоп и таблет.
Но показаният по-горе пример включва 64 умножения и 48 събирания, като всяко неголямо произведение дава значение, което трябва да бъде предварително записано някъде, за да може да се извърши математическото сумиране с другите три неголеми произведения, за да може да бъде изчислено окончателното значение на тензора. Ето защо, въпреки математическата простота на умножението на матрици, те са тежки за изчисление – необходимо е използването на множество регистри, а кешът трябва да може бързо да се справя с голям брой операции за четене и запис на данни.

В продължение на много години в процесорите на AMD и на Intel се появяваха различни разширени инструкции – MMX, SSE, а сега и AVX. Всички те са SIMD инструкции (single instruction multiple data), с помощта на които процесорът може да обработва множество числа с плаваща запетая – именно това, което е необходимо за умножението на матрици.
Но има друг, особен тип процесори, които са специално проектирани за обработване на SIMD операциите. Естествено, това са графичните процесори (graphics processing unit, GPU).
По-умен от обикновения калкулатор?
В света на графиката е необходимо да се обменят и обработват огромни количества информация във вид на вектори. Благодарение на възможността за паралелна обработка, GPU са идеални за обработване на тензорите, като всички съвременни графични процесори поддържат функционалността GEMM (General Matrix Multiplication).
Това е стандартна за GPU операция, при която се умножават две матрици, а след това резултатът се получава в друга матрица. Има важни ограничения относно формата на матриците, като всичките тези ограничения се отнасят до броя редове и колони на всяка матрица.

Алгоритмите за работа с матриците работят най-добре, когато матриците са квадратни – тоест при масив 10х10 алгоритъмът работи по-добре, отколкото с 50х2. Също така, всичко се извършва по-бързо, когато матриците са с по-малки размери. Но разликите не са особено големи и действията с матриците стават много по-бързо с помощта на този специализиран хардуер.
През месец декември 2017 година Nvidia представи видеокарта с процесор, базиран на архитектурата Volta. Тя бе предназначена за професионалния сектор и този чип не се използваше в моделите GeForce. Тази графична карта бе уникална с това, че имаше GPU с ядра предназначени единствено за тензорни изчисления.

Тези тензорни ядра на Nvidia бяха предназначени за изпълняването на по 64 GEMM на такт за 4х4 матрици с FP16 значения (16-битови числа с размер 16 бита) или FP16 умножения, съчетани с FP32 сумирания. Тези тензори са съвсем малки по размер и в реалността постепенно обработват малки части от големите матрици докато образуват окончателния отговор.
След по-малко от една година Nvidia представи архитектурата Turing. Този път имаше тензорни ядра и в потребителските модели на GeForce. Направени бяха подобрения за поддръжката и на други формати данни, като например INT8 (8-битови цели числа), но всичко останало работеше като при Volta.
В началото на тази година архитектурата Ampere дебютира в нов графичен процесор и този път Nvidia отново повиши производителността (256 GEMM на цикъл вместо предишните 64). Добавени са нови формати данни и възможност за изключително бързата обработка на разредените тензори (sparse tensor) – матрици с голям брой нули.
Програмистите могат да получат достъп до тензорните ядра на чиповете Volta, Turing и Ampere. Това става много лесно: кодът трябва да използва флаг, съобщаващ на API и драйверите, че ще бъдат използвани тензорните ядра, а размерът на матрицата трябва да е кратен на 8. При изпълнение на тези условия, всичко останало върши хардуерът.
Всичко това е супер, но доколко тензорните ядра са по-добри в обработката на GEMM в сравнение с обикновените графични ядра.
Когато излезе архитектурата Volta, уеб порталът Anandtech направи тестове на три графични карти на Nvidia – с новата Volta, най-мощната от фамилията Pascal и стара Maxwell карта.
Понятието за точност (precision) се отнася до броя битове, използвани за числата с плаваща запетая в матриците: двойна (double) означава 64, единична (single) – 32 и т.н. Хоризонталната ос показва максималното количество операции с плаваща запетая, извършени за една секунда или съкратено FLOPs. Да уточним, че една GEMM операция е равна на три FLOP.
Просто погледнете какви са резултатите при използването на тензорни ядра вместо стандартните CUDA процесорни ядра.Очевидно е, че те по потресаващ начин се справят с подобна работа, но какво можем да правим с тези тензорни ядра?
Математиката, която подобрява всичко
Тензорните изчисления са изключително полезни във физиката и проектирането. Те се използват за решаване на всевъзможни сложни задачи – механиката на течностите, електромагнетизма и астрофизиката и други.
Друга област, където масово се използват тензори е машинното обучение, особено варианта ‘дълбоко машинно обучение’. Обработват се огромни набори от данни в гигантски масиви, някои от които е прието да се наричан невронни мрежи. Връзките между различните клетки и техните данни се задава чрез математическо тегло – число, което показва и определя важността на дадена ‘невронна’ връзка.
За да разберем как взаимодействат тези стотици и дори хиляди връзки, трябва да умножим всеки елемент на тези комплексни данни с всички възможни математически тегла на връзките. С други думи, трябва да бъдат умножени две, макар и големи матрици. А това е класическа тензорна математика.

Някои компании създадоха собствени процесори с тензорни ядра. Google например, през 2016 година обви своя първи TPU (tensor processing unit) – специализирани чипове, които не могат да правят нищо друго освен математически операции с матрици.
Тензорните ядра в потребителските GPU (GeForce RTX)
Тензорните ядра обикновено не се използват за обикновено рендиране, кодиране или декодиране на видео, и може да ви се стори, че напразно сте си дали парите, ако сте си купили графична карта с тензорни ядра. Да напомним, че Nvidia вгради тензорни ядра в своите потребителски продукти от 2018 година (Turing GeForce RTX) и по този начин внедри DLSS — Deep Learning Super Sampling.
Принципът на работа на DLSS не изглежда сложен: рендираме кадъра в сравнително ниска резолюция, а след това повишаваме неговата разделителна способност дотолкова, че съвсем точно да съвпада с резолюцията на монитора – например, рендираме при 1080р, а след това мащабираме до 1400р. По този начин осезателно се повишава производителността, понеже се обработват по-малко пиксели, а на екрана изображението е все така красиво.
Конзолите използват тази функция от години. Много съвременни игри за десктоп компютри също имат тази възможност. В Assassin’s Creed: Odyssey например, е възможно да се намали резолюцията за рендиране на кадъра до едва 50% от разделителната способност на монитора. Но при толкова голяма разлика в резолюциите резултатът не е така красив. Ето как изглежда играта с 4К резолюция при максимални настройки на графиката:
В тези случаи, при високите резолюции текстурите изглежда по-красиво, понеже имат във себе си повече детайли. Но за извеждането на тези пиксели на екрана, се изисква много обработка. А ето какво става, когато намалим резолюцията на рендирания кадър до 1080р (25% от предишния брой пиксели) и използване на шейдъри за мащабиране до 4К:
Заради jpeg компресията на каченото в уеб страницата изображение, разликите са минимални, но се вижда, че бронята на персонажа и скалата изглеждат някак размити. Да приближим тази част от изображението:
Отляво кадърът е рендиран при 4К, а отдясно – при 1080р и мащабиран до 4К. Има разлики, които обаче се забелязват много по-добре при подвижните елементи на кадрите.
Именно тук се използва DLSS. В първата версия на тази технология Nvidia анализира няколко подбрани военни игри, които можеха да се стартират с висока резолюция, ниска резолюция, с изглаждане и без него. Във всички тези режими бяха генерирани комплект изображения, които бяха обработени от невронните мрежи на суперкомпютрите на Nvidia. По този начин бе определено по какъв начин може да се мащабира едно 1080р изображение в идеален кадър с по-висока резолюция.
DLSS 1.0 не бе идеален. Губеха се детайли и в някои места се появяваше странно трептене. Наложи се Nvidia да направи допълнителни изследвания.
В началото на 2020 година излезе версия 2.0, в която бяха направени сериозни подобрения. Тук суперкомпютрите на компанията са използвани само за създаването на общия алгоритъм за увеличаване на мащаба. В новата версия на DLSS за обработката на кадъра се използват само тензорните ядра на графичния процесор и данните от вече рендирания кадър.
Възможностите на DLSS 2.0 са впечатляващи, но засега тази технология се поддържа от съвсем малко игри.
Благодарение на качественото и на практика почти произволното мащабиране може да се постигне сериозен ръст на производителността.
И въпреки, че резултатите от работата на DLSS засега не са винаги идеални, освободените от рендирането ресурси дават възможност за добавяне на много повече визуални ефекти и осигуряване на едно и също ниво на графиката за широк диапазон от платформи.
Удобно е използването на DLSS заедно с технологията за трасиране на лъчите, която се поддържа от новите видеокарти на Nvidia. Трасирането на лъчите изисква огромни изчислителни ресурси и мащабирането с помощта на DLSS, производителността на целия процес може значително да се повиши.
Има мнения, че транзисторите в кристалите на GPU е по-добре да се използват за допълнителни шейдърни ядра, отколкото за тензорни. Точно така постъпи Nvidia със своите бюджетни Turing чипове, а в GeForce GTX 1650 компанията изцяло се отказа от тензорните ядра и ги замени с допълнителни FP16 шейдъри. Но в топ-графичните процесори на Nvidia тази технология се поддържа и предлага наистина много.