NVIDIA CUDA — неграфические вычисления на графических ...
NVIDIA CUDA — неграфические вычисления на графических ...
NVIDIA CUDA — неграфические вычисления на графических ...
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>NVIDIA</strong> <strong>CUDA</strong> <strong>—</strong> <strong>неграфические</strong><strong>вычисления</strong> <strong>на</strong> <strong>графических</strong> процессорахВведениеУстройства для превращения персо<strong>на</strong>льных компьютеров в маленькие суперкомпьютерыизвестны довольно давно. Ещё в 80-х годах прошлого века <strong>на</strong> рынке предлагались так<strong>на</strong>зываемые транспьютеры, которые вставлялись в распространенные тогда слотырасширения ISA. Первое время их производительность в соответствующих задачахвпечатляла, но затем рост быстродействия универсальных процессоров ускорился, ониусилили свои позиции в параллельных <strong>вычисления</strong>х, и смысла в транспьютерах неосталось. Хотя подобные устройства существуют и сейчас <strong>—</strong> это разнообразныеспециализированные ускорители. Но зачастую сфера их применения узка и особогораспространения такие ускорители не получили.Но в последнее время эстафета параллельных вычислений перешла к массовому рынку,так или и<strong>на</strong>че связанному с трёхмерными играми. Универсальные устройства смногоядерными процессорами для параллельных векторных вычислений, используемых в3D-графике, достигают высокой пиковой производительности, которая универсальнымпроцессорам не под силу. Конечно, максималь<strong>на</strong>я скорость достигается лишь в рядеудобных задач и имеет некоторые ограничения, но такие устройства уже <strong>на</strong>чали довольношироко применять в сферах, для которых они из<strong>на</strong>чально и не пред<strong>на</strong>з<strong>на</strong>чались.Отличным примером такого параллельного процессора является процессор Cell,разработанный альянсом Sony-Toshiba-IBM и применяемый в игровой приставке SonyPlayStation 3, а также и все современные видеокарты от лидеров рынка <strong>—</strong> компаний<strong>NVIDIA</strong> и AMD.Cell мы сегодня трогать не будем, хоть он и появился раньше и является универсальнымпроцессором с дополнительными векторными возможностями, речь сегодня не о нём. Для3D видеоускорителей ещё несколько лет <strong>на</strong>зад появились первые технологиине<strong>графических</strong> расчётов общего <strong>на</strong>з<strong>на</strong>чения GPGPU (General-Purpose computation onGPUs). Ведь современные видеочипы содержат сотни математических исполнительныхблоков, и эта мощь может использоваться для з<strong>на</strong>чительного ускорения множествавычислительно интенсивных приложений. И нынешние поколения GPU обладаютдостаточно гибкой архитектурой, что вместе с высокоуровневыми языками
программирования и программно-аппаратными архитектурами, подобнымирассматриваемой в этой статье, раскрывает эти возможности и делает их з<strong>на</strong>чительноболее доступными.На создание GPCPU разработчиков побудило появление достаточно быстрых и гибкихшейдерных программ, которые способны исполнять современные видеочипы.Разработчики задумали сделать так, чтобы GPU рассчитывали не только изображение в3D приложениях, но и применялись в других параллельных расчётах. В GPGPU для этогоиспользовались графические API: OpenGL и Direct3D, когда данные к видеочипупередавались в виде текстур, а расчётные программы загружались в виде шейдеров.Недостатками такого метода является сравнительно высокая сложностьпрограммирования, низкая скорость обме<strong>на</strong> данными между CPU и GPU и другиеограничения, о которых мы поговорим далее.Вычисления <strong>на</strong> GPU развивались и развиваются очень быстро. И в дальнейшем, дваосновных производителя видеочипов, <strong>NVIDIA</strong> и AMD, разработали и анонсировалисоответствующие платформы под <strong>на</strong>званием <strong>CUDA</strong> (Compute Unified Device Architecture)и CTM (Close To Metal или AMD Stream Computing), соответственно. В отличие отпредыдущих моделей программирования GPU, эти были выполнены с учётом прямогодоступа к аппаратным возможностям видеокарт. Платформы не совместимы между собой,<strong>CUDA</strong> <strong>—</strong> это расширение языка программирования C, а CTM <strong>—</strong> виртуаль<strong>на</strong>я маши<strong>на</strong>,исполняющая ассемблерный код. Зато обе платформы ликвидировали некоторые изважных ограничений предыдущих моделей GPGPU, использующих традиционныйграфический конвейер и соответствующие интерфейсы Direct3D или OpenGL.Конечно же, открытые стандарты, использующие OpenGL, кажутся <strong>на</strong>иболеепортируемыми и универсальными, они позволяют использовать один и тот же код длявидеочипов разных производителей. Но у таких методов есть масса недостатков, ониз<strong>на</strong>чительно менее гибкие и не такие удобные в использовании. Кроме того, они не даютиспользовать специфические возможности определённых видеокарт, такие, как быстраяразделяемая (общая) память, присутствующая в современных вычислительныхпроцессорах.Именно поэтому компания <strong>NVIDIA</strong> выпустила платформу <strong>CUDA</strong> <strong>—</strong> C-подобный языкпрограммирования со своим компилятором и библиотеками для вычислений <strong>на</strong> GPU.Конечно же, <strong>на</strong>писание оптимального кода для видеочипов совсем не такое простое и этазадача нуждается в длительной ручной работе, но <strong>CUDA</strong> как раз и раскрывает всевозможности и даёт программисту больший контроль <strong>на</strong>д аппаратными возможностямиGPU. Важно, что поддержка <strong>NVIDIA</strong> <strong>CUDA</strong> есть у чипов G8x, G9x и GT2xx,применяемых в видеокартах GeForce серий 8, 9 и 200, которые очень широкораспространены. В <strong>на</strong>стоящее время выпуще<strong>на</strong> фи<strong>на</strong>ль<strong>на</strong>я версия <strong>CUDA</strong> 2.0, в которойпоявились некоторые новые возможности, <strong>на</strong>пример, поддержка расчётов с двойнойточностью. <strong>CUDA</strong> доступ<strong>на</strong> <strong>на</strong> 32-битных и 64-битных операционных системах Linux,Windows и MacOS X.Разница между CPU и GPU в параллельных расчётахРост частот универсальных процессоров упёрся в физические ограничения и высокоеэнергопотребление, и увеличение их производительности всё чаще происходит за счётразмещения нескольких ядер в одном чипе. Продаваемые сейчас процессоры содержатлишь до четырёх ядер (дальнейший рост не будет быстрым) и они пред<strong>на</strong>з<strong>на</strong>чены дляобычных приложений, используют MIMD <strong>—</strong> множественный поток команд и данных.
Каждое ядро работает отдельно от остальных, исполняя разные инструкции для разныхпроцессов.Специализированные векторные возможности (SSE2 и SSE3) для четырехкомпонентных(оди<strong>на</strong>р<strong>на</strong>я точность вычислений с плавающей точкой) и двухкомпонентных (двой<strong>на</strong>яточность) векторов появились в универсальных процессорах из-за возросших требований<strong>графических</strong> приложений, в первую очередь. Именно поэтому для определённых задачприменение GPU выгоднее, ведь они из<strong>на</strong>чально сделаны для них.Например, в видеочипах <strong>NVIDIA</strong> основной блок <strong>—</strong> это мультипроцессор с восемьюдесятьюядрами и сотнями ALU в целом, несколькими тысячами регистров и небольшимколичеством разделяемой общей памяти. Кроме того, видеокарта содержит быструюглобальную память с доступом к ней всех мультипроцессоров, локальную память вкаждом мультипроцессоре, а также специальную память для констант.Самое главное <strong>—</strong> эти несколько ядер мультипроцессора в GPU являются SIMD(одиночный поток команд, множество потоков данных) ядрами. И эти ядра исполняютодни и те же инструкции одновременно, такой стиль программирования являетсяобычным для <strong>графических</strong> алгоритмов и многих <strong>на</strong>учных задач, но требуетспецифического программирования. Зато такой подход позволяет увеличить количествоисполнительных блоков за счёт их упрощения.Итак, перечислим основные различия между архитектурами CPU и GPU. Ядра CPUсозданы для исполнения одного потока последовательных инструкций с максимальнойпроизводительностью, а GPU проектируются для быстрого исполнения большого числапараллельно выполняемых потоков инструкций. Универсальные процессорыоптимизированы для достижения высокой производительности единственного потокакоманд, обрабатывающего и целые числа и числа с плавающей точкой. При этом доступ кпамяти случайный.Разработчики CPU стараются добиться выполнения как можно большего числаинструкций параллельно, для увеличения производительности. Для этого, <strong>на</strong>чи<strong>на</strong>я спроцессоров Intel Pentium, появилось суперскалярное выполнение, обеспечивающеевыполнение двух инструкций за такт, а Pentium Pro отличился внеочереднымвыполнением инструкций. Но у параллельного выполнения последовательного потокаинструкций есть определённые базовые ограничения и увеличением количестваисполнительных блоков кратного увеличения скорости не добиться.У видеочипов работа простая и распараллелен<strong>на</strong>я из<strong>на</strong>чально. Видеочип принимает <strong>на</strong>входе группу полигонов, проводит все необходимые операции, и <strong>на</strong> выходе выдаётпиксели. Обработка полигонов и пикселей независима, их можно обрабатыватьпараллельно, отдельно друг от друга. Поэтому, из-за из<strong>на</strong>чально параллельнойорганизации работы в GPU используется большое количество исполнительных блоков,которые легко загрузить, в отличие от последовательного потока инструкций для CPU.Кроме того, современные GPU также могут исполнять больше одной инструкции за такт(dual issue). Так, архитектура Tesla в некоторых условиях запускает <strong>на</strong> исполнениеоперации MAD+MUL или MAD+SFU одновременно.GPU отличается от CPU ещё и по принципам доступа к памяти. В GPU он связанный илегко предсказуемый <strong>—</strong> если из памяти читается тексель текстуры, то через некотороевремя придёт время и для соседних текселей. Да и при записи то же <strong>—</strong> пиксельзаписывается во фреймбуфер, и через несколько тактов будет записываться
расположенный рядом с ним. Поэтому организация памяти отличается от той, чтоиспользуется в CPU. И видеочипу, в отличие от универсальных процессоров, просто ненуж<strong>на</strong> кэш-память большого размера, а для текстур требуются лишь несколько (до 128-256 в нынешних GPU) килобайт.Да и сама по себе работа с памятью у GPU и CPU несколько отличается. Так, не всецентральные процессоры имеют встроенные контроллеры памяти, а у всех GPU обычноесть по несколько контроллеров, вплоть до восьми 64-битных ка<strong>на</strong>лов в чипе <strong>NVIDIA</strong>GT200. Кроме того, <strong>на</strong> видеокартах применяется более быстрая память, и в результатевидеочипам доступ<strong>на</strong> в разы большая пропуск<strong>на</strong>я способность памяти, что также весьмаважно для параллельных расчётов, оперирующих с огромными потоками данных.В универсальных процессорах большие количества транзисторов и площадь чипа идут <strong>на</strong>буферы команд, аппаратное предсказание ветвления и огромные объёмы <strong>на</strong>чиповой кэшпамяти.Все эти аппаратные блоки нужны для ускорения исполнения немногочисленныхпотоков команд. Видеочипы тратят транзисторы <strong>на</strong> массивы исполнительных блоков,управляющие потоками блоки, разделяемую память небольшого объёма и контроллерыпамяти <strong>на</strong> несколько ка<strong>на</strong>лов. Вышеперечисленное не ускоряет выполнение отдельныхпотоков, оно позволяет чипу обрабатывать нескольких тысяч потоков, одновременноисполняющихся чипом и требующих высокой пропускной способности памяти.Про отличия в кэшировании. Универсальные центральные процессоры используют кэшпамятьдля увеличения производительности за счёт снижения задержек доступа к памяти,а GPU используют кэш или общую память для увеличения полосы пропускания. CPUснижают задержки доступа к памяти при помощи кэш-памяти большого размера, а такжепредсказания ветвлений кода. Эти аппаратные части занимают большую часть площадичипа и потребляют много энергии. Видеочипы обходят проблему задержек доступа кпамяти при помощи одновременного исполнения тысяч потоков <strong>—</strong> в то время, когда одиниз потоков ожидает данных из памяти, видеочип может выполнять <strong>вычисления</strong> другогопотока без ожидания и задержек.Есть множество различий и в поддержке многопоточности. CPU исполняет 1-2 потокавычислений <strong>на</strong> одно процессорное ядро, а видеочипы могут поддерживать до 1024потоков <strong>на</strong> каждый мультипроцессор, которых в чипе несколько штук. И еслипереключение с одного потока <strong>на</strong> другой для CPU стоит сотни тактов, то GPUпереключает несколько потоков за один такт.Кроме того, центральные процессоры используют SIMD (од<strong>на</strong> инструкция выполняется<strong>на</strong>д многочисленными данными) блоки для векторных вычислений, а видеочипыприменяют SIMT (од<strong>на</strong> инструкция и несколько потоков) для скалярной обработкипотоков. SIMT не требует, чтобы разработчик преобразовывал данные в векторы, идопускает произвольные ветвления в потоках.Вкратце можно сказать, что в отличие от современных универсальных CPU, видеочипыпред<strong>на</strong>з<strong>на</strong>чены для параллельных вычислений с большим количеством арифметическихопераций. И з<strong>на</strong>чительно большее число транзисторов GPU работает по прямому<strong>на</strong>з<strong>на</strong>чению <strong>—</strong> обработке массивов данных, а не управляет исполнением (flow control)немногочисленных последовательных вычислительных потоков. Это схема того, сколькоместа в CPU и GPU занимает разнообраз<strong>на</strong>я логика:
В итоге, основой для эффективного использования мощи GPU в <strong>на</strong>учных и иныхне<strong>графических</strong> расчётах является распараллеливание алгоритмов <strong>на</strong> сотниисполнительных блоков, имеющихся в видеочипах. К примеру, множество приложений помолекулярному моделированию отлично приспособлено для расчётов <strong>на</strong> видеочипах, онитребуют больших вычислительных мощностей и поэтому удобны для параллельныхвычислений. А использование нескольких GPU даёт ещё больше вычислительныхмощностей для решения подобных задач.Выполнение расчётов <strong>на</strong> GPU показывает отличные результаты в алгоритмах,использующих параллельную обработку данных. То есть, когда одну и ту жепоследовательность математических операций применяют к большому объёму данных.При этом лучшие результаты достигаются, если отношение числа арифметическихинструкций к числу обращений к памяти достаточно велико. Это предъявляет меньшиетребования к управлению исполнением (flow control), а высокая плотность математики ибольшой объём данных отменяет необходимость в больших кэшах, как <strong>на</strong> CPU.В результате всех описанных выше отличий, теоретическая производительностьвидеочипов з<strong>на</strong>чительно превосходит производительность CPU. Компания <strong>NVIDIA</strong>приводит такой график роста производительности CPU и GPU за последние нескольколет:Естественно, эти данные не без доли лукавства. Ведь <strong>на</strong> CPU гораздо проще <strong>на</strong> практикедостичь теоретических цифр, да и цифры приведены для оди<strong>на</strong>рной точности в случаеGPU, и для двойной <strong>—</strong> в случае CPU. В любом случае, для части параллельных задач
оди<strong>на</strong>рной точности хватает, а разница в скорости между универсальными играфическими процессорами весьма велика, и поэтому овчинка стоит выделки.Первые попытки применения расчётов <strong>на</strong> GPUВидеочипы в параллельных математических расчётах пытались использовать довольнодавно. Самые первые попытки такого применения были крайне примитивными иограничивались использованием некоторых аппаратных функций, таких, как растеризацияи Z-буферизация. Но в нынешнем веке, с появлением шейдеров, <strong>на</strong>чали ускорять<strong>вычисления</strong> матриц. В 2003 году <strong>на</strong> SIGGRAPH отдель<strong>на</strong>я секция была выделе<strong>на</strong> под<strong>вычисления</strong> <strong>на</strong> GPU, и о<strong>на</strong> получила <strong>на</strong>звание GPGPU (General-Purpose computation onGPU) <strong>—</strong> универсальные <strong>вычисления</strong> <strong>на</strong> GPU).Наиболее известен BrookGPU <strong>—</strong> компилятор потокового языка программирования Brook,созданный для выполнения не<strong>графических</strong> вычислений <strong>на</strong> GPU. До его появленияразработчики, использующие возможности видеочипов для вычислений, выбирали одиниз двух распространённых API: Direct3D или OpenGL. Это серьёзно ограничивалоприменение GPU, ведь в 3D графике используются шейдеры и текстуры, о которыхспециалисты по параллельному программированию з<strong>на</strong>ть не обязаны, они используютпотоки и ядра. Brook смог помочь в облегчении их задачи. Эти потоковые расширения кязыку C, разработанные в Стэндфордском университете, скрывали от программистовтрёхмерный API, и представляли видеочип в виде параллельного сопроцессора.Компилятор обрабатывал файл .br с кодом C++ и расширениями, производя код,привязанный к библиотеке с поддержкой DirectX, OpenGL или x86.Естественно, у Brook было множество недостатков, <strong>на</strong> которых мы оста<strong>на</strong>вливались, и окоторых ещё подробнее поговорим далее. Но даже просто его появление вызвалоз<strong>на</strong>чительный прилив внимания тех же <strong>NVIDIA</strong> и ATI к инициативе вычислений <strong>на</strong> GPU,так как развитие этих возможностей серьёзно изменило рынок в дальнейшем, открывцелый новый его сектор <strong>—</strong> параллельные вычислители <strong>на</strong> основе видеочипов.В дальнейшем, некоторые исследователи из проекта Brook влились в командуразработчиков <strong>NVIDIA</strong>, чтобы представить программно-аппаратную стратегиюпараллельных вычислений, открыв новую долю рынка. И главным преимуществом этойинициативы <strong>NVIDIA</strong> стало то, что разработчики отлично з<strong>на</strong>ют все возможности своихGPU до мелочей, и в использовании графического API нет необходимости, а работать саппаратным обеспечением можно <strong>на</strong>прямую при помощи драйвера. Результатом усилийэтой команды стала <strong>NVIDIA</strong> <strong>CUDA</strong> (Compute Unified Device Architecture) <strong>—</strong> новаяпрограммно-аппарат<strong>на</strong>я архитектура для параллельных вычислений <strong>на</strong> <strong>NVIDIA</strong> GPU,которой посвяще<strong>на</strong> эта статья.Области применения параллельных расчётов <strong>на</strong> GPUЧтобы понять, какие преимущества приносит перенос расчётов <strong>на</strong> видеочипы, приведёмусреднённые цифры, полученные исследователями по всему миру. В среднем, припереносе вычислений <strong>на</strong> GPU, во многих задачах достигается ускорение в 5-30 раз, посравнению с быстрыми универсальными процессорами. Самые большие цифры (порядка100-кратного ускорения и даже более!) достигаются <strong>на</strong> коде, который не очень хорошоподходит для расчётов при помощи блоков SSE, но вполне удобен для GPU.Это лишь некоторые примеры ускорений синтетического кода <strong>на</strong> GPU против SSEвекторизованногокода <strong>на</strong> CPU (по данным <strong>NVIDIA</strong>):
Флуоресцент<strong>на</strong>я микроскопия: 12x; Молекуляр<strong>на</strong>я ди<strong>на</strong>мика (non-bonded force calc): 8-16x; Электростатика (прямое и многоуровневое суммирование Куло<strong>на</strong>): 40-120x и 7x.А это табличка, которую очень любит <strong>NVIDIA</strong>, показывая её <strong>на</strong> всех презентациях, <strong>на</strong>которой мы подробнее остановимся во второй части статьи, посвящённой конкретнымпримерам практических применений <strong>CUDA</strong> вычислений:Как видите, цифры весьма привлекательные, особенно впечатляют 100-150-кратныеприросты. В следующей статье, посвящённой <strong>CUDA</strong>, мы подробно разберём некоторые изэтих цифр. А сейчас перечислим основные приложения, в которых сейчас применяются<strong>вычисления</strong> <strong>на</strong> GPU: а<strong>на</strong>лиз и обработка изображений и сиг<strong>на</strong>лов, симуляция физики,вычислитель<strong>на</strong>я математика, вычислитель<strong>на</strong>я биология, фи<strong>на</strong>нсовые расчёты, базыданных, ди<strong>на</strong>мика газов и жидкостей, криптография, адаптив<strong>на</strong>я лучевая терапия,астрономия, обработка звука, биоинформатика, биологические симуляции, компьютерноезрение, а<strong>на</strong>лиз данных (data mining), цифровое кино и телевидение, электромагнитныесимуляции, геоинформационные системы, военные применения, горное планирование,молекуляр<strong>на</strong>я ди<strong>на</strong>мика, магнитно-резо<strong>на</strong>нс<strong>на</strong>я томография (MRI), нейросети,океанографические исследования, физика частиц, симуляция свёртывания молекул белка,квантовая химия, трассировка лучей, визуализация, радары, гидроди<strong>на</strong>мическоемоделирование (reservoir simulation), искусственный интеллект, а<strong>на</strong>лиз спутниковыхданных, сейсмическая разведка, хирургия, ультразвук, видеоконференции.
Подробности о многих применениях можно <strong>на</strong>йти <strong>на</strong> сайте компании <strong>NVIDIA</strong> в разделепо технологии <strong>CUDA</strong>. Как видите, список довольно большой, но и это ещё не всё! Егоможно продолжать, и <strong>на</strong>верняка можно предположить, что в будущем будут <strong>на</strong>йдены идругие области применения параллельных расчётов <strong>на</strong> видеочипах, о которых мы пока недогадываемся.Возможности <strong>NVIDIA</strong> <strong>CUDA</strong>Технология <strong>CUDA</strong> <strong>—</strong> это программно-аппарат<strong>на</strong>я вычислитель<strong>на</strong>я архитектура <strong>NVIDIA</strong>,основан<strong>на</strong>я <strong>на</strong> расширении языка Си, которая даёт возможность организации доступа к<strong>на</strong>бору инструкций графического ускорителя и управления его памятью при организациипараллельных вычислений. <strong>CUDA</strong> помогает реализовывать алгоритмы, выполнимые <strong>на</strong><strong>графических</strong> процессорах видеоускорителей GeForce восьмого поколения и старше (серииGeForce 8, GeForce 9, GeForce 200), а также Quadro и Tesla.Хотя трудоёмкость программирования GPU при помощи <strong>CUDA</strong> довольно велика, о<strong>на</strong>ниже, чем с ранними GPGPU решениями. Такие программы требуют разбиенияприложения между несколькими мультипроцессорами подобно MPI программированию,но без разделения данных, которые хранятся в общей видеопамяти. И так как <strong>CUDA</strong>программирование для каждого мультипроцессора подобно OpenMP программированию,оно требует хорошего понимания организации памяти. Но, конечно же, сложностьразработки и переноса <strong>на</strong> <strong>CUDA</strong> сильно зависит от приложения.Набор для разработчиков содержит множество примеров кода и хорошо документирован.Процесс обучения потребует около двух-четырёх недель для тех, кто уже з<strong>на</strong>ком сOpenMP и MPI. В основе API лежит расширенный язык Си, а для трансляции кода с этогоязыка в состав <strong>CUDA</strong> SDK входит компилятор командной строки nvcc, созданный <strong>на</strong>основе открытого компилятора Open64.Перечислим основные характеристики <strong>CUDA</strong>:унифицированное программно-аппаратное решение для параллельных вычислений<strong>на</strong> видеочипах <strong>NVIDIA</strong>;большой <strong>на</strong>бор поддерживаемых решений, от мобильных до мультичиповыхстандартный язык программирования Си;стандартные библиотеки численного а<strong>на</strong>лиза FFT (быстрое преобразование Фурье)и BLAS (линей<strong>на</strong>я алгебра);оптимизированный обмен данными между CPU и GPU;взаимодействие с графическими API OpenGL и DirectX;поддержка 32- и 64-битных операционных систем: Windows XP, Windows Vista,Linux и MacOS X;возможность разработки <strong>на</strong> низком уровне.Касательно поддержки операционных систем нужно добавить, что официальноподдерживаются все основные дистрибутивы Linux (Red Hat Enterprise Linux 3.x/4.x/5.x,SUSE Linux 10.x), но, судя по данным энтузиастов, <strong>CUDA</strong> прекрасно работает и <strong>на</strong> другихсборках: Fedora Core, Ubuntu, Gentoo и др.Среда разработки <strong>CUDA</strong> (<strong>CUDA</strong> Toolkit) включает:компилятор nvcc;библиотеки FFT и BLAS;
профилировщик;отладчик gdb для GPU;<strong>CUDA</strong> runtime драйвер в комплекте стандартных драйверов <strong>NVIDIA</strong>руководство по программированию;<strong>CUDA</strong> Developer SDK (исходный код, утилиты и документация).В примерах исходного кода: параллель<strong>на</strong>я битон<strong>на</strong>я сортировка (bitonic sort),транспонирование матриц, параллельное префиксное суммирование больших массивов,свёртка изображений, дискретное вейвлет-преобразование, пример взаимодействия сOpenGL и Direct3D, использование библиотек CUBLAS и CUFFT, вычисление ценыопцио<strong>на</strong> (формула Блэка-Шоулза, биномиаль<strong>на</strong>я модель, метод Монте-Карло),параллельный генератор случайных чисел Mersenne Twister, вычисление гистограммыбольшого массива, шумоподавление, фильтр Собеля (<strong>на</strong>хождение границ).Преимущества и ограничения <strong>CUDA</strong>С точки зрения программиста, графический конвейер является <strong>на</strong>бором стадий обработки.Блок геометрии генерирует треугольники, а блок растеризации <strong>—</strong> пиксели, отображаемые<strong>на</strong> мониторе. Традицион<strong>на</strong>я модель программирования GPGPU выглядит следующимобразом:Чтобы перенести <strong>вычисления</strong> <strong>на</strong> GPU в рамках такой модели, нужен специальный подход.Даже поэлементное сложение двух векторов потребует отрисовки фигуры <strong>на</strong> экране иливо внеэкранный буфер. Фигура растеризуется, цвет каждого пикселя вычисляется позаданной программе (пиксельному шейдеру). Программа считывает входные данные изтекстур для каждого пикселя, складывает их и записывает в выходной буфер. И все этимногочисленные операции нужны для того, что в обычном языке программированиязаписывается одним оператором!Поэтому, применение GPGPU для вычислений общего <strong>на</strong>з<strong>на</strong>чения имеет ограничение ввиде слишком большой сложности обучения разработчиков. Да и других ограниченийдостаточно, ведь пиксельный шейдер <strong>—</strong> это всего лишь формула зависимости итоговогоцвета пикселя от его коорди<strong>на</strong>ты, а язык пиксельных шейдеров <strong>—</strong> язык записи этихформул с Си-подобным синтаксисом. Ранние методы GPGPU являются хитрым трюком,
позволяющим использовать мощность GPU, но без всякого удобства. Данные тампредставлены изображениями (текстурами), а алгоритм <strong>—</strong> процессом растеризации.Нужно особо отметить и весьма специфичную модель памяти и исполнения.Программно-аппарат<strong>на</strong>я архитектура для вычислений <strong>на</strong> GPU компании <strong>NVIDIA</strong>отличается от предыдущих моделей GPGPU тем, что позволяет писать программы дляGPU <strong>на</strong> <strong>на</strong>стоящем языке Си со стандартным синтаксисом, указателями инеобходимостью в минимуме расширений для доступа к вычислительным ресурсамвидеочипов. <strong>CUDA</strong> не зависит от <strong>графических</strong> API, и обладает некоторымиособенностями, пред<strong>на</strong>з<strong>на</strong>ченными специально для вычислений общего <strong>на</strong>з<strong>на</strong>чения.Преимущества <strong>CUDA</strong> перед традиционным подходом к GPGPU <strong>вычисления</strong>м: интерфейс программирования приложений <strong>CUDA</strong> основан <strong>на</strong> стандартном языкепрограммирования Си с расширениями, что упрощает процесс изучения ивнедрения архитектуры <strong>CUDA</strong>; <strong>CUDA</strong> обеспечивает доступ к разделяемой между потоками памяти размером в 16Кб <strong>на</strong> мультипроцессор, которая может быть использова<strong>на</strong> для организации кэша сширокой полосой пропускания, по сравнению с текстурными выборками; более эффектив<strong>на</strong>я передача данных между системной и видеопамятью отсутствие необходимости в <strong>графических</strong> API с избыточностью и <strong>на</strong>кладнымирасходами; линей<strong>на</strong>я адресация памяти, и gather и scatter, возможность записи попроизвольным адресам; аппарат<strong>на</strong>я поддержка целочисленных и битовых операций.Основные ограничения <strong>CUDA</strong>:отсутствие поддержки рекурсии для выполняемых функций;минималь<strong>на</strong>я шири<strong>на</strong> блока в 32 потока;закрытая архитектура <strong>CUDA</strong>, при<strong>на</strong>длежащая <strong>NVIDIA</strong>.Слабыми местами программирования при помощи предыдущих методов GPGPU являетсято, что эти методы не используют блоки исполнения вершинных шейдеров в предыдущихнеунифицированных архитектурах, данные хранятся в текстурах, а выводятся вовнеэкранный буфер, а многопроходные алгоритмы используют пиксельные шейдерныеблоки. В ограничения GPGPU можно включить: недостаточно эффективноеиспользование аппаратных возможностей, ограничения полосой пропускания памяти,отсутствие операции scatter (только gather), обязательное использование графическогоAPI.Основные преимущества <strong>CUDA</strong> по сравнению с предыдущими методами GPGPUвытекают из того, что эта архитектура спроектирова<strong>на</strong> для эффективного использованияне<strong>графических</strong> вычислений <strong>на</strong> GPU и использует язык программирования C, не требуяпереноса алгоритмов в удобный для концепции графического конвейера вид. <strong>CUDA</strong>предлагает новый путь вычислений <strong>на</strong> GPU, не использующий графические API,предлагающий произвольный доступ к памяти (scatter или gather). Такая архитектуралише<strong>на</strong> недостатков GPGPU и использует все исполнительные блоки, а также расширяетвозможности за счёт целочисленной математики и операций битового сдвига.Кроме того, <strong>CUDA</strong> открывает некоторые аппаратные возможности, недоступные из<strong>графических</strong> API, такие как разделяемая память. Это память небольшого объёма (16
килобайт <strong>на</strong> мультипроцессор), к которой имеют доступ блоки потоков. О<strong>на</strong> позволяеткэшировать <strong>на</strong>иболее часто используемые данные и может обеспечить более высокуюскорость, по сравнению с использованием текстурных выборок для этой задачи. Что, всвою очередь, снижает чувствительность к пропускной способности параллельныхалгоритмов во многих приложениях. Например, это полезно для линейной алгебры,быстрого преобразования Фурье и фильтров обработки изображений.Удобнее в <strong>CUDA</strong> и доступ к памяти. Программный код в <strong>графических</strong> API выводитданные в виде 32-х з<strong>на</strong>чений с плавающей точкой оди<strong>на</strong>рной точности (RGBA з<strong>на</strong>ченияодновременно в восемь render target) в заранее предопределённые области, а <strong>CUDA</strong>поддерживает scatter запись <strong>—</strong> неограниченное число записей по любому адресу. Такиепреимущества делают возможным выполнение <strong>на</strong> GPU некоторых алгоритмов, которыеневозможно эффективно реализовать при помощи методов GPGPU, основанных <strong>на</strong><strong>графических</strong> API.Также, графические API в обязательном порядке хранят данные в текстурах, что требуетпредварительной упаковки больших массивов в текстуры, что усложняет алгоритм изаставляет использовать специальную адресацию. А <strong>CUDA</strong> позволяет читать данные полюбому адресу. Ещё одним преимуществом <strong>CUDA</strong> является оптимизированный обменданными между CPU и GPU. А для разработчиков, желающих получить доступ к низкомууровню (<strong>на</strong>пример, при <strong>на</strong>писании другого языка программирования), <strong>CUDA</strong> предлагаетвозможность низкоуровневого программирования <strong>на</strong> ассемблере.История развития <strong>CUDA</strong>Разработка <strong>CUDA</strong> была анонсирова<strong>на</strong> вместе с чипом G80 в ноябре 2006, а релизпубличной бета-версии <strong>CUDA</strong> SDK состоялся в феврале 2007 года. Версия 1.0 вышла виюне 2007 года под запуск в продажу решений Tesla, основанных <strong>на</strong> чипе G80, ипред<strong>на</strong>з<strong>на</strong>ченных для рынка высокопроизводительных вычислений. Затем, в конце годавышла бета-версия <strong>CUDA</strong> 1.1, которая, несмотря <strong>на</strong> малоз<strong>на</strong>чительное увеличение номераверсии, ввела довольно много нового.Из появившегося в <strong>CUDA</strong> 1.1 можно отметить включение <strong>CUDA</strong>-функцио<strong>на</strong>льности вобычные видеодрайверы <strong>NVIDIA</strong>. Это оз<strong>на</strong>чало, что в требованиях к любой <strong>CUDA</strong>программе достаточно было указать видеокарту серии GeForce 8 и выше, а такжеминимальную версию драйверов 169.xx. Это очень важно для разработчиков, присоблюдении этих условий <strong>CUDA</strong> программы будут работать у любого пользователя.Также было добавлено асинхронное выполнение вместе с копированием данных (толькодля чипов G84, G86, G92 и выше), асинхрон<strong>на</strong>я пересылка данных в видеопамять,атомарные операции доступа к памяти, поддержка 64-битных версий Windows ивозможность мультичиповой работы <strong>CUDA</strong> в режиме SLI.На данный момент актуальной является версия для решений <strong>на</strong> основе GT200 <strong>—</strong> <strong>CUDA</strong>2.0, вышедшая вместе с линейкой GeForce GTX 200. Бета-версия была выпуще<strong>на</strong> ещёвесной 2008 года. Во второй версии появились: поддержка вычислений двойной точности(аппарат<strong>на</strong>я поддержка только у GT200), <strong>на</strong>конец-то поддерживается Windows Vista (32 и64-битные версии) и Mac OS X, добавлены средства отладки и профилирования,поддерживаются 3D текстуры, оптимизирован<strong>на</strong>я пересылка данных.Что касается вычислений с двойной точностью, то их скорость <strong>на</strong> текущем аппаратномпоколении ниже оди<strong>на</strong>рной точности в несколько раз. Причины рассмотрены в <strong>на</strong>шейбазовой статье по GeForce GTX 280. Реализация в GT200 этой поддержки заключается в
том, блоки FP32 не используются для получения результата в четыре раза меньшем темпе,для поддержки FP64 вычислений в <strong>NVIDIA</strong> решили сделать выделенные вычислительныеблоки. И в GT200 их в десять раз меньше, чем блоков FP32 (по одному блоку двойнойточности <strong>на</strong> каждый мультипроцессор).Реально производительность может быть даже ещё меньше, так как архитектураоптимизирова<strong>на</strong> для 32-битного чтения из памяти и регистров, кроме того, двой<strong>на</strong>яточность не нуж<strong>на</strong> в <strong>графических</strong> приложениях, и в GT200 о<strong>на</strong> сдела<strong>на</strong> скорее,чтобы просто была. Да и современные четырехъядерные процессоры показывают не<strong>на</strong>много меньшую реальную производительность. Но будучи даже в 10 раз медленнее, чемоди<strong>на</strong>р<strong>на</strong>я точность, такая поддержка полез<strong>на</strong> для схем со смешанной точностью. Од<strong>на</strong> израспространенных техник <strong>—</strong> получить из<strong>на</strong>чально приближенные результаты води<strong>на</strong>рной точности, и затем их уточнить в двойной. Теперь это можно сделать прямо <strong>на</strong>видеокарте, без пересылки промежуточных данных к CPU.Ещё од<strong>на</strong> полез<strong>на</strong>я особенность <strong>CUDA</strong> 2.0 не имеет отношения к GPU, как ни странно.Просто теперь можно компилировать код <strong>CUDA</strong> в высокоэффективный многопоточныйSSE код для быстрого исполнения <strong>на</strong> центральном процессоре. То есть, теперь этавозможность годится не только для отладки, но и реального использования <strong>на</strong> системахбез видеокарты <strong>NVIDIA</strong>. Ведь использование <strong>CUDA</strong> в обычном коде сдерживается тем,что видеокарты <strong>NVIDIA</strong> хоть и самые популярные среди выделенных видеорешений, ноимеются не во всех системах. И до версии 2.0 в таких случаях пришлось бы делать дваразных кода: для <strong>CUDA</strong> и отдельно для CPU. А теперь можно выполнять любую <strong>CUDA</strong>программу <strong>на</strong> CPU с высокой эффективностью, пусть и с меньшей скоростью, чем <strong>на</strong>видеочипах.Решения с поддержкой <strong>NVIDIA</strong> <strong>CUDA</strong>Все видеокарты, обладающие поддержкой <strong>CUDA</strong>, могут помочь в ускорении большинстватребовательных задач, <strong>на</strong>чи<strong>на</strong>я от аудио- и видеообработки, и заканчивая медициной и<strong>на</strong>учными исследованиями. Единственное реальное ограничение состоит в том, чтомногие <strong>CUDA</strong> программы требуют минимум 256 мегабайт видеопамяти, и это <strong>—</strong> од<strong>на</strong> изважнейших технических характеристик для <strong>CUDA</strong>-приложений.Актуальный список поддерживающих <strong>CUDA</strong> продуктов можно получить <strong>на</strong> вебсайте<strong>NVIDIA</strong>. На момент <strong>на</strong>писания статьи расчёты <strong>CUDA</strong> поддерживали все продукты серийGeForce 200, GeForce 9 и GeForce 8, в том числе и мобильные продукты, <strong>на</strong>чи<strong>на</strong>я сGeForce 8400M, а также и чипсеты GeForce 8100, 8200 и 8300. Также поддержкой <strong>CUDA</strong>обладают современные продукты Quadro и все Tesla: S1070, C1060, C870, D870 и S870.
Особо отметим, что вместе с новыми видеокартами GeForce GTX 260 и 280, былианонсированы и соответствующие решения для высокопроизводительных вычислений:Tesla C1060 и S1070 (представленные <strong>на</strong> фото выше), которые будут доступны дляприобретения осенью этого года. GPU в них применён тот же <strong>—</strong> GT200, в C1060 он один,в S1070 <strong>—</strong> четыре. Зато, в отличие от игровых решений, в них используется по четырегигабайта памяти <strong>на</strong> каждый чип. Из минусов разве что меньшая частота памяти и ПСП,чем у игровых карт, обеспечивающая по 102 гигабайт/с <strong>на</strong> чип.Состав <strong>NVIDIA</strong> <strong>CUDA</strong><strong>CUDA</strong> включает два API: высокого уровня (<strong>CUDA</strong> Runtime API) и низкого (<strong>CUDA</strong> DriverAPI), хотя в одной программе одновременное использование обоих невозможно, нужноиспользовать или один или другой. Высокоуровневый работает «сверху»низкоуровневого, все вызовы runtime транслируются в простые инструкции,обрабатываемые низкоуровневым Driver API. Но даже «высокоуровневый» APIпредполагает з<strong>на</strong>ния об устройстве и работе видеочипов <strong>NVIDIA</strong>, слишком высокогоуровня абстракции там нет.
Есть и ещё один уровень, даже более высокий <strong>—</strong> две библиотеки:CUBLAS <strong>—</strong> <strong>CUDA</strong> вариант BLAS (Basic Linear Algebra Subprograms), пред<strong>на</strong>з<strong>на</strong>ченныйдля вычислений задач линейной алгебры и использующий прямой доступ к ресурсамGPU;CUFFT <strong>—</strong> <strong>CUDA</strong> вариант библиотеки Fast Fourier Transform для расчёта быстрогопреобразования Фурье, широко используемого при обработке сиг<strong>на</strong>лов. Поддерживаютсяследующие типы преобразований: complex-complex (C2C), real-complex (R2C) и complexreal(C2R).Рассмотрим эти библиотеки подробнее. CUBLAS <strong>—</strong> это переведённые <strong>на</strong> язык <strong>CUDA</strong>стандартные алгоритмы линейной алгебры, <strong>на</strong> данный момент поддерживается толькоопределённый <strong>на</strong>бор основных функций CUBLAS. Библиотеку очень легко использовать:нужно создать матрицу и векторные объекты в памяти видеокарты, заполнить ихданными, вызвать требуемые функции CUBLAS, и загрузить результаты из видеопамятиобратно в системную. CUBLAS содержит специальные функции для создания иуничтожения объектов в памяти GPU, а также для чтения и записи данных в эту память.Поддерживаемые функции BLAS: уровни 1, 2 и 3 для действительных чисел, уровень 1CGEMM для комплексных. Уровень 1 <strong>—</strong> это векторно-векторные операции, уровень 2 <strong>—</strong>векторно-матричные операции, уровень 3 <strong>—</strong> матрично-матричные операции.CUFFT <strong>—</strong> <strong>CUDA</strong> вариант функции быстрого преобразования Фурье <strong>—</strong> широкоиспользуемой и очень важной при а<strong>на</strong>лизе сиг<strong>на</strong>лов, фильтрации и т.п. CUFFTпредоставляет простой интерфейс для эффективного <strong>вычисления</strong> FFT <strong>на</strong> видеочипахпроизводства <strong>NVIDIA</strong> без необходимости в разработке собственного варианта FFT дляGPU. <strong>CUDA</strong> вариант FFT поддерживает 1D, 2D, и 3D преобразования комплексных идействительных данных, пакетное исполнение для нескольких 1D трансформаций в
параллели, размеры 2D и 3D трансформаций могут быть в пределах [2, 16384], для 1Dподдерживается размер до 8 миллионов элементов.Основы создания программ <strong>на</strong> <strong>CUDA</strong>Для понимания дальнейшего текста следует разбираться в базовых архитектурныхособенностях видеочипов <strong>NVIDIA</strong>. GPU состоит из нескольких кластеров текстурныхблоков (Texture Processing Cluster). Каждый кластер состоит из укрупнённого блокатекстурных выборок и двух-трех потоковых мультипроцессоров, каждый из которыхсостоит из восьми вычислительных устройств и двух суперфункцио<strong>на</strong>льных блоков. Всеинструкции выполняются по принципу SIMD, когда од<strong>на</strong> инструкция применяется ковсем потокам в warp (термин из текстильной промышленности, в <strong>CUDA</strong> это группа из 32потоков <strong>—</strong> минимальный объём данных, обрабатываемых мультипроцессорами). Этотспособ выполнения <strong>на</strong>звали SIMT (single instruction multiple threads <strong>—</strong> од<strong>на</strong> инструкция имного потоков).Каждый из мультипроцессоров имеет определённые ресурсы. Так, есть специаль<strong>на</strong>яразделяемая память объемом 16 килобайт <strong>на</strong> мультипроцессор. Но это не кэш, так какпрограммист может использовать её для любых нужд, подобно Local Store в SPUпроцессоров Cell. Эта разделяемая память позволяет обмениваться информацией междупотоками одного блока. Важно, что все потоки одного блока всегда выполняются одним итем же мультипроцессором. А потоки из разных блоков обмениваться данными не могут,и нужно помнить это ограничение. Разделяемая память часто бывает полезной, кроме техслучаев, когда несколько потоков обращаются к одному банку памяти.Мультипроцессоры могут обращаться и к видеопамяти, но с большими задержками ихудшей пропускной способностью. Для ускорения доступа и снижения частотыобращения к видеопамяти, у мультипроцессоров есть по 8 килобайт кэша <strong>на</strong> константы итекстурные данные.
Мультипроцессор использует 8192-16384 (для G8x/G9x и GT2xx, соответственно)регистра, общие для всех потоков всех блоков, выполняемых <strong>на</strong> нём. Максимальное числоблоков <strong>на</strong> один мультипроцессор для G8x/G9x равно восьми, а число warp <strong>—</strong> 24 (768потоков <strong>на</strong> один мультипроцессор). Всего топовые видеокарты серий GeForce 8 и 9 могутобрабатывать до 12288 потоков единовременно. GeForce GTX 280 <strong>на</strong> основе GT200предлагает до 1024 потоков <strong>на</strong> мультипроцессор, в нём есть 10 кластеров по тримультипроцессора, обрабатывающих до 30720 потоков. З<strong>на</strong>ние этих ограниченийпозволяет оптимизировать алгоритмы под доступные ресурсы.Первым шагом при переносе существующего приложения <strong>на</strong> <strong>CUDA</strong> является егопрофилирование и определение участков кода, являющихся «бутылочным горлышком»,тормозящим работу. Если среди таких участков есть подходящие для быстрогопараллельного исполнения, эти функции переносятся <strong>на</strong> Cи расширения <strong>CUDA</strong> длявыполнения <strong>на</strong> GPU. Программа компилируется при помощи поставляемого <strong>NVIDIA</strong>компилятора, который генерирует код и для CPU, и для GPU. При исполнениипрограммы, центральный процессор выполняет свои порции кода, а GPU выполняет<strong>CUDA</strong> код с <strong>на</strong>иболее тяжелыми параллельными <strong>вычисления</strong>ми. Эта часть,пред<strong>на</strong>з<strong>на</strong>чен<strong>на</strong>я для GPU, <strong>на</strong>зывается ядром (kernel). В ядре определяются операции,которые будут исполнены <strong>на</strong>д данными.Видеочип получает ядро и создает копии для каждого элемента данных. Эти копии<strong>на</strong>зываются потоками (thread). Поток содержит счётчик, регистры и состояние. Длябольших объёмов данных, таких как обработка изображений, запускаются миллионыпотоков. Потоки выполняются группами по 32 штуки, <strong>на</strong>зываемыми warp'ы. Warp'ам<strong>на</strong>з<strong>на</strong>чается исполнение <strong>на</strong> определенных потоковых мультипроцессорах. Каждыймультипроцессор состоит из восьми ядер <strong>—</strong> потоковых процессоров, которые выполняютодну инструкцию MAD за один такт. Для исполнения одного 32-поточного warp'атребуется четыре такта работы мультипроцессора (речь о частоте shader domain, котораярав<strong>на</strong> 1.5 ГГц и выше).Мультипроцессор не является традиционным многоядерным процессором, он отличноприспособлен для многопоточности, поддерживая до 32 warp'ов единовременно. Каждыйтакт аппаратное обеспечение выбирает, какой из warp'ов исполнять, и переключается отодного к другому без потерь в тактах. Если проводить а<strong>на</strong>логию с центральнымпроцессором, это похоже <strong>на</strong> одновременное исполнение 32 программ и переключениемежду ними каждый такт без потерь <strong>на</strong> переключение контекста. Реально ядра CPUподдерживают единовременное выполнение одной программы и переключаются <strong>на</strong>другие с задержкой в сотни тактов.Модель программирования <strong>CUDA</strong>Повторимся, что <strong>CUDA</strong> использует параллельную модель вычислений, когда каждый изSIMD процессоров выполняет ту же инструкцию <strong>на</strong>д разными элементами данныхпараллельно. GPU является вычислительным устройством, сопроцессором (device) дляцентрального процессора (host), обладающим собственной памятью и обрабатывающимпараллельно большое количество потоков. Ядром (kernel) <strong>на</strong>зывается функция для GPU,исполняемая потоками (а<strong>на</strong>логия из 3D графики <strong>—</strong> шейдер).Мы говорили выше, что видеочип отличается от CPU тем, что может обрабатыватьодновременно десятки тысяч потоков, что обычно для графики, которая хорошораспараллеливается. Каждый поток скалярен, не требует упаковки данных в 4-компонентные векторы, что удобнее для большинства задач. Количество логических
потоков и блоков потоков превосходит количество физических исполнительныхустройств, что даёт хорошую масштабируемость для всего модельного ряда решенийкомпании.Модель программирования в <strong>CUDA</strong> предполагает группирование потоков. Потокиобъединяются в блоки потоков (thread block) <strong>—</strong> одномерные или двумерные сеткипотоков, взаимодействующих между собой при помощи разделяемой памяти и точексинхронизации. Программа (ядро, kernel) исполняется <strong>на</strong>д сеткой (grid) блоков потоков(thread blocks), см. рисунок ниже. Одновременно исполняется од<strong>на</strong> сетка. Каждый блокможет быть одно-, двух- или трехмерным по форме, и может состоять из 512 потоков <strong>на</strong>текущем аппаратном обеспечении.Блоки потоков выполняются в виде небольших групп, <strong>на</strong>зываемых варп (warp), размеркоторых <strong>—</strong> 32 потока. Это минимальный объём данных, которые могут обрабатываться вмультипроцессорах. И так как это не всегда удобно, <strong>CUDA</strong> позволяет работать и сблоками, содержащими от 64 до 512 потоков.Группировка блоков в сетки позволяет уйти от ограничений и применить ядро к большемучислу потоков за один вызов. Это помогает и при масштабировании. Если у GPUнедостаточно ресурсов, он будет выполнять блоки последовательно. В обратном случае,блоки могут выполняться параллельно, что важно для оптимального распределенияработы <strong>на</strong> видеочипах разного уровня, <strong>на</strong>чи<strong>на</strong>я от мобильных и интегрированных.Модель памяти <strong>CUDA</strong>Модель памяти в <strong>CUDA</strong> отличается возможностью побайтной адресации, поддержкой какgather, так и scatter. Доступно довольно большое количество регистров <strong>на</strong> каждыйпотоковый процессор, до 1024 штук. Доступ к ним очень быстрый, хранить в них можно32-битные целые или числа с плавающей точкой.
Каждый поток имеет доступ к следующим типам памяти:Глобаль<strong>на</strong>я память <strong>—</strong> самый большой объём памяти, доступный для всехмультипроцессоров <strong>на</strong> видеочипе, размер составляет от 256 мегабайт до 1.5 гигабайт <strong>на</strong>текущих решениях (и до 4 Гбайт <strong>на</strong> Tesla). Обладает высокой пропускной способностью,более 100 гигабайт/с для топовых решений <strong>NVIDIA</strong>, но очень большими задержками внесколько сот тактов. Не кэшируется, поддерживает обобщённые инструкции load и store,и обычные указатели <strong>на</strong> память.Локаль<strong>на</strong>я память <strong>—</strong> это небольшой объём памяти, к которому имеет доступ толькоодин потоковый процессор. О<strong>на</strong> относительно медлен<strong>на</strong>я <strong>—</strong> такая же, как и глобаль<strong>на</strong>я.Разделяемая память <strong>—</strong> это 16-килобайтный (в видеочипах нынешней архитектуры) блокпамяти с общим доступом для всех потоковых процессоров в мультипроцессоре. Этапамять весьма быстрая, такая же, как регистры. О<strong>на</strong> обеспечивает взаимодействиепотоков, управляется разработчиком <strong>на</strong>прямую и имеет низкие задержки. Преимуществаразделяемой памяти: использование в виде управляемого программистом кэша первогоуровня, снижение задержек при доступе исполнительных блоков (ALU) к данным,сокращение количества обращений к глобальной памяти.Память констант <strong>—</strong> область памяти объемом 64 килобайта (то же <strong>—</strong> для нынешнихGPU), доступ<strong>на</strong>я только для чтения всеми мультипроцессорами. О<strong>на</strong> кэшируется по 8килобайт <strong>на</strong> каждый мультипроцессор. Довольно медлен<strong>на</strong>я <strong>—</strong> задержка в несколько соттактов при отсутствии нужных данных в кэше.Текстур<strong>на</strong>я память <strong>—</strong> блок памяти, доступный для чтения всеми мультипроцессорами.Выборка данных осуществляется при помощи текстурных блоков видеочипа, поэтомупредоставляются возможности линейной интерполяции данных без дополнительныхзатрат. Кэшируется по 8 килобайт <strong>на</strong> каждый мультипроцессор. Медлен<strong>на</strong>я, какглобаль<strong>на</strong>я <strong>—</strong> сотни тактов задержки при отсутствии данных в кэше.
Естественно, что глобаль<strong>на</strong>я, локаль<strong>на</strong>я, текстур<strong>на</strong>я и память констант <strong>—</strong> это физическиод<strong>на</strong> и та же память, извест<strong>на</strong>я как локаль<strong>на</strong>я видеопамять видеокарты. Их отличия вразличных алгоритмах кэширования и моделях доступа. Центральный процессор можетобновлять и запрашивать только внешнюю память: глобальную, константную итекстурную.Из <strong>на</strong>писанного выше понятно, что <strong>CUDA</strong> предполагает специальный подход кразработке, не совсем такой, как принят в программах для CPU. Нужно помнить о разныхтипах памяти, о том, что локаль<strong>на</strong>я и глобаль<strong>на</strong>я память не кэшируется и задержки придоступе к ней гораздо выше, чем у регистровой памяти, так как о<strong>на</strong> физически <strong>на</strong>ходитсяв отдельных микросхемах.Типичный, но не обязательный шаблон решения задач:задача разбивается <strong>на</strong> подзадачи;входные данные делятся <strong>на</strong> блоки, которые вмещаются в разделяемую память;каждый блок обрабатывается блоком потоков;подблок подгружается в разделяемую память из глобальной;<strong>на</strong>д данными в разделяемой памяти проводятся соответствующие <strong>вычисления</strong>;результаты копируются из разделяемой памяти обратно в глобальную.Среда программированияВ состав <strong>CUDA</strong> входят runtime библиотеки:общая часть, предоставляющая встроенные векторные типы и подмножествавызовов RTL, поддерживаемые <strong>на</strong> CPU и GPU;CPU-компонента, для управления одним или несколькими GPU;GPU-компонента, предоставляющая специфические функции для GPU.Основной процесс приложения <strong>CUDA</strong> работает <strong>на</strong> универсальном процессоре (host), онзапускает несколько копий процессов kernel <strong>на</strong> видеокарте. Код для CPU делаетследующее: инициализирует GPU, распределяет память <strong>на</strong> видеокарте и системе,
копирует константы в память видеокарты, запускает несколько копий процессов kernel <strong>на</strong>видеокарте, копирует полученный результат из видеопамяти, освобождает память изавершает работу.В качестве примера для понимания приведем CPU код для сложения векторов,представленный в <strong>CUDA</strong>:Функции, исполняемые видеочипом, имеют следующие ограничения: отсутствуетрекурсия, нет статических переменных внутри функций и переменного числа аргументов.Поддерживается два вида управления памятью: линей<strong>на</strong>я память с доступом по 32-битным указателям, и <strong>CUDA</strong>-массивы с доступом только через функции текстурнойвыборки.Программы <strong>на</strong> <strong>CUDA</strong> могут взаимодействовать с графическими API: для рендерингаданных, сгенерированных в программе, для считывания результатов рендеринга и ихобработки средствами <strong>CUDA</strong> (<strong>на</strong>пример, при реализации фильтров постобработки). Дляэтого ресурсы <strong>графических</strong> API могут быть отображены (с получением адреса ресурса) впространство глобальной памяти <strong>CUDA</strong>. Поддерживаются следующие типы ресурсов<strong>графических</strong> API: Buffer Objects (PBO / VBO) в OpenGL, вершинные буферы и текстуры(2D, 3D и кубические карты) Direct3D9.Стадии компиляции <strong>CUDA</strong>-приложения:
Файлы исходного кода <strong>на</strong> <strong>CUDA</strong> C компилируются при помощи программы NVCC,которая является оболочкой <strong>на</strong>д другими инструментами, и вызывает их: cudacc, g++, cl идр. NVCC генерирует: код для центрального процессора, который компилируется вместе состальными частями приложения, <strong>на</strong>писанными <strong>на</strong> чистом Си, и объектный код PTX длявидеочипа. Исполнимые файлы с кодом <strong>на</strong> <strong>CUDA</strong> в обязательном порядке требуют<strong>на</strong>личия библиотек <strong>CUDA</strong> runtime library (cudart) и <strong>CUDA</strong> core library (cuda).Оптимизация программ <strong>на</strong> <strong>CUDA</strong>Естественно, в рамках обзорной статьи невозможно рассмотреть серьёзные вопросыоптимизации в <strong>CUDA</strong> программировании. Поэтому просто вкратце расскажем о базовыхвещах. Для эффективного использования возможностей <strong>CUDA</strong> нужно забыть прообычные методы <strong>на</strong>писания программ для CPU, и использовать те алгоритмы, которыехорошо распараллеливаются <strong>на</strong> тысячи потоков. Также важно <strong>на</strong>йти оптимальное местодля хранения данных (регистры, разделяемая память и т.п.), минимизировать передачуданных между CPU и GPU, использовать буферизацию.В общих чертах, при оптимизации программы <strong>CUDA</strong> нужно постараться добитьсяоптимального баланса между размером и количеством блоков. Большее количествопотоков в блоке снизит влияние задержек памяти, но снизит и доступное число регистров.Кроме того, блок из 512 потоков неэффективен, сама <strong>NVIDIA</strong> рекомендует использоватьблоки по 128 или 256 потоков, как компромиссное з<strong>на</strong>чение для достижения оптимальныхзадержек и количества регистров.Среди основных моментов оптимизации программ <strong>CUDA</strong>: как можно более активноеиспользование разделяемой памяти, так как о<strong>на</strong> з<strong>на</strong>чительно быстрее глобальнойвидеопамяти видеокарты; операции чтения и записи из глобальной памяти должны бытьобъединены (coalesced) по возможности. Для этого нужно использовать специальныетипы данных для чтения и записи сразу по 32/64/128 бита данных одной операцией. Еслиоперации чтения трудно объединить, можно попробовать использовать текстурныевыборки.Выводы
Представлен<strong>на</strong>я компанией <strong>NVIDIA</strong> программно-аппарат<strong>на</strong>я архитектура для расчётов <strong>на</strong>видеочипах <strong>CUDA</strong> хорошо подходит для решения широкого круга задач с высокимпараллелизмом. <strong>CUDA</strong> работает <strong>на</strong> большом количестве видеочипов <strong>NVIDIA</strong>, и улучшаетмодель программирования GPU, з<strong>на</strong>чительно упрощая её и добавляя большое количествовозможностей, таких как разделяемая память, возможность синхронизации потоков,<strong>вычисления</strong> с двойной точностью и целочисленные операции.<strong>CUDA</strong> <strong>—</strong> это доступ<strong>на</strong>я каждому разработчику ПО технология, её может использоватьлюбой программист, з<strong>на</strong>ющий язык Си. Придётся только привыкнуть к иной парадигмепрограммирования, присущей параллельным <strong>вычисления</strong>м. Но если алгоритм в принципехорошо распараллеливается, то изучение и затраты времени <strong>на</strong> программирование <strong>на</strong><strong>CUDA</strong> вернутся в многократном размере.Вполне вероятно, что в силу широкого распространения видеокарт в мире, развитиепараллельных вычислений <strong>на</strong> GPU сильно повлияет <strong>на</strong> индустриювысокопроизводительных вычислений. Эти возможности уже вызвали большой интерес в<strong>на</strong>учных кругах, да и не только в них. Ведь потенциальные возможности ускоренияхорошо поддающихся распараллеливанию алгоритмов (<strong>на</strong> доступном аппаратномобеспечении, что не менее важно) сразу в десятки раз бывают не так часто.Универсальные процессоры развиваются довольно медленно, у них нет таких скачковпроизводительности. По сути, пусть это и звучит слишком громко, все нуждающиеся вбыстрых вычислителях теперь могут получить недорогой персо<strong>на</strong>льный суперкомпьютер<strong>на</strong> своём столе, иногда даже не вкладывая дополнительных средств, так как видеокарты<strong>NVIDIA</strong> широко распространены. Не говоря уже об увеличении эффективности втерми<strong>на</strong>х GFLOPS/$ и GFLOPS/Вт, которые так нравятся производителям GPU.Будущее множества вычислений явно за параллельными алгоритмами, почти все новыерешения и инициативы <strong>на</strong>правлены в эту сторону. Пока что, впрочем, развитие новыхпарадигм <strong>на</strong>ходится <strong>на</strong> <strong>на</strong>чальном этапе, приходится вручную создавать потоки ипланировать доступ к памяти, что усложняет задачи по сравнению с привычнымпрограммированием. Но технология <strong>CUDA</strong> сделала шаг в правильном <strong>на</strong>правлении и вней явно проглядывается успешное решение, особенно если <strong>NVIDIA</strong> удастся убедить какможно разработчиков в его пользе и перспективах.Но, конечно, GPU не заменят CPU. В их нынешнем виде они и не пред<strong>на</strong>з<strong>на</strong>чены дляэтого. Сейчас что видеочипы движутся постепенно в сторону CPU, становясь всё болееуниверсальными (расчёты с плавающей точкой оди<strong>на</strong>рной и двойной точности,целочисленные <strong>вычисления</strong>), так и CPU становятся всё более «параллельными»,обзаводясь большим количеством ядер, технологиями многопоточности, не говоря пропоявление блоков SIMD и проектов гетерогенных процессоров. Скорее всего, GPU и CPUв будущем просто сольются. Известно, что многие компании, в том числе Intel и AMDработают <strong>на</strong>д подобными проектами. И неважно, будут ли GPU поглощены CPU, или<strong>на</strong>оборот.В статье мы в основном говорили о преимуществах <strong>CUDA</strong>. Но есть и ложечка дёгтя. Одиниз немногочисленных недостатков <strong>CUDA</strong> <strong>—</strong> слабая переносимость. Эта архитектураработает только <strong>на</strong> видеочипах этой компании, да ещё и не <strong>на</strong> всех, а <strong>на</strong>чи<strong>на</strong>я с серииGeForce 8 и 9 и соответствующих Quadro и Tesla. Да, таких решений в мире очень много,<strong>NVIDIA</strong> приводит цифру в 90 миллионов <strong>CUDA</strong>-совместимых видеочипов. Это простоотлично, но ведь конкуренты предлагают свои решения, отличные от <strong>CUDA</strong>. Так, у AMDесть Stream Computing, у Intel в будущем будет Ct.
Которая из технологий победит, станет распространённой и проживёт дольше остальных<strong>—</strong> покажет только время. Но у <strong>CUDA</strong> есть неплохие шансы, так как по сравнению сStream Computing, <strong>на</strong>пример, о<strong>на</strong> представляет более развитую и удобную дляиспользования среду программирования <strong>на</strong> обычном языке Си. Возможно, в определениипоможет третья сторо<strong>на</strong>, выпустив некое общее решение. К примеру, в следующемобновлении DirectX под версией 11, компанией Microsoft обещаны вычислительныешейдеры, которые и могут стать неким усреднённым решением, устраивающим всех, илипочти всех.Судя по предварительным данным, этот новый тип шейдеров заимствует многое измодели <strong>CUDA</strong>. И программируя в этой среде уже сейчас, можно получить преимуществасразу и необходимые <strong>на</strong>выки для будущего. С точки зрения высокопроизводительныхвычислений, у DirectX также есть явный недостаток в виде плохой переносимости, так какэтот API ограничен платформой Windows. Впрочем, разрабатывается и ещё один стандарт<strong>—</strong> открытая мультиплатформен<strong>на</strong>я инициатива OpenCL, которая поддерживаетсябольшинством компаний, среди которых <strong>NVIDIA</strong>, AMD, Intel, IBM и многие другие.Не забывайте, что в следующей статье по <strong>CUDA</strong> вас ждёт исследование конкретныхпрактических применений <strong>на</strong>учных и других не<strong>графических</strong> вычислений, выполненныхразработчиками из разных уголков <strong>на</strong>шей планеты при помощи <strong>NVIDIA</strong> <strong>CUDA</strong>.Алексей Берилло (sbe@ixbt.com)Обсудить в конференции (комментариев: 287)Опубликовано <strong>—</strong> 23 сентября 2008 г.Другие обсуждения в конференции:o [22:48] Выбор видеокарты для готовой конфигурации ПК (часть 3) (2101сообщений)o [22:44] AMD(ATI) vs <strong>NVIDIA</strong> (часть 18) (1275 сообщений)o [22:25] AMD Radeon HD 7750/7770 (Cape Verde) (198 сообщений)o [22:25] Имеет ли смысл ждать чего-то интересного под AGP? / Выбор картып… (1593 сообщений)o [21:06] Выбор видеокарты до $100 (часть 2) (453 сообщений)Технология <strong>NVIDIA</strong> <strong>CUDA</strong> - это фундаментально новая архитектура вычислений <strong>на</strong>GPU, пред<strong>на</strong>з<strong>на</strong>чен<strong>на</strong>я для решения комплекса вычислительных задач потребителей,бизнеса и технической индустрии. Технология <strong>CUDA</strong> (compute unified device architecture -<strong>вычисления</strong> <strong>на</strong> унифицированной аппаратной архитектуре) предоставляет приложениям,активно работающим с данными, доступ к потрясающим процессинговым мощностям<strong>графических</strong> процессоров <strong>NVIDIA</strong> через революционную вычислительную архитектуру,связанную с новыми возможностями. Придавая з<strong>на</strong>чение большей производительности иупрощению разработки программного обеспечения через стандартный язык C, технология<strong>CUDA</strong> даёт возможность разработчикам создавать решения для интенсивной работы сданными в кратчайшие сроки.
Что это за технология "<strong>CUDA</strong>"?Вычисления <strong>на</strong> GPU с технологией <strong>CUDA</strong> - это инновационное сочетаниевычислительных способностей следующего поколения <strong>графических</strong> процессоров <strong>NVIDIA</strong>,доступныз через стандартный язык 'C'. Тогда как предыдущее поколение <strong>графических</strong>процессоров было основано <strong>на</strong> "потоковых шейдерных программах", программисты<strong>CUDA</strong> могут испльзовать 'C' для создания программ, вызывающих потоки также, как и <strong>на</strong>традиционных многопоточных CPU (Блин, традиционных. _Ни у кого_ из моих з<strong>на</strong>комыхнет двуядерника. Да даже Пня4 с гипер-трейдингом.). Но многоядерные процессорымогут исполнять лишь несколько потоков одновременно, а графические процессоры<strong>NVIDIA</strong> с технологией <strong>CUDA</strong> обработают сразу тысячи потоков с высоким уровнеминформационной <strong>на</strong>грузки. (Блин. Вот у "них" есть thread и flow. А как я должен <strong>на</strong>звать"поток", чтобы не повториться?)Од<strong>на</strong> из <strong>на</strong>иболее важных инноваций в технологии <strong>CUDA</strong> - возможность объединенияпотоков <strong>графических</strong> процессоров <strong>NVIDIA</strong> для решения одной задачи, что позволяетприложениям работать с большей эффективностью. Графические процессоры <strong>NVIDIA</strong> стехнологией <strong>CUDA</strong> имеют параллельные кэши данных, которых сохраняют частоиспользуемую информацию прямо в GPU. Хранение информации в GPU позволяетисполнять потоки, использующие общую информацию, во много раз быстрее, чем если быо<strong>на</strong> запрашивалась из системной памяти. Эта прогрессив<strong>на</strong>я технология даёт возможностьпользователям решать вычислительные задачи в режиме реального времени.Какие преимущества получают приложения от <strong>CUDA</strong>?Вычисления <strong>на</strong> GPU подходят для решения широкого спектра задач, связанных собработкой больших объёмов информации. Например игровые приложения могутиспользовать графический процессор <strong>NVIDIA</strong> для физических расчётов, поднимающихпроизводительность и эффектность <strong>на</strong> новый уровень. Также, коммерческие приложения,используемые для разработки программ или а<strong>на</strong>лиза больших массивов данных, ранеетребовавших высокой производительности системы, получат преимущество отиспользования <strong>на</strong> рабочей станции или сервере с технологией <strong>CUDA</strong>. Это перелом втехнологиях, позволяющий выполнять а<strong>на</strong>лиз и решение задач любого рода в режимереального времени. Кроме того, <strong>на</strong>учные приложения, которые требуют высокойинтенсивности вычислений больше не будут занимать всё процессорное время.Вычисления с <strong>CUDA</strong> предоставляет платформу с высоким уровнем производительностивне зависимости от предполагаемого использования.Почему используется технология <strong>CUDA</strong>?Производительность. Графические процессоры <strong>NVIDIA</strong> предоставляют немыслимыйуровень производительности для приложений, интенсивно работающих с данными.Технология <strong>CUDA</strong> предоставляет стандартное, широко доступное решение для поставкиновых приложений с беспрецендентными возможностями.Совместимость. Приложения, разработанные с использованием <strong>CUDA</strong> C-компилятасовместимы с будующим поколением <strong>графических</strong> процессоров <strong>NVIDIA</strong> (лучше бы онипредыдущее добавили). Разработчики, вкладывающие силы в разработку приложений дляGPU, сразу получат преимущество от использования производительных <strong>графических</strong>процессоров текущего поколения и могут быть уверены, что <strong>NVIDIA</strong> в будущем будетвкладывать средства в разработку ещё более производительных решений.Продуктивность. Разработчики, ищущие доступ к вычислительной мощи <strong>графических</strong>процессоров <strong>NVIDIA</strong> могут теперь пользоваться стандартным языком программирования'C' для разработки приложений. <strong>CUDA</strong> предоставляет законченное решение дляразработчиков, которое интегрируется в программное обеспечение для CPU и GPU, чтобы
быстро получить доступ к новым возможностям и высокой оценке потребителей(возможно, они имели ввиду что-то другое. но получилось так).Масштабируемость. Приложения, разработанные с использованием технологии <strong>CUDA</strong>масштабируются в производительности и возможностях по всей линейке <strong>графических</strong>процессоров <strong>NVIDIA</strong>, <strong>на</strong>чи<strong>на</strong>я от интегрированных решений и заканчиваявысокопроизводительными профессио<strong>на</strong>льными графическими картами, использующимимножество <strong>графических</strong> процессоров. Производительность <strong>CUDA</strong> теперь фактическидоступ<strong>на</strong> в системах любого уровня от специальных вычислительных станций допотребительских продуктов.Разрабатывайте с <strong>CUDA</strong>Комплект разработки программного обеспечения <strong>CUDA</strong> (<strong>CUDA</strong> SDK) - это законченноерешение для разработчиков, использующих возможности <strong>графических</strong> процессоров длярешения задач общего <strong>на</strong>з<strong>на</strong>чения. SDK включает стандартные библиотеки FFT и BLAS (яне в курсе об этом), компилятор C для графического процессора <strong>NVIDIA</strong> и runtimeдрайвер.<strong>CUDA</strong> runtime-драйвер работающий совместно с самостоятельным драйвером,решающим задачи распределения <strong>на</strong>грузки OpenGL и MS DirectX. Технология <strong>CUDA</strong> вравной степени поддерживается операционными системами MS Windows XP (ага! вистане поддерживается) и Linux.Возможности технологии- Унификация программных и аппаратных решений для потоковых вычислений <strong>на</strong><strong>графических</strong> процессорах <strong>NVIDIA</strong> с поддержкой <strong>CUDA</strong>.- Графические процессоры с <strong>CUDA</strong> поддерживают кэш параллельных данных (ParallelData Cache) и менеджер исполняемых потоков (Thread Execution Manager) длявысокопроизводительных вычислений.- Стандартный язык программирования C для GPU.- Стандартные числовые библиотеки для FFT и BLAS.- Отдельный драйвер CUDА для вычислений.- Оптимизированный путь загрузки и выгрузки с CPU <strong>на</strong> GPU с <strong>CUDA</strong>.- <strong>CUDA</strong>-драйвер, работающий совместно с графическим драйвером.- Поддержка Linux и WinXP- Масштабируемость от высокопроизводительных профессио<strong>на</strong>льных <strong>графических</strong>решений до мабильных и интегрированных GPU.- Встроен<strong>на</strong>я поддержка multi-GPU для высоко"плотных" вычислений.- Поддержка аппаратной отладки и профилер для разработки и оптимизации программ.Материал взят со страницы (<strong>на</strong> англ. языке)Немного больше...Основу аппаратных средств <strong>CUDA</strong>-вычислителя образует потоковый процессор (SP,Streaming Processor), 32-битовое арифметико-логическое устройство которого ипредоставляет каждому потоку вычислительные возможности.Восемь SP, каждый со своим модулем регистровой памяти емкостью 32 KB,объединяются в потоковый мультипроцессор (SM, Streaming Multiprocessor) –вычислительную машину SIMD-архитектуры, имеющую собственные механизм выборкии декодирования команд, независимые кэши команд и данных (констант), диспетчерпотоков и блок памяти емкостью 16 KB, разделяемой между всеми восемью SP.Работающий <strong>на</strong> тактовой частоте 1,35 GHz, SM способен предоставлять более чем
семистам потокам вычислительную мощность порядка 20 GFLOPS. SP выполняет однуSIMD-команду за один машинный такт.Два SM, дополненные более высокоуровневой кэш-памятью команд и данных, образуюткластер обработки текстур (TPC, Texture Processing Cluster). И, <strong>на</strong>конец, из восьми TPCформируется собственно <strong>CUDA</strong>-вычислитель, – массив потоковых процессоров (SPA,Streaming Processor Array).Таким образом, в распоряжении <strong>CUDA</strong>-программиста имеется вычислитель<strong>на</strong>я система,пусть весьма слож<strong>на</strong>я из-за разнообразия адресных пространств и специфическихмеханизмов, но все же ос<strong>на</strong>щен<strong>на</strong>я 128 32-разрядными арифметико-логическимиустройствами, способными за один такт исполнять такие команды, как умножение с<strong>на</strong>коплением (обычно обоз<strong>на</strong>чаются MADD, смысл этой трехоперандной операциипонятен из псевдокода A=A+B*C). Потенциаль<strong>на</strong>я пиковая производительность такойсистемы – 346 GFLOPS. Это одновременно и немало, и не очень много, если учесть тотфакт, что пиковая производительность четырехъядерных процессоров класса Core 2 Duoсовсем немного не дотягивает до 100 GFLOPS.Маленький пример программ использующие <strong>CUDA</strong>Приведу пару примеров, софт возьму от одного из пользователей <strong>на</strong>шего форума, аименно Xserg, за что ему спасибо)Mini Release nv<strong>CUDA</strong>.exeXP необходимо установить последние драйверы ForceWare: 169.21MD5 хеши // Заточено <strong>на</strong> популярную GF8600GTПредваритель<strong>на</strong>я атака 2..5 символов (0x21..0x7f)Команд<strong>на</strong>я строка:// перебирает 0..9,a..znv<strong>CUDA</strong>.exe -f=mypas.txt -s=7 -e=7-f= файл с паролями до 50 шт. типа admin:9987d22788e810116a45109f2ea88648-s= <strong>на</strong>чальное количество символов в пароле 6 - by default-e= конечное количество символов в пароле 8 - by defaultНеобходимые библиотеки dll.rar (158кб.) // cudart.dll , cutil32.dllСобранный файл + Исходник nv<strong>CUDA</strong>.rar (82кб.)Mini Release nv<strong>CUDA</strong>sql.exeMySql хешиКоманд<strong>на</strong>я строка:nv<strong>CUDA</strong>sql.exe -f=mysqlpas.txt -s=4 -e=10 -sl=91 –bl=20-f= файл с паролями до 50 шт. типа hash:6cb1963d2018c3ea-s= <strong>на</strong>чальное количество символов в пароле 4 - by default
-e= конечное количество символов в пароле 10 - by default-sl= 25 , 35 , 71 , 91 <strong>на</strong>боры символов-bl=производительность видеокарты. (20 - 128)Собранный файл + Исходник ncCuda_mysql.rar (81кб.)Скорость перебора одного хеша 8 000 000 000 000 п/c. <strong>на</strong> GF8600GT