Как скопировать переменные-указатели массива структур с хоста на устройство в CUDA - PullRequest
2 голосов
/ 15 октября 2019

Я хочу скопировать массив структуры с хоста на устройство разными способами. Я могу подключить кабель для копирования хоста с полной структурой с устройства на устройство, но не могу скопировать отдельный элемент структуры с хоста на устройство, пока один из элементов является переменной-указателем,Я получаю ошибку сега, делая это. Проблема возникает для переменной указателя, но не для нормальной переменной.

Я отладил и обнаружил, что ошибка находится в строке ниже.

cudaMemcpy(d_s[i].data,h_s[i].data,sizeof(float*),cudaMemcpyHostToDevice);

Я не смог решить эту проблему.

#include<iostream>

using namespace std;

struct structure
{
   int count;
   float *data;
};


structure * fillStructure(int n,  float *tdata )
{

   structure *h_s;
   h_s = (structure *) malloc( n * sizeof(structure));

   for(int i =0; i< n; i++)
   {
           h_s[i].count =i;
           h_s[i].data = &tdata[i];
   }
   cout<<"Input:\n";
   for(int i=0; i<n ;i++)
   {
       cout<<h_s[i].count<<"\t";
   }
   cout<<endl;
   for(int i=0; i<n ;i++)
   {
       cout<<*(h_s[i].data)<<"\t";
   }
   cout<<endl;
   structure *d_s;

   cudaMalloc((void**)&d_s, n * sizeof(structure));
   for(int i=0; i<n ;i++)
   {
       cudaMemcpy(&d_s[i].count,&h_s[i].count, sizeof(int), cudaMemcpyHostToDevice);
       cudaMemcpy(d_s[i].data,h_s[i].data,sizeof(float *),cudaMemcpyHostToDevice);
   }
                                                                                                                             1,1           Top
 return d_s;

}

int main()
{
   int N =5;
   float *ldata;
   ldata = (float*) malloc(N * sizeof(float));
   for(int i=0 ; i< N ; i++)
   {
    ldata[i] =i*i;
   }
        structure *ps = fillStructure(N, ldata);

        structure *ls;
        ls =(structure *) malloc( N  * sizeof(structure));
        cudaMemcpy(ls,ps,N * sizeof(structure),cudaMemcpyDeviceToHost);

   cout<<"Result:\n";
   for(int i=0; i< N;i++)
   {
       cout<<ls[i].count<<"\t";
   }
   cout<<endl;
   for(int i =0 ; i< N; i++)
   {
     cout<<*(ls[i].data)<<"\t";
   }
   cout<<endl;

}

Ожидаемый вывод

Input:
0   1   2   3   4   
0   1   4   9   16  
Result:
Input:
0   1   2   3   4   
0   1   4   9   16  

Но фактический вывод

Input:
0   1   2   3   4   
0   1   4   9   16  
Segmentation fault (core dumped)

Заранее спасибо

1 Ответ

2 голосов
/ 15 октября 2019

относительно этой строки:

cudaMemcpy(d_s[i].data,h_s[i].data,sizeof(float *),cudaMemcpyHostToDevice);

что вы просили cudaMemcpy сделать так:

  1. получить указатель источника из h_s[i].data
  2. используя этот указатель, получить количество float * из местоположения, на которое указывает этот указатель
  3. , получить указатель назначения из d_s[i].data
  4. , используя этот указатель, сохранить количество, полученное на шаге 2,в любое место указатель с шага 3 указывает на.

Есть множество проблем с этим, но самая основная проблема заключается в том, что вы не хотите делать.

То, что вы пытаетесь скопировать, это значение указателя, содержащееся в (исходное местоположение) h_s[i].data, и вы хотите сохранить его в (место назначения) d_s[i].data. Чтобы это работало, вы должны передать указатель в эти местоположения (источник и место назначения).

Это можно исправить, добавив амперсанд к обоим элементам:

cudaMemcpy(&(d_s[i].data),&(h_s[i].data),sizeof(float *),cudaMemcpyHostToDevice);

Это должно исправить ошибку сегмента. И он будет правильно скопировать числовое значение указателя, содержащегося в h_s[i].data, в d_s[i].data.

Однако , как я уже говорил ранее, указатель, с которого вы копируетерасположение источника задается здесь:

       h_s[i].data = &tdata[i];

, и это указатель на местоположение в памяти хоста . Такой указатель нельзя безопасно использовать в коде устройства CUDA, поэтому на самом деле нет особого смысла усердно работать, чтобы правильно скопировать этот указатель на устройство. Это будет бесполезно в коде устройства.

Вы все еще не поняли необходимость глубокой копии CUDA, чтобы эта схема работала. Как указывалось ранее, это рассматривается пошагово здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...