4

我们有一个功能,可以让用户通过UI界面拖拽一个模块,形成一个数据处理流水线,比如读取数据,做预处理,做分类训练等,拖拽完成后,这些模块会依次执行。

每个模块会启动一个容器(通过k8s)运行,上一个模块处理的结果作为文件保存到cephfs,下一个模块读取文件然后执行操作。这种序列化/反序列化过程很慢。我们计划使用 RAPIDS 来加速这个管道:通过将数据放在 GPU MEM 中来改进模块间的数据交换。并使用 cuDF/cuML 代替 Pandas/SKLearn 以获得更快的处理速度。

目前我们已经确认这些模块可以从 Pandas/SKLearn 移植到 cuDF/cuML,但是因为每个模块都运行在一个容器中,一旦模块运行完毕,容器消失,进程也消失,所以,对应的 cuDF数据不能继续存在于 GPU MEM 中。

在这种情况下,如果你想使用 RAPIDS 来改进管道,有什么好的建议吗?

4

2 回答 2

2

如果您希望进程产生和终止,并且它们的内存可以被远程访问,那么您需要一些东西来在此期间保存您的数据。一种解决方案是构建一个流程来进行分配,然后从 ipc 创建 cudf 列。我不确定如何在 python 中执行此操作。在 c++ 中,它非常简单。

类似的东西

//In the code handling your allocations
gdf_column col;

cudaMemHandle_t handle_data, handle_valid;
cudaIpcGetMemHandle(&handle,col.data);
cudaIpcGetMemHandle(&valid,col.valid);



//In the code consuming it
gdf_column col;

//deserialize these by reading from a file or however you want to make this 
//binary data avaialable
cudaMemHandle_t handle_data, handle_valid;

cudaIpcOpenMemHandle ( (void**) &col.data, cudaIpcMemHandle_t handle, cudaIpcMemLazyEnablePeerAccess );
cudaIpcOpenMemHandle ( (void**) &col.valid, cudaIpcMemHandle_t handle, cudaIpcMemLazyEnablePeerAccess );

还有来自 RAPIDs 贡献者的第三方解决方案,例如 BlazingSQL,它们在 python 中提供此功能,并为 cudfs 提供 SQL 接口。

在这里你会做类似的事情

#run this code in your service to basically select your entire table and get it
#as a cudf
from blazingsql import BlazingContext
import pickle
bc = BlazingContext()
bc.create_table('performance', some_valid_gdf) #you can also put a file or list of files here
result= bc.sql('SELECT * FROM main.performance', ['performance'])
with open('context.pkl', 'wb') as output:
    pickle.dump(bc, output, pickle.HIGHEST_PROTOCOL)
with open('result.pkl', 'wb') as output:
    pickle.dump(result, output, pickle.HIGHEST_PROTOCOL)


#the following code can be run on another process as long as result
# contains the same information from above, its existence is managed by blazingSQL 
from blazingsql import BlazingContext
import pickle
with open('context.pkl', 'rb') as input:
  bc = pickle.load(input)
with open('result.pkl', 'rb') as input:
  result = pickle.load(input)

#Get result object
result = result.get()
#Create GDF from result object
result_gdf = result.columns

免责声明,我为 Blazing 工作。

于 2019-04-04T18:52:03.527 回答
1

免责声明:我是 NVIDIA 的员工,也是 RAPIDS 的贡献者。

我们有一个功能,可以让用户通过UI界面拖拽一个模块,形成一个数据处理流水线,比如读取数据,做预处理,做分类训练等。拖拽之后,这些模块会依次执行。

每个模块会启动一个容器(通过k8s)运行,上一个模块处理的结果作为文件保存到cephfs,下一个模块读取文件然后执行操作。这种序列化/反序列化过程很慢。我们计划使用 RAPIDS 来加速这个管道:通过将数据放在 GPU MEM 中来改进模块间的数据交换。并使用 cuDF/cuML 代替 Pandas/SKLearn 以获得更快的处理速度。

目前我们已经确认这些模块可以从 Pandas/SKLearn 移植到 cuDF/cuML,但是因为每个模块都运行在一个容器中,一旦模块运行完毕,容器消失,进程也消失,所以,对应的 cuDF数据不能继续存在于 GPU MEM 中。

在这种情况下,如果你想使用 RAPIDS 来改进管道,有什么好的建议吗?

Kubernetes 中 Pod 中的容器共享一个 IPC 命名空间 [[1]][2,],它允许 CUDA IPC 在容器之间工作。上面介绍的@flips将是最有效的数据管道的理想案例,但由于 Kubernetes 与 GPU 的当前限制,这并不容易实现。在 Kubernetes [2]中,允许启动多个可以与同一个 GPU 通信的容器仍处于探索/实验阶段。这给您留下了几个选择:

  1. 尝试使用[2]中提出的变通办法/解决方案来运行一个长期运行的“sidecar”容器,其唯一目的是充当 pod 中不同容器之间 GPU 内存的中间人。
  2. 将 GPU 内存对象复制到托管内存对象(例如 Apache Arrow 对象),然后在没有 GPU 资源和 IPC 内存的情况下运行“sidecar”容器到/来自该容器。例如使用箭头[3]
  3. 像现在一样继续使用 cephfs 文件系统,未来会出现 GPU 加速的输出写入器,并希望它有助于缓解您当前的瓶颈。
于 2019-04-05T14:58:16.827 回答