Cuda, как скопировать char ** из ядра на хост - PullRequest
0 голосов
/ 08 октября 2018
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <fstream>
#include <algorithm>
#include <time.h>

using namespace std;

__global__ void kern_2D(char **desc, char** merge_char) {

    int idx = threadIdx.x + blockDim.x*blockIdx.x;
    int idy = threadIdx.y + blockDim.y*blockIdx.y;

    if (idx < 10000)
    {
        char* s1 = desc[idx];
        merge_char[idx] = s1;
        //printf("From key = %s\n", merge_char[idx]);
    }

}


int main() {
    cudaError_t err = cudaSuccess;
    size_t max_line_len = 255;
    char line[255];
    size_t line_len;
    size_t max_lines_desc = 10000;
    //---------------------------------------------------------------------------------//

    char **d_desc;
    cudaMalloc(&d_desc, max_lines_desc * sizeof(char *));

    char **m_desc = NULL;
    m_desc = (char**)malloc(max_lines_desc * sizeof(char**));
    char **d_temp_desc = NULL;
    d_temp_desc = (char **)malloc(max_lines_desc * sizeof(char **));

    FILE *f_desc = fopen("desc.txt", "r");
    if (!f_desc)
    {
        fprintf(stderr, "Error opening file!\n");
    }
    int idesc = 0;

    do
    {
        if (!fgets(line, max_line_len, f_desc))
        {
            if (ferror(f_desc) && !feof(f_desc))
            {
                fprintf(stderr, "Error reading from file!\n");
                fclose(f_desc);
            }
            break;
        }

        line_len = strlen(line);
        if ((line_len > 0) && (line[line_len - 1] == '\n'))
        {
            line[line_len - 1] = '\0';
            --line_len;
        }
        m_desc[idesc] = line;
        cudaMalloc(&(d_temp_desc[idesc]), sizeof(line) * sizeof(char));
        cudaMemcpy(d_temp_desc[idesc], m_desc[idesc], sizeof(line) * sizeof(char), cudaMemcpyHostToDevice);
        cudaMemcpy(d_desc + idesc, &(d_temp_desc[idesc]), sizeof(char *), cudaMemcpyHostToDevice);

        ++idesc;
    } while (idesc < max_lines_desc);
    fclose(f_desc);

    //---------------------------------------------------------------------------------//


    char **merge_char;
    cudaMallocManaged(&merge_char, max_lines_desc * sizeof(char *));


    kern_2D << < 1, 1000 >> > (d_desc , merge_char);

    err = cudaDeviceSynchronize();
    if (err != cudaSuccess) {
        fprintf(stderr, "cudaDeviceSynchronize returned error code %s after launching addKernel!\n", cudaGetErrorString(err));
    }


    //---------------------------------------------------------------------------------//

    char** h_dev;

    cudaMalloc((void**)(&h_dev), max_lines_desc * sizeof(char*));
    err = cudaMemcpy(h_dev, merge_char, max_lines_desc * sizeof(char*), cudaMemcpyDeviceToHost);
    if (err == cudaSuccess) printf("2: Okay \n");


    for (int i = 0; i < max_lines_desc; i++)
    {
        printf("%s\n", h_dev[i]);
    }


    return 0;


}
//nvcc - arch = sm_30 - o kernel kernel.cu
// cuda - memcheck . / kernel

Извините за ошибку.Я уже обновил свой код.Это закончено.

Для desc.txt файл имеет 10000 строк, как показано ниже.Я проверил статус после копирования с устройства на хост, но я не прав.Я не могу напечатать char ** h_dev.

мотоцикл ckd новый apsonic ckd 2017 ckd 2018 мотоцикл apsoni новый мотоцикл apsonic no 125 мотоцикл apsonic ap125 новый мотоцикл apsonic ap125

1 Ответ

0 голосов
/ 10 октября 2018

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

Но ответить на ваш вопрос, насколько я могу судить, ваша «копия обратно на хост» действительно неверно.Вы эффективно выполняете глубокую копию своих данных с хоста на устройство, поэтому вам потребуется также глубокая копия (двухэтапная копия) в другом направлении.

Для этого мы не используем cudaMalloc при копировании на хост.cudaMalloc выделяет память устройства.Если вы хотите скопировать что-либо на хост, ваша цель копирования - это память хоста.Поэтому нам понадобится набор cudaMemcpy операций для глубокого копирования данных обратно на хост, используя буферы хоста в качестве целей.

Следующий код представляет простейшие модификации, которые я мог бы внести в то, что вы показали, чтобы выполнить это, и мне кажется, что это работает для моего простого теста:

$ cat desc.txt
1motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap125
2motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap125
3motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap125
4motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap125
5motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap125
6motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap1
$ cat t301.cu
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <fstream>
#include <algorithm>
#include <time.h>

using namespace std;

__global__ void kern_2D(char **desc, char** merge_char) {

    int idx = threadIdx.x + blockDim.x*blockIdx.x;
    int idy = threadIdx.y + blockDim.y*blockIdx.y;

    if (idx < 10000)
    {
        char* s1 = desc[idx];
        merge_char[idx] = s1;
        //printf("From key = %s\n", merge_char[idx]);
    }

}


int main() {
    cudaError_t err = cudaSuccess;
    size_t max_line_len = 255;
    char line[255];
    size_t line_len;
    size_t max_lines_desc = 10000;
    //---------------------------------------------------------------------------------//

    char **d_desc;
    cudaMalloc(&d_desc, max_lines_desc * sizeof(char *));

    char **m_desc = NULL;
    m_desc = (char**)malloc(max_lines_desc * sizeof(char**));
    char **d_temp_desc = NULL;
    d_temp_desc = (char **)malloc(max_lines_desc * sizeof(char **));

    FILE *f_desc = fopen("desc.txt", "r");
    if (!f_desc)
    {
        fprintf(stderr, "Error opening file!\n");
    }
    int idesc = 0;

    do
    {
        if (!fgets(line, max_line_len, f_desc))
        {
            if (ferror(f_desc) && !feof(f_desc))
            {
                fprintf(stderr, "Error reading from file!\n");
                fclose(f_desc);
            }
            break;
        }

        line_len = strlen(line);
        if ((line_len > 0) && (line[line_len - 1] == '\n'))
        {
            line[line_len - 1] = '\0';
            --line_len;
        }
        m_desc[idesc] = line;
        cudaMalloc(&(d_temp_desc[idesc]), sizeof(line) * sizeof(char));
        cudaMemcpy(d_temp_desc[idesc], m_desc[idesc], sizeof(line) * sizeof(char), cudaMemcpyHostToDevice);
        cudaMemcpy(d_desc + idesc, &(d_temp_desc[idesc]), sizeof(char *), cudaMemcpyHostToDevice);

        ++idesc;
    } while (idesc < max_lines_desc);
    fclose(f_desc);

    //---------------------------------------------------------------------------------//


    char **merge_char;
    cudaMallocManaged(&merge_char, max_lines_desc * sizeof(char *));


    kern_2D << < 1, 1000 >> > (d_desc , merge_char);

    err = cudaDeviceSynchronize();
    if (err != cudaSuccess) {
        fprintf(stderr, "cudaDeviceSynchronize returned error code %s after launching addKernel!\n", cudaGetErrorString(err));
    }


    //---------------------------------------------------------------------------------//

    char** h_dev;

    h_dev = (char **)malloc(max_lines_desc * sizeof(char*));
    err = cudaMemcpy(h_dev, merge_char, max_lines_desc * sizeof(char*), cudaMemcpyDeviceToHost);
    if (err == cudaSuccess) printf("2: Okay \n");


    for (int i = 0; i < 6; i++)
    {
        cudaMemcpy(line, h_dev[i], sizeof(line), cudaMemcpyDeviceToHost);
        printf("%s\n", line);
    }


    return 0;


}
$ nvcc -o t301 t301.cu
t301.cu(15): warning: variable "idy" was declared but never referenced

$ cuda-memcheck ./t301
========= CUDA-MEMCHECK
2: Okay
1motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap125
2motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap125
3motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap125
4motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap125
5motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap125
6motorcycle ckd new apsonic ckd 2017 ckd 2018 motorcycle apsoni new motorcycle apsonic no 125 motorcycle apsonic ap125 new motorcycle apsonic ap1
========= ERROR SUMMARY: 0 errors
$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...