transpiler_cn.rst 12.1 KB
Newer Older
H
1207  
Hao Wang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
#################
 fluid.transpiler
#################



.. _cn_api_fluid_transpiler_DistributeTranspiler:

DistributeTranspiler
-------------------------------

.. py: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分布式模式。 




**代码示例**

R
RaindragonD 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
.. code-block:: python

    x = fluid.layers.data(name='x', shape=[13], dtype='float32')
    y = fluid.layers.data(name='y', shape=[1], dtype='float32')
    y_predict = fluid.layers.fc(input=x, size=1, act=None)

    cost = fluid.layers.square_error_cost(input=y_predict, label=y)
    avg_loss = fluid.layers.mean(cost)

    sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.001)
    sgd_optimizer.minimize(avg_loss)

    # pserver 模式下
    pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
    trainer_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
    current_endpoint = "192.168.0.1:6174"
    trainer_id = 0
    trainers = 4
    role = "PSERVER"
    t = fluid.DistributeTranspiler()
    t.transpile(
         trainer_id, pservers=pserver_endpoints, trainers=trainers)
    if role == "PSERVER":
         pserver_program = t.get_pserver_program(current_endpoint)
         pserver_startup_program = t.get_startup_program(current_endpoint,
                                                        pserver_program)
    elif role == "TRAINER":
         trainer_program = t.get_trainer_program()

    # nccl2 模式下
    trainer_num = 2
    trainer_id = 0
    config = fluid.DistributeTranspilerConfig()
    config.mode = "nccl2"
    trainer_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
    t = fluid.DistributeTranspiler(config=config)
    t.transpile(trainer_id=trainer_id, trainers=trainer_endpoints, current_endpoint="192.168.0.1:6174")
    exe = fluid.ParallelExecutor(
        use_cuda=True,
        loss_name=avg_loss.name,
        num_trainers=trainer_num,
        trainer_id=trainer_id
    )
H
1207  
Hao Wang 已提交
68 69 70 71 72



.. py:method:: 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')

R
RaindragonD 已提交
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
该方法可以运行该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模式不使用该参数

**代码示例**

.. code-block:: python

    transpiler = fluid.DistributeTranspiler()
    t.transpile(
        trainer_id=0,
        pservers="127.0.0.1:7000,127.0.0.1:7001",
        trainers=2,
        sync_mode=False,
        current_endpoint="127.0.0.1:7000")
H
1207  
Hao Wang 已提交
96 97 98 99 100 101 102


.. py:method:: get_trainer_program(wait_port=True)


该方法可以得到Trainer侧的program。

R
RaindragonD 已提交
103
返回:    Trainer侧的program
H
1207  
Hao Wang 已提交
104

R
RaindragonD 已提交
105
返回类型:    Program
H
1207  
Hao Wang 已提交
106

R
RaindragonD 已提交
107 108 109 110 111 112 113 114 115 116 117 118
**代码示例**

.. code-block:: python

        import paddle.fluid as fluid
        # 这是一个示例,请根据你的情况更改endpoint
        pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
        trainer_id = 0
        trainers = 4
        t = fluid.DistributeTranspiler()
        t.transpile(trainer_id, trainers=trainers, pservers=pserver_endpoints)
        trainer_program = t.get_trainer_program()
H
1207  
Hao Wang 已提交
119 120 121 122 123 124 125


.. py:method:: get_pserver_program(endpoint)


该方法可以得到Pserver(参数服务器)侧的程序
 
R
RaindragonD 已提交
126 127
参数:    
    - **endpoint** (str) – 当前Pserver终端
H
1207  
Hao Wang 已提交
128
 
R
RaindragonD 已提交
129
返回:    当前Pserver需要执行的program
H
1207  
Hao Wang 已提交
130

R
RaindragonD 已提交
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
返回类型:    Program

**代码示例**

.. code-block:: python

          import paddle.fluid as fluid
          # 这是一个示例,请根据你的情况更改endpoint
          pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
          current_endpoint = "192.168.0.1:6174"
          trainer_id = 0
          trainers = 4
          t = fluid.DistributeTranspiler()
          t.transpile(
               trainer_id, pservers=pserver_endpoints, trainers=trainers)
          pserver_program = t.get_pserver_program(current_endpoint)
H
1207  
Hao Wang 已提交
147 148 149 150 151 152 153


.. py:method:: get_pserver_programs(endpoint)


该方法可以得到Pserver侧用于分布式训练的 ``main_program`` 和 ``startup_program`` 。

R
RaindragonD 已提交
154 155
参数:    
    - **endpoint** (str) – 当前Pserver终端
H
1207  
Hao Wang 已提交
156

R
RaindragonD 已提交
157
返回:    (main_program, startup_program), “Program”类型的元组
H
1207  
Hao Wang 已提交
158

R
RaindragonD 已提交
159
返回类型:    tuple 
H
1207  
Hao Wang 已提交
160 161
 
 
R
RaindragonD 已提交
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
**代码示例**

.. code-block:: python

          import paddle.fluid as fluid
          # 这是一个示例,请根据你的情况更改endpoint
          pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
          current_endpoint = "192.168.0.1:6174"
          trainer_id = 0
          trainers = 4
          t = fluid.DistributeTranspiler()
          t.transpile(
               trainer_id, pservers=pserver_endpoints, trainers=trainers)
          pserver_program, pserver_startup_program = t.get_pserver_programs(current_endpoint)


H
1207  
Hao Wang 已提交
178 179 180 181 182 183
.. py:method:: get_startup_program(endpoint, pserver_program=None, startup_program=None)


**该函数已停止使用**
获取当前Pserver的startup_program,如果有多个被分散到不同blocks的变量,则修改operator的输入变量。

R
RaindragonD 已提交
184 185 186 187
参数:    
    - **endpoint** (str) – 当前Pserver终端
    - **pserver_program** (Program) – 已停止使用。 先调用get_pserver_program
    - **startup_program** (Program) – 已停止使用。应在初始化时传入startup_program
H
1207  
Hao Wang 已提交
188

R
RaindragonD 已提交
189
返回:    Pserver侧的startup_program
H
1207  
Hao Wang 已提交
190

R
RaindragonD 已提交
191
返回类型:    Program
H
1207  
Hao Wang 已提交
192

R
RaindragonD 已提交
193
**代码示例**
H
1207  
Hao Wang 已提交
194

R
RaindragonD 已提交
195
.. code-block:: python
H
1207  
Hao Wang 已提交
196

R
RaindragonD 已提交
197 198 199 200 201 202 203 204 205 206 207
          pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
          trainer_endpoints = "192.168.0.1:6174,192.168.0.2:6174"
          current_endpoint = "192.168.0.1:6174"
          trainer_id = 0
          trainers = 4
           
          t = fluid.DistributeTranspiler()
          t.transpile(trainer_id, pservers=pserver_endpoints, trainers=trainers)
          pserver_program = t.get_pserver_program(current_endpoint)
          pserver_startup_program = t.get_startup_program(current_endpoint,
                                                          pserver_program)
H
1207  
Hao Wang 已提交
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232



.. _cn_api_fluid_transpiler_DistributeTranspilerConfig:

DistributeTranspilerConfig
-------------------------------

.. py:class:: paddle.fluid.transpiler.DistributeTranspilerConfig

.. py:method:: slice_var_up (bool)

为Pserver将张量切片, 默认为True

.. py:method:: split_method (PSDispatcher)

可使用 RoundRobin 或者 HashName

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


.. py:attribute:: min_block_size (int)

最小数据块的大小

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

R
RaindragonD 已提交
235
**代码示例**
H
1207  
Hao Wang 已提交
236

R
RaindragonD 已提交
237
.. code-block:: python
H
1207  
Hao Wang 已提交
238

R
RaindragonD 已提交
239 240
        config = fluid.DistributeTranspilerConfig()
        config.slice_var_up = True
H
1207  
Hao Wang 已提交
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255



.. _cn_api_fluid_transpiler_HashName:

HashName
-------------------------------

.. py:class:: paddle.fluid.transpiler.HashName(pserver_endpoints)

使用 python ``Hash()`` 函数将变量名散列到多个pserver终端。

参数:
  - **pserver_endpoints** (list) - endpoint (ip:port)的 list 

R
RaindragonD 已提交
256
**代码示例**
H
1207  
Hao Wang 已提交
257

R
RaindragonD 已提交
258
.. code-block:: python
H
1207  
Hao Wang 已提交
259

R
RaindragonD 已提交
260 261 262 263
          pserver_endpoints = [“127.0.0.1:6007”, “127.0.0.1:6008”]
          vars = [“var1”,”var2”,”var3”,”var4”,”var5”]
          rr = RoundRobin(pserver_endpoints)
          rr.dispatch(vars)
H
1207  
Hao Wang 已提交
264 265 266 267 268 269 270 271 272 273 274




.. _cn_api_fluid_transpiler_memory_optimize:

memory_optimize
-------------------------------

.. py:function:: paddle.fluid.transpiler.memory_optimize(input_program, skip_opt_set=None, print_log=False, level=0, skip_grads=False)

R
RaindragonD 已提交
275 276 277 278 279 280 281 282 283 284
历史遗留内存优化策略,通过在不同operators之间重用可变内存来减少总内存消耗。
用一个简单的例子来解释该算法:

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

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

c = a + b
a = b * c
H
1207  
Hao Wang 已提交
285

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

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

注意:
此API已弃用,请避免在新代码中使用它。
不支持会创建子块的运算符,如While,IfElse等。
H
1207  
Hao Wang 已提交
294 295 296 297 298

参数:
  - **input_program** (str) – 输入Program。
  - **skip_opt_set** (set) – set中的vars将不被内存优化。
  - **print_log** (bool) – 是否打印debug日志。
R
RaindragonD 已提交
299
  - **level** (int) - 0或1,0代表我们仅在a.size == b.size时用b替换a,1代表我们可以在a.size <= b.size时用b替换a
H
1207  
Hao Wang 已提交
300 301 302

返回: None

R
RaindragonD 已提交
303
**代码示例**
H
1207  
Hao Wang 已提交
304

R
RaindragonD 已提交
305
.. code-block:: python
H
1207  
Hao Wang 已提交
306

R
RaindragonD 已提交
307 308 309 310 311 312 313 314 315
          import paddle.fluid as fluid
          main_prog = fluid.Program()
          startup_prog = fluid.Program()
           
          place = fluid.CPUPlace()
          exe = fluid.Executor(place)
           
          exe.run(startup_prog)
          fluid.memory_optimize(main_prog)
H
1207  
Hao Wang 已提交
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338




.. _cn_api_fluid_transpiler_release_memory:

release_memory
-------------------------------

.. py:function:: paddle.fluid.transpiler.release_memory(input_program, skip_opt_set=None) 


该函数可以调整输入program,插入 ``delete_op`` 删除算子,提前删除不需要的变量。
改动是在变量本身上进行的。

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

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

返回: None

R
RaindragonD 已提交
339
**代码示例**
H
1207  
Hao Wang 已提交
340

R
RaindragonD 已提交
341
.. code-block:: python
H
1207  
Hao Wang 已提交
342

R
RaindragonD 已提交
343 344 345 346 347 348
        import paddle.fluid as fluid
        # 构建网络
        # ...
        
        # 已弃用的API
        fluid.release_memory(fluid.default_main_program())
H
1207  
Hao Wang 已提交
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373











.. _cn_api_fluid_transpiler_RoundRobin:

RoundRobin
-------------------------------

.. py:class:: paddle.fluid.transpiler.RoundRobin(pserver_endpoints)

使用 ``RondRobin`` 方法将变量分配给服务器端点。

`RondRobin <https://en.wikipedia.org/wiki/Round-robin_scheduling>`_

参数:
  - **pserver_endpoints** (list) - endpoint (ip:port)的 list 
 
R
RaindragonD 已提交
374
**代码示例**
H
1207  
Hao Wang 已提交
375

R
RaindragonD 已提交
376
.. code-block:: python
H
1207  
Hao Wang 已提交
377

R
RaindragonD 已提交
378 379 380 381
          pserver_endpoints = [“127.0.0.1:6007”, “127.0.0.1:6008”]
          vars = [“var1”,”var2”,”var3”,”var4”,”var5”]
          rr = RoundRobin(pserver_endpoints)
          rr.dispatch(vars)
H
1207  
Hao Wang 已提交
382 383 384 385