Какво е CUDA? Паралелно програмиране за графични процесори

CUDA е паралелна изчислителна платформа и модел за програмиране, разработен от Nvidia за общи изчисления на собствени графични процесори (графични процесори). CUDA дава възможност на разработчиците да ускорят изчислително интензивните приложения, като използват мощността на графичните процесори за паралелизиращата се част на изчислението.

Въпреки че има и други предложени API за графични процесори, като OpenCL, и има конкурентни графични процесори от други компании, като AMD, комбинацията от графични процесори CUDA и Nvidia доминира в няколко области на приложение, включително задълбочено обучение, и е основа за някои от най-бързите компютри в света.

Графичните карти са може би толкова стари, колкото компютърът, т.е. ако смятате, че IBM Monochrome Display Adapter от 1981 г. е графична карта. До 1988 г. можете да получите 16-битова 2D VGA Wonder карта от ATI (компанията в крайна сметка е придобита от AMD). До 1996 г. можете да закупите 3D графичен ускорител от 3dfx Interactive, за да можете да стартирате пълен шутър от първо лице Quake.

Също през 1996 г. Nvidia започва да се опитва да се конкурира на пазара на 3D ускорители със слаби продукти, но се учи, докато върви, и през 1999 г. представя успешната GeForce 256, първата графична карта, наречена GPU. По това време основната причина за наличието на графичен процесор беше за игрите. Едва по-късно хората използват графични процесори за математика, наука и инженерство.

Произходът на CUDA

През 2003 г. екип от изследователи, ръководен от Иън Бък, представи Brook, първият широко приет програмен модел, който разширява C с паралелни с данни конструкции. По-късно Бък се присъединява към Nvidia и ръководи пускането на CUDA през 2006 г., първото търговско решение за изчисления с общо предназначение на графични процесори.

OpenCL срещу CUDA

Конкурентът на CUDA OpenCL стартира от Apple и Khronos Group през 2009 г. в опит да осигури стандарт за хетерогенни изчисления, който не се ограничаваше до процесори Intel / AMD с графични процесори Nvidia. Въпреки че OpenCL звучи привлекателно поради своята обща характеристика, той не се е представил толкова добре, колкото CUDA на графичните процесори на Nvidia и много рамки за задълбочено обучение или не го поддържат, или го поддържат само като допълнителна мисъл, след като поддръжката им за CUDA бъде освободена.

Повишаване на производителността на CUDA

CUDA подобри и разшири обхвата си през годините, горе-долу на крачка с подобрени графични процесори на Nvidia. От CUDA версия 9.2, използвайки множество P100 сървърни графични процесори, можете да реализирате до 50 пъти подобрения в производителността спрямо процесорите. V100 (не е показан на тази фигура) е още 3 пъти по-бърз за някои товари. Предишното поколение сървърни графични процесори, K80, предлага 5x до 12x подобрения в производителността спрямо CPU.

Nvidia

Повишаването на скоростта от графичните процесори дойде за кратко време за високопроизводителни изчисления. Еднонишковото увеличение на производителността на процесорите с течение на времето, което според закона на Мур се удвоява на всеки 18 месеца, се забави до 10 процента годишно, тъй като производителите на чипове срещнаха физически ограничения, включително ограничения за размера на разделителната способност на маската на чипа и добива на чипове по време на производствения процес и топлинни ограничения на тактовите честоти по време на изпълнение.

Nvidia

CUDA приложения домейни

Nvidia

Графичните процесори CUDA и Nvidia са приети в много области, които се нуждаят от висока производителност на изчисленията с плаваща запетая, както е обобщено нагледно на изображението по-горе. По-изчерпателен списък включва:

  1. Изчислителни финанси
  2. Моделиране на климат, време и океан
  3. Наука за данни и анализ
  4. Дълбоко обучение и машинно обучение
  5. Отбрана и разузнаване
  6. Производство / AEC (Архитектура, инженеринг и строителство): CAD и CAE (включително изчислителна динамика на флуида, изчислителна структурна механика, проектиране и визуализация и електронна автоматизация на проектирането)
  7. Мултимедия и развлечения (включително анимация, моделиране и изобразяване; корекция на цветовете и управление на зърната; композиране; довършителни работи и ефекти; редактиране; кодиране и дигитално разпространение; ефирна графика; инструменти на екрана, преглед и стерео; и графики за времето)
  8. Медицинска образна диагностика
  9. Нефт и газ
  10. Изследвания: Висше образование и суперкомпютри (включително изчислителна химия и биология, числена аналитика, физика и научна визуализация)
  11. Безопасност и сигурност
  12. Инструменти и управление

CUDA в дълбокото обучение

Дълбокото обучение има огромна нужда от изчислителна скорост. Например, за да обучат моделите за Google Translate през 2016 г., екипите на Google Brain и Google Translate извършиха стотици едноседмични TensorFlow писти, използващи графични процесори; за целта бяха закупили 2000 графични процесора от сървърен клас от Nvidia. Без графичните процесори тези тренировъчни тренировки биха отнели месеци, а не седмица, за да се сближат. За производственото внедряване на тези модели за превод на TensorFlow, Google използва нов персонализиран чип за обработка, TPU (обработващ блок на тензор).

В допълнение към TensorFlow, много други DL рамки разчитат на CUDA за своята GPU поддръжка, включително Caffe2, CNTK, Databricks, H2O.ai, Keras, MXNet, PyTorch, Theano и Torch. В повечето случаи те използват библиотеката cuDNN за изчисленията на дълбоката невронна мрежа. Тази библиотека е толкова важна за обучението на рамки за дълбоко обучение, че всички рамки, използващи дадена версия на cuDNN, имат по същество еднакви номера на производителност за еквивалентни случаи на употреба. Когато CUDA и cuDNN се подобряват от версия на версия, всички рамки за дълбоко обучение, които се актуализират до новата версия, виждат повишаване на производителността. Когато производителността има тенденция да се различава от рамка до рамка, е в това колко добре те се мащабират до множество графични процесори и множество възли.

Програмиране на CUDA

Nvidia

Набор от инструменти CUDA

CUDA Toolkit включва библиотеки, инструменти за отстраняване на грешки и оптимизация, компилатор, документация и библиотека за изпълнение за разполагане на вашите приложения. Той има компоненти, които поддържат задълбочено обучение, линейна алгебра, обработка на сигнали и паралелни алгоритми. Като цяло библиотеките CUDA поддържат всички семейства графични процесори на Nvidia, но се представят най-добре на най-новото поколение, като V100, който може да бъде 3 пъти по-бърз от P100 за задълбочени учебни натоварвания. Използването на една или повече библиотеки е най-лесният начин да се възползвате от графичните процесори, стига алгоритмите, от които се нуждаете, да са внедрени в съответната библиотека.

Nvidia

CUDA библиотеки за дълбоко обучение

В сферата на дълбокото обучение има три основни GPU-ускорени библиотеки: cuDNN, която споменах по-рано като GPU компонент за повечето рамки за дълбоко обучение с отворен код; TensorRT, който е високоефективният оптимизатор на извода за дълбоко обучение и изпълнение на Nvidia; и DeepStream, библиотека за видео изводи. TensorRT ви помага да оптимизирате модели на невронни мрежи, да калибрирате за по-ниска точност с висока точност и да внедрите обучените модели в облаци, центрове за данни, вградени системи или платформи за автомобилни продукти.

Nvidia

CUDA линейна алгебра и библиотеки по математика

Линейната алгебра лежи в основата на тензорни изчисления и следователно дълбоко обучение. BLAS (Basic Linear Algebra Subprograms), колекция от матрични алгоритми, внедрени във Fortran през 1989 г., се използва оттогава от учени и инженери. cuBLAS е GPU-ускорена версия на BLAS и най-ефективният начин за матрична аритметика с графични процесори. cuBLAS приема, че матриците са плътни; cuSPARSE обработва оскъдни матрици.

Nvidia

Библиотеки за обработка на сигнали CUDA

Бързото преобразуване на Фурие (FFT) е един от основните алгоритми, използвани за обработка на сигнала; той превръща сигнал (като звукова форма на вълната) в спектър от честоти. cuFFT е ускорен с GPU FFT.

Кодеците, използващи стандарти като H.264, кодират / компресират и декодират / декомпресират видео за предаване и показване. SDK на Nvidia Video Codec ускорява този процес с графични процесори.

Nvidia

CUDA библиотеки за паралелни алгоритми

Всичките три библиотеки за паралелни алгоритми имат различни цели. NCCL (Nvidia Collective Communications Library) е за мащабиране на приложения в множество графични процесори и възли; nvGRAPH е за анализиране на паралелни графи; и Thrust е C ++ библиотека с шаблони за CUDA, базирана на C ++ Standard Template Library. Thrust осигурява богата колекция от данни паралелни примитиви като сканиране, сортиране и намаляване.

Nvidia

CUDA срещу производителност на процесора

В някои случаи можете да използвате падащи функции CUDA вместо еквивалентните функции на процесора. Например подпрограмите за умножение на матрица GEMM от BLAS могат да бъдат заменени от версии на графичния процесор просто чрез свързване към библиотеката NVBLAS:

Nvidia

Основи на програмирането на CUDA

Ако не можете да намерите рутинни библиотечни програми за ускоряване на вашите програми, ще трябва да опитате ръката си в програмирането на CUDA на ниско ниво. Сега това е много по-лесно, отколкото когато го опитах за първи път в края на 2000-те. Наред с други причини, има по-лесен синтаксис и има по-добри инструменти за разработка. Единственият ми спор е, че на MacOS най-новият компилатор на CUDA и най-новият компилатор на C ++ (от Xcode) рядко се синхронизират. Трябва да изтеглите по-стари инструменти от командния ред от Apple и да преминете към тях, като използвате xcode-selectCUDA кода за компилиране и свързване.

Например, помислете за тази проста C / C ++ рутина, за да добавите два масива:

void add (int n, float * x, float * y)

{  

       за (int i = 0; i <n; i ++)      

             y [i] = x [i] + y [i];

}

Можете да го превърнете в ядро, което ще работи на графичния процесор, като добавите __global__ключовата дума към декларацията и да извикате ядрото, като използвате синтаксиса на тройната скоба:

добавете << >> (N, x, y);

Също така трябва да смените вашите malloc/ newи free/ deleteразговори cudaMallocManagedи cudaFreeтака, че да разпределяте място на графичния процесор. И накрая, трябва да изчакате да завърши изчислението на GPU, преди да използвате резултатите на процесора, с които можете да постигнете cudaDeviceSynchronize.

Тройната скоба по-горе използва един блок на резба и един конец. Текущите графични процесори на Nvidia могат да обработват много блокове и нишки. Например, графичният процесор на Tesla P100, базиран на архитектурата Pascal GPU, има 56 поточни мултипроцесори (SM), всеки от които може да поддържа до 2048 активни нишки.

Кодът на ядрото ще трябва да знае своя индекс на блок и нишка, за да намери своето изместване в предадените масиви. Паралелизираното ядро ​​често използва мрежа-крачка , като например следното:

__global__

void add (int n, float * x, float * y)

{

   int индекс = blockIdx.x * blockDim.x + threadIdx.x;

   int stride = blockDim.x * gridDim.x;

   за (int i = индекс; i <n; i + = крачка)

     y [i] = x [i] + y [i];

}

Ако разгледате примерите в CUDA Toolkit, ще видите, че има какво да се вземе предвид от основите, които разгледах по-горе. Например, някои повиквания на функцията CUDA трябва да бъдат обвити в checkCudaErrors()повиквания. Също така, в много случаи най-бързият код ще използва библиотеки, като например cuBLASзаедно с разпределението на паметта на хоста и устройството и копиране на матрици напред и назад.

В обобщение, можете да ускорите приложенията си с графични процесори на много нива. Можете да напишете CUDA код; можете да се обадите на библиотеки CUDA; и можете да използвате приложения, които вече поддържат CUDA.