在使用 Cuda 的Thrust 进行加速时,需要将一些复杂信息从C++层传递到Cuda层,比如说 多个Device端的内存地址。
- 一种常用的方式是,使用device_vector 与 STL vector 进行传递。
- 本文使用另外一种方式,是将信息Pack成Device内存中的地址,传递到Cuda层后,再进行Unpack 处理。
下面的例子,表示的是将 std::vector<void*> 与 std::vector 进行 pack的方法,以及 unpack 的验证。
#include <stdio.h>
#include <vector>
#include <iostream>
void test_pack_unpack()
{
// step1: Create Test Data
std::vector<float> ratio;
ratio.push_back(0.5f);
ratio.push_back(0.5f);
std::vector<void*> address;
int temp_1 = 20;
int temp_2 = 40;
address.push_back(&temp_1);
address.push_back(&temp_2);
std::cout << "temp_1: " << &temp_1 << " temp_2 " << & temp_2 << std::endl;
// step2: pack data to info_buffer
int num = 2;
std::vector<char> info_buffer(num * (sizeof(void*) + sizeof(float)));
void* ptr = info_buffer.data();
std::cout << "original pack address : " << (char**)ptr << std::endl;
for (int i = 0; i < num; ++i)
{
memcpy(ptr, &address[i], sizeof(void*));
ptr = (void*)((char*)(ptr)+sizeof(void*));
((float*)ptr)[0] = ratio[i];
ptr = (void*)((char*)(ptr)+sizeof(float));
}
// step3: unpack data
void* ptr_new = info_buffer.data();
std::cout << "original unpack address : " << (char**)ptr_new << std::endl;
for (int i = 0; i < num; ++i)
{
std::cout << " address : " << i << std::hex << (int)(*((char**)ptr_new)) << std::endl;
ptr_new = (void*)((char*)(ptr_new)+sizeof(void*));
std::cout << " ratio : " << i << *((float*)ptr_new) << std::endl;
ptr_new = (void*)((float*)(ptr_new)+1);
}
std::cout << "end" << std::endl;
}
int main ()
{
test_pack_unpack();
return 0;
}
最终,输出的信息如下
temp_1: 00000000006FF664 temp_2 00000000006FF684
original pack address : 0000000000CE9C70
original unpack address : 0000000000CE9C70
address : 06ff664
ratio : 00.5
address : 16ff684
ratio : 10.5
ptr0000000000CE9C88
可以看到,pack 的 temp_1, temp_2的地址: 00000000006FF664, 00000000006FF684 正确的 unpack 得到了。
示例中,缺少的一步是 需要将 pack 的内存,使用CUDA 的API,变成Device Momery. 然后在 Device Momery中进行unpack.