【问题标题】:convert hexdecimal array to char array in CUDA在CUDA中将十六进制数组转换为char数组
【发布时间】:2020-08-06 09:49:20
【问题描述】:

我有 C++ CUDA 项目,但出现错误“标识符“sprintf”在设备代码中未定义”)。 sprintf() 在主机代码中使用,那么如何在 CUDA 内核中将十六进制转换为字符?

C++ 代码:

//md5Hash - its unsigned char hexdecimal array with length = 32
char str[16][2];
for (int j = 0; j < 16; ++j) {
    sprintf(str[j], "%02x", md5Hash[j]);//convert by 2 symbols
}

//convert from array str[16][2] to array new_word[32]
char* new_word = (char*) malloc(sizeof(char)*32);
for (int i = 0; i < 16; i++) {
    new_word[2 * i] = str[i][0];
    new_word[2 * i + 1] = str[i][1];
}

string_to_hex(我需要一个类似的 hex_to_string)

void string_to_hex(unsigned char* output, size_t out_size, char* input, size_t in_size)
{
    //example: string_to_hex(md5Hash, 16, "1c0d894f6f6ab511099a568f6e876c2f", 32);
    memset(output, '\0', out_size);
    for (int i = 0; i < in_size; i += 2)
    {
        unsigned char msb = (input[i + 0] <= '9' ? input[i + 0] - '0' : (input[i + 0] & 0x5F) - 'A' + 10);
        unsigned char lsb = (input[i + 1] <= '9' ? input[i + 1] - '0' : (input[i + 1] & 0x5F) - 'A' + 10);
        output[i / 2] = (msb << 4) | lsb;
    }
}

数组 md5Hash[32] 和 str[16][2] 中的第一个符号(str 数组中的所有符号将 = "1c0d894f6f6ab511099a568f6e876c2f")。我想将 uchar md5Hash 十六进制数组转换为 char 数组 without sprintf 和其他命名空间 std 函数。我需要从 CUDA device

调用它

【问题讨论】:

标签: arrays cuda char hex


【解决方案1】:

看来您需要做两件事才能达到您的需要:

  1. 将 unsigned char 输入分解为 16 位基数(其中始终为 2)
  2. 将两位以 16 为基数的数字转换为一对以十六进制表示数字的 ascii 字符。

第一步可以这样完成:

__device__ __host__ void makedigits(unsigned char x, unsigned char (&digits)[2])
{
    unsigned char d0 = x / 16;
    digits[1] = x - d0 * 16;
    unsigned char d1 = d0 / 16;
    digits[0] = d0 - d1 * 16;
}

这将返回digits[0] 中的最高有效基数 16 位和digits[1] 中的最低有效位。

第二步可以通过简单地将两个基数 16 数字添加偏移量来将它们转换为正确的 ASCII 值:

__device__ __host__ void makehex(unsigned char (&digits)[2], char (&hex)[2])
{
    for(int i=0; i<2; ++i) {
        if (digits[i] < 10) {
            hex[i] = '0' + digits[i];
    } else {
            hex[i] = 'a' + (digits[i] - 10);
        }
    }
}

一个完整的例子可能如下所示:

#include <iostream>
#include <cstdio>

__device__ __host__ void makedigits(unsigned char x, unsigned char (&digits)[2])
{
    unsigned char d0 = x / 16;
    digits[1] = x - d0 * 16;
    unsigned char d1 = d0 / 16;
    digits[0] = d0 - d1 * 16;
}

__device__ __host__ void makehex(unsigned char (&digits)[2], char (&hex)[2])
{
    for(int i=0; i<2; ++i) {
        if (digits[i] < 10) {
            hex[i] = '0' + digits[i];
    } else {
            hex[i] = 'a' + (digits[i] - 10);
        }
    }
}

__global__ void kernel(unsigned char* input, char* output)
{

    for (int i = 0; i < 16; ++i) {
        unsigned char val = input[i];
        unsigned char d[2];
        char h[2];
        makedigits(val, d);
        makehex(d, h);
        output[2*i] = h[0];
        output[2*i+1] = h[1];
    }
}

int main()
{
    unsigned char md5Hash[32];
    for(int i=0; i<32; ++i) md5Hash[i] = 255-i;

    unsigned char* d_md5Hash;
    cudaMalloc(&d_md5Hash, 32 * sizeof(unsigned char));
    cudaMemcpy(d_md5Hash, &md5Hash[0], 32 * sizeof(unsigned char), 
    cudaMemcpyHostToDevice);

    char str[16][2];
    for (int j = 0; j < 16; ++j) {
        sprintf(str[j], "%02x", md5Hash[j]);//convert by 2 symbols
    }

    for(int i=0; i<16; i++) std::cout << str[i][0] << str[i][1];
    std::cout << std::endl;

    char* d_str1;
    cudaMalloc(&d_str1, 32 * sizeof(char));
    char str1[32];
    kernel<<<1,1>>>(d_md5Hash, d_str1);
    cudaMemcpy(&str1[0], d_str1, 32 * sizeof(char), cudaMemcpyDeviceToHost);
    for(int i=0; i<32; i+=2) std::cout << str1[i] << str1[i+1];
    std::cout << std::endl;

    return 0;
}

[注意所有在茶歇期间编写的代码,并且经过了非常简单的测试。使用风险自负]

编译和运行这个:

$ nvcc -o hexconv hexconv.cu 

$ ./hexconv 
fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0
fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0

这似乎产生与您问题中基于 sprintf 的主机代码相同的输出。

【讨论】:

  • 它对我有用!谢谢,我花了很多时间在这上面。你帮了我很多。
  • 直到 1 小时前我才知道该怎么做。我首先在谷歌上搜索“将整数转换为十六进制”。然后我阅读了第一个链接并编写了您看到的代码。如果您想了解其工作原理以及您拥有的其他代码的作用,我相信您也可以这样做
猜你喜欢
  • 1970-01-01
  • 2020-01-24
  • 2013-07-27
  • 2011-08-12
  • 1970-01-01
  • 1970-01-01
  • 2013-02-14
  • 2016-03-24
  • 1970-01-01
相关资源
最近更新 更多