С++ с CUDA: как выразить байт как символ или набор символов?

ВНУТРИ ЯДРА CUDA

Предположим, у меня есть байт, который может иметь двоичное значение от 0 до 255.

У меня есть массив символов (char *) длиной три:

char * c = (char *) malloc(300000000*sizeof(char)); // 30 mb

За исключением следующего (например, я хотел бы исключить «решения», которые включают ручное представление байта в символ):

switch(my_byte){
    case 0:
       c[0] = '0';
    case 1:
       c[1] = '1';
    ...
    case 255:
       c[0] = '2';
       c[1] = '5';
       c[2] = '5';
}

Как преобразовать байт в строку стиля char * в ядре Cuda?


person Chris    schedule 28.09.2018    source источник
comment
Использовать std::to_string, а затем скопировать строку в буфер?   -  person NathanOliver    schedule 29.09.2018
comment
@NathanOliver Я не уверен, что это будет работать в ядре cuda ... Есть ли функция NVCC to_string? Все операции std:: недействительны для ядра. По сути, это C с пространствами имен и структурами с функциями, но не более того.   -  person Chris    schedule 29.09.2018
comment
my_byte - это массив байтов или просто один байт?   -  person Yucel_K    schedule 29.09.2018
comment
@Yucel_K Это один байт в массиве байтов. Просто byte -> номер строки в стиле c для каждого из набора байтов в коде устройства cuda. Я сделаю оператор гигантского переключателя, это будет десять минут в vi, но должен быть лучший способ...   -  person Chris    schedule 29.09.2018
comment
stackoverflow.com/q/36878640/681865   -  person talonmies    schedule 29.09.2018
comment
кто когда-либо отрицал ответ, пожалуйста, укажите причину, по которой вы проголосовали против, чтобы я мог понять, что было сделано неправильно.   -  person Yucel_K    schedule 29.09.2018


Ответы (2)


Это мое решение на данный момент, чтобы избежать проблемы управления потоком в векторизованном коде.

/*! \brief byte to raw chars; this is not a string! */
__device__ void byte_to_chars(uint8_t b,char * str_arr_ptr){
  uint8_t buf[4];

  buf[0] = b / 100;
  buf[1] = (b % 100 - b % 10) / 10;      
  buf[2] = b % 10;

  buf[3] = 3 - !buf[0] + !buf[0]*!buf[1]; // size

  // buf[3] = sz
  // 3 - buf[3] = missing digits; i.e., 1 for 023, 2 for 003
  for(int i = 0; i < buf[3]; i++) str_arr_ptr[0][i] = buf[ i + 3 - buf[3] ]+'0';              

  // modify function signature as needed -- i.e., return
  // useful info 
}

Однако решение, основанное на библиотечных вызовах, было бы лучшим.

person Chris    schedule 30.09.2018
comment
Большая часть функций стандартной библиотеки C++ (или даже C) в настоящее время недоступна в коде CUDA; поэтому вы вряд ли получите решение, которое вас интересует. Кроме того, вы часто используете магические числа; и это решение будет трудно адаптировать к большим числовым типам. - person einpoklum; 30.09.2018
comment
@einpoklum да, это установлено. однако оставался вопрос, существуют ли хорошие, поддерживаемые решения для преобразования байтов в строки edit: list of chars. Простым примером, для которого вам может понадобиться поддерживаемое решение, является взаимодействие между машинами, которое может произвольно отличаться с точки зрения порядка следования байтов, порядка полубайтов и т. д., и для которого поддерживаемый код существует на стороне хоста — и которым я оказался иметь дело с. - person Chris; 30.09.2018
comment
@einpoklum тем временем, это решение гораздо полезнее, чем неработающий и более сложный код, который вы разместили ниже, после педантичной лекции о материале, выходящем за рамки. - person Chris; 30.09.2018

Во-первых, не используйте malloc() для небольшого фиксированного объема памяти; использовать массив. Во-вторых, не переключайтесь и вообще в коде ядра старайтесь избегать расхождения путей управления. Наконец, если предполагается, что это строка в стиле C, она должна заканчиваться на '\0'.

Итак, рассмотрим что-то вроде:

#include <cstdint>

enum { max_digits = 3, modulus = 10 };
struct stringized_byte_t {
    char[max_digits+1] buffer;
}

stringized_byte_t stringize_a_byte(uint8_t my_byte)
{
    uint8_t digits[max_digits];
    uint8_t num_digits = 1;

    uint8_t remainder = my_byte;
    while(remainder >= modulus) {
       uint8_t dividend = remainder / modulus;
       digits[num_digits - 1] = remainder - dividend * modulus;
       num_digits++;
       remainder = dividend;
    }

    // at this point we have one digit left (although it might be 0),
    // and we know the overall number of digits, so:

    digits[num_digits - 1] = remainder;

    // Now we need to flip the digit direction to fit the printing order,
    // and terminate the string

    stringized_byte_t sb;
    for(int i = 0; i < num_digits; i++) {
       sb.buffer[i] = '0' + digits[num_digits - i - 1];
    }
    sb.buffer[num_digits] = '\0';
    return sb;
}

Обратите внимание, что я использовал кодирование в стиле C, а не «прокачку» класса, поэтому вы можете очень легко преобразовать этот код в правильный C.

person einpoklum    schedule 30.09.2018
comment
Указатель правильный для этого варианта использования; Я не буду использовать массив. Почему вы начинаете с позиции 1? Используйте «цифровой индекс» и начните с нуля для согласованности. - person Chris; 30.09.2018
comment
В любом случае, спасибо за внимание к управлению потоком. - person Chris; 30.09.2018
comment
Кроме того, у вас есть бесконечный цикл while — ваш первый цикл while. - person Chris; 30.09.2018
comment
@bordeo: Вы правы насчет бесконечного цикла, исправил. О позиции 1. Это потому, что если my_byte равно 0, вы хотите сказать, что у него 1 цифра - во всяком случае, для строкового преобразования. - person einpoklum; 30.09.2018
comment
@bordeo: Кроме того, вы заявляете, что использование указателя правильно для вашего варианта использования, но вы не сказали, почему это так. Ваш самостоятельный ответ предполагает, что память выделена в другом месте, и вам нужно в нее печатать, но в вашем вопросе этого не было сказано. - person einpoklum; 30.09.2018
comment
На самом деле, вопрос заключался в поиске библиотечного решения, а не преобразования собственного байта в строковое представление (которое я указываю в вопросе), поэтому все, что связано со строками, выходило за рамки. На самом деле весь ответ вышел за рамки. - person Chris; 30.09.2018