数据传输
原理介绍
- 数据传输是通过内存拷贝的方式实现的,LXHPL提供了同步拷贝和异步拷贝接口:
同步拷贝:调用lynMemcpy接口,接口返回后代表数据已经完成了C2S、S2C或S2S传输。
异步拷贝:调用lynMemcpyAsync接口,在特定Stream中执行异步拷贝,确定拷贝完成需要调用lynSynchronizeStream接口同步等待,该接口返回后代表数据已经完成拷贝。
需要向Server端拷贝数据时,需要提前调用lynMalloc接口分配Server侧内存。
Client端的内存分配,用户可自行调用标准库提供的new或malloc接口申请内存,并在内存生命周期结束后调用delete或free接口进行释放,LXHPL未提供额外接口。
- 当同一个应用的可执行文件既可以在Client上执行,也支持在Server上执行时,需要根据软件栈运行模式来判断后续的内存申请接口调用逻辑。
如果应用的可执行文件在Client侧执行,则可能涉及Client和Server的数据传输,需要调用lynMemcpy(同步接口)或lynMemcpyAsync接口(异步接口)通过内存拷贝的方式实现数据传输。
- S2S(ServerToServer)的拷贝分为两种情况,一种是在同一个Device上的两个内存地址之间的拷贝;另一种是一个Device拷贝到另一个Device上的拷贝;在SDK层会自动根据传进接口的src和dst两个地址参数来判断拷贝方式,当src和dst是在同一个Device上lynMalloc出来的,就会在同一个Device上拷贝,当src和dst是不同Device上lynMalloc出来的就会进行跨Device进行拷贝。跨Device的直接拷贝在很多场景可以提升很大的效率,相比于原来的Device1→Host,Host→Device2的这种跨设备拷贝,减少了Host侧临时内存开销,以及多一步拷贝的耗时。
注意
不能跨进程拷贝。
MultiProcessP2P的拷贝,可以实现多进程之间的不同Device之间的P2P拷贝。
C2S数据传输
用户可以从LynSDK提供的示例代码中查看完整样例,在示例代码中,调用各接口后都添加了异常判断和处理,以下是关键步骤代码示例,仅供参考,不可以直接拷贝编译。
//创建解码器发送Stream
lynCreateStream(&vdec_send_stream);
//分配Server侧内存
lynMalloc(&buf, 1024 * 1024);
//执行异步内存拷贝
lynMemcpyAsync(stream, buf, packet->data, packet->size, ClientToServer);
//同步等待拷贝完成并释放Server侧内存
lynSynchronizeStream(vdec_send_stream);
lynFree(buf);
//销毁Stream
lynDestroyStream(vdec_send_stream);
S2C数据传输
用户可以从LynSDK提供的示例代码中查看完整样例,在示例代码中,调用各接口后都添加了异常判断和处理,以下是关键步骤代码示例,仅供参考,不可以直接拷贝编译。
//创建Stream
lynStream_t stream;
lynCreateStream(&stream);
//初始化Server侧内存,同步接口
lynMemset(m_buffer1, 5, 1024*1024);
//将数据拷贝回Client侧,检查Server内存是否初始化成功,同步接口
lynMemcpy(hostMem1, m_buffer1, 1024*1024, ServerToClient);
//初始化Server侧内存,异步接口
lynMemsetAsync(m_buffer1, 6, 1024*1024, stream);
//同步等待直至异步初始化完成
lynSynchronizeStream(stream);
//将数据拷贝回Client侧,检查Server内存是否初始化成功,异步接口
lynMemcpyAsync(stream, hostMem1, m_buffer1, 1024*1024, ServerToClient);
//同步等待直至异步拷贝完成
lynSynchronizeStream(stream);
//销毁Stream
lynDestroyStream(stream);
S2S数据传输
如下示例用于说明在不同Device上申请的地址,通过调用lynMemcpy接口进行跨Device的P2P拷贝。
lynContext_t ctx0;
lynContext_t ctx1;
void *devPtr0;
void *devPtr1;
lynCreateContext(&ctx0, 0);
lynMalloc(&devPtr0, 1024);
lynCreateContext(&ctx1, 1);
lynMalloc(&devPtr1, 1024);
lynMemcpy(devPtr0, devPtr1, 1024, ServerToServer); //两个地址分别在device0和device1上会进行跨设备P2P的拷贝
lynSetCurrentContext(ctx0);
lynFree(devPtr0);
lynDestroyContext(ctx0);
lynSetCurrentContext(ctx1);
lynFree(devPtr1);
lynDestroyContext(ctx1);
MultiProcessP2P数据传输
MultiProcessP2P的拷贝,可以实现多进程之间的不同Device之间的P2P拷贝。
read.cpp示例:
typedef struct{
uint64_t pid = 0;
uint64_t devPtr = 0;
}MEM_DATA;
int fd = open("./sharemem", O_RDWR|O_CREAT,0666);
ftruncate(fd, sizeof(MEM_DATA));
// 申请共享内存
MEM_DATA* mem = (MEM_DATA)mmap(NULL, sizeof(MEM_DATA), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
lynContext_t ctx;
void *devPtr;
lynCreateContext(&ctx, 0);
lynMalloc(&devPtr, 1024);
// 从共享内存中得到mem->devPtr,将write进程中的这个devPtr内存拷贝到该进程中的devPtr中
lynMemcpy(devPtr, reinterpret_cast<void*>(mem->devPtr), 1024, MultiProcessP2P);
lynFree(devPtr);
lynDestroyContext(ctx);
write.cpp示例:
typedef struct{
uint64_t pid = 0;
uint64_t devPtr = 0;
}MEM_DATA;
int fd = open("./sharemem", O_RDWR|O_CREAT,0666);
ftruncate(fd, sizeof(MEM_DATA));
// 申请共享内存
MEM_DATA* mem = (MEM_DATA)mmap(NULL, sizeof(MEM_DATA), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
lynContext_t ctx;
void *devPtr;
lynCreateContext(&ctx, 0);
lynMalloc(&devPtr, 1024);
lynMemSet(devPtr, 1, 1024);
// 将该进程申请的devPtr放到共享内存
mem->devPtr = reinterpret_cast<uint64_t>(devPtr);
sleep(1);
lynFree(devPtr);
lynDestroyContext(ctx);