@landwatersun

Научно-образовательный IT-форум при КНИТУ-КАИ

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Научно-образовательный IT-форум при КНИТУ-КАИ » Теоретические материалы » Программирования графических процессоров NVIDIA


Программирования графических процессоров NVIDIA

Сообщений 1 страница 10 из 11

1

Предлагаем Вам пройти видеокурсы по программированию массивно-параллельных процессоров. Пройдя предлагаемые курсы, Вы получите широкий спектр практических навыков, которые позволят Вам к концу занятий овладеть основами программирования современных графических процессоров (GPU) NVIDIA.

Видеокурс №1
(А. Шевченко, А. Ивахненко, 2013 г.)

http://forumfiles.ru/files/000c/4b/84/94641.png

Видеокурс №2
(Е. Перепёлкин, 2014 г.)

http://forumfiles.ru/files/000c/4b/84/94641.png

Материалы к видеокурсам

http://forumfiles.ru/files/000c/4b/84/76762.gif

Онлайн-тестирование
по видеокурсу №1

http://forumfiles.ru/files/000c/4b/84/22783.png

Заметка:
Для лучшего усвоения видеоматериалов по программированию графических процессоров NVIDIA следует знать основы программирования на С/C++. Для тех, кто не обладает знаниями в данных языках программирования и не имеет достаточно времени для покрытия данного пробела, рекомендую пройти обучение по С++ посредством ресурса sololearn. Приложение по обучению можно установить на смартфон или планшет, что позволяет иметь обучающий ресурс всегда под рукой.

C++ Tutorial

http://forumfiles.ru/files/000c/4b/84/91778.png

2

Вопрос:

Почему первый параметр функции cudaMalloc имеет двойной указатель?


Ответ:

In C, data can be passed to functions by value or via simulated pass-by-reference (i.e. by a pointer to the data). By value is a one-way methodology, by pointer allows for two-way data flow between the function and its calling environment.

When a data item is passed to a function via the function parameter list, and the function is expected to modify the original data item so that the modified value shows up in the calling environment, the correct C method for this is to pass the data item by pointer. In C, when we pass by pointer, we take the address of the item to be modified, creating a pointer (perhaps a pointer to a pointer in this case) and hand the address to the function. This allows the function to modify the original item (via the pointer) in the calling environment.

Normally malloc returns a pointer, and we can use assignment in the calling environment to assign this returned value to the desired pointer. In the case of cudaMalloc, the CUDA designers chose to use the returned value to carry an error status rather than a pointer. Therefore the setting of the pointer in the calling environment must occur via one of the parameters passed to the function, by reference (i.e. by pointer). Since it is a pointer value that we want to set, we must take the address of the pointer (creating a pointer to a pointer) and pass that address to the cudaMalloc function.

Первоисточник: http://stackoverflow.com/questions/1293 … to-pointer

А после перевода получим следующее:

В языке Cи данные могут быть переданы функции по значению или по ссылке (т.е. указателем, где расположен адрес с данными). По значению это методология с односторонним путем, а указатель позволяет получить двусторонний поток к данным: между функцией и ее вызывающей среде.

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

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

3

Вопрос:

Почему в коде, исполняемом на GPU, обычно заменяют многомерные массивы одномерными?


Ответ:

Так как выделить память из хоста на видеокарте можно только динамическим путем, то речь идет о массивах динамического типа. Понять, почему число обращений в многомерных массивах с динамической природой больше, чем в одномерных массивах помогут статьи:
Массивы в C++ на практике (часть 1)
Массивы в C++ на практике (часть 2)

4

Вопрос:

Что возвращают функции библиотеки cuRAND?


Ответ:

All cuRAND host library calls have a return value of curandStatus_t. Calls that succeed without errors return CURAND_STATUS_SUCCESS. If errors occur, other values are returned depending on the error. Because CUDA allows kernels to execute asynchronously from CPU code, it is possible that errors in a non-cuRAND kernel will be detected during a call to a library function. In this case, CURAND_STATUS_PREEXISTING_ERROR is returned

Read more at: http://docs.nvidia.com/cuda/curand/inde … z43hfNHxS3

5

Вопрос:

Почему в лекции №5 "Прикладные CUDA библиотеки" при рассмотрении примера работы библиотеки cuBLAS вместо функции cublasCreate() была использована функции cublasInit()?


Ответ:

The functions cublasInit() and cublasShutdown() are used to initialize and shutdown the cuBLAS library. It is recommended for cublasInit() to be called before any other function is invoked. It allocates hardware resources on the GPU device that is currently bound to the host thread from which it was invoked.

The legacy initialization and shutdown functions are similar to the cuBLAS library API routines cublasCreate() and cublasDestroy().

Read more at: http://docs.nvidia.com/cuda/cublas/inde … z43i34CWaS

https://pp.vk.me/c628827/v628827045/3b968/mBEoHkaipyI.jpg

Таким образом, старый API в том числе cublasInit() можно использовать, когда мы запускаем cuBLAS-функции только из одного потока на host. Когда потоков, работающих с CUDA-библиотеками, на host много, рекомендуется использовать потокобезопасный API, т.е. вместо cublasInit() использовать cublasCreate().

6

Вопрос:

Что означает утверждение "Многомерные структуры данных в CUBLAS хранятся по столбцам"?


Ответ:
Во многих языках программирования, например в Си, элементы двумерного массива располагаются в памяти ЭВМ по строкам, в Фортране - по столбцам. Если массив двумерный, например DIMENSION В(2,4).

http://cs631224.vk.me/v631224045/1d225/kSRiJFLlGeI.jpg

То его элементы хранятся в памяти в таком порядке:
В(1,1), В(2,1), В(1,2), В(2,2), В(1,3), В(2,3), В(1,4), В(2,4).
Тот же принцип сохраняется и для массивов большей размерности: быстрее всего изменяется первый индекс, затем второй и т.д. Это следует учитывать при вводе/выводе и инициализации многомерного массива.

7

Вопрос:
В лекции №7 "Оптимизация CUDA программ" на 16 слайде отмечено:

Латентность инструкций ~ 11 тактов.
Требуется 44 варпа для покрытия латентности.

О какой латентности идет речь и почему именно 44 варпа?

8

Латентность – это время выборки данных из памяти, чем меньше данный параметр, тем лучше, так как не будут наблюдаться значительные задержки при обращении к памяти.
Один такт латентности скрывается четырьмя варпами.

9

landwatersun написал(а):

Вопрос:
В лекции №7 "Оптимизация CUDA программ" на 16 слайде отмечено:

О какой латентности идет речь и почему именно 44 варпа?


1. Латентность - количество тактов между появлением инструкции и завершением ее исполнения.
     Судя по количеству тактов, которое равно 11, можно сделать вывод что речь идет латентности арифметических операций. (Т.к. латентность инструкций обращения в память в разы выше, например для доступа к глобальной памяти это 400-800 тактов).
     Полная загруженность вычислительных ресурсов достигается когда все планировщики варпов в каждом такте имеют варп, готовый на исполнение. Таким образом, латентности каждой инструкции скрывается путем передачи инструкций на исполнение другим варпам.

2. Существует теорема Литтла (Little's Law), которая может быть применена и для GPU:

Необходимое_число_варпов = Латентность * Число_исполняемых_варпов_за_такт

     В нашем случае латентность равна 11, чтобы иметь 4 варпа (при этом достигается полная загруженность при 4х планировщиках варпов) запущенными в одном и том же цикле, нам нужно 11*4 = 44 варпа.

Professional CUDA  Programming (page 90)

Отредактировано Вадим Коробейников (2016-04-13 23:27:50)

10

landwatersun написал(а):

Вопрос:
В лекции №7 "Оптимизация CUDA программ" на 16 слайде отмечено:

О какой латентности идет речь и почему именно 44 варпа?


Латентность - общая задержка всех потоков warp’а при выполнении инструкции.

Что касается количества варпов, в лекции рассматривается чип GK110, который поддерживает CUDA Compute Capability 3.5. Для Compute Capability 3.Х характерно выполнение пары инструкций за варп, при этом за один такт запускается 4 варпа для покрытия (hide) латентности.
Т.о. получаем, что для покрытия латентности в 11 тактов, необходимо 44 варпа.

Информация взята и переведена из CUDA C Programming Guide с 73-74.

http://docs.nvidia.com/cuda/pdf/CUDA_C_ … _Guide.pdf


Вы здесь » Научно-образовательный IT-форум при КНИТУ-КАИ » Теоретические материалы » Программирования графических процессоров NVIDIA