将十六进制数组转换为CUDA中的char数组
convert hexdecimal array to char array in CUDA
我有 C++ CUDA 项目,但出现错误 "identifier "sprintf" is undefined in device code")。 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, '[=11=]', 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 数组 而无需 sprintf 和其他命名空间标准函数。我需要从 CUDA device
调用它
看来您需要做两件事才能达到您的要求:
- 将 unsigned char 输入分解为 16 位数字(其中总是有 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;
}
这将 return digits[0]
中最重要的 16 位数字和 digits[1]
中的最低有效数字。
第二步可以通过简单地将偏移量添加到两个 base 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
的主机代码相同的输出。
我有 C++ CUDA 项目,但出现错误 "identifier "sprintf" is undefined in device code")。 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, '[=11=]', 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 数组 而无需 sprintf 和其他命名空间标准函数。我需要从 CUDA device
调用它看来您需要做两件事才能达到您的要求:
- 将 unsigned char 输入分解为 16 位数字(其中总是有 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;
}
这将 return digits[0]
中最重要的 16 位数字和 digits[1]
中的最低有效数字。
第二步可以通过简单地将偏移量添加到两个 base 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
的主机代码相同的输出。