virtualGraph和pipelineStage Graphcore的PopART/杨树库之间的差异

2024-06-08 23:49:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用Graphcore的PopART framework(杨树API的一部分)实现一个基本的流水线模型,以加速我的模型,该模型被拆分为多个处理器

我正在关注他们的example code,但是我注意到这个示例没有使用pipelineStage()调用,这在他们的一些其他应用程序(即Bert)中使用,而是使用virtualGraph()来定义操作应该运行的处理器

下面是示例的一小部分:

#  Dense 1
W0 = builder.addInitializedInputTensor(
    init_weights(num_features, 512))
b0 = builder.addInitializedInputTensor(init_biases(512))

with builder.virtualGraph(0):
    x1 = builder.aiOnnx.gemm([x0, W0, b0], debugPrefix="gemm_x1")
    x2 = builder.aiOnnx.relu([x1], debugPrefix="relu_x2")

#  Dense 2
W1 = builder.addInitializedInputTensor(init_weights(512, num_classes))
b1 = builder.addInitializedInputTensor(init_biases(num_classes))

with builder.virtualGraph(1):
    x3 = builder.aiOnnx.gemm([x2, W1, b1], debugPrefix="gemm_x3")
    x4 = builder.aiOnnx.relu([x3], debugPrefix="relu_x4")

相反,Bert示例似乎创建了一个结合了virtualGraph()pipelineStage()的上下文:

self.stack.enter_context(self.builder.pipelineStage(self.pipelineStage))

我不确定哪一种应该是首选的款式。只使用virtualGraph()有什么影响吗


Tags: 模型示例initbuildernumrelux1x2
1条回答
网友
1楼 · 发布于 2024-06-08 23:49:54

virtualGraphpipelineStage是Graphcore PopART框架中的两个不同概念,尽管它们也相互关联

virtualGraph(请参阅《PopART用户指南》的Setting the IPU number for operations部分和PopART C++ API以供参考)支持将图形拆分为多个部分,以便在多个IPU上运行。如您提到的code example中所示,单独使用virtualGraph意味着在模型的分配部分上按顺序运行

另一方面,pipelineStage允许您将图形切割成几个阶段,如果可能,这些阶段可以在不同的IPU上并行运行。您可以灵活地选择在每个管道阶段中放置哪些操作。通过选项opts.enablePipelining(参见PopART C++ API)启用管道。 默认情况下,管道隐式地为每个virtualGraph创建一个pipelineStage

但是,可以为单个virtualGraph指定多个pipelineStage。当模型的两个部分共享相同的大型数据集时,这可能很有用。这就是为什么在BERT模型中使用pipelineStagevirtualGraph的组合:BERT有一个大的嵌入矩阵,在模型的开始和结束时使用。可以将两个操作放在同一个IPU上的相同virtualGraph中,这样共享数据就不会复制到多个IPU,而是在不同的管道阶段保持可用,因为它们不是按顺序执行的

相关问题 更多 >