• fluid.transpiler
    • DistributeTranspiler
    • DistributeTranspilerConfig
    • HashName
    • memory_optimize
    • release_memory
    • RoundRobin

    fluid.transpiler

    SourceEnglish

    DistributeTranspiler

    SourceEnglish

    • class paddle.fluid.transpiler.DistributeTranspiler(config=None)
    • 该类可以把fluid program转变为分布式数据并行计算程序(distributed data-parallelism programs),可以有Pserver和NCCL2两种模式。当program在Pserver(全称:parameter server)模式下, main_program (主程序)转为使用一架远程parameter server(即pserver,参数服务器)来进行参数优化,并且优化图会被输入到一个pserver program中。在NCCL2模式下,transpiler会在 startup_program 中附加一个 NCCL_ID 广播算子(broadcasting operators)来实现在该集群中所有工作结点共享NCCL_ID 。调用 transpile_nccl2 后, 你 必须trainer_id , num_trainers 参数提供给 ParallelExecutor 来启动NCCL2分布式模式。

    代码示例

    1. x = fluid.layers.data(name='x', shape=[13], dtype='float32')
    2. y = fluid.layers.data(name='y', shape=[1], dtype='float32')
    3. y_predict = fluid.layers.fc(input=x, size=1, act=None)
    4.  
    5. cost = fluid.layers.square_error_cost(input=y_predict, label=y)
    6. avg_loss = fluid.layers.mean(cost)
    7.  
    8. sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.001)
    9. sgd_optimizer.minimize(avg_loss)
    10.  
    11. # pserver 模式下
    12. pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
    13. trainer_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
    14. current_endpoint = "192.168.0.1:6174"
    15. trainer_id = 0
    16. trainers = 4
    17. role = "PSERVER"
    18. t = fluid.DistributeTranspiler()
    19. t.transpile(
    20. trainer_id, pservers=pserver_endpoints, trainers=trainers)
    21. if role == "PSERVER":
    22. pserver_program = t.get_pserver_program(current_endpoint)
    23. pserver_startup_program = t.get_startup_program(current_endpoint,
    24. pserver_program)
    25. elif role == "TRAINER":
    26. trainer_program = t.get_trainer_program()
    27.  
    28. # nccl2 模式下
    29. trainer_num = 2
    30. trainer_id = 0
    31. config = fluid.DistributeTranspilerConfig()
    32. config.mode = "nccl2"
    33. trainer_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
    34. t = fluid.DistributeTranspiler(config=config)
    35. t.transpile(trainer_id=trainer_id, trainers=trainer_endpoints, current_endpoint="192.168.0.1:6174")
    36. exe = fluid.ParallelExecutor(
    37. use_cuda=True,
    38. loss_name=avg_loss.name,
    39. num_trainers=trainer_num,
    40. trainer_id=trainer_id
    41. )
    • transpile(trainer_id, program=None, pservers='127.0.0.1:6174', trainers=1, sync_mode=True, startup_program=None, current_endpoint='127.0.0.1:6174')
    • 该方法可以运行该transpiler(转译器)。转译输入程序。

    • 参数:

      • trainer_id (int) – 当前Trainer worker的id, 如果有n个Trainer worker, id 取值范围为0 ~ n-1
      • program (Program|None) – 待transpile(转译)的program, 缺省为 fluid.default_main_program()
      • startup_program (Program|None) - 要转译的 startup_program ,默认为 fluid.default_startup_program()
      • pservers (str) – 内容为Pserver列表的字符串,格式为:按逗号区分不同的Pserver,每个Pserver的格式为 ip地址:端口号
      • trainers (int|str) – 在Pserver模式下,该参数指Trainer机的个数;在nccl2模式下,它是一个内容为Trainer终端列表的字符串
      • sync_mode (bool) – 是否做同步训练(synchronous training), 默认为True
    • startup_program (Program|None) – 待transpile(转译)的startup_program,默认为 fluid.default_main_program()
    • current_endpoint (str) – 当需要把program转译(transpile)至NCCL2模式下时,需要将当前endpoint(终端)传入该参数。Pserver模式不使用该参数代码示例
    1. transpiler = fluid.DistributeTranspiler()
    2. t.transpile(
    3. trainer_id=0,
    4. pservers="127.0.0.1:7000,127.0.0.1:7001",
    5. trainers=2,
    6. sync_mode=False,
    7. current_endpoint="127.0.0.1:7000")
    • gettrainer_program(_wait_port=True)
    • 该方法可以得到Trainer侧的program。

    返回: Trainer侧的program

    返回类型: Program

    代码示例

    1. import paddle.fluid as fluid
    2. # 这是一个示例,请根据你的情况更改endpoint
    3. pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
    4. trainer_id = 0
    5. trainers = 4
    6. t = fluid.DistributeTranspiler()
    7. t.transpile(trainer_id, trainers=trainers, pservers=pserver_endpoints)
    8. trainer_program = t.get_trainer_program()
    • getpserver_program(_endpoint)
    • 该方法可以得到Pserver(参数服务器)侧的程序

    • 参数:

      • endpoint (str) – 当前Pserver终端返回: 当前Pserver需要执行的program

    返回类型: Program

    代码示例

    1. import paddle.fluid as fluid
    2. # 这是一个示例,请根据你的情况更改endpoint
    3. pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
    4. current_endpoint = "192.168.0.1:6174"
    5. trainer_id = 0
    6. trainers = 4
    7. t = fluid.DistributeTranspiler()
    8. t.transpile(
    9. trainer_id, pservers=pserver_endpoints, trainers=trainers)
    10. pserver_program = t.get_pserver_program(current_endpoint)
    • getpserver_programs(_endpoint)
    • 该方法可以得到Pserver侧用于分布式训练的 main_programstartup_program

    • 参数:

      • endpoint (str) – 当前Pserver终端返回: (main_program, startup_program), “Program”类型的元组

    返回类型: tuple

    代码示例

    1. import paddle.fluid as fluid
    2. # 这是一个示例,请根据你的情况更改endpoint
    3. pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
    4. current_endpoint = "192.168.0.1:6174"
    5. trainer_id = 0
    6. trainers = 4
    7. t = fluid.DistributeTranspiler()
    8. t.transpile(
    9. trainer_id, pservers=pserver_endpoints, trainers=trainers)
    10. pserver_program, pserver_startup_program = t.get_pserver_programs(current_endpoint)
    • getstartup_program(_endpoint, pserver_program=None, startup_program=None)
    • 该函数已停止使用获取当前Pserver的startup_program,如果有多个被分散到不同blocks的变量,则修改operator的输入变量。

    • 参数:

      • endpoint (str) – 当前Pserver终端
      • pserver_program (Program) – 已停止使用。 先调用get_pserver_program
      • startup_program (Program) – 已停止使用。应在初始化时传入startup_program返回: Pserver侧的startup_program

    返回类型: Program

    代码示例

    1. pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
    2. trainer_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
    3. current_endpoint = "192.168.0.1:6174"
    4. trainer_id = 0
    5. trainers = 4
    6.  
    7. t = fluid.DistributeTranspiler()
    8. t.transpile(trainer_id, pservers=pserver_endpoints, trainers=trainers)
    9. pserver_program = t.get_pserver_program(current_endpoint)
    10. pserver_startup_program = t.get_startup_program(current_endpoint,
    11. pserver_program)

    DistributeTranspilerConfig

    SourceEnglish

    • class paddle.fluid.transpiler.DistributeTranspilerConfig
    • slicevar_up(_bool)
    • 为Pserver将张量切片, 默认为True

    • splitmethod(_PSDispatcher)

    • 可使用 RoundRobin 或者 HashName

    注意: 尝试选择最佳方法来达到负载均衡。

    • minblock_size(_int)
    • 最小数据块的大小

    注意: 根据:https://github.com/PaddlePaddle/Paddle/issues/8638#issuecomment-369912156 , 当数据块大小超过2MB时,我们可以有效地使用带宽。如果你想更改它,请详细查看slice_variable函数。

    代码示例

    1. config = fluid.DistributeTranspilerConfig()
    2. config.slice_var_up = True

    HashName

    SourceEnglish

    • class paddle.fluid.transpiler.HashName(pserver_endpoints)
    • 使用 python Hash() 函数将变量名散列到多个pserver终端。

    • 参数:

      • pserver_endpoints (list) - endpoint (ip:port)的 list代码示例
    1. pserver_endpoints = [“127.0.0.1:6007”, 127.0.0.1:6008”]
    2. vars = [“var1”,”var2”,”var3”,”var4”,”var5”]
    3. rr = RoundRobin(pserver_endpoints)
    4. rr.dispatch(vars)

    memory_optimize

    SourceEnglish

    • paddle.fluid.transpiler.memoryoptimize(_input_program, skip_opt_set=None, print_log=False, level=0, skip_grads=False)
    • 历史遗留内存优化策略,通过在不同operators之间重用可变内存来减少总内存消耗。用一个简单的例子来解释该算法:

    c = a + b # 假设此处是最后一次使用ad = b * c

    因为在“c = a + b”之后将不再使用a,并且a和d的大小相同,所有我们可以使用变量a来替换变量d,即实际上我们可以将上面的代码优化为如下所示:

    c = a + ba = b * c

    请注意,在这个历史遗留设计中,我们使用变量a直接替换d,这意味着在调用此API之后,某些变量可能会消失,而某些变量可能会保留非预期值,如在上面的例子中,实际上执行代码后a保持d的值。

    因此,为了防止重要变量在优化中被重用/删除,我们提供skip_opt_set用于指定变量白名单。skip_opt_set中的变量不受memory_optimize API的影响。

    注意:此API已弃用,请避免在新代码中使用它。不支持会创建子块的运算符,如While,IfElse等。

    • 参数:
      • input_program (str) – 输入Program。
      • skip_opt_set (set) – set中的vars将不被内存优化。
      • print_log (bool) – 是否打印debug日志。
      • level (int) - 0或1,0代表我们仅在a.size == b.size时用b替换a,1代表我们可以在a.size <= b.size时用b替换a返回: None

    代码示例

    1. import paddle.fluid as fluid
    2. main_prog = fluid.Program()
    3. startup_prog = fluid.Program()
    4.  
    5. place = fluid.CPUPlace()
    6. exe = fluid.Executor(place)
    7.  
    8. exe.run(startup_prog)
    9. fluid.memory_optimize(main_prog)

    release_memory

    SourceEnglish

    • paddle.fluid.transpiler.releasememory(_input_program, skip_opt_set=None)
    • 该函数可以调整输入program,插入 delete_op 删除算子,提前删除不需要的变量。改动是在变量本身上进行的。

    提醒 : 该API还在试验阶段,会在后期版本中删除。不建议用户使用。

    • 参数:
      • input_program (Program) – 在此program中插入 delete_op
      • skip_opt_set (set) – 在内存优化时跳过的变量的集合返回: None

    代码示例

    1. import paddle.fluid as fluid
    2. # 构建网络
    3. # ...
    4.  
    5. # 已弃用的API
    6. fluid.release_memory(fluid.default_main_program())

    RoundRobin

    SourceEnglish

    • class paddle.fluid.transpiler.RoundRobin(pserver_endpoints)
    • 使用 RondRobin 方法将变量分配给服务器端点。

    RondRobin

    • 参数:
      • pserver_endpoints (list) - endpoint (ip:port)的 list代码示例
    1. pserver_endpoints = [“127.0.0.1:6007”, 127.0.0.1:6008”]
    2. vars = [“var1”,”var2”,”var3”,”var4”,”var5”]
    3. rr = RoundRobin(pserver_endpoints)
    4. rr.dispatch(vars)