在使用 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.