В настоящее время я пытаюсь удалить часть громоздкого cudaMallocHost/cudaFreeHost из моего кода. Для этого я готов использовать только std :: vector, но мне абсолютно необходимо, чтобы базовая память была связана с типом памяти cuda.Странное поведение с использованием thrust experimental :: pinned_allocator в cuda
Но я столкнулся странное поведение с помощью thrust::system::cuda::experimental::pinned_allocator<>
из библиотеки тяги:
//STL
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
//CUDA
#include <cuda_runtime.h>
#include <thrust/device_vector.h>
#include <thrust/transform.h>
#include <thrust/system/cuda/experimental/pinned_allocator.h>
#define SIZE 4
#define INITVAL 2
#define ENDVAL 4
//Compile using nvcc ./main.cu -o test -std=c++11
int main(int argc, char* argv[])
{
// init host
std::vector<float,thrust::system::cuda::experimental::pinned_allocator<float> > hostVec(SIZE);
std::fill(hostVec.begin(),hostVec.end(),INITVAL);
//Init device
thrust::device_vector<float> thrustVec(hostVec.size());
//Copy
thrust::copy(hostVec.begin(), hostVec.end(), thrustVec.begin());
//std::cout << "Dereferencing values of the device, values should be "<< INITVAL << std::endl;
std::for_each(thrustVec.begin(),thrustVec.end(),[](float in){ std::cout <<"val is "<<in<<std::endl;});
std::cout << "------------------------" << std::endl;
//Do Stuff
thrust::transform(thrustVec.begin(), thrustVec.end(), thrust::make_constant_iterator(2), thrustVec.begin(), thrust::multiplies<float>());
//std::cout << "Dereferencing values of the device, values should now be "<< ENDVAL << std::endl;
std::for_each(thrustVec.begin(),thrustVec.end(),[](float in){ std::cout <<"val is "<<in<<std::endl;});
std::cout << "------------------------" << std::endl;
//Copy back
thrust::copy(thrustVec.begin(), thrustVec.end(), hostVec.begin());
//Synchronize
//cudaDeviceSynchronize(); //makes the weird behaviour to go away
//Check result
//std::cout << "Dereferencing values on the host, values should now be "<< ENDVAL << std::endl;//Also makes the weird behaviour to go away
std::for_each(hostVec.begin(),hostVec.end(),[](float in){ std::cout <<"val is "<<in<<std::endl;});
return EXIT_SUCCESS;
}
Который, в моей установке, дает:
val is 2
val is 2
val is 2
val is 2
------------------------
val is 4
val is 4
val is 4
val is 4
------------------------
val is 2
val is 4
val is 4
val is 4
Почему копии от устройства к хосту кажется потерпеть неудачу ? Однако Nvvp показывает прекрасную хронограмму с правильными значениями для копирования.
Кстати, я использую NVCC/cuda/thrust из пакета 7.5 и gcc (GCC) 4.8.5 с карточкой titanX.
Заранее благодарю вас за помощь.
Я не могу воспроизвести это на любой платформе, к которой у меня есть доступ. Что произойдет, если вы добавите вызов синхронизации, прежде чем пытаться распечатать вектор после копирования экземпляра устройства? – talonmies
Я также могу воспроизвести ошибку на gtx680 (вычислительная способность 3.0). Действительно, добавление cudaDeviceSynchronize заставляет код запускаться по назначению. Я полагал, что thrust :: copy имеет синхронное поведение, но на самом деле нет информации об синхронном/асинхронном поведении тяги в документации: http://thrust.github.io/doc/group__copying.html#ga24ccfaaa706a9163ec5117758fdb71b9 – Tobbey