Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
CUDA:cufftExecR2C-不必要的内存拷贝_Cuda_Gpu_Cufft - Fatal编程技术网

CUDA:cufftExecR2C-不必要的内存拷贝

CUDA:cufftExecR2C-不必要的内存拷贝,cuda,gpu,cufft,Cuda,Gpu,Cufft,我正在使用cuda进行实验,并观察到在调用时数据从主机复制到设备 cufftExecR2C(plan, src, dst); 我不理解这一点,因为我的src指针是我想要转换的设备内存的有效句柄。在使用ECR2C(…)之前,我初始化了参数,如下所示: float* src; cudaMalloc((&src), image_rows * image_cols * sizeof(float) ); cudaMemcpy(src, image.data() , image

我正在使用cuda进行实验,并观察到在调用时数据从主机复制到设备

cufftExecR2C(plan, src, dst);
我不理解这一点,因为我的src指针是我想要转换的设备内存的有效句柄。在使用ECR2C(…)之前,我初始化了参数,如下所示:

  float* src;
  cudaMalloc((&src),  image_rows * image_cols  * sizeof(float) );
  cudaMemcpy(src, image.data()  ,  image_rows * image_cols  * sizeof(float)  , cudaMemcpyHostToDevice);

启动英伟达探查器(NVPROF)-仅考虑FFT-I得到以下结果< /P>

...
cudaProfilerStart();
cufftExecR2C(plan, src, dst);
cudaProfilerStop();
...

我希望避免3个不必要的主机到设备复制调用。我不明白为什么cuda会执行这些额外的拷贝(特别是为什么主机到设备-数据已经在设备内存中)

该程序使用Cuda 8.0在GeForce GT 540M上执行


谢谢大家!

尽管您对cuFFT在执行
cufftExecR2C
期间执行不必要的数据传输做出了相当认真的断言,但要证明事实并非如此并不重要

考虑以下示例,这些示例是根据您在问题中提供的代码片段拼凑而成的:

#include "cufft.h"
#include "cuda_profiler_api.h"
#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <functional>

int main()
{
  const int image_rows = 1600, image_cols = 2048;

  std::random_device rnd_device;
  std::mt19937 mersenne_engine {rnd_device()};
  std::uniform_real_distribution<float> dist {0.0, 255.0};

  auto gen = [&dist, &mersenne_engine](){
                 return dist(mersenne_engine);
             };

  std::vector<float> image(image_rows * image_cols);
  std::generate(std::begin(image), std::end(image), gen);

  float* src;
  cudaMalloc((&src),  image_rows * image_cols  * sizeof(float) );
  cudaMemcpy(src, &image[0],  image_rows * image_cols  * sizeof(float)  , cudaMemcpyHostToDevice);
  cufftComplex* dst;
  cudaMalloc((void**)&dst    , image_rows * (image_cols/2+1) * sizeof(cufftComplex) );

  cufftHandle plan;
  cufftPlan2d(&plan, image_rows, image_cols, CUFFT_R2C);

  cudaProfilerStart();
  cufftExecR2C(plan, src, dst);
  cudaProfilerStop();

  return 0;
}
[为了简洁起见,再次删除API调用]

memcpy
不见了。分析器报告的全部内容是与转换执行相关的四次内核启动。没有内存传输。原始探查器输出中报告的内存传输是程序开始时主机到设备的传输,与CUFT调用无关。包含它的原因是nvprof默认从程序执行开始就启用评测,并且初始的
cudaProfilerStart
调用无效,因为评测已经启用。您可以在工具链文档中阅读有关配置代码的正确方法


在没有承诺的MCVE的情况下,我将提供我自己的假设——您没有正确使用探查器,并且报告的传输实际上是代码中其他地方发生的传输,这些传输包含在探查器输出中,但与cuFFT的操作完全无关。

您如何知道这些传输是正确的“没有必要"? 可能与设置调用所需的库内部相关。第一个看起来很慢,因为它捕获了应用程序的上下文建立成本,这是必要的,因为数据已经驻留在设备上。分析工具显示主机到设备的副本。我不明白为什么需要这样做。这意味着数据将被复制回主机,然后再复制到设备。同样,您不知道它正在复制什么,并且不太可能是您的数据。我敢打赌这是转移到图书馆内部。发布一个适当的最小、完整和可验证的示例以及附带的探查器API跟踪,我相信通过仔细思考,可以通过检查来反驳您的假设,您将得出结论,
cuft
API(以及由此产生的任何函数)未接触您的
image.data()
指针引用的主机数据。为了假设这一点,我们最终会得出关于cufft API行为的荒谬结论。一旦你对此达成一致,那么这个问题的前提,即数据副本“不必要”不再是必然的结论,你需要证明为什么你认为它们“不必要”。我认为这很难,除非你真的知道复制的是什么数据。我理解图书馆可能需要内部副本。我还发现库访问的不是我的主机数据。但我想理解为什么库需要从主机到设备的数据传输(这就是我在说“不必要”(也许不是正确的术语)时所指的。我对设备到设备的数据传输没问题,但是…)@我明天会提供一个例子。。。谢谢
...
cudaProfilerStart();
cufftExecR2C(plan, src, dst);
cudaProfilerStop();
...
#include "cufft.h"
#include "cuda_profiler_api.h"
#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <functional>

int main()
{
  const int image_rows = 1600, image_cols = 2048;

  std::random_device rnd_device;
  std::mt19937 mersenne_engine {rnd_device()};
  std::uniform_real_distribution<float> dist {0.0, 255.0};

  auto gen = [&dist, &mersenne_engine](){
                 return dist(mersenne_engine);
             };

  std::vector<float> image(image_rows * image_cols);
  std::generate(std::begin(image), std::end(image), gen);

  float* src;
  cudaMalloc((&src),  image_rows * image_cols  * sizeof(float) );
  cudaMemcpy(src, &image[0],  image_rows * image_cols  * sizeof(float)  , cudaMemcpyHostToDevice);
  cufftComplex* dst;
  cudaMalloc((void**)&dst    , image_rows * (image_cols/2+1) * sizeof(cufftComplex) );

  cufftHandle plan;
  cufftPlan2d(&plan, image_rows, image_cols, CUFFT_R2C);

  cudaProfilerStart();
  cufftExecR2C(plan, src, dst);
  cudaProfilerStop();

  return 0;
}
$ nvcc -std=c++11 -o unecessary unecessary.cu -lcufft
$ nvprof ./unecessary
==10314== NVPROF is profiling process 10314, command: ./unecessary
==10314== Profiling application: ./unecessary
==10314== Profiling result:
            Type  Time(%)      Time     Calls       Avg       Min       Max  Name
 GPU activities:   74.39%  2.2136ms         1  2.2136ms  2.2136ms  2.2136ms  [CUDA memcpy HtoD]
                    6.66%  198.30us         1  198.30us  198.30us  198.30us  void spRadix0064B::kernel1Mem<unsigned int, float, fftDirection_t=-1, unsigned int=32, unsigned int=4, CONSTANT, ALL, WRITEBACK>(kernel_parameters_t<fft_mem_radix1_t, unsigned int, float>)
                    6.50%  193.47us         1  193.47us  193.47us  193.47us  void spRadix0025B::kernel1Mem<unsigned int, float, fftDirection_t=-1, unsigned int=64, unsigned int=4, CONSTANT, ALL, WRITEBACK>(kernel_parameters_t<fft_mem_radix1_t, unsigned int, float>)
                    6.25%  185.98us         1  185.98us  185.98us  185.98us  void spVector1024C::kernelMem<unsigned int, float, fftDirection_t=-1, unsigned int=2, unsigned int=5, LUT, ALL, WRITEBACK>(kernel_parameters_t<fft_mem_t, unsigned int, float>)
                    6.20%  184.38us         1  184.38us  184.38us  184.38us  __nv_static_45__32_spRealComplex_compute_70_cpp1_ii_1f28721c__ZN13spRealComplex24postprocessC2C_kernelMemIjfL9fftAxii_t3EEEvP7ComplexIT0_EPKS4_T_15coordDivisors_tIS8_E7coord_tIS8_ESC_S8_S3_10callback_t
$ nvprof --profile-from-start off ./unecessary
==11674== NVPROF is profiling process 11674, command: ./unecessary
==11674== Profiling application: ./unecessary
==11674== Profiling result:
            Type  Time(%)      Time     Calls       Avg       Min       Max  Name
 GPU activities:   25.96%  196.28us         1  196.28us  196.28us  196.28us  void spRadix0064B::kernel1Mem<unsigned int, float, fftDirection_t=-1, unsigned int=32, unsigned int=4, CONSTANT, ALL, WRITEBACK>(kernel_parameters_t<fft_mem_radix1_t, unsigned int, float>)
                   25.25%  190.91us         1  190.91us  190.91us  190.91us  void spRadix0025B::kernel1Mem<unsigned int, float, fftDirection_t=-1, unsigned int=64, unsigned int=4, CONSTANT, ALL, WRITEBACK>(kernel_parameters_t<fft_mem_radix1_t, unsigned int, float>)
                   24.65%  186.39us         1  186.39us  186.39us  186.39us  void spVector1024C::kernelMem<unsigned int, float, fftDirection_t=-1, unsigned int=2, unsigned int=5, LUT, ALL, WRITEBACK>(kernel_parameters_t<fft_mem_t, unsigned int, float>)
                   24.15%  182.59us         1  182.59us  182.59us  182.59us  __nv_static_45__32_spRealComplex_compute_70_cpp1_ii_1f28721c__ZN13spRealComplex24postprocessC2C_kernelMemIjfL9fftAxii_t3EEEvP7ComplexIT0_EPKS4_T_15coordDivisors_tIS8_E7coord_tIS8_ESC_S8_S3_10callback_t