Я только что получил мою видеокарту с поддержкой графического процессора и начал играть с CUDA. Просто, чтобы разобраться с блоками и потоками, я написал простое ядро, которое просто сохраняет свои идентификаторы в общей памяти, которые позже я копирую обратно на хост и печатаю. Но тогда я думаю, почему бы просто не использовать printf
внутри функции ядра? Я попробовал это, хотя я полагал, что это было невозможно. Вот как выглядела моя попытка:
__global__ void
printThreadXInfo (int *data)
{
int i = threadIdx.x;
data[i] = i;
printf ("%d\n", i);
}
.. но внезапно я увидел вывод в консоли. Затем я искал руководство разработчика и обнаружил printf
, упомянутый в разделе об эмуляции устройства. Было сказано, что эмуляция устройства дает преимущество запуска кода ядра в ядре, например, вызова printf
.
Мне действительно не нужно звонить printf
. Но сейчас я немного растерялся. У меня есть два предположения. Во-первых, разработчики NVidia реализовали специальное printf
на устройстве, которое каким-то образом прозрачно для разработчика обращается к вызывающему процессу и выполняет стандартную функцию printf
, а также заботится о копировании памяти и т. Д. Это звучит немного безумно. Другое предположение состоит в том, что скомпилированный код каким-то образом работает в режиме эмуляции, а не на реальном устройстве. Но это тоже звучит неправильно, потому что я просто измерил производительность сложения двух чисел в массиве из 1 миллиона элементов, и ядру CUDA удалось сделать это примерно на 200 быстрее, чем я могу сделать на процессоре. Или, может быть, он работает в режиме эмуляции, когда обнаруживает некоторый специфичный для хоста код? Если это правда, то почему я не выпустил предупреждение?
Пожалуйста, помогите мне разобраться. Я использую NVidia GeForce GTX 560 Ti в Linux (Intel Xeon, 1 процессор с 4 физическими ядрами, 8 ГБ оперативной памяти, если это имеет значение). Вот моя nvcc
версия:
$ /usr/local/cuda/bin/nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2011 NVIDIA Corporation
Built on Thu_May_12_11:09:45_PDT_2011
Cuda compilation tools, release 4.0, V0.2.1221
А вот как я компилирую свой код:
/usr/local/cuda/bin/nvcc -gencode=arch=compute_20,code=\"sm_21,compute_20\" -m64 --compiler-options -fno-strict-aliasing -isystem /opt/boost_1_46_1/include -isystem /usr/local/cuda/include -I../include --compiler-bindir "/usr/local/cuda/bin" -O3 -DNDEBUG -o build_linux_release/ThreadIdxTest.cu.o -c ThreadIdxTest.cu
/usr/local/cuda/bin/nvcc -gencode=arch=compute_20,code=\"sm_21,compute_20\" -m64 --compiler-options -fno-strict-aliasing -isystem /opt/boost_1_46_1/include -isystem /usr/local/cuda/include -I../include --compiler-bindir "/usr/local/cuda/bin" -O3 -DNDEBUG --generate-dependencies ThreadIdxTest.cu | sed -e "s;ThreadIdxTest.o;build_linux_release/ThreadIdxTest.cu.o;g" > build_linux_release/ThreadIdxTest.d
g++ -pipe -m64 -ftemplate-depth-1024 -fno-strict-aliasing -fPIC -pthread -DNDEBUG -fomit-frame-pointer -momit-leaf-frame-pointer -fno-tree-pre -falign-loops -Wuninitialized -Wstrict-aliasing -ftree-vectorize -ftree-loop-linear -funroll-loops -fsched-interblock -march=native -mtune=native -g0 -O3 -ffor-scope -fuse-cxa-atexit -fvisibility-inlines-hidden -Wall -Wextra -Wreorder -Wcast-align -Winit-self -Wmissing-braces -Wmissing-include-dirs -Wswitch-enum -Wunused-parameter -Wredundant-decls -Wreturn-type -isystem /opt/boost_1_46_1/include -isystem /usr/local/cuda/include -I../include -L/opt/boost_1_46_1/lib -L/usr/local/cuda/lib64 -lcudart -lgtest -lgtest_main build_linux_release/ThreadIdxTest.cu.o ../src/build_linux_release/libspartan.a -o build_linux_release/ThreadIdxTest
... и, кстати, и код хоста, и код ядра смешаны в одном исходном файле с расширением .cu
(возможно, я не должен этого делать, но я видел этот стиль в примерах SDK).
Ваша помощь высоко ценится. Спасибо!