Алматы 2015 Almaty



Pdf көрінісі
бет105/130
Дата01.02.2017
өлшемі20,3 Mb.
#3199
1   ...   101   102   103   104   105   106   107   108   ...   130

Расширения языка С++ 

Основной  программой  среды  разработки  является  компилятор  nvcc,  который  управляет  всей 

цепочкой  преобразований.  Исходная  программа  может  быть  на  языке  C  (.c),  C++  (.cc,  .cxx,  .cpp), 

расширении языка C (.cu; .cup для препроцессированных файлов) [3].  

Проrраммы  для  CUDA  (соответствующие  файлы  обычно  имеют  расширение  .сu)  пишутся  на 

«расширенном С и компилируются при помощи команды nvcc.  

Вводимые в CUDA расширения языка С состоят из:  

– спецификаторов функций, показывающих, где будет выполняться функция и откуда она может 

быть вызвана;  

– спецификаторов переменных, задающих тип памяти, используемый для данных переменных;  

– директивы, служащей для запуска ядра, задающей как данные, так и иерархию нитей;  

– встроенных переменных, содержащих информацию о текущей нити;  

– runtime, включающей в себя дополнительные типы данных.  

В CUDA используется следующие спецификаторы функций (таблица 1).  

 

Таблица 1 



Спецификаторы функций и переменных: 

 

Спецификатор  



 

Функция выполняется на  

 

Функция может вызываться из  



_device_ 

device (GPU)  

device (GPU)  

_global_ 

device (GPU)  

host (CPU)  

_host_ 

host (CPU)  



host (CPU)  

 

В  язык  добавлены  1/2/3/4-  мepныe  векторы  из  базовых  типов  (сhar,  unsi  gned,  char,  short,  unsigned 



short, int, unsigned int, long, unsigned long, longlong, float и double)  charl, char2, char3,char4, ucharl, uchar2, 

uchar3, uchar4, shortl, short2, short3, short4, ushortl, ushort2, ushort3, ushort4, intl, int2,  int3, int4, uintl, uint2, 

uint3,  uint4,  longl,  long2,  long3,  long4,  ulongl,  ulong2,  ulong3,  ulong4,  floatl,  float2,  float3,  float4,  longlongl, 

longlong2, doublel и double2. Также добавлен тип dim3, используемый для задания размерности.  

В язык добавлены следующие специальные переменные:  

– gridDim –  размер сетки (имеет тип dimз);  

– blockDim – размер блока (имеет тип dim3);  

– blockldx – индекс текущеrо блока в сетке (имеет тип uint3);  

– threadIdx – индекс текущей нити в блоке (имеет тип uint3);  

– warpSize – размер warp'a (имеет тип int).  

Для запуска ядра на GPU используется следующая конструкция:  

kernelName <<>> ( args );  

Здесь  kemelName  это  имя  (адрес)  соответствующей  _global_  функции.  Через  Dg  обозначена 

переменная (или значение) типа dim3, задающая размерность и размер сетки (в блоках). Переменная (или 

значение) Db – типа dim3, задает размерность и размер блока (в нитях). Необязательная переменная (или 

значение)  Ns  типа  size_t  задает  дополнительный  объем  разделяемой  памяти  в  байтах,  которая  должна 

быть динамически выделена каждому блоку (к уже статически выделенной разделяемой памяти), если не 

задано, то используется значение О. Переменная (или значение) S типа cudaStream_t задает поток (CUDA 

stream), в котором должен произойти вызов, по умолчанию используется поток 0.  Через args обозначены 

арrументы вызова функции kenelName (их может быть несколько ).  

CUDA  поддерживает  все    функции  из  стандартной  библиотеки  языка  С.  Однако  при  этом 

следует  иметь  в  виду,  что  большинство  стандартных  математических  функций  используют  числа  с 

двойной точностью (double).  

CUDA  предоставляет  также  специальный  набор  функций  пониженной  точности,  но 

обеспечивающих  большее  быстродействие.  В  таблице  2  приведены  основные  f1оаt  –  функции  и  их 

оптимизированные вepсии пониженной точности.  

Для ряда функций можно задать требуемый способ округления. Используемый способ задается 

при помощи одноrо из следующих суффиксов:  

– rn – окруrление к ближайшему;  

– rz – окруrление к нулю;  

– ru – окруrление вверх;  

– rd – окруrление вниз.  



744 

Таблица 2 

Функции для работы с числами с плавающей точкой 

 

Функция 



Значение 

_fadd_ [rn, rz, ru,rd] (х, у) 

Сложение, никоrда не переводимое в команду 

FMAD  


_fmul_ [rn, rz, ru,rd] (х, у) 

Умножение, никоrда не переводимое в команду 

FMAD  

_fmaf_ [rn, rz, rU,rd] (х, у, z )  



(x×y)+z 

_frcp_ [rn, rz, ru,rd] (х)  

1/x 

_fsqrt_ [rn, rz, ru,rd] (x)  



 

_fdiv_ [rn, rz, ru,rd] (х, у)  

x/y 

_fdividef_(х, у)  



х/у, но если 2

126


 < У < 2

128


, то 0 

_expf ( х )  

e

x

 



_ехр 10f ( х ) 

10



_logf ( х ) 

log(x) 


_log2f ( х )  

log


2

(x) 


_log10f ( х )  

log


10

(x) 


_sinf ( х )  

sinx 


_cosf ( х ) 

cosx 


_sincosf ( х, sptr, cptr )  

*sptr = sin(x); *cptr = cos(x) 

_tanf ( х ) 

tanx 


_powf ( х, у )  

x

y



 

_int_as_float ( х )  

32 бита, образующие целочисленное значение, 

интерпретируются как flоаt 

значение. Так, значение 0хС000000 будет 

переведено в –2.0f  

_float_as_int ( х )  

32 бита, образующие flоаt значение, 

интерпретируются как целочисленное значение. 

Так, значение 1.0f будет переведено в – 

0x3F80000  

 

_ saturate ( х )  



min(0,max(1,х))  

_float_to_int [rn, rz, ru,rd] (х)  

Приведение flоаt значения к целочисленному 

значению с заданным округлением  

_float_to_uint [rn, rz, ru,rd] (х)  

Приведение flоаt значения к беззнаковому 

целочисленному значению с заданным 

окруrлением  

_int_to_float [rn, rz, ru,rd] (х)  

При ведение целочисленного значения   к flоаt 

значению с заданным округлением  

_uint_to_float [rn, rz, ru,rd] (х)  

Приведение беззнаковоrо целочисленноrо 

значения к flоаt значению с заданным 

округлением  

_float_to_II [rn, rz, ru,rd] (х) 

Приведение flоаt значения к 64 битовому 

целочисленному значению с заданным 

округлением  

_float_to_uII [rn, rz, ru,rd] (х)  

При ведение flоаt значения к 64-битовому 

беззнаковому целочисленному значению с 

заданным округлением 

  

Кроме ряда оптимизированных функций для работы с числами с плавающей точкой, также есть 



ряд быстрых функций для работы с целыми числами, приводимый в таблице 3.  

 

 



 

 


745 

Таблица 3  

Целочисленныe функции в CUDA 

 

Функция 



Значение 

_[u]muI24 ( х, у ) 

Вычисляет произведение младших 24 бит 

целочисленных параметров х и у, возвращает младшие 

32 бита результата. Старшие 8 бит аргументов 

игнорируются  

_[u]mulhi ( х, y )  

Значение возвращает старшие 32 бита произведения 

целочисленных операндов х и y  

_[u]mul64hi ( х, y )  

Вычисляет произведение 64 битовых целых чисел и 

возвращает младшие 64 бита этого произведения  

_[u]sad ( х, y, z ) 

Возвращает z + |x – у|  

_clz ( х ) 

Возвращает целое число от 0 до 32 включительно 

последовательных нулевых битов для целочисленноrо 

параметра х, начиная со старших бит  

_clzll ( х ) 

Возвращает целое число от 0 до 64 включительно 

последовательных нулевых битов для целочисленного 

64-битовоrо параметра х, начиная со старших бит  

_ffs ( х ) 

Возвращает позицию первоrо (наименее значимоrо) 

единичнoгo бита для apгумента х. Если х равен нулю, 

то возвращается нуль  

_ffsII ( х )  

Возвращает позицию первоrо (наименее значимого) 

единичного бита для целочисленноrо 64-битового 

аргумента х. Если х равен нулю, то возвращается нуль  

_popc ( х ) 

Возвращает число бит, которые равны единице в 

двоичном представлении 32-битовоrо целочисленного 

aргумента х 

_popcII ( х )  

Возвращает число бит, которые равны единице в 

двоичном представлении 64-битовоrо целочисленноrо 

apгумента х  

_brev ( х ) 

Возвращает число, полученное перестановкой (то есть 

биты в позициях k и 31-k меняются местами для всех k 

от 0 до 31) битов исходноrо 32-битовоrо 

целочисленного apгумента х  

_brevll ( х ) 

Возвращает число, полученное перестановкой (то есть 

биты в позициях k и 63-k меняются местами для всех k 

от 0 до 63) битов исходноrо 64-битовоrо 

целочисленного apгумента х  



 

Для  того,  чтобы  подключить  к  работе  графический  процессор  и  использовать  его,  существуют 

функции управления GPU:  

– cudaGetDeviceCount (int  *) - узнать число устройств; при отсутствии GPU возвращает число 1 

(эмулятор GPU); 

–  cudaSetDevice  (int)  -  выбрать  устройство  для  использования;  необходимо  сделать  до  первого 

запуска или обращения к устройству; нумерация с 0. 

– cudaGetDevice (int *) - узнать номер используемого GPU; 

–  cudaGetDeviceProperties  (cudaDeviceProp*,  dev)  -  узнать  характеристики  указанного 

устройства: имя, объём глобальной памяти, объём разделяемой паяти на MP, число регистров, размер 

порции,  максимальное  число  потоков  на  блок,  максимальная  размерность  блока,  максимальная 

размерность  сетки,  объём  памяти  констант,  версия  GPU,  частота  GPU  (непонятно  какого 

функционального блока), количество MP, возможность асинхронной пересылки; 

–  cudaChooseDevice  (int*,  const  struct  cudaDeviceProp*)  -  выбор  наиболее  подходящего 

устройства; 

В  состав  программы  входит  ядро,  реализуемая  через  центральный  процессор(CPU)  и 

необходимая для распределения потоков в GPU и имеет собственные функции управления:  

– cudaConfigureCall  (dim3 gridDim,  dim3 blockDim, size_t sharedMem = 0, int tokens = 0) - задать 



746 

размерность  сетки  и  блока  процессов  для  будущего  запуска;  помещаются  в  стек  для  дальнейшего 

использования в cudaLaunch; 

– cudaSetupArgument (void* arg, size_t count, size_t offset) - задать аргументы запуска; 

– cudaLaunch (T entry)  - запустить ядро  entry, которое задаётся либо функцией __global__, либо 

текстовой  строкой  с  именем  такой  функции;  размерности  и  параметры  извлекаются  из  стека, 

создаваемого cudaConfigureCall. 

Управление памятью и пересылкой (размер в байтах):  

– cudaMalloc (void**, size_t) - выделить линейный массив из глобальной памяти 

–  cudaMallocPitch  (void**,  size_t*  pitch,  size_t  widthInBytes,  size_t  height)  -  выделить  двумерный 

массив из глобальной памяти (заботится о выравниваниях и прочей оптимизации) 

– cudaFree (void *) 

– cudaMallocHost (void**, size_t) - выделить из ОП хоста в режиме блокировки от подкачки; это 

сильно  ускоряет  обмен  с  GPU;  асинхронные  операции  копирования  допустимы  только  с 

блокированной памятью 

– cudaFreeHost (void *) 

– cudaMemset (void*, int, size_t) - заполнить память GPU константой 

– cudaMemcpy (void* dst, const void* src, size_t count, enum cudaMemcpyKind kind) - копирование, 

где cudaMemcpyKind определяет направление пересылки (перекрытие областей запрещено):  

– cudaMemcpyHostToHost 

– cudaMemcpyHostToDevice 

– cudaMemcpyDeviceToHost 

– cudaMemcpyDeviceToDevice 

–  cudaMemcpyAsync  (void*  dst,  const  void*  src,  size_t  count,  enum  cudaMemcpyKind  kind, 

cudaStream_t) - асинхронное копирование, только для блокированной памяти 

–  cudaMemcpyToSymbol  (const  T&  symbol,  const  void*  src,  size_t  count,  size_t  offset,  enum 

cudaMemcpyKind  kind)  -  копирование  count  байт  с  адреса  src  на  адрес,  определяемый  переменной 

symbol,  со  смещением  offset;  переменная  глобальной  памяти  или  памяти  констант  задаётся  либо 

переменной  с  адресом  в  GPU,  либо  текстовой  строкой  с  именем  переменной;  cudaMemcpyKind 

определяет направление пересылки (перекрытие областей запрещено):  

– cudaMemcpyHostToDevice 

– cudaMemcpyDeviceToDevice 

–  cudaMemcpyToSymbol  (void*  dst,  const  T&  symbol,  size_t  count,  size_t  offset,  enum 

cudaMemcpyKind  kind)  -  копирование  count  байт  на  адрес  dst  с  адреса,  определяемого  переменной 

symbol,  со  смещением  offset;  переменная  глобальной  памяти  или  памяти  констант  задаётся  либо 

переменной  с  адресом  в  GPU,  либо  текстовой  строкой  с  именем  переменной;  cudaMemcpyKind 

определяет направление пересылки (перекрытие областей запрещено):  

– cudaMemcpyDeviceToHost 

– cudaMemcpyDeviceToDevice 

– cudaGetSymbolAddress (void** devPtr, const T& symbol) - получить указатель на переменную в 

глобальной  памяти  GPU;  переменная  глобальной  памяти  или  памяти  констант  задаётся  либо 

переменной с адресом в GPU, либо текстовой строкой с именем переменной  

– cudaGetSymbolSize (size_t* size, const T& symbol) - получить размер переменной в глобальной 

памяти  GPU;  переменная  глобальной  памяти  или  памяти  констант  задаётся  либо  переменной  с 

адресом в GPU, либо текстовой строкой с именем переменной  

– cudaMallocArray - выделение памяти под CUDA-массив 

– cudaFreeArray 

– cudaMemset2D 

–  cudaMemcpy2D,  cudaMemcpy2DAsync,  cudaMemcpyToArray,  cudaMemcpyToArrayAsync, 

cudaMemcpy2DToArray,  cudaMemcpy2DToArrayAsync,  cudaMemcpyFromArray,  cudaMemcpy2DFromArray, 

cudaMemcpyArrayToArray, cudaMemcpy2DArrayToArray - копирование матриц 

– cudaMalloc3D, cudaMalloc3DArray 

– cudaMemset3D 

– cudaMemcpy3D 

В связи с асинхронностью запуска ядра введены дополнительные средства управления задачами 

(stream). Задача - это последовательность операций, выполняемых строго по очереди. Относительный 

порядок  операций,  принадлежащих  различным  задачам,  не  определён.  По  умолчанию,  операция 

относится к задаче 0. При необходимости организовать выполнение нескольких паралелльных задач 



747 

необходимо  определить  задачи  и  указывать  их  номера  в  командах  запуска  ядра  и  копирования  из 

памяти  в  память.  Установка  переменной  окружения  CUDA_LAUNCH_BLOCKING  в  1  блокирует 

асинхронное выполнение.  

Функции синхронизации ядра:  

– cudaStreamCreate (cudaStream_t*) 

–  cudaStreamQuery  (cudaStream_t)  -  проверить,  завершились  ли  все  операции  задачи: 

cudaErrorNotReady (единственный способ синхронизации без 100% загрузки CPU, однако уменьшает 

эффективность работы) 

– cudaStreamSynchronize (cudaStream_t) - ждать завершения всех операций задачи (реализовано в 

виде непрерывного опроса устройства, что полностью загружает CPU) 

– cudaStreamDestroy (cudaStream_t) - ждать завершения всех операций задачи и завершить задачу 

– cudaThreadSynchronize (void) - ждать завершения всех операций всех задач (реализовано в виде 

непрерывного опроса устройства, что полностью загружает CPU) 

–  cudaThreadExit  (void)  -  ждать  завершения  всех  операций  всех  задач,  освободить  все  ресурсы; 

последующее  обращение  к  одной  из  функций  API  повторно  инициализирует  API  (глючит,  не 

советую) 

PTX – ассемблер 

Для анализа программы и написания аппаратно–зависимых программ используется специальный 

язык  PTX  –  ассемблер.  Программы  PTX  являются  набором  исходных  текстов  модулей  (файлов). 

Модули  PTX  имеют  синтаксис  в  стиле  в  языке  ассемблера  с  кодами  команд  и  операндами:  псевдо-

операции, использующие символы и адресацию [2].  

Модули  источника  –  текст  в  формате  ASCII.  Строки  разделяются  символом  новой  строки.  Все 

пробелы эквивалентны; пробелы игнорируются для использования его в качестве разделителя. 

C-препроцессор  CPP  может  быть  использован  для  обработки  исходных  модулей  PTX.  Строки, 

начинающиеся  с  #  –  директивы  препроцессора.  PTX  является  чувствительным  к  регистру  и 

использует  нижний  регистр  для  ключевых  слов.  Каждый  модуль  PTX  должен  начинаться  с  .version 

директивы с указанием языковой версии PTX, с последующим .target директивы с указанием целевой 

предполагаемой архитектуры .  

Опрераторы  состоят  из  кода  операции,  разделённый  запятой  со  списком  из  нуля  или  более 

операндов,  и  завершается  точкой  с  запятой.  Операнды  могут  быть  регистровыми  переменными, 

константами,  адресными  выражениями,  или  именами  меток.  Инструкция  имеет  дополнительный 

защитный  предикат,  который  управляет  условием  выполнения.  Защитный  предикат  следует 

дополнительной  метке  и  предопределяет  код  операции,  записывается  как  @p,  где  р  –  регистр 

предикат. Защитный предикат может быть  отрицательным, записанный как @!С. 

Пользовательские  идентификаторы  используют  расширенным  правилам  языка  C++:  они  либо 

начинаться  с  буквы,  за  которой  следует  нуль  или  более  буквы,  цифры,  подчеркивание  или  символ 

доллара; или они начинаются с символа подчеркивания, доллара, или процента, за которым следуют 

один или более буквы, цифры, подчеркивание или знак доллара. 

PTX  поддерживает  целые  и  с  плавающей  точкой  константы  и  константные  выражения.  Эти 

константы могут быть использованы при инициализации данных и в качестве операндов инструкции. 

Тип проверки правил остаётся  одинаковым для целого, с плавающей точкой, а также типы битового 

размера.  Для  предикат  типа  данных  и  инструкций,  целочисленные  константы  могут  и 

интерпретируются как в С, т.е. нулевые значения являются ложными и ненулевые значения True. 

Хотя  конкретные  ресурсы,  имеющиеся  в  данной  целевой  GPU  будет  варьироваться,  виды 

ресурсов будет общим для всех платформ, и эти ресурсы абстрагируются в PTX через пространства 

состояний и типов данных. 

Пространство состояний – набор с конкретными характеристиками. Все переменные находятся в 

каком-то  пространстве  состояний.  Характеристики  пространства  состояний  включают  его  размер, 

адресацию, скорость доступа, права доступа, и уровень обмена между потоками. 

Пространства  состояний,  определенные  в  PTX  являются  побочным  продуктом  параллельного 

программирования и графического программирования.  

В  PTX  основные  типы  отражают  собственные  типы  данных,  поддерживаемые  целевыми 

архитектурами.  Фундаментальный  тип  определяет  как  базовый  тип  и  размер.  Регистровые 

переменные всегда имеют фундаментальный тип, и команды действуют для этих типов.  

PTX  включает  в  себя  встроенные  непрозрачные  типы  для  определения  текстуры  и 

поверхностные дескрипторные переменные. Эти типы названы как и поля, аналогичные структурам, 

но  вся  информация  о  макете,  заказ  поля,  базовый адрес,  и  общий  размер  скрыты  в  программе  PTX, 


748 

отсюда и термин непрозрачный. Использование этих непрозрачных типов ограничивается: 

–  определение  переменных  в  глобальных  (модульных)  рамках  и  в  списках  параметров 

начального ядра 

– статическая инициализация модуля –  область видимости переменных, используя разделённые 

запятыми выражений статического назначения для названных членов типа 

–  ссылки  на  текстуры,  пробники,  или  поверхности  с  помощью  текстуры  и  поверхности 

инструкций загрузки / сохранения (tex, suld, sust, sured). 

– получение значения именованного члена по инструкции запроса (txq, suq) 

–  cоздание  ссылки  на  непрозрачные  переменные  с  помощью  MOV,  например,  mov.u64  reg, 

opaque_var;.  

–  непрозрачные  переменные  не  могут  появиться  в  инициализаторах,  например,  для 

инициализации указателя на непрозрачной переменной. 

Косвенный  доступ  к  текстурам  поддерживается  только  в  едином  режиме  текстур.  Три 

встроенных типа – это .texref, .samplerref и .surfref. Для работы с текстурами и шаблонами PTX имеет 

два  режима  работы.  В  едином  режиме,  текстурная  и  шаблонная  информация  доступна  через  одну 

комманду  .texref.  В  автономном  режиме,  текстурная  и  шаблонная  информации  имеют  свои 

собственные  источники,  что  позволяет  им  быть  определенными  отдельно  и  в  сочетании  в 

зависимости  от  использования  в  программе.  В  автономном  режиме,  поля  типа  .texref,  которые 

описывают  свойства  шаблона  игнорируются,  так  как  эти  свойства  определяются  .samplerref  - 

переменными. 

В PTX, объявление переменной  описывает как тип переменной и  ее пространство состояний. В 

дополнение к базовым типам, PTX поддерживает типы для простых совокупных объектов, таких как 

вектора и массивы. 

Поддерживаются  векторные  типы  ограниченной  длины.  Векторы  длиной  2  и  4  любого 

непредикатного  фундаментального  типа  может  быть  объявлен  с  помощью  префикса  типа  с  .х2  или 

.v4.  Векторы  должны  быть  основаны на фундаментальном  типе,  и  они  могут  находиться  в  регистре 

места. Вектор не может превышать 128-бит в длину; например, .v4.f64 не допускается. Трехмерный 

векторы  может  быть  обработан  с  помощью  .v4  вектор,  в  котором  четвертый  элемент  обеспечивает 

заполнение. Это общий случай для трехмерных сеток, текстур и т.д. 

Объявление  массива  небходимо  для  того,  чтобы  позволить  программисту  выделить  резервное 

пространство.  Чтобы  объявить  массив:  имя  переменной  следует  из  одномерных  объявлений, 

подобных объявлениям фиксированного размера массива в C, размер каждого измерения постоянное 

выражение. 

Выравнивание  хранения  для  всех  адресуемых  переменных  может  быть  указано  в  объявлении 

переменной. Выравнивание задается с помощью спецификатора дополнительного подсчета .alignbyte 

сразу после пространства состояний спецификатора.  

Переменные  будут  выровнены  по  адресу,  который  является  целым  числом,  кратным  байту-

количеству.  Значение  выравнивания  байт-счетчик  должен  быть  степенью  двойки.  Для  массивов, 

выравнивание  определяет  выравнивание  адресов  для  начального  адреса  всего  массива,  а  не  для 

отдельных элементов. 

Выравнивание по умолчанию для скалярных и матричных переменных кратно размеру базового 

типа.  Выравнивание  по  умолчанию  для  векторных  переменных  является  кратным  общему  размеру 

вектора. 

Все операнды в инструкции – известный тип из своих деклараций. Каждый тип операнда должен 

быть  совместим  с  типом  определяемого  шаблоном  инструкции  и  типа  команды.  Там  нет 

автоматического  преобразования  между  типами.Тип  бит  совместим  с  каждым  типом,  имеющий  тот 

же размер. Целые типы общего размера совместимы друг с другом. 

Исходные  операнды  обозначаются  в  описаниях  команд  именами  a,  b  и  с.  Операнды  для 

инструкций  ALU  должны  быть  переменными  .reg,  объявленными  в      регистровом  пространстве 

состояний. Для большинства операций, размеры операндов должны быть совместимыми. 

cvt  (конвертировать)  команда  проводится  над  различными  типами  операндов,  так  как  его  работа 

заключается в преобразовании практически из любого типа данных в любой другой тип данных (и размер). 

ld, st, mov, и cvt – инструкции, чтобы скопировать данные из одного места в другое. Инструкци b 

ld и st перемещают данные из / в адресные пространства состояний в / из регистров. Инструкция mov 

копирует Данные между регистрами. 

Большинство  инструкций  имеет  дополнительный  защитный  предикат,  который  контролирует 

условное выполнение. Предикатные операнды обозначаются именами p, q, r, s. 



749 

Инструкции PTX, которые сохраняют результат в поле, обозначаются именем d (для назначения) 

в  описаниях  команд.  Операнд  назначения  является  скалярной  или  векторной  переменной  в 

регистровом пространстве состояний. 

Инструкции  PTX,  как  правило,  имеют  от  нуля  до  четырех  операндов  плюс,  по  желанию, 

защитный  предикат  после  символа  @  слева  от  opcode:Для  инструкций,  которые  создают 

результирующее  значение,  d  операнд  является  операндом  назначения,  a,  b,  c  являются  исходными 

операндами.Инструкция setp пишет два регистра назначения. Мы используем символ | для разделения 

нескольких  регистров  назначения.Для  некоторых  инструкций  операнд  назначения  является 

обязательным.  Операнд  –  битоприемник  обозначается  символом  подчеркивания  (_)  и  может  быть 

использован вместо регистра назначения. 

В  PTX,  предикатные  регистры  являются  виртуальными  и  имеют  .pred  как  спецификатор  типа. 

Так,  предикат  регистры  могут  быть  объявлены  как  .reg  .pred  p,  q,  r;  Все  инструкции  имеют 

дополнительный 

защитный 

предикат, 

который 

управляет 

условным 

выполнением 

инструкции.Синтаксисом,  указывающим  условное  выполнение,  является  префикс  –  инструкция  с  @ 

{!}  p,  где  р  –  предикатная  переменная,  возможно  отрицательная.  Инструкции  без  предикат 

выполняются безоговорочно. 

Предикаты  обычно  устанавливается  в  результате  сравнения,  выполненного  setp-  инструкции. 

Предикатные значения могут быть вычислены и управляемы, используя следующие инструкции: and, 

or, xor, not, и mov. 

Там  нет  прямого  преобразования  между  предикатами  и  целочисленными  значениями,  и  никакого 

прямого способа загрузки или хранения предикатных значений регистров. Тем не менее, setp может быть 

использован  для  создания  предикат  из  целого  числа,  и  выбор  (selp  –инструкция  на  основе  предиката) 

может быть использован для создания целочисленного значение в зависимости от значения предиката. 




Достарыңызбен бөлісу:
1   ...   101   102   103   104   105   106   107   108   ...   130




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет