使用Thrust实验性的pinned_allocator在CUDA中出现奇怪的行为

4
我目前正在试图从我的代码中删除繁琐的cudaMallocHost/cudaFreeHost部分。为此,我愿意只使用std::vector,但我绝对需要底层内存必须是固定的cuda内存类型。
但是,我使用thrust库中的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显示出正确值的完美时序图。

顺便说一下,我使用的是7.5包中的NVCC/cuda/thrust和GCC (GCC) 4.8.5以及TitanX显卡。

非常感谢您的帮助。


我无法在我可以访问的任何平台上重现这个问题。如果在设备到主机复制后尝试打印向量之前添加同步调用,会发生什么? - talonmies
我也能在gtx680(计算能力为3.0)上再现错误。实际上,添加一个cudaDeviceSynchronize可以使代码按预期运行。我认为thrust :: copy具有同步行为,但实际上在文档中没有有关thrust同步/异步行为的信息:http://thrust.github.io/doc/group__copying.html#ga24ccfaaa706a9163ec5117758fdb71b9 - Tobbey
1个回答

6

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接