From 39d1a5f69aa389cdaea36cd92055f776a472b8cb Mon Sep 17 00:00:00 2001 From: Travis CI Date: Tue, 6 Mar 2018 04:01:27 +0000 Subject: [PATCH] Deploy to GitHub Pages: d398b96823e6df38897fc881b5b71d7bc66013dc --- develop/api_doc/.buildinfo | 2 +- develop/doc/.buildinfo | 2 +- develop/doc/_images/control_flow_graph.png | Bin 85311 -> 0 bytes develop/doc/_images/dataflow_equations.png | Bin 23064 -> 0 bytes develop/doc/_images/deep_learning.png | Bin 40605 -> 0 bytes develop/doc/_images/fluid-compiler.png | Bin 124118 -> 0 bytes .../graph_construction_example_all.png | Bin 57513 -> 0 bytes ..._construction_example_forward_backward.png | Bin 50107 -> 0 bytes ...raph_construction_example_forward_only.png | Bin 30790 -> 0 bytes develop/doc/_images/pprof_1.png | Bin 352710 -> 0 bytes develop/doc/_images/pprof_2.png | Bin 194000 -> 0 bytes develop/doc/_images/trainer.png | Bin 145107 -> 0 bytes develop/doc/_sources/design/api.md.txt | 262 -------- .../design/auto_gradient_check.md.txt | 150 ----- develop/doc/_sources/design/backward.md.txt | 158 ----- develop/doc/_sources/design/block.md.txt | 336 ---------- .../design/build_system/README.md.txt | 152 ----- .../design/cluster_train/README.md.txt | 182 ------ .../design/cluster_train/checkpointing.md.txt | 44 -- .../design/cluster_train/data_dispatch.md.txt | 160 ----- .../large_model_dist_train.md.txt | 101 --- .../design/cluster_train/master_server.md.txt | 91 --- .../cluster_train/pserver_client.md.txt | 171 ----- .../remote_parameter_updater.md.txt | 21 - .../design/cluster_train/save_model.md.txt | 111 ---- .../design/cluster_train/submit-job.md.txt | 127 ---- .../design/concurrent_programming.md.txt | 163 ----- .../_sources/design/cpp_data_feeding.md.txt | 79 --- develop/doc/_sources/design/csp.md.txt | 224 ------- .../distributed_architecture.md.txt | 197 ------ .../design/dist_refactor/multi_cpu.md.txt | 43 -- .../dist_refactor/parameter_server.md.txt | 96 --- develop/doc/_sources/design/error_clip.md.txt | 92 --- develop/doc/_sources/design/evaluator.md.txt | 58 -- develop/doc/_sources/design/executor.md.txt | 29 - .../design/file_manager/README.md.txt | 87 --- .../design/file_manager/pfs/pfsclient.md.txt | 129 ---- develop/doc/_sources/design/float16.md.txt | 105 ---- develop/doc/_sources/design/fluid.md.txt | 114 ---- .../doc/_sources/design/fluid_compiler.md.txt | 110 ---- .../design/functions_operators_layers.md.txt | 100 --- develop/doc/_sources/design/gan_api.md.txt | 253 -------- develop/doc/_sources/design/graph.md.txt | 70 --- .../doc/_sources/design/graph_survey.md.txt | 232 ------- develop/doc/_sources/design/if_else_op.md.txt | 51 -- .../doc/_sources/design/infer_var_type.md.txt | 78 --- .../_sources/design/kernel_hint_design.md.txt | 57 -- .../_sources/design/kernel_selection.md.txt | 99 --- .../design/memory_optimization.md.txt | 217 ------- .../doc/_sources/design/mkl/mkl_packed.md.txt | 108 ---- develop/doc/_sources/design/mkl/mkldnn.md.txt | 210 ------- .../_sources/design/mkl/mkldnn_fluid.md.txt | 149 ----- .../doc/_sources/design/model_format.md.txt | 36 -- .../00.why_plain_c.md.txt | 118 ---- .../01.inference_implementation.md.txt | 131 ---- .../design/operator_kernel_type.md.txt | 91 --- develop/doc/_sources/design/ops/rnn.md.txt | 153 ----- .../design/ops/sequence_decoder.md.txt | 229 ------- develop/doc/_sources/design/optimizer.md.txt | 91 --- .../doc/_sources/design/paddle_nccl.md.txt | 65 -- .../doc/_sources/design/parallel_do.md.txt | 163 ----- .../_sources/design/parameter_average.md.txt | 72 --- .../_sources/design/parameters_in_cpp.md.txt | 41 -- develop/doc/_sources/design/profiler.md.txt | 97 --- develop/doc/_sources/design/program.md.txt | 139 ---- develop/doc/_sources/design/prune.md.txt | 63 -- develop/doc/_sources/design/python_api.md.txt | 304 --------- .../doc/_sources/design/reader/README.md.txt | 206 ------ .../_sources/design/refactorization.md.txt | 249 -------- .../_sources/design/register_grad_op.md.txt | 92 --- .../doc/_sources/design/regularization.md.txt | 72 --- .../_sources/design/releasing_process.md.txt | 90 --- develop/doc/_sources/design/scope.md.txt | 124 ---- .../doc/_sources/design/selected_rows.md.txt | 74 --- .../_sources/design/simple_op_design.md.txt | 202 ------ .../design/speech/deep_speech_2.md.txt | 168 ----- .../_sources/design/support_new_device.md.txt | 240 ------- develop/doc/_sources/design/switch.md.txt | 31 - .../doc/_sources/design/tensor_array.md.txt | 271 -------- develop/doc/_sources/design/var_desc.md.txt | 81 --- develop/doc/_sources/dev/index_en.rst.txt | 1 + develop/doc/_sources/dev/new_op_en.md.txt | 336 ---------- .../doc/_sources/dev/new_op_kernel_en.md.txt | 121 ---- develop/doc/_sources/dev/use_eigen_en.md.txt | 146 ----- .../cluster/fluid_cluster_train_en.md.txt | 153 ----- develop/doc/_sources/howto/index_en.rst.txt | 1 + .../optimization/cpu_profiling_en.md.txt | 196 ------ .../optimization/gpu_profiling_en.rst.txt | 6 +- develop/doc/_sources/howto/read_source.md.txt | 67 -- .../cross_compiling_for_android_en.md.txt | 189 ------ .../mobile/cross_compiling_for_ios_en.md.txt | 120 ---- .../cross_compiling_for_raspberry_en.md.txt | 62 -- .../survey/cluster_bootstrapping_tools.md.txt | 71 --- .../build_from_source_en.html | 7 + .../build_and_install/docker_install_en.html | 7 + develop/doc/build_and_install/index_en.html | 7 + .../doc/build_and_install/pip_install_en.html | 7 + develop/doc/design/api.html | 487 --------------- develop/doc/design/auto_gradient_check.html | 423 ------------- develop/doc/design/backward.html | 394 ------------ develop/doc/design/block.html | 559 ----------------- develop/doc/design/build_system/README.html | 401 ------------ develop/doc/design/cluster_train/README.html | 430 ------------- .../design/cluster_train/checkpointing.html | 305 --------- .../design/cluster_train/data_dispatch.html | 406 ------------ .../cluster_train/large_model_dist_train.html | 343 ---------- .../design/cluster_train/master_server.html | 341 ---------- .../design/cluster_train/pserver_client.html | 418 ------------- .../remote_parameter_updater.html | 273 -------- .../doc/design/cluster_train/save_model.html | 360 ----------- .../doc/design/cluster_train/submit-job.html | 389 ------------ .../doc/design/concurrent_programming.html | 413 ------------ develop/doc/design/cpp_data_feeding.html | 322 ---------- develop/doc/design/csp.html | 451 ------------- .../distributed_architecture.html | 424 ------------- .../doc/design/dist_refactor/multi_cpu.html | 306 --------- .../dist_refactor/parameter_server.html | 354 ----------- develop/doc/design/error_clip.html | 332 ---------- develop/doc/design/evaluator.html | 312 --------- develop/doc/design/executor.html | 284 --------- develop/doc/design/file_manager/README.html | 365 ----------- .../design/file_manager/pfs/pfsclient.html | 391 ------------ develop/doc/design/float16.html | 370 ----------- develop/doc/design/fluid.html | 350 ----------- develop/doc/design/fluid_compiler.html | 352 ----------- .../design/functions_operators_layers.html | 331 ---------- develop/doc/design/gan_api.html | 518 --------------- develop/doc/design/graph.html | 312 --------- develop/doc/design/graph_survey.html | 445 ------------- develop/doc/design/if_else_op.html | 301 --------- develop/doc/design/infer_var_type.html | 318 ---------- develop/doc/design/kernel_hint_design.html | 306 --------- develop/doc/design/kernel_selection.html | 337 ---------- develop/doc/design/memory_optimization.html | 446 ------------- develop/doc/design/mkl/mkl_packed.html | 380 ----------- develop/doc/design/mkl/mkldnn.html | 461 -------------- develop/doc/design/mkl/mkldnn_fluid.html | 405 ------------ develop/doc/design/model_format.html | 285 --------- .../00.why_plain_c.html | 391 ------------ .../01.inference_implementation.html | 390 ------------ develop/doc/design/operator_kernel_type.html | 327 ---------- develop/doc/design/ops/rnn.html | 386 ------------ develop/doc/design/ops/sequence_decoder.html | 461 -------------- develop/doc/design/optimizer.html | 341 ---------- develop/doc/design/paddle_nccl.html | 319 ---------- develop/doc/design/parallel_do.html | 410 ------------ develop/doc/design/parameter_average.html | 331 ---------- develop/doc/design/parameters_in_cpp.html | 290 --------- develop/doc/design/profiler.html | 343 ---------- develop/doc/design/program.html | 378 ----------- develop/doc/design/prune.html | 312 --------- develop/doc/design/python_api.html | 526 ---------------- develop/doc/design/reader/README.html | 438 ------------- develop/doc/design/refactorization.html | 583 ----------------- develop/doc/design/register_grad_op.html | 328 ---------- develop/doc/design/regularization.html | 320 ---------- develop/doc/design/releasing_process.html | 363 ----------- develop/doc/design/scope.html | 373 ----------- develop/doc/design/selected_rows.html | 319 ---------- develop/doc/design/simple_op_design.html | 441 ------------- develop/doc/design/speech/deep_speech_2.html | 460 -------------- develop/doc/design/support_new_device.html | 453 -------------- develop/doc/design/switch.html | 283 --------- develop/doc/design/tensor_array.html | 503 --------------- develop/doc/design/var_desc.html | 327 ---------- develop/doc/dev/contribute_to_paddle_en.html | 7 + develop/doc/dev/index_en.html | 8 + develop/doc/dev/new_layer_en.html | 27 +- develop/doc/dev/new_op_en.html | 561 ----------------- develop/doc/dev/new_op_kernel_en.html | 366 ----------- develop/doc/dev/use_eigen_en.html | 380 ----------- develop/doc/dev/write_docs_en.html | 11 +- .../doc/faq/build_and_install/index_en.html | 7 + develop/doc/faq/cluster/index_en.html | 7 + develop/doc/faq/index_en.html | 11 +- develop/doc/faq/local/index_en.html | 7 + develop/doc/faq/model/index_en.html | 7 + develop/doc/faq/parameter/index_en.html | 7 + develop/doc/genindex.html | 7 + .../getstarted/concepts/use_concepts_en.html | 7 + develop/doc/getstarted/index_en.html | 7 + develop/doc/getstarted/quickstart_en.html | 7 + .../doc/howto/capi/compile_paddle_lib_en.html | 29 +- develop/doc/howto/capi/index_en.html | 27 +- .../capi/organization_of_the_inputs_en.html | 29 +- .../doc/howto/capi/workflow_of_capi_en.html | 29 +- .../doc/howto/cluster/cmd_argument_en.html | 7 + .../howto/cluster/fluid_cluster_train_en.html | 386 ------------ develop/doc/howto/cluster/index_en.html | 7 + .../cluster/multi_cluster/fabric_en.html | 7 + .../howto/cluster/multi_cluster/index_en.html | 7 + .../cluster/multi_cluster/k8s_aws_en.html | 11 +- .../multi_cluster/k8s_distributed_en.html | 7 + .../howto/cluster/multi_cluster/k8s_en.html | 7 + .../cluster/multi_cluster/openmpi_en.html | 7 + .../multi_cluster/src/k8s_data/README.html | 7 + .../multi_cluster/src/k8s_train/README.html | 7 + .../doc/howto/cluster/preparations_en.html | 7 + .../doc/howto/cmd_parameter/arguments_en.html | 7 + .../cmd_parameter/detail_introduction_en.html | 7 + develop/doc/howto/cmd_parameter/index_en.html | 7 + .../doc/howto/cmd_parameter/use_case_en.html | 7 + develop/doc/howto/index_en.html | 8 + .../howto/optimization/cpu_profiling_en.html | 420 ------------- .../howto/optimization/gpu_profiling_en.html | 7 + develop/doc/howto/read_source.html | 334 ---------- .../doc/howto/rnn/hierarchical_layer_en.html | 7 + .../howto/rnn/hrnn_rnn_api_compare_en.html | 7 + develop/doc/howto/rnn/index_en.html | 11 +- develop/doc/howto/rnn/recurrent_group_en.html | 7 + develop/doc/howto/rnn/rnn_config_en.html | 7 + develop/doc/index_en.html | 7 + .../cross_compiling_for_android_en.html | 427 ------------- .../mobile/cross_compiling_for_ios_en.html | 369 ----------- .../cross_compiling_for_raspberry_en.html | 303 --------- develop/doc/objects.inv | Bin 3384 -> 1516 bytes develop/doc/search.html | 7 + develop/doc/searchindex.js | 2 +- .../survey/cluster_bootstrapping_tools.html | 357 ----------- develop/doc_cn/.buildinfo | 2 +- develop/doc_cn/_images/control_flow_graph.png | Bin 85311 -> 0 bytes develop/doc_cn/_images/dataflow_equations.png | Bin 23064 -> 0 bytes develop/doc_cn/_images/deep_learning.png | Bin 40605 -> 0 bytes develop/doc_cn/_images/fluid-compiler.png | Bin 124118 -> 0 bytes .../graph_construction_example_all.png | Bin 57513 -> 0 bytes ..._construction_example_forward_backward.png | Bin 50107 -> 0 bytes ...raph_construction_example_forward_only.png | Bin 30790 -> 0 bytes develop/doc_cn/_images/pprof_1.png | Bin 352710 -> 0 bytes develop/doc_cn/_images/pprof_2.png | Bin 194000 -> 0 bytes develop/doc_cn/_sources/design/api.md.txt | 262 -------- .../design/auto_gradient_check.md.txt | 150 ----- .../doc_cn/_sources/design/backward.md.txt | 158 ----- develop/doc_cn/_sources/design/block.md.txt | 336 ---------- .../design/build_system/README.md.txt | 152 ----- .../design/cluster_train/README.md.txt | 182 ------ .../design/cluster_train/checkpointing.md.txt | 44 -- .../design/cluster_train/data_dispatch.md.txt | 160 ----- .../large_model_dist_train.md.txt | 101 --- .../design/cluster_train/master_server.md.txt | 91 --- .../cluster_train/pserver_client.md.txt | 171 ----- .../remote_parameter_updater.md.txt | 21 - .../design/cluster_train/save_model.md.txt | 111 ---- .../design/cluster_train/submit-job.md.txt | 127 ---- .../design/concurrent_programming.md.txt | 163 ----- .../_sources/design/cpp_data_feeding.md.txt | 79 --- develop/doc_cn/_sources/design/csp.md.txt | 224 ------- .../distributed_architecture.md.txt | 197 ------ .../design/dist_refactor/multi_cpu.md.txt | 43 -- .../dist_refactor/parameter_server.md.txt | 96 --- .../doc_cn/_sources/design/error_clip.md.txt | 92 --- .../doc_cn/_sources/design/evaluator.md.txt | 58 -- .../doc_cn/_sources/design/executor.md.txt | 29 - .../design/file_manager/README.md.txt | 87 --- .../design/file_manager/pfs/pfsclient.md.txt | 129 ---- develop/doc_cn/_sources/design/float16.md.txt | 105 ---- develop/doc_cn/_sources/design/fluid.md.txt | 114 ---- .../_sources/design/fluid_compiler.md.txt | 110 ---- .../design/functions_operators_layers.md.txt | 100 --- develop/doc_cn/_sources/design/gan_api.md.txt | 253 -------- develop/doc_cn/_sources/design/graph.md.txt | 70 --- .../_sources/design/graph_survey.md.txt | 232 ------- .../doc_cn/_sources/design/if_else_op.md.txt | 51 -- .../_sources/design/infer_var_type.md.txt | 78 --- .../_sources/design/kernel_hint_design.md.txt | 57 -- .../_sources/design/kernel_selection.md.txt | 99 --- .../design/memory_optimization.md.txt | 217 ------- .../_sources/design/mkl/mkl_packed.md.txt | 108 ---- .../doc_cn/_sources/design/mkl/mkldnn.md.txt | 210 ------- .../_sources/design/mkl/mkldnn_fluid.md.txt | 149 ----- .../_sources/design/model_format.md.txt | 36 -- .../00.why_plain_c.md.txt | 118 ---- .../01.inference_implementation.md.txt | 131 ---- .../design/operator_kernel_type.md.txt | 91 --- develop/doc_cn/_sources/design/ops/rnn.md.txt | 153 ----- .../design/ops/sequence_decoder.md.txt | 229 ------- .../doc_cn/_sources/design/optimizer.md.txt | 91 --- .../doc_cn/_sources/design/paddle_nccl.md.txt | 65 -- .../doc_cn/_sources/design/parallel_do.md.txt | 163 ----- .../_sources/design/parameter_average.md.txt | 72 --- .../_sources/design/parameters_in_cpp.md.txt | 41 -- .../doc_cn/_sources/design/profiler.md.txt | 97 --- develop/doc_cn/_sources/design/program.md.txt | 139 ---- develop/doc_cn/_sources/design/prune.md.txt | 63 -- .../doc_cn/_sources/design/python_api.md.txt | 304 --------- .../_sources/design/reader/README.md.txt | 206 ------ .../_sources/design/refactorization.md.txt | 249 -------- .../_sources/design/register_grad_op.md.txt | 92 --- .../_sources/design/regularization.md.txt | 72 --- .../_sources/design/releasing_process.md.txt | 90 --- develop/doc_cn/_sources/design/scope.md.txt | 124 ---- .../_sources/design/selected_rows.md.txt | 74 --- .../_sources/design/simple_op_design.md.txt | 202 ------ .../design/speech/deep_speech_2.md.txt | 168 ----- .../_sources/design/support_new_device.md.txt | 240 ------- develop/doc_cn/_sources/design/switch.md.txt | 31 - .../_sources/design/tensor_array.md.txt | 271 -------- .../doc_cn/_sources/design/var_desc.md.txt | 81 --- develop/doc_cn/_sources/dev/index_cn.rst.txt | 1 + .../doc_cn/_sources/dev/new_layer_cn.rst.txt | 6 +- develop/doc_cn/_sources/dev/new_op_cn.md.txt | 318 ---------- .../doc_cn/_sources/dev/use_eigen_cn.md.txt | 146 ----- .../optimization/cpu_profiling_cn.md.txt | 155 ----- .../optimization/gpu_profiling_cn.rst.txt | 6 +- .../doc_cn/_sources/howto/read_source.md.txt | 67 -- .../cross_compiling_for_android_cn.md.txt | 187 ------ .../mobile/cross_compiling_for_ios_cn.md.txt | 117 ---- .../cross_compiling_for_raspberry_cn.md.txt | 62 -- .../survey/cluster_bootstrapping_tools.md.txt | 71 --- .../build_from_source_cn.html | 1 + .../build_and_install/docker_install_cn.html | 1 + .../doc_cn/build_and_install/index_cn.html | 1 + .../build_and_install/pip_install_cn.html | 1 + develop/doc_cn/design/api.html | 495 --------------- .../doc_cn/design/auto_gradient_check.html | 431 ------------- develop/doc_cn/design/backward.html | 402 ------------ develop/doc_cn/design/block.html | 567 ----------------- .../doc_cn/design/build_system/README.html | 409 ------------ .../doc_cn/design/cluster_train/README.html | 438 ------------- .../design/cluster_train/checkpointing.html | 313 ---------- .../design/cluster_train/data_dispatch.html | 414 ------------ .../cluster_train/large_model_dist_train.html | 351 ----------- .../design/cluster_train/master_server.html | 349 ----------- .../design/cluster_train/pserver_client.html | 426 ------------- .../remote_parameter_updater.html | 281 --------- .../design/cluster_train/save_model.html | 368 ----------- .../design/cluster_train/submit-job.html | 397 ------------ .../doc_cn/design/concurrent_programming.html | 421 ------------- develop/doc_cn/design/cpp_data_feeding.html | 330 ---------- develop/doc_cn/design/csp.html | 459 -------------- .../distributed_architecture.html | 432 ------------- .../design/dist_refactor/multi_cpu.html | 314 ---------- .../dist_refactor/parameter_server.html | 362 ----------- develop/doc_cn/design/error_clip.html | 340 ---------- develop/doc_cn/design/evaluator.html | 320 ---------- develop/doc_cn/design/executor.html | 292 --------- .../doc_cn/design/file_manager/README.html | 373 ----------- .../design/file_manager/pfs/pfsclient.html | 399 ------------ develop/doc_cn/design/float16.html | 378 ----------- develop/doc_cn/design/fluid.html | 358 ----------- develop/doc_cn/design/fluid_compiler.html | 360 ----------- .../design/functions_operators_layers.html | 339 ---------- develop/doc_cn/design/gan_api.html | 526 ---------------- develop/doc_cn/design/graph.html | 320 ---------- develop/doc_cn/design/graph_survey.html | 453 -------------- develop/doc_cn/design/if_else_op.html | 309 --------- develop/doc_cn/design/infer_var_type.html | 326 ---------- develop/doc_cn/design/kernel_hint_design.html | 314 ---------- develop/doc_cn/design/kernel_selection.html | 345 ---------- .../doc_cn/design/memory_optimization.html | 454 -------------- develop/doc_cn/design/mkl/mkl_packed.html | 388 ------------ develop/doc_cn/design/mkl/mkldnn.html | 469 -------------- develop/doc_cn/design/mkl/mkldnn_fluid.html | 413 ------------ develop/doc_cn/design/model_format.html | 293 --------- .../00.why_plain_c.html | 399 ------------ .../01.inference_implementation.html | 398 ------------ .../doc_cn/design/operator_kernel_type.html | 335 ---------- develop/doc_cn/design/ops/rnn.html | 394 ------------ .../doc_cn/design/ops/sequence_decoder.html | 469 -------------- develop/doc_cn/design/optimizer.html | 349 ----------- develop/doc_cn/design/paddle_nccl.html | 327 ---------- develop/doc_cn/design/parallel_do.html | 418 ------------- develop/doc_cn/design/parameter_average.html | 339 ---------- develop/doc_cn/design/parameters_in_cpp.html | 298 --------- develop/doc_cn/design/profiler.html | 351 ----------- develop/doc_cn/design/program.html | 386 ------------ develop/doc_cn/design/prune.html | 320 ---------- develop/doc_cn/design/python_api.html | 534 ---------------- develop/doc_cn/design/reader/README.html | 446 ------------- develop/doc_cn/design/refactorization.html | 591 ------------------ develop/doc_cn/design/register_grad_op.html | 336 ---------- develop/doc_cn/design/regularization.html | 328 ---------- develop/doc_cn/design/releasing_process.html | 371 ----------- develop/doc_cn/design/scope.html | 381 ----------- develop/doc_cn/design/selected_rows.html | 327 ---------- develop/doc_cn/design/simple_op_design.html | 449 ------------- .../doc_cn/design/speech/deep_speech_2.html | 468 -------------- develop/doc_cn/design/support_new_device.html | 461 -------------- develop/doc_cn/design/switch.html | 291 --------- develop/doc_cn/design/tensor_array.html | 511 --------------- develop/doc_cn/design/var_desc.html | 335 ---------- .../doc_cn/dev/contribute_to_paddle_cn.html | 1 + develop/doc_cn/dev/index_cn.html | 2 + develop/doc_cn/dev/new_layer_cn.html | 27 +- develop/doc_cn/dev/new_op_cn.html | 559 ----------------- develop/doc_cn/dev/use_eigen_cn.html | 388 ------------ develop/doc_cn/dev/write_docs_cn.html | 5 +- .../faq/build_and_install/index_cn.html | 1 + develop/doc_cn/faq/cluster/index_cn.html | 1 + develop/doc_cn/faq/index_cn.html | 5 +- develop/doc_cn/faq/local/index_cn.html | 1 + develop/doc_cn/faq/model/index_cn.html | 1 + develop/doc_cn/faq/parameter/index_cn.html | 1 + develop/doc_cn/genindex.html | 1 + .../getstarted/concepts/use_concepts_cn.html | 1 + develop/doc_cn/getstarted/index_cn.html | 1 + develop/doc_cn/getstarted/quickstart_cn.html | 1 + .../howto/capi/compile_paddle_lib_cn.html | 1 + develop/doc_cn/howto/capi/index_cn.html | 1 + .../capi/organization_of_the_inputs_cn.html | 1 + .../howto/capi/workflow_of_capi_cn.html | 1 + .../doc_cn/howto/cluster/cmd_argument_cn.html | 1 + develop/doc_cn/howto/cluster/index_cn.html | 1 + .../cluster/multi_cluster/fabric_cn.html | 1 + .../howto/cluster/multi_cluster/index_cn.html | 1 + .../cluster/multi_cluster/k8s_aws_cn.html | 1 + .../howto/cluster/multi_cluster/k8s_cn.html | 1 + .../multi_cluster/k8s_distributed_cn.html | 1 + .../cluster/multi_cluster/openmpi_cn.html | 1 + .../multi_cluster/src/k8s_data/README.html | 1 + .../multi_cluster/src/k8s_train/README.html | 1 + .../doc_cn/howto/cluster/preparations_cn.html | 1 + .../howto/cmd_parameter/arguments_cn.html | 1 + .../cmd_parameter/detail_introduction_cn.html | 1 + .../doc_cn/howto/cmd_parameter/index_cn.html | 1 + .../howto/cmd_parameter/use_case_cn.html | 1 + develop/doc_cn/howto/index_cn.html | 1 + .../howto/optimization/cpu_profiling_cn.html | 382 ----------- .../howto/optimization/gpu_profiling_cn.html | 1 + develop/doc_cn/howto/read_source.html | 342 ---------- .../howto/rnn/hierarchical_layer_cn.html | 1 + .../howto/rnn/hrnn_rnn_api_compare_cn.html | 395 ++++++++++++ develop/doc_cn/howto/rnn/index_cn.html | 1 + .../doc_cn/howto/rnn/recurrent_group_cn.html | 1 + develop/doc_cn/howto/rnn/rnn_config_cn.html | 1 + develop/doc_cn/index_cn.html | 1 + .../cross_compiling_for_android_cn.html | 442 ------------- .../mobile/cross_compiling_for_ios_cn.html | 377 ----------- .../cross_compiling_for_raspberry_cn.html | 311 --------- develop/doc_cn/objects.inv | Bin 3679 -> 1841 bytes develop/doc_cn/search.html | 1 + develop/doc_cn/searchindex.js | 2 +- .../survey/cluster_bootstrapping_tools.html | 365 ----------- 432 files changed, 905 insertions(+), 79654 deletions(-) delete mode 100644 develop/doc/_images/control_flow_graph.png delete mode 100644 develop/doc/_images/dataflow_equations.png delete mode 100644 develop/doc/_images/deep_learning.png delete mode 100644 develop/doc/_images/fluid-compiler.png delete mode 100644 develop/doc/_images/graph_construction_example_all.png delete mode 100644 develop/doc/_images/graph_construction_example_forward_backward.png delete mode 100644 develop/doc/_images/graph_construction_example_forward_only.png delete mode 100644 develop/doc/_images/pprof_1.png delete mode 100644 develop/doc/_images/pprof_2.png delete mode 100644 develop/doc/_images/trainer.png delete mode 100644 develop/doc/_sources/design/api.md.txt delete mode 100644 develop/doc/_sources/design/auto_gradient_check.md.txt delete mode 100644 develop/doc/_sources/design/backward.md.txt delete mode 100644 develop/doc/_sources/design/block.md.txt delete mode 100644 develop/doc/_sources/design/build_system/README.md.txt delete mode 100644 develop/doc/_sources/design/cluster_train/README.md.txt delete mode 100644 develop/doc/_sources/design/cluster_train/checkpointing.md.txt delete mode 100644 develop/doc/_sources/design/cluster_train/data_dispatch.md.txt delete mode 100644 develop/doc/_sources/design/cluster_train/large_model_dist_train.md.txt delete mode 100644 develop/doc/_sources/design/cluster_train/master_server.md.txt delete mode 100644 develop/doc/_sources/design/cluster_train/pserver_client.md.txt delete mode 100644 develop/doc/_sources/design/cluster_train/remote_parameter_updater.md.txt delete mode 100644 develop/doc/_sources/design/cluster_train/save_model.md.txt delete mode 100644 develop/doc/_sources/design/cluster_train/submit-job.md.txt delete mode 100644 develop/doc/_sources/design/concurrent_programming.md.txt delete mode 100644 develop/doc/_sources/design/cpp_data_feeding.md.txt delete mode 100644 develop/doc/_sources/design/csp.md.txt delete mode 100644 develop/doc/_sources/design/dist_refactor/distributed_architecture.md.txt delete mode 100644 develop/doc/_sources/design/dist_refactor/multi_cpu.md.txt delete mode 100644 develop/doc/_sources/design/dist_refactor/parameter_server.md.txt delete mode 100644 develop/doc/_sources/design/error_clip.md.txt delete mode 100644 develop/doc/_sources/design/evaluator.md.txt delete mode 100644 develop/doc/_sources/design/executor.md.txt delete mode 100644 develop/doc/_sources/design/file_manager/README.md.txt delete mode 100644 develop/doc/_sources/design/file_manager/pfs/pfsclient.md.txt delete mode 100644 develop/doc/_sources/design/float16.md.txt delete mode 100644 develop/doc/_sources/design/fluid.md.txt delete mode 100644 develop/doc/_sources/design/fluid_compiler.md.txt delete mode 100644 develop/doc/_sources/design/functions_operators_layers.md.txt delete mode 100644 develop/doc/_sources/design/gan_api.md.txt delete mode 100644 develop/doc/_sources/design/graph.md.txt delete mode 100644 develop/doc/_sources/design/graph_survey.md.txt delete mode 100644 develop/doc/_sources/design/if_else_op.md.txt delete mode 100644 develop/doc/_sources/design/infer_var_type.md.txt delete mode 100644 develop/doc/_sources/design/kernel_hint_design.md.txt delete mode 100644 develop/doc/_sources/design/kernel_selection.md.txt delete mode 100644 develop/doc/_sources/design/memory_optimization.md.txt delete mode 100644 develop/doc/_sources/design/mkl/mkl_packed.md.txt delete mode 100644 develop/doc/_sources/design/mkl/mkldnn.md.txt delete mode 100644 develop/doc/_sources/design/mkl/mkldnn_fluid.md.txt delete mode 100644 develop/doc/_sources/design/model_format.md.txt delete mode 100644 develop/doc/_sources/design/multi_language_interface/00.why_plain_c.md.txt delete mode 100644 develop/doc/_sources/design/multi_language_interface/01.inference_implementation.md.txt delete mode 100644 develop/doc/_sources/design/operator_kernel_type.md.txt delete mode 100644 develop/doc/_sources/design/ops/rnn.md.txt delete mode 100644 develop/doc/_sources/design/ops/sequence_decoder.md.txt delete mode 100644 develop/doc/_sources/design/optimizer.md.txt delete mode 100644 develop/doc/_sources/design/paddle_nccl.md.txt delete mode 100644 develop/doc/_sources/design/parallel_do.md.txt delete mode 100644 develop/doc/_sources/design/parameter_average.md.txt delete mode 100644 develop/doc/_sources/design/parameters_in_cpp.md.txt delete mode 100644 develop/doc/_sources/design/profiler.md.txt delete mode 100644 develop/doc/_sources/design/program.md.txt delete mode 100644 develop/doc/_sources/design/prune.md.txt delete mode 100644 develop/doc/_sources/design/python_api.md.txt delete mode 100644 develop/doc/_sources/design/reader/README.md.txt delete mode 100644 develop/doc/_sources/design/refactorization.md.txt delete mode 100644 develop/doc/_sources/design/register_grad_op.md.txt delete mode 100644 develop/doc/_sources/design/regularization.md.txt delete mode 100644 develop/doc/_sources/design/releasing_process.md.txt delete mode 100644 develop/doc/_sources/design/scope.md.txt delete mode 100644 develop/doc/_sources/design/selected_rows.md.txt delete mode 100644 develop/doc/_sources/design/simple_op_design.md.txt delete mode 100644 develop/doc/_sources/design/speech/deep_speech_2.md.txt delete mode 100644 develop/doc/_sources/design/support_new_device.md.txt delete mode 100644 develop/doc/_sources/design/switch.md.txt delete mode 100644 develop/doc/_sources/design/tensor_array.md.txt delete mode 100644 develop/doc/_sources/design/var_desc.md.txt delete mode 100644 develop/doc/_sources/dev/new_op_en.md.txt delete mode 100644 develop/doc/_sources/dev/new_op_kernel_en.md.txt delete mode 100644 develop/doc/_sources/dev/use_eigen_en.md.txt delete mode 100644 develop/doc/_sources/howto/cluster/fluid_cluster_train_en.md.txt delete mode 100644 develop/doc/_sources/howto/optimization/cpu_profiling_en.md.txt delete mode 100644 develop/doc/_sources/howto/read_source.md.txt delete mode 100644 develop/doc/_sources/mobile/cross_compiling_for_android_en.md.txt delete mode 100644 develop/doc/_sources/mobile/cross_compiling_for_ios_en.md.txt delete mode 100644 develop/doc/_sources/mobile/cross_compiling_for_raspberry_en.md.txt delete mode 100644 develop/doc/_sources/survey/cluster_bootstrapping_tools.md.txt delete mode 100644 develop/doc/design/api.html delete mode 100644 develop/doc/design/auto_gradient_check.html delete mode 100644 develop/doc/design/backward.html delete mode 100644 develop/doc/design/block.html delete mode 100644 develop/doc/design/build_system/README.html delete mode 100644 develop/doc/design/cluster_train/README.html delete mode 100644 develop/doc/design/cluster_train/checkpointing.html delete mode 100644 develop/doc/design/cluster_train/data_dispatch.html delete mode 100644 develop/doc/design/cluster_train/large_model_dist_train.html delete mode 100644 develop/doc/design/cluster_train/master_server.html delete mode 100644 develop/doc/design/cluster_train/pserver_client.html delete mode 100644 develop/doc/design/cluster_train/remote_parameter_updater.html delete mode 100644 develop/doc/design/cluster_train/save_model.html delete mode 100644 develop/doc/design/cluster_train/submit-job.html delete mode 100644 develop/doc/design/concurrent_programming.html delete mode 100644 develop/doc/design/cpp_data_feeding.html delete mode 100644 develop/doc/design/csp.html delete mode 100644 develop/doc/design/dist_refactor/distributed_architecture.html delete mode 100644 develop/doc/design/dist_refactor/multi_cpu.html delete mode 100644 develop/doc/design/dist_refactor/parameter_server.html delete mode 100644 develop/doc/design/error_clip.html delete mode 100644 develop/doc/design/evaluator.html delete mode 100644 develop/doc/design/executor.html delete mode 100644 develop/doc/design/file_manager/README.html delete mode 100644 develop/doc/design/file_manager/pfs/pfsclient.html delete mode 100644 develop/doc/design/float16.html delete mode 100644 develop/doc/design/fluid.html delete mode 100644 develop/doc/design/fluid_compiler.html delete mode 100644 develop/doc/design/functions_operators_layers.html delete mode 100644 develop/doc/design/gan_api.html delete mode 100644 develop/doc/design/graph.html delete mode 100644 develop/doc/design/graph_survey.html delete mode 100644 develop/doc/design/if_else_op.html delete mode 100644 develop/doc/design/infer_var_type.html delete mode 100644 develop/doc/design/kernel_hint_design.html delete mode 100644 develop/doc/design/kernel_selection.html delete mode 100644 develop/doc/design/memory_optimization.html delete mode 100644 develop/doc/design/mkl/mkl_packed.html delete mode 100644 develop/doc/design/mkl/mkldnn.html delete mode 100644 develop/doc/design/mkl/mkldnn_fluid.html delete mode 100644 develop/doc/design/model_format.html delete mode 100644 develop/doc/design/multi_language_interface/00.why_plain_c.html delete mode 100644 develop/doc/design/multi_language_interface/01.inference_implementation.html delete mode 100644 develop/doc/design/operator_kernel_type.html delete mode 100644 develop/doc/design/ops/rnn.html delete mode 100644 develop/doc/design/ops/sequence_decoder.html delete mode 100644 develop/doc/design/optimizer.html delete mode 100644 develop/doc/design/paddle_nccl.html delete mode 100644 develop/doc/design/parallel_do.html delete mode 100644 develop/doc/design/parameter_average.html delete mode 100644 develop/doc/design/parameters_in_cpp.html delete mode 100644 develop/doc/design/profiler.html delete mode 100644 develop/doc/design/program.html delete mode 100644 develop/doc/design/prune.html delete mode 100644 develop/doc/design/python_api.html delete mode 100644 develop/doc/design/reader/README.html delete mode 100644 develop/doc/design/refactorization.html delete mode 100644 develop/doc/design/register_grad_op.html delete mode 100644 develop/doc/design/regularization.html delete mode 100644 develop/doc/design/releasing_process.html delete mode 100644 develop/doc/design/scope.html delete mode 100644 develop/doc/design/selected_rows.html delete mode 100644 develop/doc/design/simple_op_design.html delete mode 100644 develop/doc/design/speech/deep_speech_2.html delete mode 100644 develop/doc/design/support_new_device.html delete mode 100644 develop/doc/design/switch.html delete mode 100644 develop/doc/design/tensor_array.html delete mode 100644 develop/doc/design/var_desc.html delete mode 100644 develop/doc/dev/new_op_en.html delete mode 100644 develop/doc/dev/new_op_kernel_en.html delete mode 100644 develop/doc/dev/use_eigen_en.html delete mode 100644 develop/doc/howto/cluster/fluid_cluster_train_en.html delete mode 100644 develop/doc/howto/optimization/cpu_profiling_en.html delete mode 100644 develop/doc/howto/read_source.html delete mode 100644 develop/doc/mobile/cross_compiling_for_android_en.html delete mode 100644 develop/doc/mobile/cross_compiling_for_ios_en.html delete mode 100644 develop/doc/mobile/cross_compiling_for_raspberry_en.html delete mode 100644 develop/doc/survey/cluster_bootstrapping_tools.html delete mode 100644 develop/doc_cn/_images/control_flow_graph.png delete mode 100644 develop/doc_cn/_images/dataflow_equations.png delete mode 100644 develop/doc_cn/_images/deep_learning.png delete mode 100644 develop/doc_cn/_images/fluid-compiler.png delete mode 100644 develop/doc_cn/_images/graph_construction_example_all.png delete mode 100644 develop/doc_cn/_images/graph_construction_example_forward_backward.png delete mode 100644 develop/doc_cn/_images/graph_construction_example_forward_only.png delete mode 100644 develop/doc_cn/_images/pprof_1.png delete mode 100644 develop/doc_cn/_images/pprof_2.png delete mode 100644 develop/doc_cn/_sources/design/api.md.txt delete mode 100644 develop/doc_cn/_sources/design/auto_gradient_check.md.txt delete mode 100644 develop/doc_cn/_sources/design/backward.md.txt delete mode 100644 develop/doc_cn/_sources/design/block.md.txt delete mode 100644 develop/doc_cn/_sources/design/build_system/README.md.txt delete mode 100644 develop/doc_cn/_sources/design/cluster_train/README.md.txt delete mode 100644 develop/doc_cn/_sources/design/cluster_train/checkpointing.md.txt delete mode 100644 develop/doc_cn/_sources/design/cluster_train/data_dispatch.md.txt delete mode 100644 develop/doc_cn/_sources/design/cluster_train/large_model_dist_train.md.txt delete mode 100644 develop/doc_cn/_sources/design/cluster_train/master_server.md.txt delete mode 100644 develop/doc_cn/_sources/design/cluster_train/pserver_client.md.txt delete mode 100644 develop/doc_cn/_sources/design/cluster_train/remote_parameter_updater.md.txt delete mode 100644 develop/doc_cn/_sources/design/cluster_train/save_model.md.txt delete mode 100644 develop/doc_cn/_sources/design/cluster_train/submit-job.md.txt delete mode 100644 develop/doc_cn/_sources/design/concurrent_programming.md.txt delete mode 100644 develop/doc_cn/_sources/design/cpp_data_feeding.md.txt delete mode 100644 develop/doc_cn/_sources/design/csp.md.txt delete mode 100644 develop/doc_cn/_sources/design/dist_refactor/distributed_architecture.md.txt delete mode 100644 develop/doc_cn/_sources/design/dist_refactor/multi_cpu.md.txt delete mode 100644 develop/doc_cn/_sources/design/dist_refactor/parameter_server.md.txt delete mode 100644 develop/doc_cn/_sources/design/error_clip.md.txt delete mode 100644 develop/doc_cn/_sources/design/evaluator.md.txt delete mode 100644 develop/doc_cn/_sources/design/executor.md.txt delete mode 100644 develop/doc_cn/_sources/design/file_manager/README.md.txt delete mode 100644 develop/doc_cn/_sources/design/file_manager/pfs/pfsclient.md.txt delete mode 100644 develop/doc_cn/_sources/design/float16.md.txt delete mode 100644 develop/doc_cn/_sources/design/fluid.md.txt delete mode 100644 develop/doc_cn/_sources/design/fluid_compiler.md.txt delete mode 100644 develop/doc_cn/_sources/design/functions_operators_layers.md.txt delete mode 100644 develop/doc_cn/_sources/design/gan_api.md.txt delete mode 100644 develop/doc_cn/_sources/design/graph.md.txt delete mode 100644 develop/doc_cn/_sources/design/graph_survey.md.txt delete mode 100644 develop/doc_cn/_sources/design/if_else_op.md.txt delete mode 100644 develop/doc_cn/_sources/design/infer_var_type.md.txt delete mode 100644 develop/doc_cn/_sources/design/kernel_hint_design.md.txt delete mode 100644 develop/doc_cn/_sources/design/kernel_selection.md.txt delete mode 100644 develop/doc_cn/_sources/design/memory_optimization.md.txt delete mode 100644 develop/doc_cn/_sources/design/mkl/mkl_packed.md.txt delete mode 100644 develop/doc_cn/_sources/design/mkl/mkldnn.md.txt delete mode 100644 develop/doc_cn/_sources/design/mkl/mkldnn_fluid.md.txt delete mode 100644 develop/doc_cn/_sources/design/model_format.md.txt delete mode 100644 develop/doc_cn/_sources/design/multi_language_interface/00.why_plain_c.md.txt delete mode 100644 develop/doc_cn/_sources/design/multi_language_interface/01.inference_implementation.md.txt delete mode 100644 develop/doc_cn/_sources/design/operator_kernel_type.md.txt delete mode 100644 develop/doc_cn/_sources/design/ops/rnn.md.txt delete mode 100644 develop/doc_cn/_sources/design/ops/sequence_decoder.md.txt delete mode 100644 develop/doc_cn/_sources/design/optimizer.md.txt delete mode 100644 develop/doc_cn/_sources/design/paddle_nccl.md.txt delete mode 100644 develop/doc_cn/_sources/design/parallel_do.md.txt delete mode 100644 develop/doc_cn/_sources/design/parameter_average.md.txt delete mode 100644 develop/doc_cn/_sources/design/parameters_in_cpp.md.txt delete mode 100644 develop/doc_cn/_sources/design/profiler.md.txt delete mode 100644 develop/doc_cn/_sources/design/program.md.txt delete mode 100644 develop/doc_cn/_sources/design/prune.md.txt delete mode 100644 develop/doc_cn/_sources/design/python_api.md.txt delete mode 100644 develop/doc_cn/_sources/design/reader/README.md.txt delete mode 100644 develop/doc_cn/_sources/design/refactorization.md.txt delete mode 100644 develop/doc_cn/_sources/design/register_grad_op.md.txt delete mode 100644 develop/doc_cn/_sources/design/regularization.md.txt delete mode 100644 develop/doc_cn/_sources/design/releasing_process.md.txt delete mode 100644 develop/doc_cn/_sources/design/scope.md.txt delete mode 100644 develop/doc_cn/_sources/design/selected_rows.md.txt delete mode 100644 develop/doc_cn/_sources/design/simple_op_design.md.txt delete mode 100644 develop/doc_cn/_sources/design/speech/deep_speech_2.md.txt delete mode 100644 develop/doc_cn/_sources/design/support_new_device.md.txt delete mode 100644 develop/doc_cn/_sources/design/switch.md.txt delete mode 100644 develop/doc_cn/_sources/design/tensor_array.md.txt delete mode 100644 develop/doc_cn/_sources/design/var_desc.md.txt delete mode 100644 develop/doc_cn/_sources/dev/new_op_cn.md.txt delete mode 100644 develop/doc_cn/_sources/dev/use_eigen_cn.md.txt delete mode 100644 develop/doc_cn/_sources/howto/optimization/cpu_profiling_cn.md.txt delete mode 100644 develop/doc_cn/_sources/howto/read_source.md.txt delete mode 100644 develop/doc_cn/_sources/mobile/cross_compiling_for_android_cn.md.txt delete mode 100644 develop/doc_cn/_sources/mobile/cross_compiling_for_ios_cn.md.txt delete mode 100644 develop/doc_cn/_sources/mobile/cross_compiling_for_raspberry_cn.md.txt delete mode 100644 develop/doc_cn/_sources/survey/cluster_bootstrapping_tools.md.txt delete mode 100644 develop/doc_cn/design/api.html delete mode 100644 develop/doc_cn/design/auto_gradient_check.html delete mode 100644 develop/doc_cn/design/backward.html delete mode 100644 develop/doc_cn/design/block.html delete mode 100644 develop/doc_cn/design/build_system/README.html delete mode 100644 develop/doc_cn/design/cluster_train/README.html delete mode 100644 develop/doc_cn/design/cluster_train/checkpointing.html delete mode 100644 develop/doc_cn/design/cluster_train/data_dispatch.html delete mode 100644 develop/doc_cn/design/cluster_train/large_model_dist_train.html delete mode 100644 develop/doc_cn/design/cluster_train/master_server.html delete mode 100644 develop/doc_cn/design/cluster_train/pserver_client.html delete mode 100644 develop/doc_cn/design/cluster_train/remote_parameter_updater.html delete mode 100644 develop/doc_cn/design/cluster_train/save_model.html delete mode 100644 develop/doc_cn/design/cluster_train/submit-job.html delete mode 100644 develop/doc_cn/design/concurrent_programming.html delete mode 100644 develop/doc_cn/design/cpp_data_feeding.html delete mode 100644 develop/doc_cn/design/csp.html delete mode 100644 develop/doc_cn/design/dist_refactor/distributed_architecture.html delete mode 100644 develop/doc_cn/design/dist_refactor/multi_cpu.html delete mode 100644 develop/doc_cn/design/dist_refactor/parameter_server.html delete mode 100644 develop/doc_cn/design/error_clip.html delete mode 100644 develop/doc_cn/design/evaluator.html delete mode 100644 develop/doc_cn/design/executor.html delete mode 100644 develop/doc_cn/design/file_manager/README.html delete mode 100644 develop/doc_cn/design/file_manager/pfs/pfsclient.html delete mode 100644 develop/doc_cn/design/float16.html delete mode 100644 develop/doc_cn/design/fluid.html delete mode 100644 develop/doc_cn/design/fluid_compiler.html delete mode 100644 develop/doc_cn/design/functions_operators_layers.html delete mode 100644 develop/doc_cn/design/gan_api.html delete mode 100644 develop/doc_cn/design/graph.html delete mode 100644 develop/doc_cn/design/graph_survey.html delete mode 100644 develop/doc_cn/design/if_else_op.html delete mode 100644 develop/doc_cn/design/infer_var_type.html delete mode 100644 develop/doc_cn/design/kernel_hint_design.html delete mode 100644 develop/doc_cn/design/kernel_selection.html delete mode 100644 develop/doc_cn/design/memory_optimization.html delete mode 100644 develop/doc_cn/design/mkl/mkl_packed.html delete mode 100644 develop/doc_cn/design/mkl/mkldnn.html delete mode 100644 develop/doc_cn/design/mkl/mkldnn_fluid.html delete mode 100644 develop/doc_cn/design/model_format.html delete mode 100644 develop/doc_cn/design/multi_language_interface/00.why_plain_c.html delete mode 100644 develop/doc_cn/design/multi_language_interface/01.inference_implementation.html delete mode 100644 develop/doc_cn/design/operator_kernel_type.html delete mode 100644 develop/doc_cn/design/ops/rnn.html delete mode 100644 develop/doc_cn/design/ops/sequence_decoder.html delete mode 100644 develop/doc_cn/design/optimizer.html delete mode 100644 develop/doc_cn/design/paddle_nccl.html delete mode 100644 develop/doc_cn/design/parallel_do.html delete mode 100644 develop/doc_cn/design/parameter_average.html delete mode 100644 develop/doc_cn/design/parameters_in_cpp.html delete mode 100644 develop/doc_cn/design/profiler.html delete mode 100644 develop/doc_cn/design/program.html delete mode 100644 develop/doc_cn/design/prune.html delete mode 100644 develop/doc_cn/design/python_api.html delete mode 100644 develop/doc_cn/design/reader/README.html delete mode 100644 develop/doc_cn/design/refactorization.html delete mode 100644 develop/doc_cn/design/register_grad_op.html delete mode 100644 develop/doc_cn/design/regularization.html delete mode 100644 develop/doc_cn/design/releasing_process.html delete mode 100644 develop/doc_cn/design/scope.html delete mode 100644 develop/doc_cn/design/selected_rows.html delete mode 100644 develop/doc_cn/design/simple_op_design.html delete mode 100644 develop/doc_cn/design/speech/deep_speech_2.html delete mode 100644 develop/doc_cn/design/support_new_device.html delete mode 100644 develop/doc_cn/design/switch.html delete mode 100644 develop/doc_cn/design/tensor_array.html delete mode 100644 develop/doc_cn/design/var_desc.html delete mode 100644 develop/doc_cn/dev/new_op_cn.html delete mode 100644 develop/doc_cn/dev/use_eigen_cn.html delete mode 100644 develop/doc_cn/howto/optimization/cpu_profiling_cn.html delete mode 100644 develop/doc_cn/howto/read_source.html delete mode 100644 develop/doc_cn/mobile/cross_compiling_for_android_cn.html delete mode 100644 develop/doc_cn/mobile/cross_compiling_for_ios_cn.html delete mode 100644 develop/doc_cn/mobile/cross_compiling_for_raspberry_cn.html delete mode 100644 develop/doc_cn/survey/cluster_bootstrapping_tools.html diff --git a/develop/api_doc/.buildinfo b/develop/api_doc/.buildinfo index adac1818d96..11adacf44c6 100644 --- a/develop/api_doc/.buildinfo +++ b/develop/api_doc/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: afc32173167fc468034cdf5aae2571ec +config: 90642218475087a09239879d1159d425 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/develop/doc/.buildinfo b/develop/doc/.buildinfo index adac1818d96..11adacf44c6 100644 --- a/develop/doc/.buildinfo +++ b/develop/doc/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: afc32173167fc468034cdf5aae2571ec +config: 90642218475087a09239879d1159d425 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/develop/doc/_images/control_flow_graph.png b/develop/doc/_images/control_flow_graph.png deleted file mode 100644 index 3579998e58d07abc50bd3332128d4733a391cb3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85311 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

2lgXYv@-%QDC?iiVxEc}XZsaKW-@ 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 NxpwDj)fIcp{{g{6PO$(0 diff --git a/develop/doc/_images/deep_learning.png b/develop/doc/_images/deep_learning.png deleted file mode 100644 index 026becc4d94e01e407dacb2a5314a0e5723334ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40605 zcmcfoWmr_-8#WAsiYQ16NJ}?JOG|g>45hTh(A^+0bcb|@gmi;QcX!9o-3&0iqrboR zd%VYSzsK|K`2>5`UVC5bT34Ru+F)fxDKr#96a)kWG#P1eRRo0R<_HLg>#v@{e~DK| zQA0rRMUW8}QFmQ9Tz;+l7V?CAdU81Y`x)x94L=Ik!h=9$I!KILKCYVyVB6YsKHs@W z&*J-4MayJnVsY`86scgTzzr;Y^9|+@I(stI!IcZ2BXp)truXj|Hg+C2@~cNj?tV6V zUZ=Qa#QbEEgTE93p`KC{_wPUclz;xb|M*81g#Z5+|BpBP|4jXV`R-q>v?B1;{1W6~ zHC-R>+FZJf4S|U37vcCKzXB2?BCM^96P*)JG69sy5ne^Y*O||8Q9xh_zrw&vD|zYr zT}~;n72HnT?D$@gKPBYq>hfT^#Kq+aCTj5Idhc-#^75AS zqi@#>m|@lsBrZ0&hg?ajwblRdSoPg06@M}%fj)L6P8}L!Ri+2ro@jTUrTJtdqQI3I#{WG($=|_B*qxV>X<1K|rMRz@eMCd&*28z&E1almp zYmDkR2Oc(cjSr_Ok)Q%vfmIp-nj=39!7PL<4{m(y^j8*b`f}pl8Ety0LD#R}4MqQW zA8Lo3A1@p9B8m&An%{2GkE0p&5||)5UpTzk`drd>_(e*d9@)ikV3#(QO0>aRH8~~W zz+ytvQvmQWIU#S(bJ4p=fQ+vxqKWowA|s=;ndRy8hrM@(lt3X$O5qhY zi<`82KXUsRh71%^#k>|{#fBKXq;&g^alA6-b-0~O7dJ(ZEGM-em} zU~C9;WHp_MV1i;$V@zO-p>M&{_1tQnqGjgzQ*F?IvbPK&#OK|eeKG$$%X?SdzQV}h z$r}Y8lhv()1J@Zj*6%dztl+tUqt0Mtv%-8`TYZg8O>(7L&#=@H^3Cu*`~j$`u=0iW z(^`LI@I%1>C2F=<)2;AMvW*LH>bNNXq3||=GD}r^2V)7?T5C-`UZc0!m(hr{vddoy zF2P?hM9}b6n?_K^!Np97A#B88neonv^8xFEPkxyQQm=dM9Pu!oZ_C{@GdrFIQu*K!=Z%n8f*Eqr3OlUEHxiRlL&7L zwQ4RT@U&8pD*(ykdZmr$7K011Y=w|>XFRsLO!zYHb1reO->o||$$gF?a6-4rc&9PK z-|hCkLbc(=Ef;gjN_k?_-eSqlvUEPCvDD0Lb@>m`>1-A0s~K)NNA_bEseVhZLKg5` z1D&B>Lo1=33H7IhbwVkGqLk3o*HVt&iG32{Q@Se;VSYc3l$P%@y?bD-^Ph#on5%=v zZu{0*y7#u$;9E|fBVg!erZs$l>^-Wdf2Vuu@ERZ^(K+y8r~0~98G|lG@BFY(Gc^J= z#nR@!#w7iUjnS?8U84AdIMv>Un3%tm7twtLzsYme&k(Mahi4NC1mJi(AkUwM&>6PnUSR(Nsq3Idv>0(gq5x=Y4QT^ZSzyBmy0-EitVvXZiwAU6sPo$U5>RDZaCv zRxi$s%$;KC!Y%lN20u(@HT)r-L940uuw7(Yd(jH4F=%$=&Xx(rt=D zu@806B|Xkp&IC1oE#6$OOE#$QejwbMwY9hb z8lz;3hB*PciyuC6bPP(x9hXBy6~m!ZKkVXf{~`D5{3N=);0Hp6jcn^2TDVWr{`KB8*(e_mwtjCSv z*O}It9Ud|bSSBk0i^kPV&5WSIlbw2AS#P1%6`j4@;#GnZkn1P7XJrY%)wy$UDIQp*50006kl7|4LNWz zUUs2WC^VqT<86M=H8@wx_3At%!}sne<3Z@a%EGhfAc)D2nvTM58GV?DawGSsth;Gj2 zL`l0)Sz`gsl8YBQUoNHd@L>xtng%u`Xg zGtyvTiVZ+>4|QrqX}De$Z1m2gY)VH%05%f)xVk+SK?w*RF@6NJ)(&GUgcHN2JL=`H zMIsNy!iW^Q=acB&CJ&oW_rCN!^6hV`@kF8wq}~afTSVOuycCo99e`3;f;g~c4%)Jf zh-5`4`u4q%)@uDT1ePGqn2roOT*_nQ={PZw7biluF1f`wO!%$vW0c?XZfku|4M|CG zy6QB@+dfAMD2SysHBva8S|G`nDa@s1Yu=yTK}k#!2d3jb`%MJKaUInGzq`k~@5aT@ zXLjQ`x9%PJ*n$Z?T!tak->{kC9X^OF=PNuugpO>+Aln2*aI;{WFIa8Ko;tDxsv=ILYH52 zHi**XL3ix*>X7pA;x(y~SabDNfXPX0i+PxluHazv0~=FA#Kk9pX&9D4Pu2EplTW|! zc@i`+Xl4Sqm=Eqo@0~_?bH+`P<#Q=R6m}zY`^`uIUJ>{T~S7IsT(_bT0M8)&rn$+Au<^C@@I5t-s-2{TYT@fAdYIc680-}P%%MVO zzhZ4!gp3n?SGmfNhzUH$WWM)C?W_JSzgqOd>ap-+wciht^r-zNe2i5}%I`##lFBLT z!ycM8)*RwCZvb>IC1yTK6%~}44D`D!t)M8qDA@L|UOqLjx0a#ggJIu~03b&1J)s5S z%cR|B9|s3#Bfg(!IM`BAXyp$EnPld8TnQRcS0^yxvG+@l#4l@nr)F0c5-Uy99U$;$ zOO-#75;BM<*Ihk$6i)0Dr9magr@~q;?|dOwn({`oN?K+hI=OgAJ4&&)8`$@2PBpnE zjifF*q4p>PAa4k^zBxXwwL5`V6Yn@ZWV%#y_%s*G3EvrZLqO?T5vnndrUJM{h>UWk zSm0##kwz^o>(nEDXAB10lRyKXJDY$kWqPM{OsKPMdZH_<*pV-{gRg4*!ct#HLgYZQsbndvGv_j!1&3NlMbSNfF0gyImh@>DB8 zTb&7!2y4opCz!+Z*U|`|w|;M%zQDp+$w`NQP%GqxLuJtedYPkOO5sjI0g0rSms#Md<5E6wiI)Z5SEy zJZG!QnHHXo%a*7_+(y?BSzX-p7!tEXv+%rwava_uth(qpm#+e|Q~TRKIKD4;^uz?f z?GsEMlYHvZ`j%#5kySf>jpFt^z0J+)sNEoiNzywz1PjfQr_LizsEDkn?6eU<*?&NT z*M0X>Z|8|zkTgsUR4%JN8_*|&9r5l;IdOmgQLUMz;e01i?a4?E9iJhIuE#lLr3A!3 zg)wDlZuf#tDKk6n4&w%-7s-d{nhXF~8Xvkm>E7unAMb5&@miUBMM)M>6fMKcD+B~( za>?p1a6!^#gjnco*2Y~`=iVscv#MkL*Vn^4f+Q){h71x`Ivc(E$3Z>)BstqqGPt|K zfebp{8)#L)MKuch3rKc^N5t+2{jSd;*l?A@`|g|z`a&(TJ5d`JwnJgDAvNoaljS#J zjQ`;db0mtlmXlx&&AP6lMAewf?vcrb>636M;tMJG)c1)dKKwV6#}2};2bQ;v<3!Ck zuTdm%5&z;2(fx+d^|`7|ncx=??-HomZ&UYXXig|RlOZ4+zmmILD7VvWt<(Fo))0+U z6pgH&A=12mn)8DI{{=+B3mA0*El}MK{j=E!2t`3_=3|!m;`EKhwQIKW;#!V{?8PB+=x=`8w;FU^G zbg=|nKGd}6_@9p;uIKV8z70Ed!TF=5EWQud0_v7SydU{_@_$a36=$AUF1Ood>^$mm z7`rpan8&S`g;};)Hk)F7q@A~0C|9iiB=y?-MlZD*Kicnz>X+pQfysIZ<)XW<*-lG``_qn(N zp|aC3WZPd{kqFA0$>0%-C$3a9k^P{IsX4cxC&$W{VxXT**~ljV#&MI*KqIXu?supm zb2M#!*)YNUEply5sqKc+P8MuCOO2wK-O;YTZ}AsGpnWqS`XI%&yC!i=V=h!>=VY2U zuRRS{%y_Q|y<(yMICUm(E|0PwFiSwes^xSaMDl#A4Cx1h*-f5$aB8n~BIQ>f>U;z4 zcTQK+XwMEfonneZ`aZLjibtJ~L{oPt}^GStjZyE8c<;Wxh^t zI2r>|Ko9Fjlf)f=+-{716Sz1?5j1U0l=c>~bV0rHMPYHBCidB#Ae(n1C}&U7yaKwM z?(IMPD8)mfS^iFGkf9{VOlNaA?P$2m&(O%f67>g|QqIN2yg$keYkbp4wL$BV8D~hJ zr*pO_;NcR%SK(wZfUD0*>)rZj4YTTHC7YK`Z9=Li$#;t~fVnKJFRRFfgp)~?da|Bt zupp+>TBsDRY@^aPw7ri#Wr`T(@NfNIX<5>R=Ub#F&cQbQV+!jrt-;G+NK#}yV{SEM z&W1vhJ+J)N@ifGlp55-=phbhEFqeAPLL2)mj8ewO-PT!F7R+XX-t{Qf<&AZg5dOf} z_SE`t?JZXN!ShAk<2KEe6}Lf1M;_O!l_Bielz$*ofOPVkO> zs2Hcdn~lqQ_M?==p{}9nc0}JS_?+=7Y2%1I(*a|K3>w&{+(BIn9m0!!xsbEEeUhZL z+ncs99dh;sqTp9E;4Nac`W} ziMh9yG4VL;iTOSsX`i@jyhL{Wx#MN=?}k_;VWrKSo-KXWdQD*waX8>8kKPaCw5Pz5 zFo+~7?x$t&8ryb39xkP|$yAs>rux!1{K?oLfk=fWM$67{vd5kcq}_)pg1T!>fAnMO z1t%FkdmK5nRuSbOQOxMPuzvzm{s+a}>5nI*ay1+Eye!w}qZHeXs+d@USeR_^g;xbH zR8S^{^abmj`f?|R#+G|!5$n9!C&R4#uwC8Ng(F@=@66V2XwwS~$;;Nrt|~M$RXg;L z`Ob@rk?ug5$Q+p_D$Z|&af#}k63Wn#!W_NeqLYs~O4gA5vxI9B-9(~Zg{Pzke=cQf z(=y82q$Xba*BiFZg{Y(PExQ&(!~qYv=Ll1rdeh`f;+GI@?~@g(fpvC6HDO_v&2$c0 zJL;on&l;!t&S*zN^lj`X3nyT7PK;#eZuJ>0f>>^`g&|Ata+HTBm(*0i!WTQbWEvm8 zeR2I2JwO^3YcA8ZeMU~k*77Tl%I;~*4&w6`)j5h8T7Gh}H;^w0>L+;KI0<#+JMuM} zpN4|~G>PJ#z4?+OI^-Pk`5IOdLj<=PrkKf(b z?hRw?X77KX<|-=Jn(g@Ep-BRyl8#`n^n~ZmJV^w2YH>Ynz{Hh6lPSMy$@QFVlm=}C zmIoFeL{%>~f-A`ru`U&0hqH`J*cN*nsEP>6qTfzO7qKC~-S9iF2=?x7cmc2Id0EvqgegcWOMZv!NmAd(hlF@O5a0L~>)KvYYK`WYwDaAH ztO|KS@${J)4kFE7{|Hv)Mmw)$d0u_;#O%^uEYx z`P%gWF&+cn_GASSExJj;`7c3c< z5pqXuYROC1G1AByPn^zg|u9j%gsi~!B zsrBWb#bq&Ui6bJC*epEzMm6aR%aWsZN|yUJ4%Mdp7*tt#UFJxq|cnKMp@JF z&CWH$@JkQbMI!u1^+BHMkaeiqy+_Hw-n0rjGeDS5G2$?{%$>Uwhbf_6XU(+rB#u39^* zY7d&I+PwobIf}U5{1SqP5?rp_8cc8J zurT4i$zrQ)kG~Fw1dx+KWq|yosbLFWQlVU@NiVccXj{|FT~#t~qFja(83h>I4o`hM ze0r^-7l=q^dp*A}-@mEhr#C=NF+u;*9--%ceU9i6b=VF?iefyx(kH-IeY(Fs-EnvD z%X;Xaq0BHp<6JTMTNTK?06)l!tLCVI@keStj!3+`_x;%2#C_!UYbC^q;i$q{G1pmZ zI4rxu^Xh_=0_bkrf0g!zCGD>N$DD(xP2c9m65Vh!^}ukDY#Hq|aISD`Fl01uYHp>q zb6_qf=`_AMbW4|}Io^KKo4x(J&J?Ly@WbbmU-7xDn0u(|C<&UG8Zk%`;-fd|wRfX; z41tR&UE1SEPvUHGTx$65oUWZUV;&1c6Hp_iuwg5%h6xGGc4hwRR3s$qwO#?`u3?Dk zcndp-S&}}YwKiAZ9z`YR2ZZrU-ZJbU+L5B}4l9&KE@uv@YkGB?_w|M zFdFMsT{?OJh~dDKV%lOsK%+XL743z6IkEMkhd}RRY&5d52Uh!epSMFlotehF zY{ka?PKmG^SB8OJ9cKK(SWH*2EEmSP-DH~~9jDt1#=V^vkPauH;_h{#>UK~)E}XPc z=R%lr#9EJ>p_k*&^c&&m3rUo+IxZ(Td{9sIoynAB+V+|0rwXiB`7($WpK*;y(zqw` zT?kiLX`pOMK|f6~Ui^Y`W-xT7$E{SOo*F9^RhG#ybvbN2eMdD{mK=zEwh3pcmPXC6 z4xWV_4?o_uZ4fyK@2$FMcJb&-)LYpp)5lYa1_$3_v>#O#X?R1-pxLb}bil$=acZ?M zwDy5r`BNss2aoxAMWTcr_&07R`RD|1p|KhbouPqP22%;a>Uprqa}YD^z-wpf-Nes( zc=trf^=yee$OJI;>=OX`CVj}K!R5eyN(Rl0990ev3oP#9DQPkQr+oHK|ayW)8qUYhBALi`-4`TVGm!1qXWCC%COm`xz+gaC<;4tlEZv zD)z1gmxi3;M~j|rjbOZOfvH(NZN$%TO!Ok+nAM#UNu_T3+`uVp|Ln%r zvAz;x=fv_UU+;+@>f=APOQE571Y=R9{KO?1Mv34X?YH|ILU(+jvN>5FbU1x0wW?k9 z$V?HcAaLWp@o|USx4_#QE#V8sBI}@Gtrc%A4WD;r){@*F2ep-{-pxx_!RLR_iX{mk zyFFPXLtsK*ZP1|xs!V4Tg{DuVjdP+}uSJ3=Z`)2D%>WC=qK&K#gSNxvpaXrS|GDIT zmP|H>ItoThGGYlnUoS#Da=H+J!z;66FI%$dp-RUtwa_h zw@d%jMzFuVLTfZWzfv67#FhHFI)4pZh>u?RG_f;NeSKIl+A2ohMNh)=4!=RhQSH+} zPPgXD?XQNzC|+uv{uLMjGhIQba(nlQfH^4EE|XvZB=0(gQ$+TsfDx+EonVviT@5uI5OV!obTQd zG;xZ!X@5TXa?}$lVW^JvA84Z|&wqckK8h;OCvumi*$J%;|Md9ZX_7hO*6Y!pO-AO@ z{H|5z7)QrGMiN3tv45iv-k`;ihGBnEtrQEx-9?3#)LifXNovJq^RbPB=FB&1X?EDh zeomgOzNv`fKLtz>T(k+c+^V{#WeM~(cYhnJ*E0eA8kS zZ%AMA>MsoBi_Okj_Oa%}Xfz|8Ps{uoxwT~W|6XXNNJDZbWD4%L*uW2cch-l#+01ne z{-08R-W^OF_f4+8M#05SI$K_`I$nHv_1t$24wHS-oN0ngJ)!F_Q_^WM9>~8=g`BJ) zXuSAu@MX34@c2_$vy-Ya>Ds(8ybW*(r2QvM6)O852rb4zL3yR8eKL7u(ioff-(YMN zjwUgbsrkK{GU-a*N%c`r$UCfmgBzf9pu?qH0AQ5WI0QV_a;t6YGllVYGkk~PeFt}@ zZYTC2YdjcY#HVDbR)MpR{NMVu6PN9-dxcpaDCk_YToqB$v9dt^4A1_voVe~=y`k8@ zw8!Hzks^BPUVdr7zriwc7f5#C>y)Gy5N6NC@FQqYm^%1>gIRBnhE2vVIL_6OAj^a| z#N*yA+Eo9{Y7A1-kPs})`T>GEfLue&mo;7ee+)Uf>$xzo4(JOrHEchGYSiWXMDdq* z|C9CCcGQLN$;bQLtTByk?(D@y5hq~QKkG2$vJq%IH#dyWTIwx3j{gY|0y(Mt&s6g` zwkw3HZVeXzB5pV*+c-_FM>Ja5|MLJkN?|9!rT^O_G!eJnm)Y=FQsBz{o9W1WaSpGR zYlDbI+)hlDgs%GNg1-FofVUo-t4?gI$^YT95$3`|oImmZkE|zy?GioSy>O+gOY8PH zd*$XE==^U-5CDJ!rNS9Wy+<|Wa_6%QV(#h;DTIGp`Ns5dA=lv1<=|UZOSais-WUNX zi^V_3g1j|mj?#~gk9$w&)78ESw~#Gtq<=F(TU0FYLA_{lx|5ZyvoA;bcx)8^X8s|0 z9k%3J8+{G>FfZg6#|2Z-|Bq9O_ns_z+Sex3o}=a)&cmO&FoP=cKcB=Ltm5CSd$99P z&C;d5Nq)XX8LdAc`n?H zJ?nY&@?`(XlW!51Br&Qqs)QBqVtqLWcdu@W2dw{vtfn+?&~&y0pITd1i_f4Lavfpl zKgZ*B7KFl!m?2FEa617-Kir$eo;Cdo5>~L5pO3Ro+$bmssB>tWbg7%RFnM)xTx(3sZ?|}2JMTx(e$d7Z!})~jf0=y zAb)8HOy05&EB?lUZ+DM-l;aKDNB+j8tVy1zvd0_7xb8mIw`@7T*7w;>*PTf1&5BsMffdJ>}bqOsFmRAF*&>GU!D~0?a+Sn(hP} z6QHpGI#8G}FQKBnIP7v*k&lY=j7Nh6_%f7Skz*ZXk{Y9u$T$< z8Sa^Xl=sW@9~U(yvCo&ir~`-k;UWKTH0*@41aj@Z!brv$P7F#8FRaT!6P@pjJH)3O%&Xm|H@;9uDe_f*&m zD}xA6c7Q6dD^Er4hb7=I2?DminrB33mLF=OptFI@f~;ou?7`18UL^d+1Xzx*%de(q zWOxRof{ruq$9+{n3760)d~^iTf&^5`1e1)_jB*kGz?5`2U>q z@EW-CLB5-QV*Q4Kx>&e#YuJQmG3DO3F!6~e1y9+Vg4){R^furz9+_%R9 zlH!S1MqKPGNPa#v6WfB7;*ACo$81OU+P!6=z&pszt5;MxC!>=rD%$Dy7D`_+}4Kw4k zu)HqiTemGT7cNWwAo0H68CR2UhW(V%)QsSCuFciMi(;(fjJFJm5e$J1I$s_^7sioSsHLOE55AC<BM+&Mj|1BszG*oQD`sPm|J*E67 zP)M;#56j`j2Xh_@l}s9gUy-fZ;y2De9bwY>Mh5Rze??dIJn5!U7#(nhu@s~CtCLH+$o>`U`9 z(er)hvwANsLd-3@7HbD_Qr+l zl3Och*oce6wKzsDZd9m%-d!CUc6t$m*l}F<2@ou8G3u{7@S{+1N0ky^Xgh+gh5N?b zFxF^(l5a!RsP~g#5+N^I_vM7|?;}!a`O+yrCQ^-t?4k?%#Bdj*`NJF|;-&HW4_pgZ z*R-|T{(lNrmsxOLr-77LyxCOZZHs9atK;``;{&WBvWBRZ&Z{eB%#Z2z2YhVuNXVpL&t-s=IxbfD)*;~`c<&cfL4 z+>UUXj*F0GIuGXz|FD2>o1_yqo7?7xZm^~>mW&$3ld9?HC#{sMHipN|26>epM5R$h zUh7Or)#%E$SaDcIcASriofWc7Cuns-4Ai`VN|h%r^991?Kiu>Fdq}- zg`f21o)`E{L}apu^(plh##icjnP7-Zyj_vOaT==Y=J64za#v@qYf5^oNm@L76v5wY z)ZwESUcr+R=RoH9dXg*p$I15#d2ma4p^(P6>$|iOQzCE@yXY-x5e4Q49YA_VtWC|M z`IYHnR7b4Z=aKPL2NZb#pMz%GUV_wfPPCF(J^K)Sdc}xDA!{OJXfZ@}J8YTyWqNT4 zbOoff(Z6C&>kU!>Yuz$NdCXUQd+W|pDsq5eldIN?9T2!s%%$-$&5jUykj(65akWA~ zbAE9u&D=!mRLeAo>9sV-9LKqOI2s<-K7z|~d$m8AZcNF^{5RP0ne4H{J+2{zv1Q*t zjdcso${QOJloVZ8Y6Al1EjV@1uE}x(xjq&QYql2K0&S}H74TZUa()SwaR5-m6QA9` zsb7|rY^$_r=JD|%BlSNW4ZyW)CS(jFzGy(gyUt9&2fdh0J zK1>4_?Q<%ha~?P^UK{r$s&Hp7I966>cM)= zO}VOGi{unYpvc2jirTJg(7$dH8x~})`>2{FdkBJDRXfk*Y6Pt2avbUvs{KBq4A#o^ zhSf}Dtl3|MYi8!EHke;EHCL9#o0}#-=skDw*Z&>+tyrSM=TA1i-?KUgb4fjonzNmv z5*P;65#f+tzS!R(9ZO|ubeGHMNE=PR=F&bteA*AcCX37eWzPHofFfV#b4BxGZ-uJu zo`g7z4#3V47_b%XXRbi4q+uDRzffIokUCWuv5=tKMO9@c6*xJhRFk!uYmFm!lXvxw zXiY#r_YU13RgBZJXgjPdP%Pf^3Te8wG?H%l6C$+^Zi4-BWpc6J3I1ORY4!)mbd<_W zip4Qwz!3P^l}D^6^rB3Q*Maj$aBCci|G~5KHre55_SyD=H`9`YA0DGlnC1KGk`9$( zx*?}cp0o#db$tAsWG1MmPCl!x)q#HUHOLfTX5%DeR;I(w*Cho^mfXj}jc8;htK4p% zMXuT1WyPN#bs=jJC4xno^i{c8H8b339&a3L`#7=OH$O&(F(BQK#2xuBS@YUkhp&e} zs@Jw^HNEDuQ)0ll9WkR;N;Nsi zg$aWePhU!aS{N_>lo3n(_4YPQQ5l)payaq9NY|t@pi*rr?>UApLld|VGV?)1^Uyr2 z#|SGORi+Qili_r@91M-(aLXAuEcAk4^8nWG4D#g67d z4T*s0^k7*I`doq$rE+$0&2-XlTh}a_j%B|e0}EDk70^PlvDA7M_BUxRRQf%`U{}s@C3<-jSOK%z z5z~_J4*;e;8<^>ri;Ze!$-TWktx;NNO=0_Qw%VR;bWcsG2a1jtC=fO3!fatM<<|&Y zY4a8_Qg>0fR=7C zHJ^PtO3cV?5^(npy)MXVQS1DvLP9IoJ%P;1WO^{VG7u#<5+*k?$nrtUn%W*r_e*ZP zZ!o_yDJOdY56_N(0^T++^)xvh5KpFZTbBUgpY9Mcl3z@~@vVzDjsE9t!G!$At=^is`(a=m606ck-u z-IwUZ+7O3%1Y3hNdA@V6A?&!?EC-H%tkkaNh64O@B~tmlRvtieg;8*2ciyt=MsxR z6rh8D7f^e2dE+k{*kuBTlv3~Oiu*k>Vr&HL^gP(vZiW=B^Z6P+h@(w~nzjvWdzTM; z>OBgMsbIi6>Jp7Y#dLNKj>(A$V|GBUWWc zSO(rTb6u$n*mmN=(Tk$jw`JiEGk?BE`oE#UZV>}v<66~GG{%-!i6|`7eRAVf9PcXx*0>~(+bKVP7f$r2M^gc8v46Mmg9my{vowNPobSZ8hE21y_n3ySBMy4JC2 z&7Zaa?;cdNCk{ehzkaPGc%^P-#pEJ>Fk5l5(#p@Xv()Gi7Z(RMpD6__nM4B1oZ;RH zw_{`sQpZx;i9DId`qph%^C68Egik;tfho7jwc;`ySw4T}?6+wcEz zfSwiz21{jXmXY3HKO{BqMU&HrUThe3Jf7SiFAs1LH>6#S=9kt87)fl~93D+%XP0=1 z-Fzm?e-*He;2U?pw9(*lvU09QIs0yJbF&jt7V2?1E|r^;!|;*g$_l7s8FhdwMOdeZ&v zM?(}r!24z=(BU}!ujgVr2%jR*BWacJ45Ud(NnstxWagZNfub?d(I1@l)um1cMn;4j zw&hc~aY_0&);ag0&7Z)bRs8nt+v$#Ov$Hi2_&qa|?8bJZ3;cj2C@82^ zu1kQ2XUd*Z2U;GmL5ExBPL;`EfqaVUjF7m5gqyp&ePLr~XQzX`y`hoO-A-0I8VTR! zR)5^p{&W}^Y>e^tGX|vLDx8yLo3_pi4l)_;?mX*%$;(faw{P6R@Q*y;GlQ4-z zZ=ue5@n*#%$^iGl@nCQ7?(t?7XMA@&xAFPbxmUio6aoe({HU^E^ViY9BY%6Bz#TZQ zkGM~BW7#{hJh12?v}rCHx#zsOC*3XI{IVokl9c56lHCa&LQ&SeX9*O(Wk`O+POhHbBpMt*0$jF%JP3^Wc!XKI`?6YDgld~4${dlDX>ki3h z@rDfGO0C0nb~j!boi>ZImR4KW;fYm$fbYgTsm9%5 z3R2p-!vWe}+O8Wn#F{K`W8mzoR`YEZ4P|pg$g)4akodaX>{74I#P57)s~Djhh1Pqy z-Wkleg1r{PP8cCM_L2r0e0@kyY{JaXpPKp1Y$R<8RjaT1%}v z{@mFEl3ITizv$iVWh&Tn7 zaHv8mcUf9lZ&%mS9l3gRVc|}(T4CCtR3uXyBgoj;*aY9_VwmS{a-?wE3ofr9DsqvW zwDeD4nX8%zb7D^G-JQV+wXr^Syo=?MgZ&&6e(`z65qRD(qAC9F_&V(5q`~u4wr(D{ z-IyC>(Orc31fc}B&axJnajL&G>nXICQws>RYOlCHNz!sUf4Y^u)I?&%2h#=&$*WG)i z9HyrjrsH;d@ht9C%|!Xfmq(!FQuT5l%ZEp-q{o6Q~d2R z;wR=ek$maL0||`1QDi%rLTzzV(&B$2J1I}_YUp;K>O*xWJhp>)4;(pv+Ih*AYFZXY z6hxv=-AEQ=0p8Qn?kM6_+{!rkF3{4P{le%?)S1H$FqIRJ-Qic*oBD9La@ZMR^*F-u zRVAr<;Hv>u&I}CHn(E>7^^hFP=qCuFD5Ap-o|43Z(aXv;8H2t^MiMuEouoNt=mF!< zo(F$eg2#f9bbdJnKaCaLgxq%s0+`;y_10!frXtxthO9;F>jU;{8j$%hlhW!p_2uS37d;nVZxaM%%K)Qh=c54vk)IauSl*8$1$xz~@k5hYw_$90+G#vT z;$eGeIF*MZfowgoBdY-c0}akYo!t)Pf`6-#!Ryh&Z^P$yKRmSRN2;ubYL^TQ)ynhm z<2iJcNs_$F_P=qTiQ`ZrOr5WNwA&E(wwN;K%=Ce|4JI-t$WqUu@xFhbg~A-u{&=05 z)pZxi6z~#_klRYTI4nt+f(Pn@AVB5V^Dr%iXCTkdNN2OL>WSRf%bfWR#jbZ z!3te-ZcTD_xnIU3aQ5r=L8t*9!W3-HoICZ7Bn5-`@5XIwu0UB@Q4lO_pAeHIt% zK=OpAawaol8=(lvfS1y~K>Gg+gSuMAU;1u%rk%wU=1#*USTXb?RL^9iSI70nQctR^ zD?%S(E&Fxk(qjy-P1~KR(-n=3f`XI$!IgWly8HDZ;P_1~une@)(ijyLb)ot|+6%8( z7k+*b1AuLxV2?LdiMRD)FMK^Vf!h#x-)MpM8)h8ELnLq;vvWK#D-kf?w4)2HD4et( zIA%H8q#?SMPR|%_`G7)+AmG>$Lk7O>Y>U6WZF4TG`mx;PWO?S|lB>d!RA0&HLthIV z_Gz$LZ4>f>#`Epmo^6s$$|W*2F4n#!A<>(mcS2|&GPHSUX4xkCAE}3R)EoTrx`{|< zDwWA&#N@%9rYsH1*?+%5V7{kb&Ilvsl^HL5v2P;b*8XRsF6P&z$h>M$@IS&UuVJ>M zV_>u@QT=KmInx}Z6%61i*g{~AIY=0O03%cdUSFf z-&1exh3n0aaH@N4^+Q6H`fR%j&5a^_44u(+ud&HuPHO?97&b=Fv9_q4#g^i z^X~5M7vGKC+_(gt)R;O|lYSwfnSSmC!V@?Q0UZs0L zGbY{$wzjdC^H4LfVT_Di#0L=rIX*#f!2@p;0x5f!2oV7V5A-}Aw{eik-*Z<0tQ8qa|6cLYAi_j@TJ=F>$=k-Xm>sRC@5Xgs_8-@}A@ z&H~{OP_Kbp0dLirK1`ka+XIlis*8dX{y&yq%-Oo%(B!2#4%eMFzl>-~$2iV82eaaFf~Tm3g&8^Ri*JY|_`xhhlEWU1JlIp1*(X(1x1FYO=h6+|oJn8W%{h zh>0N%JA;J0F0iXHL7*lIjfw*HWMmvhr(p=NL_Uv)cL$;jjf@a-I~W%)Ih36@1gU}6 zPC~~P+CA@p(Q+kToyF-!kA#Sl_N~~zdGm(0wGpV#9Ay({Agu=7fo+1GO;*H2UpXBx z1YiEi+vann*50qImQ+ml*Bob;YTAls=(~R{o}TXi`iZFQnI)&EG>Tmq^wu{eb=Oid z?9))q!otGxNF14wXDU(1Ie0! zQbvvZb9{@sYR31%DH9Wu0b>?*b#)t^YuYk@nO>|)k1z4 zf+2}i(Vm0~9^TsA0d`}OAZcHd&-J>+3h`K$X|YI<6Cj=gcDAz}Qoa(ZxWw}(gzgoF z4j0$8cE`uDj#=YWN+MRoN27z<0o7KjLPbLj#pyc=tf5|~jM)Y~$$G0zP>YR`>}7JQ zyUEBn!?>dc0>mQ&3C06(!WYkP75ki2RHm0~A-acFTIC$Hv?bH|ud;4AjjE0#YXzU( zH*hvw#hUv7O#nb8xORj9z!`DW3J-z4>0O8X>(g$YS?lc`KYfJhB+kH}hTuXODyylC z)jaobucdh=8hVE<@|`?IJI|Ph=z8BAurcN+3lc^Bscbp?Cw*9geE_PMvP+3I1;0eJ zHm-3O59xhbCiP5S9dJe`fji3%uySEr9^kyGFW%z-%ulMK zFd)c9+?NU`b+Bu(kQ}fN2}?5=qsK&oPU-QI6HD}TOulBY?UG}ZE`#;<%LM72!ZX`% zz8(QZ`HSxocTKMDaT#gd`qj^W?s^4h-{1Xd;GXq9RUp6Ut%U2mSOrv-n3S@1%Wpj6 z3FnG?R#u*XH38G9m@)^8PHo-!)%kD0cAISFZx|>3|PV*(~;R?n&v20UKgXt(uqQlP>AEfi%RlSld#=MFl;CLpHX9i;ysFV$ zf@oU#Gys6}hJs$hW-(`8dH0aM)Z>6))0ymPtYG$IwrJkz1q-g@{{C*wC}FE5&(yfP zC@IH{-|Z1bI^s$pSY)+4UsS48??RH#jP7yAGUeRc;P`jT{I11npt!d%=~5y!P4qNK zGJR#ur?}EDe1QC_&lbD$BI9u{6O4g@q33-wQzITg08~3|?pJom*uFu1JJ*h-s0@?I zm+yAqv``7h4;Of~98+voqVW@zo%02b4oKY_+Vv}UR}Ghq@JeEk>(#6a7|?f37BLJq zqP!O~a0U!pM({3cY+B=ow>*zKC!}w9aS{jliu(K~zi;I}9b9xVz74m%3g1m{XMzn` zk9glw#?0(!QMXgkPe9hRh2v5`pPiaF8 zislPx?ShV?;*W+{NphexeP9HPd|C-xiJrQvO-wCA41Q7kKf#i^dwudlfm~lqE@R?z zkR~HKip|lLF}{BD+c~HRZtp1st%Qk~1G zgb@E(lO5%-NV(483=ke#ap;#*dW*&Ig_@e$4K4?)+ZfzZDzkF)?T_4Q^I!t{S!w~d)#XJ*jE50o z@4}38>UydBGs2n&H;QW$+S(}}Xrl9Y<;w)+ya5(c~o;b2$1ByB&m2fS7 zu|~2FS|^P8&)9uEh?*NE8`#lvqDW$w*JK3 z4ud;iWeN!;e_9dAc?BYka&n>#{+?aX=FPttY1?#}zH;51-h;ok$CB1im(=DCIZV$? zHqRzUAZlszK5n|3oN&S3|G;y;CioWf7yHB=17sn&!KzFnxgw7iCJpC%nNv z2;;lQ`|koi&J*K(l>+pS_w_#*t>9lyI|i0OF;p`QI6DpJy_U_aD{3rH-agd>R(}>i z|G3cxmxA?soW5s^29Ecy*~A1{&KHzcPHj$S8RPc_1>+J`4`Djnf9x{3yM>vjoPuP6 zX0WVOnZMuZORWfdf1@|4&-brxc$h28V|-Wgrl>`9U%~NUyf0JvVU9xVERwm->_QV` zI(NW1(8;n74&9*6ze13AB~c&!z?Bq;8uEA zux$E+{x6D9ATW*H*18+dS|9Yd(soz|@r_54t@;>ePt9>g7?wUE-8gRgHd=C$kNJ;8 zgh%*bvCrw%Gu5U>y4Yp(rX>~3@jcEHRhM|$IGB~_Va+FzzjCMp3K(%p-r!AU3!Y&9 zuw?&`h1JpMMDg9<&PWV&XG7uH=n#OCt{$E@Hk~TkeMu*asM0>&Q<(1d>=AHUX!r>u1W|ZNg)5E@?z(<;| zJVs#!BBztxgDr|0iKuj8NiDt_!)m%lM|(mxm>BNfjN4B##cz(rSi)?UEH!9^g6r)gHU)h zFOPX*V?%|?)Dm{h#o@cNI^+hyfdJ=%J*dp%(DAB!CZuueOGe z>M3wiTF}tjo%bte?p)6_DVNt)m(^({V`zJ-`{}Z0yA;{PxCCCdXRkigPqq1KDE(Ez zX2ue;GEveMFQYcBr|>seq$YfXpXd+*BAzoCIrzpvDfH(;Wg=1$2QoZc_Bb*8ze!WB z)8w*SO9tlDNO5v6KxEHo&~DULKT~I@O72ale*z!#b^d)-c81kYgZYy^Y0h+N2c9*jqRQjs=#3{~`^T7R zg(e-P{iFs!FSyaxqo2b zV75H9*7i$*NO;e?aa`dKLj`F|ZChP;eh&Gv?BH!nB_Dpi1xd9KpOenEG!`m2Hfgcx zx}Um~H^|3nPX)NT?z+_ULuP}>^Pz7F%6yBdjV)=lT`O769(9UNg_oYUVo38Z3(dpJ zP=WJVP98YPek@S<{dD}JBS zNdQGIZ$u^Jd9focJ)IB>t4FMNa8O!j3vql=x+F}E$P1F!BB>}q&tfpU?w)fr0#M=_ zv%~{}zjwCd=*0T@+nE7HVBtK;$mi^!0MF5Q(<0UoHOlACSWxXm4)S2_p4TMKo z$Z7YTeu)N{eC2*bF|HT#b>Pyr5(%XYH*jpvzr7Bms-eYBD951 zUFHzQMZr3oY(~mJ<-;#d%7F5@&-Aw>9)d$@aj{UqtGbAET)}5I7ob@}CMSv4&|vJ3 zz$pv%&?%RG19ScOfjRG!NW7y&5W+)0kCSYjR&q_L&Nt(Vov%IIvYI|J4U~gez_utD zev4Ka74mFQhf%2bum0Qx`^(^aYSMl}QbGJ?S<5mjS17<6SF5dfT8XIj^)P}_AlrsW zTf;=B{pB#gQr>5aCNGC7FevimU~a>ZwEOGMJLiKc0UA@*eD(K6*4b#DG=v|85d4=6 z4MkTVuhHweaBNv$HTC#y0fetJPkL0;7y!~XMGgQ6vVyeqVxui_qp+}W7r+VfdR&{| zElnIa0ZgaHf7}nAItCWj&0kD~HrVA*MTO9|iyY#^{Z^C-i>AE%=r1&Zette$S`dJ2 z*<0^H`Zj~=4cMU^_IA~xo@eSd+}}0@ABu4UM>?MUUw_5 z%RKh>_F(AJ8l{{AXRA0cjsynnj>p4NI`s-W1#)0Ge}mD%ur1=C54f8fwO{-JzV)QM zadk5zSgSk(0DV2r+RY%6)A0aX8YS@9@AD_)_z`{;Zrord<>p1;aw1@p)$fuTl5r)@ zco|)+!~ff0K65m|ibvD9fd|*t%-HoNwp+xzeGyFgIl*LM&=N&1WMS5FK~~B}#@Vqz z<+alfa>9=^B~Z>Z)Zi?yUtcfbUe*2SLmsL*Y4Qv-5Y2f!G7Sw2>oKg(%)ByvRj;M1 ztW1g>rW+8CCI}m!(c2wOZ#5mk<7^!r8sc@o+y=O_cb;WMMHB2HBu?|tN51sT6_RBepF;tvu3GkJa4wN5xHBP(O+!OtR3~+wL4UH^3C1quC zlH~G6HeOzBslSB~H313$V2E!|SB^k)wWcEu%j|P)b7e!g0GWKWOJj%4pj8K8%GOH_ z&Bef#lWAQ2L?E)eS~fB=vIK$j0D2t&QCqaAczAetd0VA87VC$+LECs_aBy(VUycqn zn*rVboY%^_z8raIrv)75STP`DnIz0hlF%hqgeR>gW)VZ2$QQ=l}cRYHuu!o0Wzpgsx6zb3^NRcO?V5$*5JV>9WcrKGgDT^I@l zHfYfMN!%PS#DZCwnVHGR$as07VN4z7m*vCI_YWx`LE`qk=b^n3Yk^9eOCQ4!Scm)M&%01zqu+S1 zb)F3{VxX(P7CHN(QIHk!8S>K=RBP$!xD-m%O0TZ2+S~E_R501LE>cryX=(2Z8%};X zES&)8Jb)m}PX%sOye9!h)7KYdd6#2->>3{zH$T==p;0Ytr<=Pj`R_KQrO~?;0MzRq z<6Noj7YmQb`Kv8^9ai9IbaX>{Noi@Y+a+6M4hpV303}{PGu<6d#^>a?)#A5X|C7XQ zgn@|(Xps6(bbn8uNU5BEQ}1)x=z0g8N$?9@Y;mT0;Takp9-g1qP`|?v=CEBIjtDTW zY)^GZb9+-*vNX9W1My02h@_CyBLmt~ud4*FQHb`hNz?*YJPO=~XsA#kK9OKT;rV#T zMJa6_^!v*OelQFgA~9+qGtM&T3{k2%B3sQ3NlfSC6MpJ>l5q{mX`cYUTZd=%|J2Sc zFBMGtP44-epEgg-sZ4K1NlD3Xs=)vEnh$iuX91Xi#|yQ9=43BHAN=I(({Fcd%j^TY z|NB?eM(taL^N3vLhhLpP#yBI@&yr;$aLRczAiKm;hK4!+7-zfMnwoos?ZQkShc(Wg zr;B-DlBElH{}aIj_Kc^1YUP;w{(Pew)+!!FbaLG#G1^BAwnB^aL-260!i(4iCRmle zU9;<%o(~1z-Lm8D4xlOFnH>wqWu=r&0(1)Rp&Rwbp05^9uF_4OQ=fNE!vG^Q@12xA ziFTq2m**JW@~>sfiJl7!SP=#tH4pF6nS~fQUcIs8&4uz@3GCD7dC=e$Zc0 zW>V7SITm+4P=l;*1#!ZC3#*SnHxy#1b1QdA!o&Y(Z~Wy9NXXx_qp%l?BSb>*)~A)3Xh=O0XSdn-7~FnirY z$mpj$9)C#1Sd@qE$qu;;^9QJr$3-Jmr6vJB9u14hxAAVcR!LFLrSbl_9qr1DMxCdX z6wk=!1hJ%4{BKJ1`Ead^sTfDt)4Jz}aCL^gU$zfZx26fRdL}>hE9MP}YO8v2S5sim%prhuqGfW1XsOADm0RytFm zOh#fn7)KK!N7K;(X!Ze4x?<|`bftAE5l}v16&^XAEY1)Sq*9QOY_xd$E)(E`MP+>` z&P$p9{i3+qWDRayuP$(KCMaQ7&G`Kw)F}jPdQZnvy?jCPEalsy{I?znb<&pF**hISg2z$BvWE_vU6{iP8S}VR6%k zEg?0EtGrVc*-|2D(r&IocdAeUQcXFa_Jq|r=Xdtn+!MFQOpw2A`3E`&f&2ldrSS2m zzMC-T0#&HP7#6p?t^dOyc6h|`L|UM@T4lYCY`qSTO|w(lO#Dj!S|z2%r^)Z1@I-=c zKL!BC1h9*gE(ZFSPsJ_b9v{dj8U5K~re9*{_TC#v&1Gyy7W+GRH`_g1I9!7NW>xCD zk3WeX+qu6t`hs)&vFo?M-TNTNYL(bwI8jm({xeWpm^P&1+$K=t;OWJ{(Wh|wd3&|+ z2(|M0Cr^xfuyML6T^LQX-*q^dH%2g9Rridqn8aXZzvHN*99h9jMZC*_LYcTBM@-dE zIZ*CB0e4G8Ieqr_sEp~?ZviMpfyWohJV6v^H$H#jc&rZwREM1XY-$(!(1@AXsM?+W*<;*tFkAw(u|tz z=40&VQ#>o0V+Fo<{LHD+%c;^(a${05|FDz)_Xx2OA@KL4s+5DU3fdS|sN%^Z(Jw6TWMl~%P+BBfLenZ!XLNS$i9wsw(oZ!=%_A$q!RxnzEt@-G!5gymw0P;q@`z;j3 zBX%R#{YGJL3fmf^W&2cI@h``UN^le{WUY^NN!iBmc`DeYt_@>O> zl;(l3qb2_z8h@Lbns$Z~?@m`z@yVpTD=?$CJ6Il9DRAlvy3Q=9hQZReUGu>iL{8}qyJkt?HCyh+Oq%w^G&D&mUD@z` zy3k{?(EVQ=VokbA{+|(}F>{_=oVS+NmilrkUs|UsJigz^BauWzJnq({Ed~yg->FIV zjj@=eRg6fMYjd9@h0>Ex;q#hIP6kehTWr8k<(g)Sl_9v~TR6m);Msgxa zA|OTD)O5wusUHu?L*w!a3Y0(XNV$g2{(%Ia1Id=(Pg|Xku&^Uvl;7B40fHmL&reW7 zrlz(HJ@$-NuLlQ5;>nJ)*XP$Ly&4^S9f$X-8|JsVUc#Bg4<5eC^F#M`E<1$?mmpbr zAGGB;s`YAK;XIo@^EzxDw#)@<`Im@t+S}`oCaaqjPhv`NqPozqE<>8?x0QHK93}Gt z#CijGdgN^rP?QhsuVv-xSos@5? zA{7M~9Qno|5?z6qBJZo;NoQ7lR`yW6IbI?Mg)>~DLk{vldmzx+Zc9C9hwBw#k#-e) z%ZQ$GV@I~|-KdB&-5PIv_=DhcN4Wo60D``ziGQ|eJ>f%AlB3#QM#aEgdc8(OSaj1f z(ya7MJr%{T_EK}`+E%=+Y@0FiFTt%%qt|n3pe{wwunnp}#W=F-B zF$GV4L=#O>7pR07DQs!J5wSP*HVr-LF`-1wKNcQ&bnH%ioK4`)NKBZ`?``>kC25XD zLT>n&TH@+Mru1G1RA%d$@^x+er=>4CCtDd$_>6R_)ABm{Bs1E1Ci;ORlak9{r669# zt6?B(#Kgo*j|>?h9`yjK&l~5J>og-%Q&U-4*;ayP@!X9y*v*_iP;s9*$vwZC%k;XG zLhuqfZ%sW1w0c{duNt#_eP2C~TwgmuCC}dQq(|ak6>YU4thfAwYzTFfb#$qzA!LTv zMj{zFQ*r`fqu45y%Zb`*TgKmfd5vHhpRo^5te(HkYFG-i_IZJV*!RMzfVbvfsh>f@>8biXw2)7<@6a6q_0)6`HFFlr2t zs&a~m1GQA?3@9@=zlTAuZ9c<>N;YZT>BITCIsM}U9>Y(%0M%o8_ z>|#oQ2B$ugn)vGv-!0^lse>ju`mnGtpitwT_I$P6q?6EmJ3a}DJ?H6xddSHfFB$Ix zUd#`VZW9V-G6bBPM-&;HJYIHrv0SL+j8)W4AY|d}w{E=*9 zd*wCh`(r~t-1`#Cduy#SKj#@I>$Z|rwOY#v#7uW){dq2r!jAOe15oM^gr+0 zM{_CRS2Ghhw#Z)u^-}d^oZwB;6mT_a9pi6D>=#WGEI56#Rxa{g`Vw2}_#16d{KxbR zLkSn{Wb&S@s&7Xwwl`mRc0KdRZpkI3q?C$PS zmQ@XuJ4<1SbPQO$kx?;Hhl4ENHh^ z%)99MD#e($x8>m)f@bbBQ?^n`YQ2>U%ReZ^m0q{X+|`E-ZG8n#YKeq*&t)m+EF^?SNTsMwB|MCbHUR7d zC=DI(K79_fcXnO`G+8L{BFf4!r3_S*lm!I^Kv6I^g9Q7u3Fr`R9!_RT6HAYaWJqbAma99TP?AB9y^RDey}fpbN+ z@nm=2Jf)!##x3VyIa>y3AR|H@CR43|;v0ZfmW_89phUh2CST_&1g?J?fsRW;d~PaS zABr!=cS6;{{dTeuhAAFi=KcDoQM<}ymdvU0R+Z0t-yd%(n`I�*v>KdtmW{i2{ic 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�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 aV$2ip-0sZfdzJxzh{N88D!&Z*{{I2&Ho|WJ diff --git a/develop/doc/_images/graph_construction_example_all.png b/develop/doc/_images/graph_construction_example_all.png deleted file mode 100644 index 261611a5721f9aa97874f7e6d897fe48cf667db2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57513 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 diff --git a/develop/doc/_images/graph_construction_example_forward_backward.png b/develop/doc/_images/graph_construction_example_forward_backward.png deleted file mode 100644 index 4c69687f4a6a181138f3df72ce5e8aa48487b5be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50107 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 diff --git a/develop/doc/_images/graph_construction_example_forward_only.png b/develop/doc/_images/graph_construction_example_forward_only.png deleted file mode 100644 index e668c16e0cac73acb4e5dc2b1827557ae77126b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30790 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 diff --git a/develop/doc/_images/pprof_1.png b/develop/doc/_images/pprof_1.png deleted file mode 100644 index 8e9edbf377672d0ef40f2fc7bd39e746923550cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 352710 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 f5jO zzQ4W+S#)+pL)wdCh^koBxWYYDef~%YXa)tQK^dFqO})8M=k=S_B&8?And^FpI7ydN z!RmIvf|+%{ZZ{eVpDcAxHmt)Q*|~{>Q6v!O?HfS6Ker7ORm)N-Gvy=<#CC4;*$RSJ zJVWl=3nBcjkY@roOE+c%AVFh&VDAZH#IgBvv8)PXHo4le*qtUgpIq!!fzr1?W*|Iz zwOvjaaI=w7)QQ6(vJebMWd4DvvpXlA_i(n1e~Gs6I2ny*f|%R^p&^1?Ew7}6TwGcT z_qld0e5{@HuWq>h<#ahXC2C=Yg$0T-MQr9OD%0%8rzSvR))9aa6B~O96NZr_>~-`L ze{5i3rHHt=WI8mhS2GtVo{XmIgxK{&iVYGr{( zWEK<$^Fn(U9WXBJB|J>wZscV`jD&d{Y1>|5PtMkh``-5(1tSM$R{IZ1Vmv5l!TH)! zHLJGHIR%Q4DTV{+<^3@!=|4g_o)(CCHW|IFV+xv=%2Bt6OyIutGHI~`3r#@~lN zaPLc*ar}4v@j7*@W&dyNZ)UK4$si0dm+Eu`4h|k9Gup1FZR|e7KrFUL32B`6W_H2w z+lxAwqHo_9$Vf?Ne=ZCt;i00^j>>6pxeW3gZ=C^o6Z{c?y*;t#Na8Lr!^-iIx(RPunVFZL{IXV^N4*qYh>eTq@D!T6Ns{@;+RtWVrc4fhN6?jwRq_L)X&DUVqrBo+Z- zDt^G!1Ea12q`4md4XeB&GBC9Jx&t06N_&Wh`+W$s!2!?ionJ{B>2bzI^G7q0(Fmn( zhsuH4hyO?>-G9BRRnV{cHdb=`U?OdX{8Ai#hbb~PDkNBe1~qyvp8=#?SrV^o_EtIG zZkp;IJ2^A;#Kp=&Dx8Ew@oP_}RTaHZGQL29C82+x+6&d(5OL6(!iY?+RRm*PUxFN0 zUc6pN_EHDW%7axKUguP9Va`{ZcZ6J7R~H-_iNMWQ#FoZbX9?Lf$DQP?T;kUjZMtOD zcH22wr1a+K+Xv(G09U_IvOw7q$nVFQRc%Uy`=$^*P6+s4ckziWpa%iSD}LL?Xf@J* zYTQ|7ULgt_T0~9ENPxLhp&%Bpg#y@@J#%rgZ2(*3%Y^UH{Vp0wc4ifE}re>KT~o{j=}>9wV_I zz`{KPe}cPOZ>t0uA59HE0aLCln_^|$fI&rDm8`z}c6s(}_yum}834%_@LthU*f^+) z)8AIWM;wGu6MQsmw&vGC58SPiIBeOXe2r(JG@b=sGF2_hRE8%Ed>=f#1=rCLSJu-b zlm22;8|j- zBhiUiW0O}<=!-W4DK3{3`K&MXwl#Xg?**N89(!a6KcEDG;MKu521did{cMHF=iF2a z1A;0VhSif)L@HH$qa2bgsZ=mtK0bI>*5Ai>)6;WeS{)iF$BusC4YR$0!TOFjy&8#) z01FftxQ45@4S80EOj08*2&h?m39$=wU&d-N(Q8VGT?z|T#;Dk+h{ocGAB83)4qs>Sf#Sg8`Lsfv3VtGEVVOZ@Rw?9VVlrR>MwUoSIPK{l2gELOY}z`9 z`Q-0+tD&UqzsleQgN{vMW)KjE)V4q=7g9ckcYW(jlHJ#oobl z-$m%aq2MxWg!Bzrkyk@hCnO=juG&JQGn<&$a;P2)u}{zt86ySO=iBze0=v!!yrzf* zv|^k#<%Bn+;%VehmpmDor9dSp+Uj0=L=y%^AVxKc1V&0Aq8hIoM1lCJMA#+USlAqrQy!S&)#HvoHPg6s@rS`s(*}X!=yXS#_Y2qcp0iXGP zN*&vy*o;+mWj+7MXK}ex9!U=#{e98N#~Z95*dm-Ax(S1FSe+OoHfBxRb;&!>{RFr1 zF<6Ksnx0`L7W$Gv#_&EuUfs47DYAH=Iq$=Za$Rp(DTCh9Ugu5F<~>@hRzS=x#|$wpS-QOh9t`hIS)4-}!F%3#(xa)y zlBWhMFEt7y~fEr}r8GKj+qHET>S%0D4>n=6A#88;o%T!y8)I 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

dDPd0is~dWdnaK(Ga_NKg>nF88*ZefVe; zR1x)kqn01pI7v76_ie?er<~G(7Z(?3?Pqz*wwO9`0M<-FbN{pW=R83=^i+L-vWA@z z;dzc~fAn9Wc|w6kNC=Dm@GEedvE5tuj$B5u10o%ZH+n7iY|Zu~&p^jK+@u$Sem!0@ zr-VZGd-b**bXI}YNAPwo9?SivCg}0eEC2csbCb!|*LSTUhatb^@X#VWDoUkS(j5*+ zfDi8gjPSBae@&F(j|mk@aJ(^Xa-Fu`Ucy`U{d+*>cgr%n1-t1dG@WjZm|gmU`Xh|S zl@B{4K6npW?p7@PiF=^^z^zlJFx6lmM#9i zzPs2EZfFVXdwDB(OhKu7NGmJEKz{k(y34v~DtO^x(a=IpyB_|2*>|+2i zl{PrJ7Pgeat{v#9`iP5()p4KfU|ZSPKzi!!4MK6gS8Q#811k5RzP^B;kq0Yw1dX0z?xDPeS^~&eniGzj6}JD-O>4Z6 zj(4Ct{%JpT8(j+eVnPNoUJ+~;Tiag`ITQ0Ap)w?AvuE<{4Gr%?!(e{y?Uo0{#?lxX zw0wfsA0L+)y70{1s=V`MXMKGfxnMOm**vHEB#oudO&z)#_dG?lU(OC$g9!wd<1~L* zpsJ82Lm8`J7FnhNvl<&>dAA)A`=i?SJ0QpMRby4ZB5la(CV?q$Sc6NqkQi#3mO%cd zQnj-#Dxn3fYEgWm`CQF4usOfnzfSEvk+-D_I`42(Qd13d@x>hDx3&a3L_B-tW#p)A z3%luJ|G^LpMx=t$LY#wp!ZkY*Dm3RQB5&2uL?rE0xBjts#Czz%OFm1;(CPuOVsJ>v zcLR$D@!DR6?gM;onZx(Dp&ggH9algR)L&D@vf^3L=I~Zgd%l2PQLcZ%CpTx2qB4?dIq~pQs{Ph%hma6;$@xfNQ>C z0u)GIk0ASdS)oTL$JYb$u9zx{&;&Oi{ z=i!eQS;z)IY^fkgkk2j8TGTdZA#<_rdC=TnTvvke5tl`H*P%*yu*D_ESy5XLrRnz8 z9#WlOe`yxG^%$On|BBt&F#3RQ_1iHam&Mc-7zg}^n3VJb-DbvWb~aIsHj9^O$qFLo zg%9Z3={jHT`j5=Vb(-TPd>ClxK0W78|Ix@mLh3bzdU}2~aGdU%c%OA!b#omSOB6JG zimKF`rShcM#V&|o@);*To9MkzT?VOuClnZbBR|litac~w9XfJRBh~S>SyPjzmDa7d zW~)a*&cWLN*W0-j9*E{dZ&KB}+E!Z33op=4LSp4#Bvce3ZAftk_CE=rp1*=NULv;(tIk3R9*Uch=;@hzH|*%aJYKI-lCl_Q z#pf&C28_AcnYJsXIlnXLE<)$Zev=XLPKv5jLD*2rB-3do&U5Jo-e2}0LKCnOXfLhB&AGc_$KID933oIGz~$)gV;Tp-v0 zN8$QT^kew5Xdr3-8pRxLvGYTfh$FfFtiBS4ioTeVcJ8J&P*-Qob|Ok@kc)t+$PWZM zY`+M1e_0`6sE-ap?6yYt@!)*p-;OWN&%2fnqh5I;%P$I$-R`(s^k7j`}XZwyD>)0IriPLds)_l{S)cUC+LzY!xyp|+9bB@=_C7c6iBt1aIvtEx^yia zMT>-Gth1$!T0*Ee(@BrBHXi!&gj`G@+c!u8$^TfKorzZ%G%n)IRq4>!(EULY3~cnr z0EQ5Xh)HFunx64{9HlI5&fiv$xNPE}8!#g!VPF3E5zSXhx5P|K8+>=?+HyZY{Klzk zfpm3`P^C7sD8_8%bfbEbexNiAT1`Hc88((5C(>B^2kEbhg?7n}PS7-N{#W z%V);JqCL!ubQ_BD@;`cC+CRh~ZfoyXy8jY<{_!5y*CM{{Y?rj*X{6i9hhGvGmm!X{ zwB`OGoLFI>YS2NfnlQM2%J5Xs!<$Aaa~q?GiK|Rn~}d$Xb}_i~q7AtHnP!T-ukB z$NBEhmYigTWni>iO%l#p-bvtu;7CATHeK))?|FD?aZNX}oSR*y>`+686kgsEW*xYH zU_dykuF=cWlb=ucpF&>>H#j)Rt(wQ+6)U8@EJ}tu{U6UL`_&67*Hy63UKnw?;zyHr zqCeoKdX7TvJJnwBar9lz`64Mv%gFp)1@Fw=&Dk~%ab;IjyVND^P zs`eKtbG-^WCp{2_Iqxq>(6>i6b5ap=c8&w@N^#-i1Lr(eGQ{e9gy}`zo@+U$If6fu z5na*Y7IbvJHfZkF>VhsZvnggZd0UZw$q#O6S!?oi?kM&4$uqbAN239ecIusXKz2Pn zlnV&~vZ!^X04kVNT{zZ&Rxa&0UsxYO&dRD^_maSNSD zGZ*q`sct*dN(U&79vTvjhdGg^>u2qMEQvblV6K;QktMBECnpT2g6QS`>)$4=Nq<%LPcHSIh zXdg6fO-Nn}NwDJsTI}(0!KPVHz<7EE-#fbb))U$KfruuH>MZ9NHgYN{^2!wU6{ULxXlpH0%$K8;fQAj7q@ z7g#sfkCMC6WQ994?12D?c03wMQE#Z!78DibiAP8n6dg@`b{4s8_Qomwt64fF^9iA0 z>cwSbj1a}Wm_@aoP;SPWAmWy_3=|9!1XR7-WdWmvtb&5}k2*s7ZB&uI7w9tPDPb2O zf-m~S!I{ccnr&y}DfSoM@UqpakRQJYd%GheRjUT!h}skrSB9;xRED0(s9yZ)i`(D| zvQjkFTdia&CRH3MDOJepzucxt7W@(y%_3VAkQSSBB?-I@F6Am;T}wcnu&9oyiG+)N zdOvq~+4+`dXagV`*|k*;7Tq=87_o4n?Ku6gsq^mO-dcP24x_bhJ%_m>5;>nsk_FRg zqe`Tk2t!L}#&XhU z_zy!!Yn+L4)tC+?;!GD_CM7wuROd5By`Nez$XJz<7}gJiehZdZ#wD zH@)V9J79DaezQHQCyPX)=M=@vw1k|VKGQGHHj7N%_-&~lXdn@2KKq?B{oT92brq$2 z)s>Qzyis7){^99vj<&aNM($SXr|qXqTS&-NJ-|?tOc3F+kRp2as7(Gaw5h2p$}yNX zMG#jUc&do62nWqYQ}D!{LVy9Pzk8)jo?Q^qQAL)tI#n`884208L9{Or@>E_w@riVR zKv*UhU#QU!nx6iEK!}ejQ3aKniUTBMU2e}4lP3ATy;ciy;2l%MZ0^mh>joZ=U%=<~ zRzNMLG^$@Z?aK;*p(MXFimJ|Ppodt@6Z{lc(%`j|DAN8qzTSYVdoOLcjU)E6{t&wF zX7<}}o^#U0VUHOHTgMzpZ@1i=k}lq4;lPWP6(po0)|$rInVHjijX`53S%y*`Kp@Fy z1YKUj6Y8NcSOxPFsDONYy83s^cV&EL*#EQ9ys@GL0lmFK6@J$$%1vnK=oVE7d7_~5 zrH?w5m0^IZs%KBQI$i4FV^dAR?v-L^H=3Zlc3|{T0igmR<{9c{0H?e!C@u&CAuq(X zNT$L>DP7vi{;)H=G34)2esd?0?3rHSQm62rm8jBJ)SLQ9*&h!z(M%Ixcc1?oGmbVuBfaZv)b{bbe&&e0BgESDXZ1 z+5-n-F%tqjQb<@45YSzPn3XIkFBg`s5qoS9IB3)XD;?Y4P zemC<|3g8R}Y-b1z3=DV9KTUuGZ;u&JZI)vTc)@R>0svoJ+Kb-ZpnDtYKQ3Szp5OZc z0@s3`doUIjA~a;mP)D=zS}2VEq|pA{mn@F>l^G?8;R*~E8^E3wRXN3lz=j?YTd4Q8 zda{^y@(pO)(zd!WxVF(SA)g>1NXz4MI3il2{Q>j^n!N`^DJ6aBLc%tvl2jm0|k%8AFEjyGOGL&POX zOUe)UV}lluROU>TA(0rv=lXzJFLYeszC?+T$LpeXp_zwyo`GR*(QV~9@~j3odC$PX z;UbFC_E>tpdQy4LWJnRU`QXl}_}hN!5eoRC|4GJ9ux|k>2%_o<=z9suJu{Pc=`quX z@6_6N$bHgWUrzive z>_k#fdVV}(NYmFF0=am52i8<}+_*3Z>F5w=`|?TzW+Xk%K?0nVjh9j8hm#OG%4 z{@5?ymKy?jrP>pj!^%jS%fR)d{hfeLx4RT8k!4wc{}u0bm_$^p^C_}@-FKw##=k_7 z6)_aympzQFTfe+R#$iZjYQG*afNF3BRLrw0;OeK+Q&Kh~*W@18qdd_JvT|dKX zCBeJ^CJ8t>9S9Vz=arl|IpyT$_OE9ho(L}OS2HSvzoozpP0-Dj04JyGjC@#F%Q?3B zjJVIopux@Gzws|59MTPQGDBg;goSZ4Cq#?n+ZSV+_6r`i=||ARMD5#}QS#0a^N$4l z-K+?UMcT!=*L9FoO}x(mv8yd_PMc$9=JX!t0I5o(hWZHL{3)M53N@4gUegs zlybqoV~Og&(?_e{KtVuh?g6EJd=F5!$TJ9t0;Zh3Hbj!P-+pVk6CSi80ISaYRxl!x zIbzE8?!)EN>fq}^53?j2R1zU$c|VZv;HfugW!VrBebR%-<7y!ckv+YXrX6=!Sw&|q z4MCiPRwPjjiWB=qrS+H_wq-w@#JNvUUnanRfTDy-3O7Db@azt)C`lgE3?WE6!8Sx+ zj~B=t&A=VY5ZU7oGayQvAN73F3iI*94igm#6kE~T=7{}=m-;iNrFAs);c=Hf1w0{A zDRT}X`R=b?Pfk{aO-BV?7^q->nb!#(o2GwwFzu>Ev2FhnK*44?ex8el7(U~O+P|CV zNIPWq9QUiV58Te%`lTXFfhCo&W5v?U)D(uAdZ>kd?~9wx}HaI@~Q-%SRz9f z24K5xIi#Yc;0M7>CB@fJI=&~y9qzBK(NV~S#Z)8=fcRt7UD7Ok?GA)}d!~T@Nh0t8 z2AdbI!~8nTsQyDoQe`~0+J>`6;Y7%h>B^R2_5So_n(-v|I}L=*dnw z#pG>i*m*1W@;dHJ!b*=Hs%ySRN_MujXXgDsK>sgx|Jxi1cqC*LA^ssdO5C>WbpIl# zCDJA#XKNy3^qnLAv%A{FBlKvK2)5;TbkMG=^y!0Za zP%!PoIN>;ATpx8pfHcbULNds$w07wQy3s3cYJ!f8;_`##W)nmK=ydys5v9Bhm+c`J zZu@+^!oostLqYyGwq#bUSHKPa$gsBva2fU{_bLi>UO%1>KnKyT==s4zuS2xX22WG8 z^M9v@_lIy!`=W{ivAGGUXbUb*sP59+Nz=9LPYug&u7|4f8OtYFC4mhNGkVdQj1Y8D zRM$n>#ibACm=wcwnhU%lpnYvI2h(GJBrX_u1}r?2&VQQ+ZcnOM*>8wUOLFjO+mC(s zogQuig|X(Fik@kWL$W0&Z7QoUyuW{Epz?*>oop=NBc9bSbWEpVR%L2WLGiEuPVey2 z@6a=^D7EkfcGqNAF#r()G{#)5ZHk*bKy#sD#N)MpUhNnbmmA2p?zdmPr#sKggkb*} zt0Yzmi-gG7&4sxGZUqgK70ujhN9O?orW^@`O4>|sM8=Qswom`*Gt>bfX9hVDi{T{K ztX*%a8TO%zr_N@akn&2H6eBOO&C}#kUa8iHMcqPH@aHby7lO{arDH|}Ol#QbDBKEG zUiKX!v$EpX&->@~Eoh!8VK(U%|*#8mtM&@pq~x9%sh zy~t3swoF)Q1)^qj*vYCwJg3t$GAj;cofj~cUC?;vrpVOiK&{u|65XJXQ3(;MZyW z618I2PpJO~Ys_*t%pG~~1ub7Kd7w~FK0#?JKBWtBiL}s;3A_05ktctyx*0#f?l*k|7T(xopIaj+iXlPBU{j9@C2IITqFxH56}^3SJl{`A5uXnp6@YR*T|(}| z<7)y+WG`Mt#fqI+Z;R1aRuKe(_8C!f7EQOal>h*-%eU;tAy4wXU)>3Y%i4{*cALwd znVxY-=z3a}lCk}^trHTm{I5-rTNWU6!V(;y-+b22qVw;KsKJ_)OWNF#-#y(?Cod;>8VTsw9)u$1`5@qmbrj-ZCClu7dw>2n zE29e&tRkStcf0ZsX0(!Zc2>=_S-k!3r#~uq__t%fjz4^B07O+ir(8lpLP=O>jWX!0 z-cgATg@p4BjQGQIOMP{Ah8p3GN_vI^q>G@zLE~1Z=aOe$C86;wZ6pQ>QUu)pn+5RI z-j)c&WJw*z43wX)Ml9Xy&ab&${e;=)6SF=aWECd-McbQbmOIV-weAs)4(?2(d9 zQbo%qD)>#Uc?Nf`Au+b+4}#9)(SrREY>i>(rXmBCj+>>mvtp~-biQP(2|E-8yNOX% zELv<`e3xX|%22)Yo|$66Jeb|I%infsdq}IKEq9GY&>5-P_jY~KMv*-@xb?oh&CnL| zpxJAox|1nuY-EvKO=o}aY^9zN7g(CF?*rhy$!nYMK>8xoHa~Vg{J+Q!0mKr(uD_HB z9(+iz6EjPU_yKbAF|QP9l8Vf;br+eF zxy?-jfJ_Jh+UXyDxa>rfr3o1uC)?|P;^IPVteO8dBWF-~C16P`828pqMM~C-GazV> z?tviNn*!CyLk00ulsd4`1BqywH4C|flbasO;5X(Ae$({%;zlUs}a}m%d zVc+A%2c-^6%TR^M_Xa($GuUXz$IuXM+emy4eixzrMkd;4Lv*DZDJ?qKN>>Ww&|2Z$ z`TqmMZ-t2+x@2#NDI)@(!Y6Wac%aV$7%cK=rO|wGvgLieW*4Aink2IeG^V-xu~NS$ zvttO0BjVuM&Rl(c^~ED03G{i6)R`e`>4)MZw+C`xM~^yPxz=Ud$~QW2Udev0#f>Sj z+7%CVR}gPxgDy~LKA$!1X0QdEqSMlbp>C8at~06H^?0LOD(1gP&54;GSp-IL=tKOu z@hP*j4C9SfiQ=&@--OhuE)Qk7=sC(9pPcccw>M|FziFyB^p{TO#62&+66-;>C+fIse2>Z33LhOm(rUPLVEzKbfSO2 zuFzcyF=ymn)WOT0jmev{RlMTKF%vmgk2A3a`o9{Ldcy;Bf4(YSV6}8j>=Y*`Lk7xQKFE0H zWgfW$Po!d*E%Ikaw6K)$ofWmW=fb1^>4j`AyuZ7>4SQ9{cE>+Krb&wIzkp-bP_!z1 z=r1oX|9{7x9L>Mti@Qg6oQ`ZR4CW&9{~sF;6;y>>ARt$As9Lv3g&iGE{h3=4QG>;O zwr$ zrKa;~6=2lD?3BZm+3>L;)~UYu0oVMYpvLc+MbY!jX0ybL@3u?T%-0u1GfdlO^6_eX zz2B;)>#VB4p+{DT11dA?Ow?gicrH2(7BF7_&u`t0_yDx}(BpuC`Mfd)@3%MK>MsSTMZ?9sYR-ui_(drp6-D?U+>WVL`=T6< zYz9+0gauVK|Gn35+F}L-4i1+FWa{ecoZj%d6TI13!Ng5m*dgWBB~VAO75VL*^FN9k ziGSKQgtq~(P#yZ*$`YFiVdirb3Q=en>Y26EueA#Ciajnb{FKDRK->65%SA8sFfTPk zNSu&4$Kqy^(m#p5$B8d-|YnWz>l#mm2#{?tnAWyFEL9mHO(g9Pb@DJ7Zu%# zhz@)mg{D&cMz#^Bb;Qo_RREsFxAx5HahIOgZlz} zHFR}>8CkG-_v!b=Od;bgw2@xl+^*#v$1FFlpzU<*t{tphlE44#ZT(<%z-ew@QTTn7 zhD#D4r1l&yg#;wOI$VD}A|Zly+eHDLp2n?AF}D1lR`>NCBu0y}@`=-Lsi=_Bk`+Q* z^8tvLjlne^*g+?|YoA-DizZi({(cc9JiW%$-Ag9`c=lqo7rUrZC~@=f;MdpJ>&{WO z3_z`j`1i-ed}n3E<*_a9`EYr8X}j4U^Pf3{3MgH>zO@ozUWkG+x$PvAA=VC3bsjsN zPm)`OpZAV%0hG--)NmRA6x}VlkHLdj>2=Xg(cL*+!mHW~o_zNAxTFE|d&|q^z^lao z6+y^|L)(lrjDPo3ya`Dg4bfJEh=icLSmw@MO;PJ+mr#+p<@$eTxHbAMrG>+(=V>da zLE0OMdK}2}G6}rHHS$9qA0LaHI6i1h!7_4R?|wle+|LxdeWObOnmm85geNk1`~zeu zoU^lYI-%U+lokkKU}i=IWuc+Sq6H@-JzZ!b#G2_uZDfTT*jHC{dp||Fj?li4e?PrO zBgFO<5g}@D0$f9Ap z2#q*enmC0G60WMU<;*0Q+ss2~;RhQP=*Y+*5?S}=M@HbZK732Z+4rH|XaTsdwfEhG zzKFfBH1a*q2lvGP^U5jW1e{gNPnHzF6F_|QGK4vMf%^8XMA%uDXr*=DpF9vH(#-n) z?jU#m(5b$b^*nc|Ym#0dORwXOIGf)?I^|NU%RjoqnH&;pO1n3k{7U!l$r%}~wY#QeuBSF3C57Eav#l`~6H*Z6+z7!4Q|aj%%OTjQ zgaLV&AfJ}lb7MaRT$ov#>gdus}PEWC&ye&UlRC)|N%6J(>yePiEb zdnMo|5sx-D&`2|o6+{oA4)ivF)|-JFD??UU76~X zSpEi^+1$(tNN&edzHJ|<^PxaH^?t~Iw|6?AfEF%pwVZQ3yNvBJ`Z@U;N9qPL_fCK57o5LoQIeV_!dxUTM3Tm0GiIWBpO ze4bzx{i`Jjqb8V|Y8m%h=jZj!>>?&+QvUI86$O`l=T8+C6?oOQI6WOl?6&rvTPtr_ zBJyn+C|D3tBY|jEj7es|MZlzbILtovlcX(mdL~XU4mAc*gnPc|K<1MOg!ug|CDx26 zRaYe(;0OMQ0?xavLx<~Eecs~VyF~Dn>7Ql;o1Yzd2U<(`-_4~SIEh4%pae|`xEdQ% zYLy(5{Ssp@G<23hO`eLdXK@pgS|S{6vmLud@I8 zRdD3TSX~Q3np2?A>zN1uw}Q2~dV&%~St9n0Xfm%gR6T9)O|y6U0`?zBD2B=(m1Whh z4jchPY3b7DSS)(Jn{Y%cZFZ6s+@xDV`mc$JHp-POEAb`|24kilmmysH13bV1a8Ct7 zdhYJeuD4cKSSZPZD3OF9Urw1DG;!3VC|V*GCZe5;Cyo;VVk033(qOxel|^-u;7jE#n5o4<%p^J-|i`%zHY+k{MK!-!wR{oM`&Ec zxVm|z3VgxKMF$7w=w|NL*3luGauE)pHE3kVQy-&EXlb5^hez+>Cf9kMmIwcJM80LS z7B~&WO+zb2plGJZ68UrS62YWgJuU-o9bm&NEJp`#uF_(a7N6VeZrfS{kEk6!u4>aU zt+q|703(15l{|fYyIV?nU)Ukv2V7n{M7I&z%~j;q#m5jMgs}$LeEyowRZQc!`m4Wo zx&|XI4*mi4&9Aqwbu9~Qiy|7N)QDJsTU6FU-4wYFGGkk~R)5&UE;d$jTIyG9qZ!7+ zd|8|k85xyYieS^oP07FpO5U0A=*2~MZ}U0CDQ>tb3R zqk*bB(Az)TZX7=gAN&Xvu?E`RS?`=ana?Eu#ptuXaF0)Gd1cK_PNrRv+TY#P#Mw5Y z-cW%uw(`i!#8McFhG4SJ%*fcqB{lu>PhX(Umj$V`ON9@LmEOqq!Y^tqB9aE$dsF)s z-*A}w*pnLF$G)}gvPAd4G9Pw`6cit{Wt~|ahIM{w<5lXY);WQGS7Zo#r<(hxIM+cnhBO07&#2S^&O{$fKwFy!PKeFLCgVR? zl=#+~7F7#GFowhL5BnOCC`7>l`#u+|E&A`kWNVh_O*C{<4d(#Y7YrdbVI|Y5@mx{U zJ-B}ZQJ4O-GpfS92A76XUU7^syLEqETr`|x>jtr^;O6EwFwTI#|@??b}j(zM%^nL$`JYG`;3=e?kwJUc?vxo7VA*9c>tyh^wSZq~vXw{*L>2U46DV;cXL z&sqb8Al5W0+X~5T-NC(}YsJyuW_5&dg zJ#T(v1htQ{!NDVos;eI9nn?P&9u%l*P)0Gmt@BnLcNl6PC2LQw6P8_uA?r*~U2>S( zkBZhf6FU8+LPC~C``jr5os2RKrPwXLV|yxQD$k8XF%u8{CF#O?2U4)*5>3m}%?1$~ zS;V+w_aPhn#FYoe_k}pAR+PbQ2&KHSbiw2(NXF63ngrVREpl115 zM!QeOEC|0Uz(Q*#w2TMOBox1*+;OL%cpTKx+Rl$Z{bAl{yt1l`HGHfwMaO7-tASfQ zK~s<=YQpM)I-IfSF#T#|H%`YCS=}0OiU4fGqo4f&ZVrpo%GGp9BUjB`MK`m7k}_$x zfs%+2+5{_q6dE5#%x%+vmH%V#g8MHGiP>UyVGYz4N9}(4%q4annx&y`+PJX<$r!#w z?50g`GMme=%Ie)_sgcwp>Dy)p%{Bx~G^i03|8fRtoRF98pt|s=pCj1ai8_K$upYTo zZ!r*%iN(q2=qwr-v-SaH#(#_X`8!q9&rt@(20+*L<|ObBWzg^K8yF_z3L;hY<-{%oJTTnNWWRQ~?gGOdAH%q(3LzV&f;Ca?A={I?jf&pe+s?sU1DA_X;}d zA1e*Fj3fN3QO``0@5YrWJ-HI6 zp@qjcV6m=Qnv{IbvS{H8PTNEN-5IROC7u zUy|T#Xy5BAlxH)_C-rvfy9rR^C>SWf<)9yPC=>nu+a zHA|9HbeYsjLc7P9R(!{n_KN;k*x4#by~T?@05izFTep?Eq|IV?u<%iz0E&a@Nac5b zm)F#mF3VGq-!}(ENP3DUI^xk`3W+0$UmI0NaJ5vCN6h%B|4mk+oLuon-A>yRZNz5y zY(&0h0MesG!@xk0h|Tq{t}eBISyH8C<^f^xju1vv1|2>co0zOE`T)t_VI7ZVQ|Go{b@mt6?`vCM zh#H@k@t%bdG29~Cynr{tUsK`?m~E8BBP9+TG+yYaQNH_8703L+3-`v^tv>+ccFlPv z(kW7ZSI$7gH$5@f`nb~Pva+_GI&UqV5+1W|Od1{fenM zZF5Vj&|ERwHp*@WwUiJw2tXM;&ao&5pQN`sfk}`2L^rMO{!ci&p9NEfi7mB~KkSU! zNdA^b2EL_^Zb4i2<)`gUSV zMHA(h*(vNtB+wQuFq`LP)}Xl?!?JS%0qxvIG=ara!!YP+%K)54Fqr}{tE)+c^O z`Xy#iHZz#Zg`&tBz9o!=O+QLwfoG8Y;ET6!c{DzyhS8=a)ilsWRS5<;>b5a?Flx^M zSIVoV>;Qt9@w(oNcv;k$JMApvVEAKa$UuxeG#Gv4=TFg=pB9tee^Jb5rpa+}Kf1qH z`m;7ak3&AxE_!l!dfGQpW1Jwn77t84QbH57o=fbis6ZTvX*4OE_}kk{_N^GX4LsLm z;^%Em3VBsF2h5ywKU}1Hrnjf-fS)Xkd24(9m6o zk{E~5kteIz@(YO2UIzxo2b=R1{qb}5AYIA#g0H3R{H31N{BDVqqo}NbR!y~Lzs$_e z))obbrunt@HJ&i1@844){&s2E?!FD2B~CjS-FAJm-7CjIC&mjK)|Ho$M+^_89kjlG zEvmX)?fMeBcB_&*(#v&N&uZ94MN;A;wR`yOi~bJ&a^j)X3;r?}oZ1(hs7S$GrgA=I z!sHfez1AdXfv&-{BN-d%=ZBiI@O?@3cmlTUr0dU82@)X4CML#>5JFKN1>3>N<^m-) z6n-%lI6A3YaP>#=m6Y*#R5Ze|J zl(J?UuxBJCIGQHkog&)}9;R3*j2%h6zUb8ePbQa{tZ;EspKf?~M9;e0!$qFJq{Z*u zA|a=L;i@vTMsh3r#z>@$Z=nRutbu0Hm2)fbgOvo&O;)}tFNp@11RWC5sXk=dv)f^! zcVx1BwjsqS*`Okpqi&Sju3<7dAOhMFd~!N16R}2Pw+H%CnQS~hT`PPEH=|JAkWtJ zoS}za1qO-6Gre@_ePUrr|5l}w*KEj7yEFyjInrK|Cebi2$mQ32`T?)Nrm@~y>@$_y zc-sO_ABtPzbfuu6*c=>H->{J2`?&Ui6N%a#++S`c%4A|{+FvAr3f?EDqB0?DSnM2o zcu3cHkf0K|cs1r~|Fzb}FkuPp$n&x@YV^U%;K@3XirUAnY3YlkyzA*hB}%ZulAM3_ zc)@$%QBy8fSOl2ueP4pV&Gf2xzeY!0zH;g$1GkKN!xzxlI`Y`=dx0i#vfH`8zaFm0 zKe9oyk4-RmcJgyCL)|=iM4u8Ebi~K)o9^!jvuGjjpQ@GCN;6F6eez>AoSYODprOwH z0_wQOYV|fB!mYaLPDwI^SBz$SefhRHKJX53ME1tPr$>#^-fADrItm_Urh14diMdXD zlvA9}teckS7O<`0ImVdm@={JtgWl1z94UK!(Xy1(!Jop}9bb@22EQN3AM_aDSt`{A zl_Oh*-d$9VbDj@Ro*hlV1= z1RK9fBe;m<7@oJHN0ph&=ounu&)8E_Duyf4YNUVm-rN*BsVUSThW^l?asle{RU~PW zJDmzdK^P_vHpWT~QdFewOCLPS|GI>VgEP6~6B4|ycoK9cMYdqx4;I13FaKnHeT5i& zdy#W)Cj<eKW-)<1vwiNOHQB!|HNm!@ z3$U`aaX{V5Ke@{E#tZyO7n=Ed_epg9lOITl&ut*Xj^vpQ{#L=q*&SjFBXJPH;C8~) z>q9f>gj zq^t;=M|D0E{ID^Td{meK52;r*?W+D-kJCE=xpXh?+R|!^3~;dt9OCUsATYSUw)FT;J1dVqM}mkb}p#?aoFac(xoE~j62m0 zO(Zk~9Z}V8yZNE!{v9s`{^6_8m9&w72pTOv-0I8J!FseR#C|fyXBFfGMMxbv=V0UG z2UO^~0DAOsm`1>LZXfJvaPVj7*yykwIuI~M6KDcEEkA1|{cqte&;kHGHasrso-ay8 z+kKRGVJ3pHVU(BKJxe!gM6wS1*?d&I z-+{J$`OaBOYkHvn4*yQUPbg9zVcl&9S}G&o&(XfjFQo*X&~F{FMOYpjwisEa^=2!x?b% z{k_BlBUvGn+Rlvm!YWU67NoP48<3$VOj+WUXb-1LqQcTLFSsE3=eY`PF}-GBsCpz zXne6hBFVb~#wsvxXbe7Ex-frr!)Dd`wslnd@uq{4N(>P&=^SM0^PCUT+O{$<73sPl zw-W!`2gHFt_`v8Q>dD*D_5P?`>~MO|j`0_xg*N-T)uflUD5HVN%gtwC8ctla z3<2D?eAYjW+vwGTEJ{>Ki;EiR+1WrV8z(KT;+mUEilWCP3c9&%dz{11Mb80pb3vVS zy~h8Ksc#I=s|~hp)Yxupv$35tXl%1_8rwFTq)8e(jcwbuZCl@N`<`>Yf4TB!Kl{e) znOSSr63KQ%{tu11;049T{>jH$)Y%DAldK)EqBY)^rVJ)RgjI=8#)PGJgk{pkXyxY~-vYtDiA6wUQ=QMGNhD5VqDje59e~ z>Z9}nzU~2JRbSabBH7!~=RBUnBosU$%-dokSg z_0{Ig_02~&Syq-o6p_HxsVdcy3^=$~0@NX1XBede^Mr~cod$+d!96)k=O?=_E{K~7 z^D4h9!1^XHaMZ#n|JaV`38b-as1T(BWTSDrnJ)dX^0W}~A%XSV0|y;NeEdt8?f~}) z?MQDW^P+$mo@apAri%uQ5Q2-B$w_;1H0yyzv9j~-47*+xlDf7w6M|O5&Gk0Nt{9S6 z+x5YuFh51d^nb%gtSE%O_RVF{yN?RL*LQb~|BQ(0Q%aMQk_(%tAfTb0L83V8QhDNi zP3MDczPf_~xY+Jae4cRg?aiQnC;-mZ>mA>Ia*{Of=8?Iqt;4Femj(BqMy(o3J9>QN zc7BDZxvA}uneh@s&46R_p5UqIG9)AjXCu#kctFL^3tK|hbXjxB!6nD=MgKdHWd zQ(gVSqV$SZY0(~z8rgrrus$bMXQYW!uR99=@MQ;Ii6v!l%LBPx3l&m3yh35T^kznR zOAU4~t*U0@kkuyB{iO|pLRUr@BGSr?TMUwuhUas;?c+-j;1=NXu(~uoz5T;igw#KE zhlw_6YTg;1MwNP8UXcDp?a$;$iR3SWw@^krj6P!keL z6iVxh4h@yhe)?VQ2bE@JnF-Hl{KhShWYSyIq%Rz{4(-8P zS_=!~941I}MN&AaN;8P!Yv9Q&_H0!t_^3Ld@w_~=yuOSb9))2LCnwa<~LKYnf zojlmwILb4dmbO1I52&Pr2T_(kW{a+cijj7)EfYvwuKp&ECPmN4EmF6 z5`uxAFwy!4cToSwI@yOVR3cKK{EXaXN#1KTkyBU*PA1x0Xq~--Sl{GToMmNny zw4on=F$Z!&ZcsY9eX9Bsy2Zm@7^)edYkc%Hh z@!>@DF}C*y=W8HsNkN;_{5^e1vQj}SIX1X{RA~`iq(3b41xQ?HrlgdNFss;JwcOV2 zZ+O#4vC+r#^p6>2vrlhuB%bzRk_T`e-%AO*?O+D2h2M&fse2gQo zv=)q3)Rh`WzS@!zR+b{sS-s(*pBM<%^#nV`>hS&@*}a))eUL8Q4Gcp=c+MtqT=i{F zu*T%CieJWGIWeQK6Pra^TSl7o4JK+IJZMC#+86g7NpN>|Wz}rndV2-KZOfZ_kRX(2 zoRHhL3%j~A`t_y_k-MvMJM6<|pdba4i!7xFY60@SNZ5@-G*G0``Y^5x!FI1tj#n5u zRFKMQkbm!s6tG(-D6p!3i7k5sAd2s-$%n_jxwqFgc8Vha<>smUeygp~LxTpnvi3tk zkXWp7k)VJGRFrchv8EwI19l^mW~}`S2TZEt0L?;}iX*0^J&WnwzFtWiQqGTFMr_GL zB~yg48&wiR1ge1FL7O07e8>5?1M#@4I$ZfqGa%cYgMBWh4$jXDaBb|z+xN#FR>a%D zdk&u_Ci1S7V_5%=S}}r@BQ4aJRjcki2_IZsR3wB2^47cvuG>miHxf7x8q!lr7`@ac z8YjHlQ|&S#sEX@hmrjEYSX@}Xnk}Cm>f$hDw+2QOK>TP(q~&p*-wd>QM}l9q#ac^^ zzKz%R^nKv*hF8d_z>ThJ>AyT40p*EJ3)XFUf%`fqhrf04O)u2zqxYly z3mVsr&xtE>DWhj>@YNs-j|rcj;w3tQr}7}-_}=}+NgGeVd1*&Q5d=B~$f;N6#<<(@ z{yApPLwjfS%-ocL5QKUa11@L4j;FT>%dGZsb+MjVQJ1|k*n?EU#=WpoE&7HJ>}`-{ zRF=LCy$(tF!3{xc@V?F)6f{R@tG6r2@uj#{b=dYfGm+f;F6KhzHS$l>&+jv8HKxd% zkhBHeUxlHdp)ZfY%P09w5J*nv#XJ0g==hxg*lG^~0gu0y0F1g&g(NEUlsOeH)|;C& zdTh7r_sA+3yC62{LWyc8CDpbs=z55*;LDhXGOTvva9NDpIE{f^N<7drHJ^$?p;;ja zwti$=7BzAShu2>aIefI0MT3uVr^!aaK1^G!*SaI z^5~5nPa}Ce8fty?Yb&8?0j90YxCVL!>I%AFF0P#wt5mPC5EGA!KT6=P*^QGVs zy<&Tvy4c!#@o4s~+hPn&agp9rGG`;En36UpPzh)$K(5JI9_qyN=Z?PRFb2=0*wuFg z{5~cab~;IC;a>@g4@R?$V=tEwC(Gr%jr{!4`vb%3)CvcO(1z}6Y8+9A3>xPUkR){G z=!v(uf`+NJ#haw=aGGBRwz+WvTi=DZSj49#c_tN&|lED zTlvGu2NudmRsfF(u6zDGha&J(PVFPcXh5ZOyr7EiFT+Ap8MeUCu?j1unAhYKi`>9Q zHq>8zia1$VNi` z>L#NFs`5J`cRU@{g3?({i$f!@*bx1}!hf{F{0B;_Z1_w6bu2k=4tvG=eW2 zI}VFU3QJJM^k9#Q*E)xr;zQQo6$5zR8C6X91H*hN3qLtLe5(SBHdKr)so=v5#&P>z z^@8_O@89qvAw~7sBN7>`>0w6<^x<3(FBPgLm z1V^7`C>1eDD&vHtkL~n+&vhsNLgZeq%8|fS#iZBDys!`iT!y~eCY2<2+<=R`vH5RG z@jU45-M~N6|HCo=-BN(C&E%WP4r%*TEgMs3+3KycvPtaRUpA!jkdR!(aNskjL{~Wvu`%$OTIVYyBWXWn z)&1b{zzgf$G~enH3ffTGNjpr6=*s46KS9%Z%KU)5gPxX(>`$Pm?d10fT3xgws~y&F}eY#8tk$#A*!tt1GmwG(K{fE!w!3+0zNq6PW_K%6Bin zIw9#kU%J+?HrdAl)Z5b)J&y|Sj zXL&)n9yjTVHQUwQKgM$r%kn>GsEo0RHUeQ3&?^W>7T+VHbP!3eHbYam2d= z!0W0nGL?riR`f4u%_HmM497d3K*kKxj>=(sfR&BE1ZS`KSz0x9QY^?1wVjVRkT>Nk zr~Pz>ykMWM{VT!u21Cw^K}`-eY0i|lH;S2C?XHsdH}tJIV)?smlK8I+Un!E#nLxZz zkYLN7cd^Ily&!JKk4!bi(NL*j`Fffm?SGr&z)u`oG=*A#lu4#Yl*X=0F-`vv& zuBn$YpS63th^UaM32Vtnz)YUL4x@#mZmgn?NyVbFmKh>1&j^U2{Xdlk&I4&PAql7@ zR^nv0p7I}$61dDfv*fRhLHg^cnm)@N7afF3mBam4I}2C4(k)AU@VfDS-_6l~G^MtL z8zK`l<1H(Y9J;akB?arxzm0~Fk8gX1k}5jD)ZOl=k`wBJ4tICiy1P8}){-}a_ph6a z)zyKMEqTnexx)k+4*F~FNc&9_*M5Kua4lCGDghtmcoOcCtzdxxF3eV3_Jw9awtKIic&rH z$Z{wdf7AYN;AcFC4v6nGp3Y~99=jg;Aw@skr1W2|7#5`XZTo?y1HV=OYT*bD?T5;? zr$*v(xtMh6%v_V!hhF78FR|D*r{8LN%#pea)Q^r);3M!{JOwt8OScbSUH$!QKCU`n z@~xUr^G08NG_Wb_c20jLb7+?qwyZnjgFIQjcso|EC>){mesZme-MO-9hau`~tNAsf zznh{}vvAZbyLIUOhW8bhH{iUbwA-0@`@6$QdR{B&dB#cI`PlhB$RE{wjgm{YmU@D` zkW9ztJ4O+3Xzv6Iw0ynYA@nz_l>Wb>CL>`Vg5%QB>8(e=69jzV8loLG2;Rk^Yh-r} zyf2s%bR~Pr5Muc`pd&{|C2+oCyRSyyI`yrlOO2Wm^7mVH>t@k0L(AjoX11E~Z*iqe zPXF{xEJo!(meMaGSd7|OGfA^Xfn7mEsLc%^2sd+RaXzOXd7ZByw)1j}rc*}=0fx|4 zTHT$O6jK*Pe=tr&ML_ftx}Ugw8JL~S?sDVg(%{gsdGE{qDqvlSA4ukeS0pIJcRO0( zO+l)fdhRmb_O5guNTepx4Y)9_wOs5Zo2P5>yMw;I&NDGH3x$6TJL(989`Wf2gx#<7 zdJV#^*&+W|JpW0(2{RF*zuO)}&A}RVEN54$I}O&QUXscg_~cP`_bx3E&n}+$3Rw#| zF# z{jHiu^fcz{VXUdQVAjzI^*~DZ|Ux^aaj#aXf}eHC);u zCo2z9{_-%S&i;w#@~J%LC1;(mMKsu3<_*7$jDqAe2^8;p+{ci2k0spovC-{u}4 zXa1;%`<(Ec-MbI9_@hX@Jat8(AqQg}ZuA(fz)Q)xsP>W#qYTWhtvb+IqVyH8w?`!= zQJqY>pD*9?d1d5;1iBP_;`V^IG$}>-{bK_U;h)p5R|mep$fIen0ubDMI-V%Je4^7U zs5BzprZ2YZod6a6p`PL;3s zx5MDC0c*}%QhPa6KDK%*vjin3C}K?4X`k~)r^!j+{Yh1$DlcIYzKaof1D%@PtHw%4 zxU%RjA8S!z@@ddOf6H3E$_N^mGwKe~cLo`o_R1m2u|!KR7@yOe4vY5g(9BlQu1ZylhKLH}nZk20h3n zEE3~Kqs58YT_%LPt$;C+&4zQ#ohIE^e5(#$FgAZ1FfV6I9Iy9JoY;z#N3EC5q>lcB z?yp`Y=GB~7onUkvZdb%3ye39_r@f)w=mLA&3wY&S^rvh*s*`^FX7RlKK6#8F{HPLN zzTE!&*hR==nI#d%#|9S;_6nqTa?|HF^ncH9BkBeghMl+2ZvxZ{V&97yJdTT=x61NW z2V$oq1MEyz$rD1iT&yX@`fctZQlxwxCY#8vtQX3@%b%YM ztdd@u1fUl7Q!o^DD(!Ybe{#xBD}wLY3G^y*Rp9=Yp%M668)62o=DrAPnTQGG1u<^V z)p4a-{Tgjo46kN69;8h3|148*f$}q`Ud(h-dKI-Q%tttygfItc6q@sdj)zs~e8tu+ zz_AJD~V~xslqf_VWx^ZAPSm?8}pCNI_bc*-v@Kc%sIwA_AdW8wMrE zg8uHP@IpncJxCB#QB#~;VGb=1VZvmDJOcZyH8-K7Wml~12YxHwUHXTDPJ6k(wo<8)|{@eJjaqG{Gre>(g* zX!_e!n7om>e&<~a24^*>g33F}GVVdy6+9r8KW6S0SV+CasXT=l*7XQBrZ9>7op8BD zRFbPdqd2 zOc`J~2EWI532AaWc&h|nMe~chK8A*hO4;xZy+3i@K7amt1G*YSjr;Z+I~Y+}z7AJ4 z&}a(FinQvvTJmKFlg#D)GqO_?;%+;A)-iu{B;C{9=7sxvXh8;#Pqz%%%$lvoa9$2& z&SQ)0Q`>uZ#zuhAIu@b!SD$g|CWCRubaJGvA;X2Kh^aX9Cw2o7XtJx>@X=(daA?*i zg`KeJXTwqRu+N#Z?6Ql7M>t{$=t)_QM;{TK10egeMWejSfU({a;`N`x>}|>7;6i5l zC6hfPIoOv<9)cT3vn6dcGZfWoJ8i*;^I7#bGoD{^j3k4 zXUT^C0knu#{W<3@BR?M8vKrq1R?c_R$EZ;UFN#{5W7l*S{^18V8F2)c7nu3Gi?R$~ zloLC{v9@#z0TU64TNPQcSar4L3Z=7yVK>=pRz^99X;6F6`bLf z4RJ5X&XNpq?P@-wQ*tO&BbYGFV;c{K1}|E7heDR;i!w9J7GEB2Pp+N^z8A9iGog5i zTs~rVI{{L9FWp1Iz`5iz`CeiUCI4JhVo>NRrj#&*2J<}$@2@L-_9J-}mB5*=g9j0CX6mqn`X05p zII&fCo!C*D%1*?#b~+4{SQQ?RcHkesrX8VX@r;_Fs+337+Jw1vCoRNXW(u$FO6f{b zfX@F8#VN-OALoA|9X7AacrA^T5R{0T8PXa!P5AD9>W{IiRRmVM{DQrCr<4*fL3zT=iFHvN`pmBrt`f$W*@18t^Xgjz)Uqz5QmBB z=|H}qZA(MmI%BR+zgQQ^INns~t7^#x#No}?c>{;wjy1At>(C$|KBf(_%2Ar477rtA zi7K2_#-Wg+VG?tTMkZ+C=?t!gX|)8>O0k;jaQY3Qp%3Io_+in}?y48|&`=J_T;3#L zl(igaKiunDk_flMJohDf9@l#JWsnjxY}8s|s3|>{iml&(Y8}&jH@aQUkk^HEDp)SZ zRt7GDM@w0`a1$G9GpsjJt^DFg0p_=ob9NQZ!RLclKFFWNH#}&PteY;8JJCsJ@r6}8 zIRj0LpLIrU02(qh3+pdo0|ON7{?qqY7aO)t!A_*-mNr^;YdE1?kn34oPfm9HaG)vm z_@!eK!pv(d_FJADXgB?pARGdMBtgw-0qNTU4i!V3J*RV-t-=9P<>K1n;^u^s%Vj$M z`i>k0eUIAxStQ3yc>F-|WwJ18ecW7GY6F&gk^q6*Nn}^H+u@XP$U!4lQK_e>lqbP% zMHWh`pH;VEW4c@P7C#>%aSq+Z)q5c*v0-d_O2}=T?`&JW%errnuU-)|pCRP#Y{jQ= z<)UbkH^_HPHZOOq=0Ul%w;n~8vrF;Ig$)cYx@EXk3jYuoeEfSxYm#m2DkGAp9*ccP ziS`?ew(EHW5$|oth8vqu7ejYw`Uv<^jUS}D6lc~=5n#{$X?+Ez(%eDvq94!M48oR2 zcQ~~|n{)teGLu|KEqnrdY25aQpB+Jw*w;gpwBN&UyYEs(e>@gVq)m}XRUH?{YAOZL zjv8Im+z~Jo2Y^p>zFx+~X$HJJJ66@!VUixrEKVfN6Xpjvd7mkYn6~tWKaSseGLEJ$ zZ`n*Sb0zcy{@3^Z(^i%4Xb10kT3@8JoTh9pLI1UHrAFtVJA8QovLDBYAdkhPTAP-3%WoNDJ*MqVbOLKb0x7>+QuKv_w*{@|`87m)=Q-8R$Zyj1byR?ub$2NHuYh}(Mq4@VHt&BL5)*~6$ z8%Ibz|Cw;NZglqEi@L|cvp6oEgouv9XPwtuRl`O{i3qSgMk5Rlf=N%Kg*=otb4af{ z6Vi{ryCobmkro{FqYc+ndcJI*^Ice>@l!$4eG`M>-&J8grkxo>7-sI%y88e?Ku!s)CAazI7Fqn+?c{l2RMa72iu6$rdKCp>Iy(cU@q4mS5n*st;;y0oA0rSw&?<@v z3H(aWR>MYli_pSzx(F%{@Zg8c`Lp6q9XZH~sx6M=M z7P)r-0@#ZQekNyL$nAXgU_hxJMRaG7$R%oeQ_BiR9v9xR$_KH2maAGy|_mIe< z09hx6*^tB>P|VuipJ_uz2F$CMheKpsWIB$uPR!4T*U^+By!Q5n%9@kUhKlZt;;`c$ z1s0rYU%A=QAB8}{jGkbj*v}SIUj6=sOG06>Z@qtp6r}x)#M1OY0SbGJjF!hk;X%1_ z^Q^3MPQ9(ZY`VQM)$TdHL%xdr)si-%hT4(6t9W2Iv5Oy(zXrRr6^~=pVUUR5M%LzY zG2Cdb3gg`#M2?>w96JI(Szs*R(;C49Mk18GBCp0rl1i&lI}x(p>{vTE=l(MRt?!T; zi8jG^$PvR4l5j$)0}w0jp!}}oFcfcV5iPG&9JV2L*xnwXk^0S4BP_cFZx7KND=+A6 z)y?1q{EuK>c7?>#z?3(Hf|awkVggc?rG0a98n zvw`gfISGNUwya{$vLFPB**{K3Mw=|r)L^pa4{eWD`!8O3Ik!2(1aSnh3xfq&(y~J! zatD}bg-|$?&}mc%X)Uj^(Dt1?=xjiBJ#=VnAk?{gk)Yt=;$l2`rgF(r`_zrT9N=|yR=j=nh9wi^y^q{cGk;+Pc)|I z*)q=BpiO|vWc*G-Vi=@v`1y9E;<(f=#p_1KkacV3Eiv12@Vh0^_NkI+UjBOd76BUi zq0&1BT~(1}K!p3q63$0Y-k7N{b5Anb6d@(0!Yrc4xonWdMEy_gb+fW9VNkG&u5cj} zPGgY9CW;SlOtam-a<0G|F?R4KT4u4Nubt?zb*W<5Ju#&^U@;zDk z+B_hxDtXo`w6eW>l`4V>h8$|U&BE2Kt*t=89_^j(VlJ)M1_ZVXG+C9jJ7iJImgTUE zB^3P#(R4LUEg8N zH#Odok=j+Q;XYA~&xUN-BS_(QvmnYV9f2RtzAYzvI%k_J^!AietDfjyA*t-zB_FzZVhW8@+7S*Hs08PMiuwnN<9MCJdmW%C)6d;x8NV+rsK`ZJ0o&-`9+7< z3@J%-Dja{!`ONF;1oPjJk$5b_y08?0y0StT-uqRa*CyqLnCv;XahDluyOPDVCvkhN zu1@*jivV8oZU+4R5sl^Zd7Iv?Myu7!rJnfDKx^cAVQuI2k^?4?n9eNZ$Tb<^xTMNRROORz1JqL1_xOD;SNaf@&i3ar20)5~C z{&BHWa9jm9*L6b%kq(C6Kir$@u3{crA&aF<3%WiRRe1nC0UjB>uA@Vy^$S6i~TXSjUYvr9h{mh8lkoY%uDgH+5EJNL`Q_5v_d!l zv@V|@d{jWDmrQ@1zi4Ab}0dHnQNx@cX`bTI3rO-7g%Kku*b%?bB;ADVb9qMI;H2L zd0$%aXvExQN>~WoPcFJW+WMHtJ%=9!1jX(CqBG)raF_*-c~S8JOyl#xmU1=JZaGD`Je^ zDTSzcoI>sK0@KQ6{Fd)K&JydXu$K^m4jE82bM~*gL;%o{E(A$znp5%x}b z>bV+?*>xe&-|)m*Q?q2arIGl&)E?OzEv*}tPNOE7$C|=@GC$AeXAO3{!LHg zl{6lWQ)1vm^aAQop^^0n2M>PGBOx8F7w8Ym>u)%>w;vrG9UFO|m`MazOa)P6yxyk- z@r!bIwq!gAW=rRW_l6V_Vtns&URM694-0tF#rVnjcT zDap#uW|`jtYYATgKOEYve|vlT0vVi!qtoVLHnpy@&*pJT0BS&FscUfXIiMY*@6PSw z`B9LN_gDASXf(xO_22f-Ly}L3son07@jErq^`t9<_#UE!!nmJdyQN^~n}bNf{^q^A zca$MrXGnN7$+*rY?@4w9!9s02W+a6UcR>3IS3sCz|0M$hA|Yo3q+?{HshK5M_SWRX zOE-t5POwouo|C3Ty)<&=l1A6GywWSxl=l-2OU&25ol%M$dkqt`ksUpS%NfM1rFzWb zrfC(!iizg_wM?sW{`PO6S42pkn$RYls1Q7heunt$!**9Z;CzxsM(xG?3p4t}K{ddU z(E;TOy_kEn>gBLffKZgyE|yaRFy$^;W=){;*axqnR-@CG&(aT1gRH|zW=vvbx6JoC zVaCmT0~4+L4e`^a_OaGnnUq+}G=m0m*`hMCPQzF)pF_@R`h$;6M(VuEcsbCZ9`F~C zd!8S7o8!-HZpHy-2sp%D>r|(RA_3I%$p@SF@Iw$!jS1b3n7|Md4~C>hk1f5q8v#+H z+YZiEY@8-|x9McVP+pLH!crM?ajY)0Q>=FAq`@-0fcU9H-LQf=`y_PE_Ai0(7kRX= zL+F-5W=GYO?L0ef@dnao9UULGwh1aCx2}|T(9w$!PTuR9EC+t@kr5)a!Xv;Dld{be zY+vd9FAVenH5vYo@K2Z?DpM+bl{w8_aezID&Cu{s<%1wLde>G|W+h%G<!T^GntzfPo1YUi%>7OB0 zQaO(8Nh8a_){;C&qJzr<^T`1L?HzB9mSF`;8u%Um8KA0!{p`(G7hM!4=4QeY)ut`J z)&<}^@0=nt2i;KqP+X&;oZw%*JkSvNtCDhfo;G8lQ~Q7%sD-ZzisY19G-n=i59Dvr zV^3O9xOPDn6pR-==;-9M^;F9TISF86ffr|v^iqd6(Go}2x_}{v_FmO!=1S8T&b)!J z`z&?8tW;O37?x*R_(10{1?#V(3szJ$Ebstiz-JWi`OXv7Vy@?l{;Gv})OJbv5t;vG zSLQ~$IzsZZ?e3K8I~C)6EC9AAU$HNSQHzF`O{tg;n_DUCcsjl;fAiBxMV$TVwL>9& zu=CqzVWY|QIzK_9<1zi!kpnN+F2Tk-Y5h6e=V7FZYmR9sq}^fDb{`TXXOe@TyzAe! zV+2u0Rs(P#ExhccA92%^BnU{{1urT2oa-t5;CHbF=bNhQeWCH_96#@PPhigb2LBMB zENWnz(<0{iLb{fBl{sF9Nn8%=T}68Qu1=IW09^cBgfH-(%F>>5_XGVxV#Mn6-6VdG z*U4%#tgCA?(uxzDjjEOiF1AH{H^rRYAlh2v8H;)zz~TzbQ7+^X)9G8Cd!2)AD!91O zzv9SOP__N!?yP>#Lq~`1!t$()%cm7pcjFPU_*37kP(W(WYYFU&Ff(@5@KAA#*xH1G znT^QG{eb_1TkpEDwB9`X-6daLMtbza@*ZroKEPcpfE?)tFm}dopdc8-6NRrPk7;C8 zAAk>VKH2xX$fQbA=1(Peyi8WyZP5Q8Yw9yu)ES^CZSeGTdmIv~F0;9&I^EZ|69T3P zvw`!OTraDl!Pfz4fK&P{0^*@EYtaF3KeeqZ>enKIhMF`+VgBIdG2pv`$wGU^{(E7A z%lnPT>11KEGgdu;9V%j~(_bYlAuc(22mTVkStP)F*15d{4YtMqqsU3?5uuvq$Ss!) zxC(Lze!s;1Ke|+J{4pLZ9vWe^K6g&3R3ue)d|->4HnwUY)x7d+0Pc|#UD|S*%QJjo z4S#%#JH?XQlQ#R1E`LyKIl5jIcciEJx)+A`+m10Ot^4O=SAeO-b9=njx=NgKUN^vfw~}ML{T} z1SkSN(hPl~PWgZni2nMZ=K2p4l4As6Ev3VRpjEhl!-zYgW`-HpYg5Du6qWtve{N(J z4>Scw&yu`Cg5v2q=);Up^9-y_`^yMi$0$$8Sk-A!J7!B%sjAc~hC?#jI;u@44Oa4% zz}9GqBW{L%#IE7`8UH2vw}^EZN9mVG_WAwg?&}Z}cJ)9BS3ER19w*)qDFvip5EU94 z&R0zKNv-@Kz8k}1hJ%El64m}9TR9LC8u~MK3;+?QzG#h=vXN-nTeI*;bN2XAAbbM< z`0-1y{2pyG1S1GHXcy`)#li)U&H8^Ka)TAr;FVM%KBPuRiyRdSHZ?TQ){ehS-4t9& z;yznmZ30eq9Q>Vyz9xglc#NHoZ>>BmT*8^;{>)Vw(!xuh4bB~%85U?hcUb(vlUQqL zlc5{P8HLhI+1uNE$n>w*n@{k673=VDZGGy2GY@u;#3J%vvy?KW+~w45*LgzWoMzDC zKt%2n+acGfHW{_-wS9IK*r0#KeWVG9ZGHfp-70Oj^RXQ<@h1(0WpM*Gwmd<ihi@E=|;z{Uw|ySWpOUgy5uD)K_1sS${ z3mCN%-5aVM9nL6MrPs}T(U3yUyVNPekR3mdLX*_s#P8nPS9Y-iwrC6rA~-D_nLL`+ zAg7{Vt}4?E3ZNE!;_v`k*?%aqJd%WOzTnYA*FP9-85M9r#|9RTN{C$lBDfu%(BP0o z6)Cu=4G+;ijBtqXt5+$YCXy!jC@9R^yg21lUH{IM^`G}k-Dto;{hriObz3y>@;AtoinZI4&Y-@vDo%Vr`mHfpqRFLKqF2Fq97a|iw@AH{C^E$Yb2!D>^jR! zFNa8Xw5XfDNI~`A7ONek*Yr6JQu4EZe!7HiS8p}Ak`d$1mM$o9Le0bKX=&GEV5?~2 zE)X#{XaH8y9l9BQFf^?ks2wBBatVCn6wn)b3A|_j zSjJ3KYi(Qd9vb{3#AcTE^9m+me0ssL`Q-d^q$j6rQ(kOk30NzySgy_Do{INb5BQE4 z;b;5ib!C*S+$7q|v8SW4U))H??3+eie_Q>)^mH}&H4@4K-8p8&mUvq&}+GeTPKe&|p|Cb0!>q&xA$a=Bt^0svX z*yId2Fw!weblvQ*vC`U#AR|rNb!flwnBP|fxyc1U8db~v3GzPWPyi!cH5a&0godDz?RC>Dtw z&btxMPSLI6dre0 zjaCj|<TT zTV!*|)ad(IclXo4=me7(C3Ply*mpPN=hS~+OiA*NAbm1^-nn0Y%(-6POM8Qo-U@DZ ziDJVrs@-nQd9DW7DRXa_Jzg%wcLH6%OkQ6mUJ>Um?Lk(zkgXZo*{onGDUFeq=qF#p zx}QMm!3Y9Utm24)vHM-%FM=CvqM8j(rz!kFdrbf4&j4L`Qb4COw;_QvD=RA@hizfk zqahCZ!OsVZ$a8;8+pN$R<;=r|DNgpn<5w?0o6}suCV)7ce7h!MzzV(G{6tA(fAH`UMMm= z;PflDvw1-4DcdiqjEB*)8W;`2A*3asG8pgfz)({|K3!Gq{rUZRfUO{LB*=fX%|8&9 zClG}SB>FePiMzV%v`nvh<#>YpfGLj}p!X!SyIdczn<|%<-+v@q@d<%5gD7Bx46J#B zI3W`gvcA6lnd6-;!zGCG@f;*FPV>jw+5*a!n|Z!Dfwpb{ukM&(SQkAW#Q{?*MvB&t zrLdxJG;eBZnpj_FSSP^XH)FG`)N2&-nty;sMmz=s^>>g6gaw}TcT*ctkchr>4?M^I z`Ojw(!Y&DhY_M~LK>Bi>U(L20_Wkr)JnP`d@?qi3P->LKF^eq~^IODz{^i*mE9V75 zA_l0B>Acz^UVl<;vtrsm6DHnBe?IGl*U7*GC=-1iK0F-cEGoDhHZ^f+6gFlEOH?AI zp&>%41uXA~S{)^QYm*K)mOu{D*JnZ53`wNZ+!JxxOX`AUqNM!3hqq@YwGW>lcZGm} zs5(BqcvX`iARv;41Q`KLm;6f?V`xBrP=j|04h_z`17Oib7ER+D3msgmh|A@&vo*K$ z-PtehhJ&n_ZEhz%zv+yO1R*7ExGu~p(h1q%-6YyO8B=$4(3qbJ1~$FZR3|;_X&oH` zI`e}k>eXC-x4;L!`^@+BkS!=Z(a%t&~=db1NAo7GZCP*6D~=^YtE zR4&}4e2N+{6*csAQFG^!5Ca?_saH*psuSf*N^pt;a6okv0z7268 zeZ4rBG%_x(bg;eupdvHURx6_zJdlSBnq8y`)sw;VuhgKF?|~^%a>@UUah*h;u0RsN*v4y zba!n)yW+plXU)8f`t|=0TY`}Qs;0g+PM#2k$N?)J7L_qo2CKGiwre zr-x8p#J`!vpKzrKo)|wF4U1ZVj8tR}^fY(O2qN_)v58xPL?xVLv9m0Ib#HXkt%g zif#I`%+Prbf;iL67ow-ovSG&R_=JG}o{;=dnX5otm1sa<;2^!7ssNDkx|7QlLy@#f z3Lau4yiWHl{c+TU{gW<27~=!_n7$CgdfR<6YK?YeUw=J02)cy_28wU=ZTQfp-&Ytz z<&cm-!D~~)dgd!`!R+<`qOZWXa>O}y-Pqi>*y-enval9@=0`V2D7g}@XSR@=);YIntnItt_M z{q)oG9j&{qy)Kek4W-ZBt{4wODn?Hbh*lSVE+af&$QgNk`@Cto z3Lf2a%MUf5_N=|%9amahyV?C+^%DST;oO3P?Q`#U96)5cmC?^bv{*=pDj`t}115}d z>Ij|2IBVEJ5*SG&=F$K|-Wxy#^mw*gZj}J`6pwF+F(XJcaNtK_uNY(c1*-)9#jXn) zkXU|a?W>RNM~u^*?N7z{uyhJz(u?1@*HMvT4bIlC%k`zg&gT zLyJtL3oF%pLvU@z^`TiMuW-3Uxx%`O&~GT0b%CqaUpNi!!~-&d7(9^i6QN;ijo(PX z_E!_d-0@3YR=hRbu%>#gnd1mj=-aF`9MWC##Wq_m+IbvnzWY>v!y$t6*7A@Q2#AeR zBYHic;S6cpIZD)$;YT==D-N_l5o2VsqtX^JFX z**8!=62iF?v7E_o+oRT*^3k|!=xbfEu~+MwDR?;6fMsom5JgAOX5brY$MrW*W-`JS z>wV$Dp(SX2#)qfl^8IcHG}hqbc{gNaBAe(<&3fz2yVK>|Zvoj0PeSUO5I_n|8Tf%f zLvASEfcL*~{WheFeqY+y@~f4_@;z9g^k7J6sOU}idk?^Yk%>xOGSwmP$2~UB1D1LM z4!HGN%VFig|6}SJqw89?c7rx-Y@@MlG`4Nqwrw?b8Z@@mq_J(=Y3zP0J@jV`-~u}?oeW3Zp`ZsU?ZV27YSZK_!V=T8#U19}`vlqi{5XflyI zz>;#T?7DZGLY*=M;2@?cjth5NXbv21kCn@H#@2hbF*!UTY}Z;pN21duU+);Mq0xgJ zTT_#L2mFLQ33b z&mL4zu!(y+{@A|Hi=3XCI!Yi@^wI8D8aygLM~MGanrmvlv8^q9Xnc0SXH`I6bF~0@ zRXMLS90P~}jH5=RbOWMMcGvTA*?ORjUQS6NU^}0YS@v7zN08mv*ZY$7s>X_#AKBIWVY-dbBBTZ#6BGtp`|M>jkA+MQQ1n zTX6;*GU%BO^PYX*-w$@26s4F5y8YWV0n`~IG&>y;adIZzs!ua9nNqxafywx*uM_UU(HOO<99iV!a=jMy`98|nf#(&SI|{pyD=3z?h7LWQ>cKoACX(tRQz7I*SuIrW3%> z+k-~+k53KS z1MmfH?O;zZmu-h?o{G)@0p5v+Pv8TYjJTz zJY2e4SOBdCO$fNl!QA93iBN8d{HuKCHCxXRg><$tJC#=PRi?b(05DLp-zHvneka(f zQ3R<}euY(HcF+xW5>x0*s0LE;0*$3#)12|pghgX+2}Os~xIIsTW^`m;g;WsJA;P(2 z9+ikdkWHT&&z2^Zjb}|eYW-Z%l>XNT6C<1hwSx@YDf~as93l`9DTOrH{{n3Ok0OAZaD5hjz#*rFFj@Xus4)CjrCBu4rXUGuFw8`PN~{(*@+v2 zZxFLMW!WN%oqJHAu7ip$w4X#}4+$VJkB*KIAe?tK0s;b#I9jUK8Y~xbrv^Q3hhCTL zW#4(36ToojZgM_k^8xqmLtJgM#t91#FSv_)rzHO)7^*qj!DdOSLuE)L6htWwC&*Hh z4Ab?@ljX!QZ-htCJv3N~pzIJ8XE^d}NF!|eix!1aL!cTuI#|(3v%6t;AMS$g@%483?-N^_#&DSKB#(#?5UjVc)1!hrN=^@!mbPZXQ56yToGO0}ttj2k(3;)w!y@ z?VZ%Yc9s@lGn;ztDEb!ZkqtX2~T?g(JR zR9A3;6xzNH&(7#4ChRbxtLX~OCX<=q6-JOMq-qb?jo-%@OsIHLk4;Q?tNzQ0_+#}j zO&K5k_v$;P*Q@Q(c$$CcLN%Lrp-)Zx%6kq@eH*Eoh=h2@x=q2^lM5!~uKA_-JHfI3 zR6v4B-zEgWpTtU5p&8ORc_7ydbL?z|=riVi7lZiz;W$bFWq&e5Jh%ttWJFF&;j^*} z92^=tkzf!@BXdD{JyKE4UBdl0QW)V!^~5hy$~ErS$v z-@^(~N!H;ZYEs#kN{VI=h@_@d+5};DYNGagk6Arpt|0X=% z?+6AY{>kvzAfWSs09N4`OXC7neP+Db;=)1NoH@6?8DmZa)uA3jJ~fBoq+#xZ`{_q; zY5_B|k~0047^sKL?tI}$f=&^U^QjYqoY)KQ+&Qw9>(Sj!%iaK&0yrUQelcuRc(%bWu>LJ385l_NiFq={Pv5T-hp8Tr7XTiIosgmD1Qpm5V=f! z0s9ZZ$2{vScqWUa5<&Pf72|#O6uu=tDh2v5~6$J|hYi9`v4B(}$Q53+9 z4L>_LP{wPf5@n%D4bceM3_D?yxHy>pR>>53xf+>S?DQU>_K=>N4V%uy!KiHj*9a}I zwEz~Dj{D6=W03J7 zpJwJU9i=ZiU%`LryVjTh-G==08ab8EIN{-zH9gUGlR!BOMVFluGj^!)Yn=M~Sjp9Q z=(K6dUX+x60%}qqYyLC=ME;?=G2tg$4S^M7kTkGJ z0vq?G_#zm8H8hCzPnRp!x5Seu&!WtH3Jqc9ieQwJynvY#l~YfR2G`8otMN$~r!33! zEVq!M13>L&k6TLjM4PNc98FV118KFbVpEH}%hg$vClS{88_tzG7wwLh#+_r-)Tb(a z#iv!Yj&&tPj6e8p1YdulUAxkFwifO$&!9QA6jvB<= zTh&kT)hSnnx>#yk&Kj}e9(K^KA=^$v5$j0LqM;RGxu)L$*M)Nu)%- z54svIOl^9I8DAk<-yBv_6vxN<a#27};qsEm`aBpx z@R11;^92bV395~I?8@eiCSNV;Ihkj32Tf4WI)=B#JPYWh=G+?Jq{~EUX+WG> zS|*hfRW12H45#CQOT1=vg>&PNw@78Jh%I~>7PDpE`J~Olh(~;(7Fg1Ns(<+Xhk1Ex zghupWR~geJu$shhG2jWGFXmSm0=U`jPG0qAV-1v(vOFqSei`*T>BUSPRe9d|$w`Fz z2JN)JH<|qOCRw(G5gfd`)PSEKJcFL2(VGYW$Mcq^o>T@4gZICV2{08yLqj`kP&yqC z;C`jBjU;sQSIaME1gSUDL4|F!I6^V)OKQ9ST@dpg$aNACC{Trk(ccM|XZQ_}!hI`c zaYMSLXQzc8XcHS7s4~m?rp;`Ff;Q(wo7yv^p-R23rn~g{Y^rH09fK9xGwJXJf%FR2 z(-U_e?uQ#=RJa*?N>}HmjH^AX*QaMnewUgta_W%0K;&uHr=lS|HfTxLUwkh$S~*dJ0T(~5O+tgu@x-F-Bf)4BTq7eJ>N}D>X^b)tZg3 zTkJwZv-9;QnjTw0+?weV!xk<-dR~$*Uz%6E`(FW=c}g}?MHaQDWoml6Ih_7pYcYE| zW{=*#1sS2G0Q9ID?7wPKFQ9v~`$L8JCo;-I?Xs`38;)^$O^{B$B(qV|g8cTCYBV0U z-h1>QoqE6~fNG=PNULopYhbPCrCm1OrA}fk*A^?~!lP!oed-pLpV#{{2E}WhjTz>P zif*ji71C+WnrCsm;!pcq2I*$E-10Q$L-d{Bt0c%cCz7g+r3lE$Au+N#0(f|cy6k38 zxg6f-5vKYD05_oa6+Tkg7<8Rz@=cdhi~N=CXyg`y@+!ZOtDz#1w?wu9Q7`X>F`T63 zFek}&IN&${UM`cE^+UJirF1rBlN;rZuWPoUuZ!-lT0ZO)LYK zlQJgL&Y-aV-r)DT%dk?XgL7?;AG^7d!~ISY5JpLzI5w*X1|rXtaExZLU*u&8_apP{ zOCZuIgwts6VI^uSTx%nAe&)4f7@3Xa4&giE*&X+$NOfz2My7x#XuI7dZvmT6t}sk` ztJ_vv@B!Hze$TlWbCb;{K)GdgACh}(YNx)5gkXiB!IVQE+Whmmq!syotCA->EO@U5TAM1oiynSV!UN5MiAvWU4w z6`9y$(drXfHJ-(g5@*0JVI3J+&j0kur0_)!)maS;)9MJsT$*2BTiD#x1EB2umZd=I zRb>&vSI){|t|%u<%d#X*H7IsE?Wg6h(iC4F)x!8fv4KH6C=#37eQ3cJ;}-w=c$ah_ z(gL6q{4kVl4T)}LE^4}Kx}so(_>3sdd6VaImsaztnoYc6dm||uz65lQsWxY)efsM4 zQ9w<@N5kE0ug|@p+WmoCc6-ypVbz07w1Abb5ogMyE`|)&{+4(Z6Zub65xa+i&cmz@ zVgD$_!5pe1WD$hc4rZ`JKA{?qB`GfhTR*_DVmAq-D^uP&?Sv@Y-(YK1048vY0kATj zfdmo;kUpfaXEGXAuRpmrEWA*W;Yb%UyCu@O@b@Kj{4~mu3T0Hec9X)pTvQQ=-#B^7 zkNh*@k!z4!TD?kH^BY>Qg!{hjctTXn6?SVr?vRPngeX8Slnc-{v}nD3;muv`%%*zx z!`)O=Em6fqjsl)&$cM$_Dx*Ur4lUCu(8u3EJdvYuHrzdj*Zz8}j7 zeAV=;v3W>mJtRjG(~<#+Khjmtye9spR7i%I;0|iayp-1SmNtHthf0|$K^WS$1C45B z{nMAI8?6I6*5;RvA=U*BJ6}>eK2RLAQ=gy*-uEEzebg5P);}|K4*0I0o+P5qh7>%H6U8}Fc_?y> zDS$cPd%rupHM8@+pPAcCEJr&=e+qMwVxnSNQAH#ZxxqvvAK?pwT_$E!u&AodM;cnB zA{rL9s`!3_^5kkO#8ik&HJ>A@e*U$D@k*Y@BMt5rKj3E;Pk5Si&zTA_F);=XecPHZ zuQQ4a>`J3CrI|zzJvWzg#bfZ2rkl%b^E*@{@ugZQT%vCLoefg_#4#KjHpm1o4aui0 zMGTW#``HO2mz=zrUXdXv3&=cQHp_A0F~= z6oNT)cDq-)eHfZs4s<7f*z|^tPTqXbY#E$SCctMY@xDi)WKyD!-*P)p+2)r_G9A2S zFMD8&DAC!)SHbtdX~C?AGAREgxkr+CMc$@llKk!HDC75(D9d7->qb3K9}(4;jUXSe z8e+++yRpon?BzQoC5pj(cN7F$OL@Y*il*GOJ#pV3bitr>}iLnW;b@JEwh{dfE{qr74Wb9QRLR>TS#N>PD(vfx< zQYAv|%p1afr82zYQw_-JvzG!r_}<=o;s#v!Zy{uTHRbO7dPBg{B&r#l-f=g4A0s-8 z7!^aHx>BDsJDzDtRots76>fV*Y~uXa1K-7chMXBA0a*jTg1%|g*?6KE)^tzqANXHp zEaVfcJy!}G4%)k4T;|sn7S{S@mTeO*2%U7V<)+;Vh=~}tPpNwW>u0j>LL!~$3}hey zxJ;P9uRX9R2KOXc45*4p?S3KEBa~IS`r=|8>g;)p27^fK16Eb@i9k_Coo{B0B#&q*S z8{-839uT#?9L|ZZJ%AV4i~DmrEtHq|Lq)3(BT^aea)jdG`<60x_ZyD_VB2eou2%#u z7yfOCTkPQ9ps(3}=8Fj);<$GM*9_m+I7I;*|qMp6>U+(`q7} znSand{Qnvn0;D&M^9yN3Mv|r4;kJb|y(zADb!U2A47DGW)YsgzVG@etg{RLMMP`Im z7B#pp_wawjk z5{;Gcu>HlS$kV!CU8BEoa{(nN^dNKycC48mCXf`dKd|%B=ybev3#t*gh#!0Cd2Bcu zD2Pd!kD&jZ1#nENtYO<~WqWdvrm8>M?0!uul#Q&~r=}Po=rqi$Sv!y}C!Mzl3hJOw zKvfNSmi!ejmqQqZHC;#WP|}oM+#o1^Q6;@>gJ!z zNit7p2MUW#Jz7}A5G?&r6fIA#zjrF0YV1~7hxiYtjdhryBjuMhy84I39z!0FPETKe zLDksRCFj%=ep_4n_V90|Cl9slf}~;wiyP`7eFP zX`o9ZT*)_8<{lq6JMLY5=?=VX!kv8&T*u`Fv|^tyu>|&N>Hq*Z+6={}%h_@f#{dN{ zM2ONW>I0q5k<&KesbQ@0EF!1?KP05TI#FCBhoMjby(}N`hAr8HkMoYm4mDz&c~JK+ zDDZ>#29e`5|VE&G%7KR zMdyKRH57E#n>rXS`+NF{+t{!{)+>Qv8HXx32d6EOj=u2izuniW?Gs$~_2Cz4U%9NX z@6LRKkbFqw&kx#~ozH>NbL5^sE0@ofKD2_Ed*{n-=_>thYffg2*IC zkFuR4Z(e=m?gUc6O@)}I;WwT#Q5(gqs;G#J z`CXveY$`wAX2L8h+R(4<+wFQAXo}bT?uF5)#sWX3)}V zOj$$9ffgJhKM#1o{)Fl@`47?jaPityR(aB@jW9>ku2eM$KJ&R5LqS*9lpHgz&U64d zN2##ATVU-^vARKfeSIz1aB7>Gn-k{fxgfV>w`l?%3JF5EnF#)i{xmUGISC2$P1LV9 zI5{QfTD{NEQ1z!-d(o~UouCv>i2n7a9rD&CT<>zT>LiQm*-~OC_m#xDAYtLX zRU{S~=d!!ede)MD8V6YPHch)n#dT6CXOkz)z(lwdkbz1~bT?KYq+bBX!p0^Ce+y_q z6WmAt|ATsEc5n9)PKt^=HYew=8$pue^%|*N^&>SpVX6oXY@S>(+M@W17{@0T%O*KR@kvQR zk}0LyPEjk5kmFo?PYoOG9Ge(c_ZTkhv9)BEkNz-sAo~V<%PUKki-Jo(aCNK2)v$wk zc9mZ)J9|q=HLJdHhu&LrF&jBmQVrk_4zQ0h(BB@nTYq(&8QuM3VQC#A(o1OI3|FJ< zY-O(h$Xr*uGRwiOps7g(%n_}A%yv@#ji4XYZH1`T=@oosYumV==nk+n!aD^XIQ^HY zK2_ZWWF8&#WRFCm(PST)8+p+Y>D^=8W#jaon-LeN=pEJCDQUkfzb5PIkbNOlbYf(H z^}OzdhlB11#t`wu8!)CJAR;ov7fp-&y;WrJ051U;d4a!wK!6jOi?&Xw#R7S6eZX)> z^ow)BgG#=k%|XNxhrhVScG-u))*pbh`fyDE3f$vuQ=eN%KZlR~3Sv?^bNSZw;iVf{ z;*a3K3{bU4;n@aetGBYkWxtES!dcY^0go&2Tths24$tmoL3W4F7rs;GO6WfHN7OlX zvj7_(Hl(7GSNKeaFNnQ$hdgq~Y=n$z$(dj&~a}+_jTXFV(S@i zVP{j5tBimuJhB93P&YN=W;7zs)kuvQGW}2VKk7)bMgJ&IfOBubiEiW%FS<@{J;Fc* z^opRsKYrYj$#M07IowCNd8)0x+ z6@Mul%nc0xR5BeE1E(>Arye5m*6}+Hdz7JTY@EHvzNG4bbyChN?7i=ftcg!8#pvYx ze8}=L)!^VFWAOU4FrfH{5H_oihK5cEKWz=kB{sergTLIH;?l?T}Bj9?fv`dl|hjtJW6-J=OA1HgEmBeq2Gm9!>z4p^WHgy z%mQ;Um+wK~*15xab0)NSbqBP(oLHb!cDjKPR9==YQ9ayU37YIO9WB8? zd5HhRLz=t)+wo~i6n_N3&0ydUd)iSwSN4Ay`(3;6fje<#Sw!_Tkw-_)EuZmS3ePY= zjb@;Wt>3;5Po#eC*xYa3MNu1VvMc!AiY|7dj+kM?D)Hb&_8muO2|K!{95mDwK9_Ij zn`YDUmo8vM^=>Ed99~g=0rBTmV$|TE?p>%~FOQu=t_tSxtO)gujS4YCGC5=LNcdf! za(px*P^t1Ea(V<&I6XAE_CT}G@}+z7u86@}BDBd&i93ovvwC}bH&4mM?(!)Yhw^)R zwjl+W0Yhaf>5JU@o*dp7Ma9=jWIAxKhU6hfnL#qfNI8N`v1+5}08aTwe5Jzp@!i8* zT%D)-mp&p}&_#RY@Qanmh&v+T;GEtL7uiS*sOtKBnm1N&UO%}_3j=MRGUPqt^6k9m z>k2>Qif4sEr_B^&Qf_P+F-HLHhf5mH;7CtTk4s1>mB1Au|I4IOhzPM;X+%^zfRdv( z1qWuP{8lfZ7u?fImzS5{jN=^_#@h^ds$TzC{4DL)= zNU6DOuhd#+p9M%|)xPpsE{bw=4M^siGqS`tRr^|bUDgfI9lsw04zS0uU}82f?@yZ* z^NWtP3R1FEZ{qztLX^)i?N`8ayVk;VWG;^nSB#>1R@2yE+=j_{q%eLUfI13wFTwb%b3ZO~ipG8|LIwS+0{F;)ZJ&X`Fz7!5 z0+y`$rLXjW69I&AOuu`I8>kNaom{cv(zgi7TK8yj=r3T7|15a;@E{nYEdg5OV8{I({)$234NZQVDlmNPYg9C3M}ZX3I3L~I&g z!yQ5rRZqrC!59J%eO-bdws-w$SI7q7>wc1IyDfn}J5C!xI-6>TJ&D;PoPYl0?DRaykYRV2WBL-vz3o7buMLv2uLh2tAv?<^x_(NEjW&ju_r+s{IOk^|0 zSsoUCeRzXT)hPe~tg$giLqCsCqSe}5&cXy$wA<;+d7VCS<8(e9Qv*fiA!8({0^J#q zO3KXJ4`p^e)JJKdBI z`b_W~vt&*{e@Od923f9wdVuT^hV-u~_KNS`AHyt_D{E`hj5qul@Ub*bGzbB79DIKw zM>em|dR&>;9S<*0)He3>H{EN}b5Ab?QD5cKii+s=bx-npo1_I|$nTTq1*msu$uB(x zQ}G_a!C(CS++d%3713~myCK0rDZWd{N+NT@qKCewmQi^Pldmo<9nGvKwUhS{s%E6y z#9V&wXc|^?RUe|m%2U075to+!jD&RB5=*D7O5t9S6@FsI*6^30q}}eDSuml0QvRy| zA^mG0Q->^D3JMI%NgZS%M=^o!D}vRQ87|Z7iTz(A1%_t0M6fJ#y#+>NML08QWiMq+ zz3W@WOxbiddt;xswh%jWq4%EgUN`c00Y^cUTH@V>_zY@*k^PDLh!XI$`A>b_k^CbC z{XR_p`Yl*Y0_NQL>hCkT>2YSmooz&%a{u2N6^;$6nfJH1`i2^ehWRm zIK7t&CgyPsBKM9BVzeW3r*j7d9&Jo&CC9+Q(CV^|7D6&MA*3StSJOk)@sik0i~mPi zcHkYdjG!7(Dws`!fPv`0YYVP^+vTHN`qS-v3~srHhU!8 z6>+oL0w@tYJj3OQjaX)RdRj$S>u|vpP^xcM@HsEjUyKqd02aekf2vc;o1^8|T0K@z zmj*%uMKS_xjG}QFkAE$b9E?AUCDOO*8jE<*T?9}I;%=Q1R|wbjGU?W|Z>BT*G|eim zADfmnOkIfJqt5BvbIAga`=dpeSy^R@B9B+bi=$tzSGhyn$D(?T9chgz{@$lADM5(7 zug_C{8*tO{>TN@Yi=BbAZfST^zR3r5TCHtu9m{5%@es(!$dWp}{o%~Y+8Jf476>AF zqr?UI$|RZs+nng`i`@+-W9f*3NG;5n!7x5)TXx0@L4M0nLPBCCv<-a3@v{F?-VK~x zV_eJkzPzGB*wOLYEq~aXke&>jy*6oVnTO1=On;h2v#H>?$K7fDTrQA30=A=rr=-ip zSuVS*0T=}$u^af60E`Tf>Gw7}&jwZ9`@5UmjWNUKA3wy~gFBvnL|g*ra*F^w9UftY zene29q2-a7LxTP2v6ViEw9uo5)G%_K4*c`yg#nx0Jy%0RLwQ}>?=M+A%`O#i#j?Hu zGVq-@t7gq2g!$>8C>k~_Fu8NahfoDk&twlpPfJ;5FikYPIetyHRE@)78&2g52Rdic z9Ruz2Y8{+D)iN@G$Y96-vCc-JLUAHOBrX5$-^i8VT?qiJ2volr0CB70F_&T%CpDUr ztLxb8C1WKz5FECx!F1hd}fYHsSC}e?J*|aO>dyBh5(ELiS%NK31_zA#PY{W6{^QX{iD+og#F$5=N2ZYid9c5fPJe7#7QJFTY<(rUZLB zuw#ylK-saI`;gtE!;enkE%a`z1}FYG@bxdSA^cEpzV^n8i-g3ffgZbX?IEVRAh&3? z-tBRAY|K2VAp-a|zkc<*d&ywR@qk;Ylu42w6_F+e#j8y0Ad0^;q2asb+kqgMdB*pj zpN6mTTJY_!J>zF3kB$fAXXS!@g*bNKIqLfx02M$Pv|F20J{JpHy5iMOrI=RPrO7m1KV|pzlg$!Z#&8?$B(C{xVZs;Q-`EZhF26+|^l>Av)bnx%4W)17| z^EzFoL-czKC7?G7`by`Z6j4nTUfEskLRMftFlCrAq)82%njB3RBA+o9oVmsS%t6O8 zL8*l0H3vQI==AB}gJb#Wy6sYrkn2b@*Pfu}3!8{?j zJYnE1>1Fx~CFf8Y-EABRVu|xt(LfzV2x8h73jYnofz#@-LN<$nq(^fY!x7SBf+m<^ zh)Hfpd}{u919#p!)m2r6uUdsc8tABDy|S{R1v~p<#fZO1D6(ZPf15qth_|9ge$?2= zO0CKTMC9{hf%Oj1Co!UU@p@{YxNgR|O5T`y?|NG4Ou!=|<)C%}02-QCOb4cLVi zuI+vO1Yudj?SYEt^To91vCpmeoDARFulYf!JS@f;b3zea#ggqfdV!lIlW`m<(?-C= z+^fsMjO|JI`4ZsgIrtO|(`Pt9hu2O{@vm$55xl3jw?@zZNsD2m>j?=LEfN|s9MVym z|2M{dd#jJu%@g^{(DwqikftF^&HvRaytI2M+x@2!^@F{U^xc^Z-O^sCk zBZv-uIvd@GOv`jOs}g&~cuM|o1mIZ@Bp@3SwMQwja!F{QJIH3G6~RmM{vMKmx7Xk6 zk`>kYnf1HP8hBPAT5(w==+xb1@4iN>YX=yo1G}`?N{j?Hc8GP!Lq1megS1#wwP$_| zUs-*sBxnX}p}!zyQ+++`$PXse7AZEYNm0Bm9Ju2*2v-C9!C&Y+0M;u-=ks~c>r$4K z+nHkz+{WDcXNTs6;2}8-^_da-`Dy!SZMDVC<{2n-9`>*qac5_i`3gl@NOPa?nCR$? zhD<3L@?E8OIA5tlhV8~yrux4^@g}ux2Hl3Q8ylFVEtgFciIZtR4?IO<9@aP) zMEj5eRT#5!hb08%(qdThA%$D#Kc5XiwN;pE?=L^O_>vM*JMDWLxWqfQZc9JZ9KuCQD^p$zr)lZ zf6WWRB?)NR&cbLKCk{s_TcE=*4q$tt!51M1b#5)_UTiz1>5ey-d-q2pt&UO2el0y*Ier8e^ zL<1+_DvE7Ux?IFU;|U2d2A^*~OvVxu?SgM9b`bxhUZE|f)&wXAsC-EyQ zqpDPDaTH(+9VmTGTRnjSa$7oaPsOoUugg~2Vk=kG3rwnQpvtJGW_2H``hE=1m%Er` z$HfYYyE;1q1u8vao&m*C?-^ZNM8H3_<&m8dfs7L4546DHvd5yJ;Taq~`B{UXBQ(0R zi~8bgv%|OO6WL4FSn#l*8h`nq+x@^+Ma+jy&RvJ-i=^=xEFtcipSaWW@?g>a!sT@2 zHd;G)Xb9Vc#Rx7m0Xh{u?APsm)I-!uP3=#&kF1Pvjtp2;dB@wqgawx$;@&!a>J`L} zj7NI%7AAB`TKoGyQEN5J3GBmhLvTFMfiOTnU(}(G{k1Fr2}!XPzdOpmzZ58mlM(0(Lgo5XZAc!c8o60>`guj z21ZzeB{B;4RSH5X1?WQM93d&GOHoLQ{l7$q1i>fLqgNtk7786K+2j2_ccV0QQc%R^ zcXI~?Y6WC~T?fdV?B#o`y2H06?D&oNV@FS=ge%{K)PCOR&|3VG-G}DA;$jk1|!6* z$^eWL3|6bq_5Y9@|M{nlXf1}Jz1U#6xn7N$9&1w>Z41b*JAfhc1>1Yp4L zy1LsA2vYFIfpSZ~d!*{Q{LNkq=#N-29ZXp;srw#}1G+m9p?A&gkZv&Tw9sd>OG{9` z&j#g<2L|l<1u_kU2q+jqom{+!3{v#<>NS(`_yMd*S%{=lW6(~nt2P(Z$$qb0_`p9&;QHLyRuLq_j!fW#yd4#ypr9)E zI5i?sOtc3rjs%li*5);XKa^!kcs-MOWDbiFR2deNeGS<}zl33CrzE}@fOoX2#**D0 zN|Y_Q4(ahppmSt(B-YwkSqQ{KZT|tbPF%|rMS}FQ1L%L8j&UW^zBuZfQyw3|ivxP;OJ|URBfEWxVmX+9AE7X3e zMXD8=nZQmSVQ-~yVo=nBTA*>|jr8oo$ckLgxBHSgm^a{OPcCGCoPrK4$ zuxI?zfgh9iSJcoabfVCbyr;sFD#Ue+2^vG8_Wk+*;3(_E0f$bj6Q+RRH$9~QVaNw& z5UR86`J)~$4N-ZS|C)0i(5b1ZNwZ91qaUK8Z$5qE_VpT2nx)yrjL!++@`oBZHyETz zSkZ{UpP1_#yZ zZpObzc(v1k6iqW~@!k3aoy_ydhFMD^Z^aKFZn43^)S`5++0wkIgyjAW^ zyr-^(D-Pplb}SA3%)Me3DGEiKD*+)d7Q?-bsD%)>L2saaQvn!MMx)^cpDw@61N7-c zS>N?QY5dX^HuoQ4`o_f2YX7J~jUXZ_uI!gU3aQ&2&%un;E2qWE{7s=9ehk73y)O#T z{_&7XN?y@PD7VJjGE!P(I$6X#^gl9~LDr4Bw+j9@P6xnwn{~5a6`I!BSmP%HP%xSi z%4OuI$tYc<2q?P+c)jx;N=cc&YKQ_yuGijf?teSUaAJ!1&%W-;Yu*s8)6n)E1?1$C z7a=?=_Qu5_MiRYC?mryhPG~taTPEuX`KpeqG8R~x=eS22IhM`|#D{`mF z@i5R7DJSA+@`oDxh(k8-VM~qsZY@U+D1VK&v9bcUE&W|QJv$qe`}p+=?o<|D+X={U z>nVVLNxJ!NCvHfXYXe$j0u8l>7+Zd6v6}-gdagJ{?tbva08ckMAwZU)YLB~z0>|k! ztx7&V5ga)Ya7Q_+GF;&8){glsp?C`mKu)|yBz zae0sUG4n*BuoL|ubBll6An~3@Hnux-y|HWVqH~TzzD!F;@GF`V!qyWn80AiY47gtX z?4g6b-v202g%0n4@710^{lOpTfEckce`NkQ2tokGBdInTQncNd(0S9)u#N=>6lzhQ&N3V> z1;@*EPmWzgscWN7mc!LD$+6yn;&K${$lb9~rKrx2k7VDRX^a&Z@ebauT)~iywxAqf zN!g%ZO8f96urNh`59`odg1YW>k&}l~9|3pKK zV!I*cdp=*QF&t#?H)C@SnoaT#IFz1$ z`#milopJd`cc!Ln6HaleQ4q87clq|Ms=lR#1zMk-mL;=+ff_LnPp_5=z@Y!D?*K z#{2mVEtxlXr7N~6g|N>bJk)N#ThL2>)ZJW+hTZ--+Iv2&5fyTkBPLyTbR-tP*Izi) z?z~$+YSFuZ*tFW_sZNa27|le%Y5U}% zpe|oOd!GoNWrG0djC*QOgmN4yZpe<7)F_I5!-ffCBVvDHa&jYLW|dgw*3-hwYiOtC zr!43ej}e9!MS@x-RK_)nzy+``hb$BF-Q+rERN8~k1XkrWoE^cvFw@n~Jgd@(X4ck) zVd`uZ>NP?t5vkHLXgcLu&I1-If++d}WYtz0&D%u;3E!5{{@NDr6?J=3cbSSkFt+u# z=>O5G?%z0zF*8CLFpA*+a1}VY*RD`^%8_if8rd!kX@73(YM^!rmeG1ZABjHbLO*y> z%~Lp9+BMR18AwPKeHe4rx7(rld?I+*Rg5zXi=eOWdbhEA*jkG6;X^QoAg8C!2-J;< z@WHtYedd0E14#BRPao;E+INIR3-5igTwatWM7d3@u8oM z=X%H`RoCq!L)Qaaa6)6Zx*MLcjDYv>=R}-QGa4S~d^WTX{O*u$-R>C^J&moY>ZwP= z5z_q@%~4n|5+_oHd7G96MK;Qrk{;e<^VO6hP|}IrH%C>g&vob|zIm4t-2YTKLfx*= zfP(=|^6|Yt-ufATAKTb(v|A*;N8SyCg)FsT(kGYATwX{!o;UmIoB0TfXX`PA!%jqf$-BUN;@6LZBTJBvT9d0b z?0&5X9GGgNJY5@DOpcC7T94jnSolm)%C^BZn^>=tD}KlOd3e!o>}x?$%2z>ytSJP- z*oxmW69P}-;Fg^U$~Uk&wQwSjrSWM#Nu8UNBGj*C!C2QK@=IMIn9TD^OGmJihgGR7f{BG#{UM~v!-^&#y z^@Mw8Wt>()48-zZ3$>QUq zS+{LH&#dV~&Yd=_J-$5M8Xkt^+OM0zUJ5i~$Bx7Tg?d@Rz~^62gh2Hpn8Qjht)gnGBaF)$d6r zIP+M$yL1jDwPl9O@#vX}*xCHs zeZ;EdWJZHJ=jnBUbU#mF*;uq5u6-!nuYQhTmBt`s$;Z86kE$oMp`=0OU5M1RmMxJ# z;SoN~6S66EJh}>Q`BKb?Ykl8?IHhmHB#c>_&p6lSHyD#geT6LoDFVgtVtKLIuS@fA z{S#38x?A-;yZ#ur`d8!5}f6iJ`8oBq?)wvr^V zs6u24Vpd4YhT6SNkEvTzH7K@LpMr)g@sBYjEc{De5ocsT9ew$Gkh;|8*9~dLM#||_ zK;5KhacyHbKr<)=@`+lTwRDu&L7l)uD@r0a1-Hpg1{GuGbBtxE^5OxmJ3CsNBXfwZ zx=y;=ii(sJv&~wkOr+YU4p|of4h*#1kTj(FKlS5B{@rlBVq1XTxYEmh!f?So>rclI5OPX|ACrCo2>JKH*?Gqf)DiHsu$93xDZMOY z$--!y9-yFgEjrM|qqzkw;xYORZe}ETz}9mV1^PvfA-cS%YlU90&s*B}-}_>kF<0S_ zb(?j*uHoNVkh>OplHa)!raawVUpKRhsHx2{wlwqaK{zwuZ+9H(Hv4vMMc#MIoQ~g| z20yhm?YJ-RZN6q^W}dE?|CYVJZ9VMvSnWKa!E`*C8H+c?)PFR#VRPa4LE_xNuNJlH zU4`6-r5{SQ%(uKmTg`mJSbf^n!LmxURz;1~W)!cno+&9jF+zFu+ z_zFR}OJ#hY7#PF=lEcifx{{-WGgG+0A?f+e+|D7YB-y_Wo4LaZUfNHK(uYVp=9bcx36}y%J;ydCgcY_q@kEmL?5~O}JqhS+mO$6{=^+a6 z1)P`1T5d2*CP@wTxfF*@tJ7%b<2d!U@e8vWixa#v)N+QhGG1VAk0h&K+bADK-hmc#*fSTb%&yn*&5sZ$m65vMk=Um4d zx*-K;{8f#FAVV1lr+8AyRHXw0Eq{OExS|KCQSl9!h4X&yjone)T0mUF)xU4A8Z$D# zTCk#_;RAqiiJ{qH{$hnZAM)qhv#Cqu_sVD~h zy1zt45%7_PA3kTo?yYOJI+c?A$nOL&f9ANDO^XVJc<%l_H-~PRY!pffOln4CkRmmh zCJrZ>__LK#4$9Pn04so6`aqL>qhm|d^NEgyot>1JcoO)(@l0+heHpfvedm`)X9K7& zVuS@JeXa>r5)8mH;U*g?oh8M{Z>toT|XS zwDUbbSGn8izBcD_c#KF9cU|qlZ1mR_w;GgiXy}o>^HUv9USD0H5;k=I<6vQUHjdbD z_rNs!a}e>mp{bHGM8Si1x26i*&;?mIa)*tiH-*Mp1Gre2C^09~>EwBxy4%n<*}BqP z(&;t}m^(JT(VtGl_D_N8?2{Bm3x~#x(f=-X57>jG=ANoxkvq%edt{#mAk6_uEp7z# zC%?9;BZRC+t!i>=lY51yvx7`HPycn~d7Hs3>U&xsV-9VD_`Nb}d)KVx^=`T^tb_=j@AP8=zWkD`bUt9GJ8}xlq@0(OHw01W|8bA5*qi zQ1K+tkwStC!)4pWSd9D{*9Wvvub+~9ddf=9-$b5$W6+2h3H*Z~ZeC7tN_zmJJ~hLUsI*4+lu2%D#{Z$0sg$Ms1wRwQM0JE=QJX|E@nvS zd4p|9CPqfGPTI`6KKs;U&qT3)E3qBmzk0{6sLJuSGqo|&f+=USM0%FQ;?@#nkMwyy zx$~Ir5cd#wANyYoNgqQgskx#b&Dow0xvjE6{ouU%{uj6v$V^z-0^JAG*~_E9mrtkS z;RCFwqDZ#V^Q%Dt&yHV4RMPg!)MB@-TRhRrs|xc}zd{VyHo0JMlNof%L>(?Y#F8A0 z49@^{Dr6k4ZTF$J!+9v~c>NS(2X?qCFkiD0Qf25NM@OSR2Y{_L+A!3w{>ys7(++@} z(L2;As1#4PUFLs+rqWtA37%e^9zmY|v;! z{^?GSzE!v)Kdf8tB20q4T-uo(6=4baLa6xIlVtkHI`*cOrWYHeX^k87NAK@)ZM zjCR-MJJKc)O;lOf0gt}NCw4hNN4i`{V@aOnyClgO$o%aMb4~d1$+o8^QLln3cv6%& zk;y>*dVZ_=#P@?I^Maj~$g68C@m|W49?vCj#^^KkEkb)wH7I9SJwckg`?@RfYOzxC z*Ra$M&T5rJg=Rb6#$tqa@-!*?X7yO_YcP`-X#p}F-@Pz|E|1yQr&Z}QQLaqv5252E zp4kMxFBzaeIts*kG~$Py(01F^z6o3<;rJad|MpMeKwWjqMSJ=>itSbEsMg-&Ci3t? zn7#k_7U9V)r*kD0kd}BcmqI3IpJ;Cq3*sxbK{!mzGHpI#a&AKhe z$1JPbckMUN?F&wueppfsf2U+T<(P(x*z!?SI%hj%CKyCO_*$}A=dc05AJeOIo4UH>79{o z@KndaWq3JV8|dDny=55+SB1WXS(wo`};fHagj=qR}(3 z4taWYY}KfwV+G5iYuu63s5YB>U{^oWNM#K2&`n$96m*MvP3aovuy1^gP%2Ps$lTU| zFDbpdipVg`izK5qnFnT$x6fcbBwp#cS+wCrG0^WqBD{tX%JSeQBt zJR)i~UerQWggV*GijQb%DAnw+XcQS1ZfkHeNt5);a7+SS+6IEUY$wYNO(8Sta+8Tu zxzWmCw7I2Ie#;p=t(FY+Vj(rTMKFYGCFbyxi zUvbXYt&KrI1VALd2r9ofN`N43N7+3&DZNefE%7*8*W#2XFIlWjZMY#DSub{@lUta2 zE{}jKC{}kZF!UB*h(LDZ%J%_o5IvvKzmz*TgYtIs>+Fw#3qVLr@s92*pTMzJ$>FM; z=oYS<_nz!AcYQ2vx7ayDws%fYbX6qSE&Up#}5UCts9NyK$UoIU&;A z3{{0w_vuTUo>gA(2hAT?4P8skHYwowv9655DGwYd?gZ4jV(Yu3=|+Y*zDTmtL_Rk+0sT=20;qoQj8bRn( z>mhS3$d_Y%$%M-vJ4w6+UrhrKk?+43ANV;@U1$W-INu?%kTZOTFFF7UUc547*0smz zK_h1IYqjYmaV;r2SvW+l?Q;Trg%uinj@ciVaoMLyeJtZ2lf<@ir{e>Pw|LH2GLSKW zA7}jS@vTd;mS`^FM|fCLybk}mt&yTkPzs2hacRQ^eY}X zE_NO9MitKeE|ugmFp?lJK=9;#Ac3Z4p-20O_OX`uEkfIW6wte2cA1Ps`<5UdfT_#2 z!G1ZKhp)v@nBuMtx-+SyPE&%$AJaYzc>De8E?sYMjzN6J`iW{~N z_nwKotwB1DcWCgh1H#w;qrUSUtfSg({YuJS`9~Ri z12OSXR;J>EKZjI>8%~c>Yrtlnl$xt@jt=t(wE_nQr|%65JtHu|Od~&dC^F$9gD*Rz z*j&TqPJF>3F02_29WR}I^5wKf+;F)OpeaK8@%}7!1lVc|@*|=uTndZaD|`0t1Wzw< z9}+Z)*UKTegi{Qt&L6bR%msVO$8%{P6pWlQAWvVUwkZ&U9kOA=O&n#%)<$!WGW+Jn zcc1ge3Uwl_P885maP*h%;1nTO4;1U_&Y$B*m<|`eb&{gqJR})yvnuI2yrP-MHK;}Q zZYr8t#eUK+h+KRAV36hWv1_qMwwIc5K;FxY2ECBY=(JdH*l|9mjqu4ud-s@g#8g4- zVSdzfI4Io?du`#IgyidpkhwXA?ys5+;}O`zK$OD-uxLI=ZYtX*e<2w)d4e2T@(kAC zYa7Ib1xdE<9vVl2sVyy*udK8X292Km4re9l_OsYiU z9#jN!^7FwnE)8bNIMBsON&eGS7RZFKS#A~--7l=yn60T($#jTNewFb9V4Q$6rh#Bp z#k9K!!Ks2Jp=Z5EahmDdA1i^^IKz7X7jwyAV>woJ1!br}mB6TDtL77t;zF3kf+~qY zmk~D=1uv8&3L;)^$Z$j2oSDSr_!L{NL)e(S9Nkdwr^}EALQ8E+C2|-kIPu|;fT}FO zYoyN1hpsX^k(iCyFlO$Q;&n(<^E-9Fe#zRau9da5%C)JS_y6$KjDW4_b|%xJOMN&{ z&H!6Q9;$k-{mLYi;Ig&LqX7djX=y=vJU-{wr+(aH8MKq(+sXG{r#tQk%wp70G_zp@ zgURurzl&mVsS>d@e~=;T8b%2?F?YoL_-mRod<=^fM39&+`l} zuRs@ct%DB^_3T3uloR@MMsqzhFfh3bpC6@Cp3qL`z&8;IzK=xch2^G{eePu(6^+sN z5!@UFF*iTF!XOADrxfyodM76Uvhf%ge>J53DNhWM%*@Sm?^@*Ta2OksxzU7DeU;5C zls>T#CX@%x;?pZ98!o*dmZ{e1N;0p!g&i z|IFssh+XSS+4?yUmeR+JbQOo(lI(g;PcZ2J+vEA+tMX>Y-PN)x!|}@Zh}axjHbm^A z1S--%n~(#lSSYx`P3mcNh-e=fUvVA6!JxR9x zvA3oi!yGr$X}>=MbBogF&PjU&Mt(X>dTjx9b*#L6ojC^b!Rl-uqA%9KGg5r<)A4wp z#4jv4Y*t73c=?M~^Mgc2!GT zIK%J^r#s%4VMnFgKF%jebL$99%H|abtf)e_rkt?$ z*hsTq?fF>eyGxqK;u9oHnTq=4@>u)VPjRNM(gbEKx6PRJ@|smVmuPJ1RAQ~r(EJ`5 zW23j6R0f&|RC!tnhI}^!m~@(7jI>(L|38bYkdd@VLw_Hjz@eZnT5+-tJye7I=&G72&#Y%!G%KDxm$d zz92-830XMt804$L6=kW!9+M19BV)OJy&5{-!j9o(8s-S}dhdEHIGk}*ZZ{&OdV@W` z!M*{Qu7CIS52ST8YSxr8FOf|10|1a@Kt^6HZ3%a9yaK^dVEr|l5IY2Z@S=zlyrt!7 zDD{c$Qsz?)uO;T~jtQK{6I+_o1mZk{H5<6uTaY5KS9=oUg2mI*@@6%@eZOLf@V!)G zVtNCUORfkWQ;j7h$0#@(!NY@9#jV$%zCH5yJ~JL1+YI*>UhUnAZe!v_lw0Bx!49tY zXgphs_JS6ilte{C0^6u4&6pY@Jqe!VAdd|g9GK8*)S~(OC$3Iangy_?iXo8vlZ7|{ zN<5+|2`ithUID}2$3AkH&(doUIwLx?>ebzaAq7AFC;WucPUm->FA0W2_aF0I+suXq1 zbP+JMl^o5r9}4|#QK1kJio#Gnd22~b{s$=Z2`ppH!T2}LyWS2uSUxhqKmrr1zDyAs z{xPJoS_MF7xuZJA$|azoZ>UtPs@PIl+khU#Tso-I!RK}@HxvdudLbnv44=1GsiBGQ z-)`#gehwV>ddgXzZ--!Jwnymcwq|^^!Rv@SQ`#C(Q zQrafmj=QkSu4@zYLY*yM?kpJe+WS+o`I7;@UO$3J?&Luo(EEEYo}_+In_|CN@t>+y zod(BCkdNx_!NSq&lnnqQzxcgjOoCkwE`SEOdAj0Lp#Qp5Np35O-GtA<-O5naS0HcKcXyNa&6Hcp z1Imts06NV9o*^%X7SZI2V7ox`+$9|OI}EC#(#b_8s$*wt9y_f4qF%r&q`Oga1Ib&> z8R^cPtv)|P2ewmUtQ+ReJ!^hmGt$EVZF>{{huH`rv~+{>W2pmSg1$wp{o&N*FLw>- zgVnEE<3wi%DD8UUJx^!+F}=`HmV4%31dZX`aR&2VPns@le0Xc`799zfzJ*J}s8kO0 z;*R0s;u=}|6N~|-QZ@R4U(DpU_LKnv#XIX9>{L;qDU2i&XvzSti0p~WHDd&wR%kYs zmMT&HTd|CuboA|)cmchn$Z-vxw-h&1X{}Le`d)j*&2KMC(^EM=e#p5Kr}Jm`8jmZ~ z)HmgBF7Ju2HXFx~$*?dInreeB8mQy2OBhU_o(yQTi5XedjIQfB^X%b189QUtsM%Z-`ZC@~M7nyQDVW z@nXKTxPnou!4BIbNLCem2cHcX3E|hECi({1iyfG=RqJ!%KT-1BQh~!OtEprNN-nbP z_a;ZL$e+qafOx{Pv$DQ->qu|8?^Li2sNyp`54(_Yr3&8*$nJ3{aVm3u&-K+Jdfe;f zUk_J%%jHAd=ky%KKOCU}ag|Jkc?~|f45`M1aD{DcQb%*NtklFQi&hB0SG5Nj6i633 z@l(EB09QZGbDrbjg&99@O6@-hLl^?+IbXu$R|7o+7B+1{6z#F+7y+cnf1^M^HQF_sZnkqBGYT!qjXhek_V%D4W&t&iX{A^0rwn* zX*`kEzc20y0O0!Ns-;}k5|^CF{;N29`e;d6E2H%6{XJ{nVKT#4!H}+pzQc~%yazZ0 z%#4BX=dBWZ*`dw6DEMMIv|Oq#r~!Zze7WWJ@TJmW=K8})#`6~T_Fnd`Gy{0yhYx4Z zc(LA}Fh8hZB<>LQy87JWdhKbg^&Oaq;m(o9IzDpk;J$8hWcl78t-j=aFyo75_i=&p zeXSHOv5Oyf_wn1!tHHmsv{oyNxL)o%ru$pGU-x7s+!MH)tz4BAUY02?Y&}uev9Nj!u{*I&yk4 z-+_KV?3b%HIX>k#ZFF2|-q@q56~)efkn6IL7}&2%l8}I8p&!DQh~`4HhkHkYFG5w( zpk-S*iebcevv#rS390ZbL8|D0xT!Y&LZ0R3g^5C9mSSwpD(kDjTfa2r@G+Q9V!pE$ z+}8K0N&J5I>w0+QhS?!hkN+ORCi{43ej?oO7$z3}xgb(vpY@nZ95D;_jqqjsuo;kr zab8JI!xFR2IBe~J0MLhzn!g00q{BfxVQd!@i?(sor$Cthgy$0gyj2(-G(KVGp=w8& z?h*ab3`yyzt)^O~!i;~3nnK-(PWD?04ZdY>&0 zZ^M^VfBTRuX|>o<9S=AbvXSV19%56`5wW?oFl&K!KS}mKqTBZN`q&z_E{JGoDNO2g zG5LoIkH6IkqO{@17B?jh61HvAz3QJ3qEFUeK;2q%^Pt6O#@2rl4)0657&*>JToTZ$ zwug{5*@Tu_+>83>j!koym$n4O#1L=YT#F{GT9C_YX!xh5Vgb^erLtdiku+HuUHa&$0L_cPot(;jAsXJVaIBXN7IgOZY+ zgaZ=mzhh!|xSyq>YB8<@4TLCZ_XZajn0BDOc85nWkGnIyuKh9@tyQz2(dhSve0aK> zFGTuE91qWm<|P9faBk8|TzW*Y!gNA$N%)A7GJzA{knN~%^_Xx%eM*;ERMElB+d^;@ zQx9t=bmlvzY&c99^t~4mT7L+t+OT9jm9MQso^^zX*WT5pkg6ai${QWOd_u!Nk*`Yc zqzbXQ%NKWAcEN*Oa-7p^BQR25efrZh{ObWOf=g2mYIwk3ropKFBMB>8stIGSjlm{Y zsF9-&+^iWjrVIZ_*Yj4?uPHe#l7p|*VBmi`*yH;wtUK>;r#J04gvd!quD3!Ezt56Q zX+Xgt=^t@z)tkcDjkm+`ij8G zUi1VzSDc+y#FK^Cyg%GlU%&W)-Wi7}=pr_87+L&f*9DKyUK9G@S+Qz`8}s|j5WF}3 zhaDsL1_d`$E$}hbg%X)5Jw9|xM_5UItDe)<&@!cHO`t{#T5`M;0_C z-Swfa)tD*frHjR_ySz6_FF|}BJ=66Xxv_*X@!_xBnIJ-a!}nn6h&)*w zYU}hXX?h=Rvwup-`Gik-5(*P8?m=>&P^6Nj z0-{pWXT?Y=IKgxnumORA2X}eT2pQXkD%OrZ7xfDj>lwE(o1GFP3JhZZTteR~cmFiv z?sVS{@-J66N1`5T8Zkh+9EXF$R+)jgZz<;-Ja2dRS4Tq$xnw3R4Kd_DaWJJs{pvYB zMGu$T;2&JJaeNX0c<(t1=@&fo{q+5p{s6lD!uet?)i;=g!vLHBmxZu;v&o4nt-1wi z?rP0yj~g6@Y0;HU-GAYWSOJOz`j;)v?9>``Y-YlgX5vabK9ut=0w`mN2Rx?z;Us1R zL!u<^xA957aPGwp*Te{Pwe`P^q=wtnDc?I>iHb0eoCf`#QIS>zQ&$rL&BoW zZiU)0{)rxj2BJ#4vjA_dLWlATg+NYS9r%v%cGzW((w{cy>#H4#j4TEoo`6{k9i_8} z+A-A0lj8*@&2ru7LaCJKh3CJ!^M#Cfb-8~d+U|+{-F-^x*2=ZDJdLry*^JJ|c=qz9 z4}MY|!x^cLhvEjiKSBcy`wKL$ZySo%4UCc-^ZURl~>l^w}suf|k#G@kU zawrq-iwg6^%V=rr+@Yf?5=j!2XGFwfQfu^jz*4wc z{>HC@{{4DWJ;AKds_hrafY#LxL;zTza;BlW%st%9UR)~eYVWi3{D$DjKE&eUB1Q67 zw`=0TO zKW50O3yH_R7A)BDrM-cJnOBOw>n8%s5%tcz z5uD5zHpZo|0^+WeGk^Ykqcr_tfOg9V|HXh6WnD&{-G;?r6ld78cwmo|=^w3KB(P55 zoZARc`|`O~tD!6W6N;i?AS4^0Wns}|TcMK?^lkCY4IDXdQ@6uKVuVI5%@X1Sg@il? zepi}}Q-TJJIhZzHy=^AhD3=xfR%Qj5oLC{I=fsXfShp^b;r62kzw{MWq@;h-+|jh$ zDu5A(<5usSca=%Djo-ac+svsLW|@Fa`CjlVlP|gT1_celLU_tRLO?`?j#!?4?eIWX z`!P$x>HbpS5;)cvP+3`t)=MSray`a&FY$YD<0*q({{tjsq=FmDb3y5U)~ZNS@8#n# zCYOrK)HplTyI^RH8(i!Iqh;9`=~YjrVdKS4dJ4UY;YusnSJg?wR%aI%8gq1G_z6RC zV{xx<(Jnz;wHubIxs@>wac z2><`d2KI$s2$UUAs1UlVWkY|NvtZEgAL00oNYH7+g?cr5ld4+ooC*~mZ-EuB@M->n zhK9!C&y$1j-$9b%oqw9JRajs30ElFxuD6aIja?ye3miX*RzN@tfUw7rRQ4BDkR|VA zMQmqDC@CdvoBjn+U7ChB&U{kl2*HuRZAylAkioi z9^Z^g1`0+5{G9CZFR!;JH^S3P0R#769d|FW*Y~HqcWrBzZHQ+pPnl;Kj>Q@n7#Px~ z1A~;}W#re;QN0fjABr57i9u23vHiot?FCoSBVxO^VhNqCPFF^CNrUb>ydG+SyVOvP zp`5sk%&3W6w0g_(vi6)~ELJ-sE1cX$zF2HW7@5F7A0z}Yb{p*!Kmgf}rJqe) zPYeP{5)XkCu*u*q8!V@ET?2@_&X9nN$Wrt7?>6&J*x1-?_~`!7L{Tj82mTB4Qtv;s zMBFVu_0ht=x5nrBB6LLFepz0!o{%Icp9Q8jTv6N)B0#G9uDgrE-2BL0RZ>zia7i4> zqEAxZjjhiR88M)|yz?#z-HNpSgnq{yrx+WfCIX8gD6JQEX_AByYHJq|xfQdpJc1Zd zg@Lw8>E8K;xib`(|2o})rn|yVW%CUL`hOpRL{u{?C$+G{++5JK?-}1ZSm7{nqX}28 zui@xOFft^ljvzGCZN()tW?FlNwP0bdrk0m!ArT3fq9Y=cWjGq^nK?O2N0SN*3ak#= z$#$w6EHS+|8zG{DCHx@rLInQcgv7ngnfdu67k6~1AmA~+*=gNf40lK42SbPx-2<*u z(>LjjPj{wd+}xD+@E=M6=Wmf7_`~17qljENRxfk{&M>ezF)=V2sxNA4J|nJf)!)s` z=#)KI(9+SBhyElN#UeDC^@bGYaMg|Erb?4nmn^L{^Q9vRQJn8Wa96Y@FYEN?~ zI(pLO_4Ig92jY@>HP9t;aBu)Cf|{50=Ai_H>~WS^C9sw!>)23;K>zo#Bk;#%uaaEI zf*B6m48C@E|8R&M0IQdIcK|0Bdu{5C6Ef${Q2G$NdfMi2+2rf0b1+5s+geYyxViZ! ze?W7yoBa|PhVLGJD`+U-E?Eh9->OaW9n_pnM2^_Rfk1!B@Y{p$Q!foBG&a=jiHT_& z8H%@p5d;mCCL*=V!RtZpvN#5TcKaq^Y8q-}Vp2NSde?#4_p|#KI{TZjaNzgPm>-w_ z{82XU9!s8@;$3XKcrqzZf%#~Fl`=WDyj&3#9c@m~;Fc4#;dOVaY%FlQv%XMQEbXpT zY~2tZmMC`b9Tag2c&$f8NmGCNMdf_);TSPbKMuBB0E;i_P}+X*T&tQEACcwN(!>H;2%(LeM?u z^zx34mv?2`DF~c94e?U#H$19;PY)=k&vTH(ApT!3+CLNd{PzlVufX_k>2#qnFd4@y z>(U>#j4zC8s*8O|=b@gagk)JVU|Pg}{n+X!rf}eaNRy%rua$o=4{OgMZm|PHSqvHB zf`$TNgr9CKr!Dr5-f)YdL?X6nlUhw%UV5P|q}+<0{r@JLegfz{m= z8+%!)AL7m_frxyESMD3)u~t-8w$e0eztYqIhYkt>A;F?&UK9&>^vUq%2ICxO(=t14;HqT~KwLW~D5omGxRy;GDhZ_W7 zsS8?LHDOUtwqGB4f~Td~f2j+A3)5ZRZ+aUUed!o4^BREF%+l7zzl}kf zfrjp6oWZh{{!MR;hH0%rt2)p-5i7#cJPS2_wxm1JxVO8TM9d)yycTkP{;z-wo+@QrW5xT-mIu` z=^X}WP`s`xK?z#i@bKqw1<|?Z-W#v>-1UH#n4TWNB)*A^gvP=`5#F^qOGiSFHXuz= z2!Fn2#KVmq^w8)O3jw)=JzM*Vn>MgO^S)!;QvD3!`k-d~tMkw8m|@!C>*_{D$+l+- zfWLi-0TB}1IzvL_Y$bY*nSsUnM2GCMK)1;jc;46CyB>+j;}RWk#KO&8j_sCOi@#vcgoY?$u%-fHdh;@&uXW) zCt8YXYPJ>}^6Jh?pr`*!9e?Ezj%0zZ@6!?ragh~{yh|r`qM`#Xa?$hd5)#8S z{{z+cOTImJpm`-UR&4G!3NEt1sXfd;$q{%$KUXNDvfwiH44hGe%)JN`j7c_^-Ns8srN-u?rV3uo*cZXRbA(11zCE;mQyUTJ8IriH>|`FCyXhA^XlSb}0V}I^Ygwl& zQ_o@}Em#NGbbJIxu7XlPD4YcztyN$=!q|AHad|V0J}ExlfGeAOmDrDQsvg~K&%=QX zSe`KwB;`IvI9k=TtSrUy2A8xyA|mA1s?5k62+%<>0&;Rqm6u0zKNjHo0#|B}OyBxd zXMdHa|IqEoyIhtYDduyY!f;sl7yvVlD)8zdc@Kqk6&LzLrSZ#u;?TMYn43>NWKsGL zJ*OKTSn>|MmE3|S&oc>4k0Q9(DDx1#ElLn%@)SD#*|@ypiQK*cgT+RMh9q~N1=TQ^ zaU{PcI|XF?As$CTP9)$>3?k1b>tn5kkdpQl^#Jn6mr9z2wY8E4hNLJpi;L)|34W$f z-LPvoF#yL>61Z+!8ER|R@(1B@yDTRXs&ku5yu6fkZJ8l$Q$Gy)KEDCBY08I3gpnb{ zj#24E@;ak-O6lG8l_WAUbJlw;pZPPak(B>?Y=V+N6ptakd%{>!Hcrl?WHnJMh=GJ` z6dF6Ci7*IuuaQKxiTV$o0W{&~vf16E?@e}qA2eWbd4DrMG(2o?^@mMKtOeBt?BxZD zRHn~vzNbzQg~-2z_*}g2{O8Z+6EPosQ1<#=6-_`$83oJ#{Rs7t`Xx;O_T`N*fU*jl`uKzd7UALsK+3vM1%2kJ$#xCHP2ug<_AO?6XNNQE!{rYxOi+%_>0=^jb*RJ? zHFcI{@_&l~lrRjiy1F_xxt^04{P89mIDF5o$E2Lk^Yq+Vm_A^-msmEowoRilQL(YG zubt5W%iW=fgpTI)x)Ks5cnnQ}av)=jfSPH1dOGg&hz99j2hdNn z+X(CQq#-mTGd*32psUCrKt=c2VV5!tqEQZneSCI#Nmy8zE%vM1CS{!h)gs`I3l5D}<$} znFJM;nWEZ@iwn3+1CrVf{2+FZz09TtmGZ*E!liODFjHewQ|1aqsFuCGz0m60{mRzP zPGS$p@wkNltM);l=b;Krjl|tKNi`O_+|IvA zgyL^|&cJsz27;nlyM8Zlu+3zmaLn}t;Zf!d0c$R?iA0*&b7Wus<#3E;JyvwxwdmOBlc**~j z=zo6+69T)quqSqI?C}a^O=Q0Pq1|GTpP7}VKaGxwxkMt=`)U3V+lu=FIRc&a>+H-V zjf&?Hp+bD9M7Ok_e$Sp$LQ;}3UpMdH)o2b1BX&rjCi5p!&`=b=;?wQzph{Pu02+bf zv7TD%^8Jdmxj;isUf6iv353M>xHxl~i1V@GVSwo+2)#81+*>?|T4^ce_;3eQ7ZR1A ziGsL|pCFLXduZf%Z|YV0z5g49QJ}E>E$6BLNqFH|tWOmF_$Xn~(J2=fHFR?ZGQ1%$ z0H@Bl+|-~qs|XI(8Ih3B>Ju&;qO?{aF4ZZ^*972_$;Khc3T-6~OufItz_^^!wcEq; z2>lf_LBLqxt{m5~!J3IhhxGD^j2wY`ghHYF^+g)hOW?cV_|QyCwoNjspoU(VukgT1iAvL=?jxVKNL{}Tg%C2+&? ze|+=+)Wf~ik;MpvoobSI(_@ZtxzV}6G^q~I9qTy_E!EqjKAecArKWxZBqH-Amk^9- zKhe`GAi$W&t!H{XE#j=^8OZL?5?~X2n__Y-tEW@#+f0a8sTBG}i>!3`f37>gA&rLm zU9zt|SEakSe_nLsmgTxda`N*h88t1_xQvy@1noWz*r!jQ0`?tSyE)oRF#NuDTD?6R z>bn8OW=F|wR$3Z0(8#2~cd4zbv*x0tIc;2te{sIW>z6(L^t4S27Pc97=E_e0YL6jt z8}fdL2xR<1HpG|>!ts#=Y*3f?ag1$jWVyIbaa0y>`y&Y#oES06J;4&X?J$M}6m)fS z9h%6}MmBRNzyF$3_T$bX0}wca4#)GK_E|ADd=|fZjJT_X^Lk)`mXm^w+}_^O#C~;@Wa6NUimnWe zjfsp*Nt!`7K5pQqB5HS(961eTJt{L)N*Dq6@KC&jZGq}l!5kyb6mc5V^MD;}aUzZr zriW|;E;H-)z~Xs6gPl3K4OxPnN#%FzF|x86E1Mhhz1|BaAaM8f2?uHYBOx(4*JT`xx%94mf#MbOkvhee}B*(9=mEI&h8AC>O&LW_iA+A1$dse z7Z|?0H`RRl2-1RRXAx2x2Ve|iTn^8vS?TVnFnib!Yk1-h4r#sD*Q}?5j!T$L1Qjhz z?5~H4g^i8u#RqJgKpp3yqrO1X9P}Y#+xdL>bw_!X{tVIB)^_#nz#*9buVO>71NZOj z)YVdEV!uxJj-mzq9j$?nH<7=)yHr#?J~2AZP-1$8ZuR(KT$)nWtG5ftRZ!0*d!^0u z92yFMW5=(Okxx-AJ;xbdKM<1up)ydn1)wt3qN^8&6FjMi|2u$7`i1C!LdHDaGQki< z%zsbZLN@9<9d|y~Dy116cS$vKUOs??d}3na;s}XR-HjObYUJRIG4o@|a7Q5QoezAmQWZ=>N`TSlV{#zFL zB|rluj>P~a<(++g=SmlUe$+Q+T>K&*TnHrUk=AaUk416Fj>=>O9K!Ra<%vm2^@ zRL+dICZ>Dpkv5+E^n9|($)k>TOI5#nC>tA>zkTQOfaShN;cT@8ghB*wFkG(n7C7G{ zupJ1fCNYT}vfj`B(Q<`#Iu6DOTV?Z&wDD};@q)gw{r#{LFDzSdY|Cu-U8TmWtINw7 znJU0uRfwywcqzK0F`<+Q$PeAUVNp?VOTwALZI*`^QH}=(*g&b@C<=o3XlR(P#XY=L zScyueev_5`|G2sesH&c?3rKfLccZ|gMH-}}LAph{yIVk|yF&@-?rx9lh{z!c+4StQk^Cn{+k}^#kD?->uQf;v8d8*NNgPysEG#D6G?bL0<(1OU z4!?%}y1B5fuhwd^$gIS2*?5=!nK9dE$j#5xG*PQ<-GM8-H3lE|jRqX(l&`Aa#-|fT zd9e|y@K792{;B?0oM{co~rdue5eXY!X9MV0$1B zB|WqO{W#dJV; z*5xIy?#lA|y0N9beI3s0feLk_1cm3%d5hLziI|S;6h?)0G2;OH0*le|-k`~158^J< znGatH$*rs$RKfCRliXdfBP1XQ^T}^eTcZ`pk6Xsp)l#Rq*Crij)UAo9P zT87Z+Y(HCeu$_}O$3|8svV4||T$|HNoNLAojm=cm@MN|`{m=NigMV)UH#Y~KVr=@& z7LN;TX_G(j$YTk*mi52H9~&P}-hAb3fK#fm&`>d>arE=vP2bF{V02C{w;Y3%XW!PU^YMT4E$ljw)V|`O zlVXj4UEr32QHf^AfSPiRQ2&0j@dR>`~^V?|+wiSl)he%aDy;8q@r$`pN|4z}E07jJB zh6Xe;M5gz&5DpG%JiKigPvoPe8MEj@Bu12y7cX9b6gf&ZvZ=L}+j+%M4HoOj;(ea_ zGYR&gB z^00s$EK5f%ik|rqvisSjU-ghtN2E%1E$QW$S1Nm46E9wL^9qJ0Yqsuipev0>wT!B^ z9dWShF+@>|!;2G0Jr(aUuKE3{NZ|Z>jt@$G`%E=7lA4JlxG)es$;v#1j7rNY8di~C zXlTrLchE61a$yy|WpW3T*G=5W!9gY@w!qkf5q;U=aAc&Gw3+yeu$!A3vc@(k0`=zy zlB1BMb>4qh5qOR#siHye;LIa2cQ$__*4WowM8+jkwsOnl=H}KPF1NTVg+A^#CkiDb z{BBSp9VN&%!_7TEKVQz4mG|jD=n?9LmxM=Ho#gMfw-4r5Dm*3EFM0biA zs&G9$JbKlASFFq*Z0!$y`cx-5I%n1PSm{5^geaUMZ9qty10)BYA%ICtBihR27SSu| z;OMAEJ?M?jOs&;gn|ZWQVyx@fxCSwS00TBD=wM-P=B5`N&l134?~o%s#A224h4r$} z6#n?W4>HBpVsXF*UaUDXJpDkWxrGB2xW#fB2tWTWNiL+@(U_jM$H4xcHndMB@FBZx z8^cbP4uq+|?u=mY(GtvSJYP}H&^h7hu=HfraCta22Rk(5L+QBwZC>#z!7 zatr6v%KEPRW1Kf?6g`bI2Dn~m-n&*(c8}3%$@wpBQlXoO1<|%SG{vifFZlRTZ$ss6 z;@k*E%XKt~IO^`#eDwpZYZ1WvVvYXt``XKRx485tHT&l)vOK8UkyumN#}Dk9WdQ+6 z=hdU!m7No7Kg>?JxzbV_K$YFDbxH8{uw~I3ALlnl!+hXoV`Xoy*dRUkF!NGF+!K{S85xmBQ|-4=KRrFQ;dgA%0hK>W3JR#I z4~P*cIw}3{VpZ~Ofr-N!5o;sx!-tmyLrwB(%gvtpqynmS)Yd{b9;Rkr*ri6}b z^%lQDE-1j%g`0tVwIlyJ_bsNhP;#m1TGEaj?)E!296Igy7_=^^Son+;mLxRya>{v) zZp{zQ?z$A@lT(abp^Vp^JC8zSZ=Rowbhpx|C=HP7BVUqx0=^D zI|Yxy7U_nDh1p)Lw9eD@yYMhoRzldr!{zF$l>{A^3WCk;K}xF7K`!a#70StpG|fkO4_$wPwD(ngVSFv1u`^Zrz=F!O0U$WWPU^&@)pQIp&-EZCMC-@st>ur+HP z0N%XwDXh>zitF^H*V{pRdU|?UV`B@6jc0xd0!Ll>a+F7{amceU_QA0@XYlyK={^&0 zk3)>l{#`esa9LCkF0R~&#%;l}jiG%a{;){6o@2nrfVrTlc|;(XO-#?lC3kvu7Rh2O zphfYi{$0@<9k^pE_m z=0SoIBl-%($dxbBF18J^%j*7QAR3{hxbjO)WhGT+<~B;<=H{!eS9t%M(8w4$!y7T7 zCAjS@@Hjtx_=T67n{JpzX@6oOXH~S-`^qk{Apgr3EdbOHK-;}3;{hxDdV-uFcySpR zimyNJnzeOw%ZFDMr1-D`ech2^J5R#+rbMG ztc++CDWb^3gsStst?MXZ`KW4;wOrGwVDi%N-*gfRT=3yFG&LWPcpoh_ZSZ~D``-N| z;ERApQDI?iab9upbGgX}8)-jFLu$pbhPSLsda2*_^&t?Gk~_-S&qX?5zlm0gAs{3T z^=@9EXKWC?$0!JWK)84e2?S}_r@=w&*IIvVen9uY=!rEMPXeFrCJKWG=k)|M?ZP`( z1IpCk$S4P(tToeqKu9)q4@Jjr9GHiICR*AUG?+a z(CA~64x{lwfTP1fOsuPZ03U;~J0~qJ?(5)tMMXta@o~WFUEhZ7qd=ANzf)Q8O{EHi5qFDzscXsvbMHdLeco6>zHgPF6o) z-x*>lc>gwOKhm+kNO{Wcg6Pnqg*D%sWx6}+heh)%GHYaHDqk2sLrh9x+@OW;>TE@= z=Oq!_=13A4(3@p~%lN)M0DZqOfw25nH%@R} z39hKB0NF;rzHJLQ3#p)>01%Q_=q}@SJg6Ia;6RgfjJ1=V-+da4|oJVS!!W z)^<^Fu-s9z)QzV({%QAf#qj<|!}x}@2czW7Bo8#V>IkulzFChC@9&Iw_E%(i>l^Tw zZGSZI)GtTO%5i!yR(ND$NZA?^{vqoDEO^$K06gRg$ieH9PT`n#gr;~}n$*jS!r*&1*El_YQDuxiiT zp1+)!sBTIWwLHcDn9L7!IN%BCm{h3sxIUE(oNZEBBZvhX@C(QP4nzPvnOLXS(K|(I zx}Bw^j3R$Pb5Bh=&gS(1t3$PdCTJw0t*y-<6w#fUnhFw5FdS}DFe~+s9t{gXdEf?K z!&Oh@-7!A;{o`S$y^Gn+x(Xro>@v9|_p*5DsmB%g%mcx*t8t4*txWzWr^ftOodHXr z^A5jHxyD!)KdreU=Z9lJ_MRVtY##Xy&Km5^Eic4B;8h^qG~!8MZl7d~5V>ZA5MwCmH|cpXYktTr0| zM;$RWKT(Q3Q;|a$gJwv6p)kNcv*@`p@bdD4l$h%O*}<8XSu!LV=R$hi+v2q6@*Y+C{sT*m9YXs}|D)4|riRUf zl9tVDzO*{$`dciD4-Z0Q7VUfm_$%7mv#7sNz+|MSFQW|QWTRod+ugO)ZIk_pRq`GC zf3YF<3pli)PEJ8Vo02oWj_W!FqzZA9F++UO7wIMgBiFv~*_oJJ?wtn#3%;~p>;1&U zCvX!;Ygv%T5mD&2mP>(J$~zQrTD?_}j^pW=sj@(-NE?gfsrbA}SS$KSLr3Q}=8iWztsgcSJg zmp=5n*}M7j8S{4JvxFE74jYlwQ~X!jjK4!?Gzk8S8~rshoh|SzRy-2Nr1tt3k&Z^9 z!#JgjJ`XTj&zAX~wcn+Eu|nF}Iw;~gU1+JW2sK$szqN5-Sv@A~U}rQGq_4>Oo~)MI zYK_%9HQEd)gA37zP1%X_^V*iy);!eDm|9OyQRAZo{)-9du+hQUi$e8Qhf7T+TyX5b zg>?H$SH<&Y*W6}kX-N>!;B~ug#WG6cF$Wo~3RqaNxvf;!2$HJWrdJ1--E&V61p+-1 zO*~BJh2G~Kt!5|f7NIb+6;)!HJxaS)XSMOVT4@8T*3mk1u>ftm2B)B#UnS*3X>wzLZS;I@7$XbLdHhmVF`Y zw)~a*j8S1X5&M`&WVeBRuM(#)kx%$XmW$td<$>2vN&Xk-rQ2e9vBY!Sf~!7?EQ#jF zKlT~x($dDWV%ReTS;M~A-iq!7=&W9&S!$H<@8pXcs89zRuq@D5FxjsYDv?*$$%nL{ zfP}eN5++cDv5SJZwGSvi^3yK~cq2O*=%5C?fA-rs8rVGQt{{nA08fU?boszK^|rM9 zR8Uf0p42K>^BynMfXJupD*^3CS3TW%q~O}x+Omx9YPz+ja8*@~)wMRi+8y>pb?gn3 z+ipqRR)h%j4__B=1*MU4%27!N%6p!iYisM0CLb}I9A{^?EQ z*``nKhQeh(6p}FQs@}h+79+~AAhdoWXg%1Xd`e70QoH3EszUOp>MuvcU-Qz44o2dr zxA(P5egu}a(|R`&kQ-vgXRRs~9ZA*M(A>+!s}G0J=a82tzScIg4E^^k-E#IR>y7KVkLhj z_Lo7=cL#1O1{+X2SjT5fKk@6*ihUC94w;4KFO%UPs&~3NL{N3E5{&t-GnT&zos4E*AnP_Qg>tPL>T_)=T z9Q^zg0d$o&HNF$_I!^%-=#n`DBV+nGMS zFuhgV4>X0$R*Zd`ZGSx5?r<5HsTmUPcTISTW$3-4X|z_HA@H&L*|<`njB}>nP9U1S zk4n4C&88Q-I!6RzS5ezZ>mDc>pPu*_3DBbRts$wGJkNo7VJrN(Kk4lu9 zVjm>^96fv!@2>2|5wtE+>0~|ZG*>cGSw_ag!`d0gv09l8Z@TueoN)Kc?7owSnn&j) zFD!JDtCFlV4X%>fH2M2WO}8v^pCDpI0-vlAU*8QB1N?oF$xy|ZLmPU(diAQ%VWjCN z1#p2>@RpE0ahP~0X_ku+a{M*-Sr&}AlagXo$$t8;!Ld#YN<6&VK_@#VhmTuHr~(F5 z+Iq)(p~H2#!u>^k^mfNY6eI_UKVCokG>E=JbI=`MF)ZMJ`ys<;%ax!0Xeh-0hv>C-_-GsWSGh^gzF`at?F?|D3v@>K@Kfc_qh&}KC3BXS@_!UK zKmjQl9WrQ0?*8h>oyc?fm(@PyvLV`Pe0CoWtNCOewbrnWjhCqB3~3$k@!D5313`+j zVsD|r{?{eTnzk;@n(jKW7yB--lFCU)ubIE#x1SsJfzZswg| zTr7xlH`LcZ2h}f@=n%5*H*yvFcn_7nyDZrzSD&K3El^(ip*PTbplY%WhoIz}@&FwX zO?$=vh@Ai0a%*AF$n%%x5Yp8*wYX{lc+U<#F2cMaEynO|M#O{$#{zsih**dx^<%w{ zPvSeLOEmLpU7{_GH5Hob`Gqo^Bt>)>!v)Yxq%)8p@~w)q*hAIEG5OcLrkUq<(BxDUj{sS zx-9rZHIw)R4_`k3zLB`tL_9!%AvUHq<-o*C$_`l?)8agjv;Z_zWJ!3w-q@FAT#a}1c+oSsJpHM8Q%p=)c;H8e)}=bp>Sxqn#{ zjSnRt*f$<@f5ETxUkMn*wWSA`n3!{W&ESkSKz=FQG&Ol@8`P6NrSQKiEFyDz7aneU zb-2tRBq%|wGxhp46faQF=lIWRXV+wMFL{%*s;YT+%Id!~)Kd&-3eoq2ork&rl<;zl z=RPMV2h+kH;ZF3}dAh%jC7lOI3rI>xWe6;o~9`z`mx!s->cS@x96b z7x^J9qc?{8if!!D-AjT~5e}^$Qz1Gkpp5~4=QG?tAA$*xY2^cU)E1xy99zJp)S{aH zWG3RuRR^ZF{G1#I-5%+b9Neg=OBCA1bwi;t(lpP zY~_HSCG`q(-G#aa22ni>Vtz)bD6i8x&03kIrKJ(Bb=qixgD)jX4Twnxj2W;$wi{+P z7rw8%Za&CusJsqxw3mi=@UL!dr2!h7K(RR^aBIcB{?r#gmkTY6;cV)q`G$7{qFu z3TkUrdhdFh`j8Dg4Frm-DU+^_=95vmM_nkVynfE7n#h~4W#IHS~~D1^+^Emzt{7Oi{4L&8zGxhYhs zhd=8J29>$DRa;dUIkNWM!n=Je`1I~H$0ZKf>7OfUw!F}oeOjb@5RL@hbCB3*!oZAM zvxJKGH>XYxbZh!>$nk^+cYGSOAKiD$qR|az2Z^tk09;n5Mjp-T12UJamDOIZ;+EsT z%m0`TR^CfTVznE_Mxi9odqniT{nhtH#=+0l_|NP4F?|Ej6H=fbz@_L z_h?qyr7JNE32}tK6fR_gf{d)T3Yd3QO0GWZ@te7&{kwhf%E4T{28>U^*SQX_i+8eN znSGMpG85h1;zgyUoQZw+8o(I`{@0nHxwjr!`f;t+?RfBljI#S8fsbi2ISl7-S%vKmC4kKm(m+#<}gh1`b1WC z_J;fkU>B-Ogxc1qJm9f|mPtM_dDPV~;3AU;{`di}?W7#FKGwooU2$mi4RItbH%Zjp zJ=y3z*&jlwvkBz!ZijWo6dHDE-0Xr%itvps$<#x1Wo^_oE!Xu#6 zd(#?bn~lcYaG}|!812N0n{;Rx5??9S$`!K89)Y%2N^&$?>rUdj0~r=|022-}<9GPf z45IkmPbi<*nH+k?qSki^Q*Iy3~N{i3{5}aCD zv70hx6kf4A02N<}Ae~dwCWlWb9S*T`4qJ9cv_cS7EuxI{QOWV4=}oQG~~ z0XyxR@Njo|Cd=)Imt#9ambAM^NAX|3zLa)(6s4j^=14w=0@i~$V14IOXG7Y6X6=Ct z3X)JpO@2^IQg{{uQRbs2q#HXUEsX(iIwaws3TAQ0%Q~f3THNG6$&&{>ERlEF`wYh; zUhY?yFt3r0fkV`$u4~SEv@IPlmbaJRYZ8H#(d4rV)OBMAcRXw8nz3fVtV23a2D zJe_)l!1?I_fz39aGe2Ik<7;~oTd33s972PjB!LFC)%Q+P=MW|y&a zrETu$Tcb7U+-SN&eYK-wl~th5yQ0VFB7ro?or`=#vBvU|j=%8+_(2+ZQ7-g~XTk|C zKu0N>UnMdo0mom!XKb<_NVb#VLBj)lJV^baZXWR8yTxHbjhFGQ^)r6#rb*RZ6r#%Fl|q}@)6)Q z;s6!L63)b+l_v##_P|VBB1*~{R^fTeOu=mUZZT0bdUE6F^`9%=aY2E5X68?M(&vfA z#a2MAzY*tJgk^zF3@Ul}si~=HcMYe`nW3Q}n^kjIv}T#q04B5+y)VXYuDbA*IaZdQ zmbyEL8+j{-m;jQtt*>f87L3Rz)Xu;|qW+Q5mgPW9x>0geG zHD+dFn&S-p`ts^^P1h6qWvlAQljC(-Kc(G;g{O;-zwh98fL)S+i4`q81jB&j5S2KAML34#VZ)TtBN3hiU0B;qfBJO z?jvg!9zWb5M=P#a^!j#sa(=6o;U-L_sS;l2OUcmK%X9keHSpMiQedl!)>p<1gKw43 zX=u=V7tXiCO2&khg*X2rVwtv}{QE+k91BbF-P27h11+uNBa;X5NdMZu%yBx8TyvDi zlG*fYU0rN!h z8CTqPVfEhA=GlUI?g|4$Q1CIJkn6qG?W5Cje`95L=mc1vjc#KMEToxOT%=7*B#0*C zI=!U2O2F$QLB!1xpOH28xXsHe6@dUejI2SZ27RNyuWlvLXswsFO+`hYwokl&{fy|u zn_~&2@l8ldVu@}HrFjSQ~9T|K?M@LWj zqUGTBt9^M+S3gqFcN>{vex6@dOUvRZr2z7+{Ga$YCkXq@h=`Q5E^}gL=Ai>@R9Vh2 zz6^c9D(Slh6e>=c#)`AdZELW}1~hazx!}+SAS3|G!s7Gmho_1aA*~3!073!vo*qnA zYj$!0MYu@`n9!;6a<=)F2D2Wq4KW=;qEK2^JiLt|YtNxC7#;}fFJ7d%%w&Q}p+(Ob z&VRL3WO*YC3z>XFtqw*}W_b-BzSa6nh=73kXKGVPu|WQD6JTvkNKRfHqDkPI5>fv1 zYJ!vi#VrORh7G~&>@3>DSucftsW4Lyj|uCZuO5%#Uz%*Z@?`cwgW29b93DIlNJvuG z_3GBgMaG2Peu#-FJ@b2~U1z}d+?Q>X9=Qa+RZn^i6iMMS!RHENd)z(a%plT`(E&cy zl_Vshc+%*&+FI_w2AscTs}Hd-ermHbBg40hjEsr1Df3TY?9;J?Jyt^pcS1~fXUxpZ zhJN1H0gu$xVcqW9Ckc}Z47A@gHMSev54Q616%S*FIRX5yh~aXVh03M$)OI1$(rKb( zf}xt-=0tXFzWSHbQ@T&4W|xP*UtL`l9hK9tW5t^Mp4CdwEjKC{>YPD^sbaUsh>u<&z#8m{r*v{8Nzn3z<)X|u43=Ro)kn(6HYu8a?Za>2VV61ptPah$+~hJa z(2fiGAY^PA9SLfFZm*6?#?Ru6a2WoAV){@hHhb~XUY4pDxl;gnrSsww*YAiOq~Zl9E5D zkwb<=)XK5px5z?&3>HXtWH6}e;M-XG0A+3vGm}1Mc`eM~ybiLlu&CS(E=x&Gt=i&x zw#d)F$c5g+w6tuSEsEvVp-uT0Eu)13JY@^5-sa{{?ib;2v^l6LJDs zwy3r37Pxw0Mk+^nAOBU>V-pPHr=+7}H+*;J)ytHJj%?mrXzSv=_))LJ3(6YQ`wA<$ z2m`HM_p|lu53^;XBdlbo<)zMFY}nHU2Q zq`^V#yr|GEWA}Kmxw6t|Y5>&5TNVlJEP*0Zn^1kCKs;Pr`5ouK!B@A~T4!L-&~eOx zJ?gmSAo-D`rLsvKTkq-DC%K;T!qMybF*HQq_LCBpE#s2LS}Uj#$hQ)EbcxVh|DGvO z=0Ko=)LQ{Ai*90hxy+NrcTbJ+9_!ZE*B36=suG@>v+Vsq%tj^1G+Gg;OdL2-jFv5ooWVC;ZGoI?SO3#A3x>n@{m$on5<$01 z$a{#6gX2@d>RUkKbh|tiPuCWzkw^H;OSHxUCnx7N9yK|sQswuHmZc90)vFNFV0vG@ za}`H0Xx-Y{sy_p?iS5(B!37lw3e{+gYn3{;(^|^1EDS{t5TB{{eTK_QRGVfggcx37 zRDUg`o0y#?bqKV2(Y=-feZjzD3*y{vh)IKN=O{dg1Y4l8)Cu$q?V`I;QxYoM;(ylO z^F8!~n6C!E*EvcF%eUM1%Iq#KGo-fQ(wN^^gNh280j;zRTCW0M=b2fs+ zku-P0@C;0{Cl&&f{RY;rP%E~jYcaC^rXlC31CzFOIXMOMrU3x8k;AC%*&}y;dMKxp zX8*K6$DzbA1KAjH)@ojyCXLeJ7{?`o`5Xjw~KfavQGVlwm zCt}4PuNG)Q6%-(X$0j%97o|(foQb?$242t8C3E49&&3|XD1r$Aq)uoeE-->JzoTvr zPL6R3B|Jb_Ik*8h9%g1bo^az9p16Red*PQ(C&t$6a}kpcDpWnSx;k$QQCx@uR2W!o zed8$Nf1;qA6bR?a=b(70y{G!F*ZL!tOrYM5%Hs=B(3i)5oKJ=H0dLDwQ;9+3hj54v znmry7lM&Vj%tM`Tt})R7APdfEeqI69>Q{Yx;92R;-oTIFU>`a_*u-#?=Oc-knWV&n zHavfzi}vy&qOMMQh1}@Rek0A{8<|ciP&E`y=DAex@sB~EQy+fDd}?Xh{xS*VA3^Zv z6C5=)SL(>A{Jnj{2AwA2yi@z}jJ5Hy4D96o%ez&6)A+dAhTx!A&ei<<%9`xj- z!>W*>nx9cQiXN-4txvEQa-sH;e=bofxcA3I1}WL`>s`X0+n=-1zRh=9ARyGYwiT9CR}UFxw;S`| z?|c1+4f^ezL9w9d8I}|KuCufJa9(p~8GBzWq;JUW8F(uXSbLXM@&$kUNoA;LKrDzt zcH?~xw@zKz++0j-Wjvyvy1H2ct#lNL`=15}S&RWkPCf&q9XmKPlpVBQb{?Xg?$_Q&ZH(iBXAy5v9$xqM zrS{x!G;CH4kjQUU*4VH5rH_#)bZZ3s9aTWdEgb|LmGx-&5oaMy6v)og9@2QDAk)~6 z77gmn^P@9=&)+YOmOLZUaOUia+ucPWrX)?ezX%Ibr{AXz#6anUkTH>uhcX`jnG*pf zD8P6$C)X1tDF7?q+@pmead>lEz1rAP9b`-7U6C4>f z-{M}e&0p$03mWEJD}5Ro(g=N(9jm3;y%v%Dd2=d1d`Q4U$Q^QHKBBu@`?FdEy8Hmc z_9L^?9@P)cMGXE;R~I#C9P(Lx;dX%1KW{67GpVm>=177lD%TEai z+(up3Z%kKdeJ2vEbCEdCW!PA~&eTcWwW#8VR9}BD;_N67dR0s-WZQq}DB2BOqb8GD zPffKHOELEd<)0k123AARrR;sTVY)M+?mLHM=vGCh0MkKu%p|7ho(sC=57)l~5J3UE zsVl{taCKEn=G8eI?@W*F-`vz+qVyWxkI{;sfLHukOIPffl{pAZxi0m5!?BFQP4QM9 zY$!JGU^19l9z9YRPe^~t5flPi_%V484XInTv?5;yDM0z404|hXYQdcL1*D@JIRum! zi|vU#fzh{!dC3C;HY5GM=9sB%PN=Xx25@agFd;;%Wn1SP?VQ#++6mhF)BAeUd;O03 zN4N4vQ-XHyugJMb-F!`FT{(t=-5edo9+hP0b_^6In(tR=*^>6_++lQ5?F&3Cu^s5| zx9Hbv?TLBkrGgl0u(=YVLWpRfALicb#xi&j&OzMfW-K4D4kNWPByy+LbZ!5OP+Q&P zT+XaL?+(kKt_tOC&|Ty=TBsg*8MV~qA+}_JPeDnk_Gr}Hl4z!!>K91H9Y_MJs#F$x zc*Wi5K`Fd*UG6xjKj+L7XV$^!8JxFH+}mr@NW8rN-hbq1yg)*W?{q^pvOD?dOYlil5);~616&@#qD#P~GA(2D z<$`#_=vmO3zQ6XBnyP9oitL7?39&Ef5%#iHsr~*D=y)--;b0&T)vT;2Qebb5IxRvr zRVo5!Dt@FjzOK8To4eLqyl^8pk1QmLG zbB;e2o{2tFat^v9L|lAAGq>~zaVD4b-sfI#mA^4cCz6DApX2*r@J5OYqFjPDdsr~h z;LVO$1=fzZGOxC03e8fiU-^m8etmoNNskdq1-%WDS0HomP1HW-1IC+&cr|`(L&W>q zt6>!H1J|`luR1MCNZnMBqD&|kg>%{Vx_01>p4j;y^jMT&9N_#~<0`t6U`I89Ng+PF z4C<@1)~q|u_Tq1)U1fKI59UH&c#0+D@=fpF@oiaQ;{(LXWv zWVKNS>9*N{r&clOUyK6{LTiF>MV7l*+cotw4c3~%F;%f*MJuy84^PaCJhPVL%2$}_ zu&v;bY4!E=aQDo#M1JqKqC_aYnNLpM#_)b5g*_>^&+QVu4Loli`(d|qIbB35;`nO0 z(8^}qeC|tBaeduOteYCUALp6Yg4>JzO*b4wyAiiPaf?;SYU+z9XUF*tbsN6#JgQ+# z``p{HzNjm5Y(#0_&iO6)sB+w>n0yj**Y%r;)V(nI%DL@v*QJ!}x2=ey{!a@D zeJS0Ib~gy>Pq8`E7cKUJwubtZNpW7%$m;f`F37tI zG!KyeSfP?#ZNZEs#l@-mzegh!jsc~5&s%tb9Gd2*H0npJf+oapm;a?sHzmG$=Vz+e zMwCJX@%v^j&KZekJux4mr^$1T*Z~M%5;yYk(c_vS5pt_~M`E0g1rRey|CcYdyDcb4 zII*zoCEVQHTIxC!?&)#=Y;&-Hkf3|JAlR3|+&7b^K2JcOa<3_WY zASX!?ATIM;TIA4ptPj>M_BBmc+jUr1i^?g9zRjYSNkt1T^}4yZ6jtBf_e(9+g02m0 zKx9m9HDF-q=TVX}d4lS}OJnoWa<^Fp?R(d)J!p2N_CrUI2&irI5h7}8@z0YF?J0M9 zj1a55mUB8zPEZy&z?o}~>U?>7I_)iQVT7fR^Xd%jiLlo%?9OjO2-$=wXJl{c>oov9 z*Ux>b+b0b`HJAlSO%9{sctk;ct>fNNNUSx>S^{|K<~#QyG}U29VK5rv`3xw zn%s?_dB!p+$MHDWb@gfnhI5k z!TMP>a1gp&T+9NhXBKZ3Up*52qoDo;Cf>pvW+x>*l)thsfTNi2y8o7umJ4k7<2W9# z-lzygXc6>{5mq^z5kc&C!_&fQt%aonx6?KA@5fmA9X9de43%52hqU70>qU*6oW#>L z`vh73qN@bpUy_hw%?T13`*4!vov$CR8k(oWhltHuypYm<{gsu8>5I}?M~}1872R|q zWQ@9@SY1N{duIMI#7)~i3&Md`L0$p~AWKB^Tnb}X# z#fT`%ZdOM?!TGOk3V(O(h?bU?#RY=hgM;J!bEF{PLi;6-QrWkPB$#0QICO0t)}K~` zgCq(qf!ZS(9Hi=>ft#JhoX>tASm&X2$-&@z61qYqZiaMYv*B!c&jvc#Rp}G9Q9zOP zGbC7_aUK5#h|}G}Z>#A~-+Es?we9%$B=q=JqlzTNu{9@0lvU%5b#QX{_R#Xn74zS$ z>+ebQ4SvnRVXYHq@#|3zAO1Qj8tOX>{HS9dWYaUPwMsIhu`^@av6XCHL?pR1@;70=%B2ffEf)GQ$rzH3yckBmej=()h|29>?lb#<kHOb zu0lim$|(`)=2@bM639D=PW3Cu=L)``X2(IDR8c;0Qe92QW3!SKl>OHFYx!8P4Xv$$ z06?KHH~OuKS*V^LZA6PqMdhyEtXcsr>PG(drjYyv*nQz7YShaO4ab?uveVe+!=_g| zKmKYeohDCQ+F-oz2M>_XDcMo62 zqWpI%{Z@Iz#bC~4kr~?vnkr~o%LI?{XT~Kqd-^2?@@q#ZGG*9%+;QiafkK=@u`94O zc=ns|v4kJd5cznac!AVU`+BnKIf%%kcuqz}qDEv~L#LI=N+8X7$bb}@Ai zXCeb8_NAT>m7d#{UVg^d_Og&UKstRI)I~Hf@$d#QFjnucuFhZ*7h1Tk=u91csX&G0y4npm%8TY&QM#ih5G*WK(xVCy9^ z($(?FnlUOOEyW4d;~UuvwLNI4yB5rhloBU0TDP>qCt`I)loIL=)JFq4*0~oNa(b!Lk7=R|ZYX)#P;*U3wv023oUGn!&T5{O)045!<&v1=Z0<`1{ zjRi)jV{fbbG0vI3|CfsZ_Z$-J6XS1ZBI&kAKSydyA75`{J1V|Ztrk4lbXIL1_<2w> z|5Q5)o>$N{W~YNvJ!=5^)&a_Z8Ym%YCb6%Jjv!Qfp-OGC9>Xu;w61DHC_+^| zg!bM$UQ|Ptx@uJU2KT($k0JtoIzkk4B*M})0NjELW{jxqw}vqhXf-a2zkn#}3iUYJ zIyxIa4tI96Ei*NSm*O{}oM0phIN^t&Ml?c zZ`1;SrY==L%ulUzW4(!>BmYv)@)9m-2MfD)+wi@BLc$;VC^POC51Yq6Kq2Yh7aLW; zt)$@oet41ogsEFBygYn!%Tt8Vm4zFr_@BlCl>W!{=;ya&#%s)XUp@*yvScA33V|1w zT|3R|HOUBvc*@EY0Qg87){rdFC!gBkqE|Itg>0ps!jvNL8X+$}?8qLf9r; zLt^=rwR2-(cf^nRx%_5)biP>g;!D`ym+qNTUPLL6x43^yTL_FLK{T|cI26rl(!kQH zoxN`BNW7jjmaP!EE8On!YTcGI#Ip8Ix3n>KkxBct&Et9V>)ME`PaCwaF$#l+WBt%Y zL*;QoqZ**Xrq@U%9ZkXGEArA&Q!j&`0HM7DIKRvV)fX}G_b8c3|I!Wq8o^2&P`Qtp zsutdLH9NET@U6W|6zK)I`y!o0{_xP4+gP_PpOeeWY>w!$Augx8VM$wP7%lZ}tpCY4L5 zVX@Ngs~bgjvb8wfg3zXpJ;R|KH339t>&bwAX$tKyM{kb@jw%LM=m|{29d5L$q@|#SBPTUKj-qZfW&$2>*;%i6*$k$fAS_feJjoRdobMxBKC_4lGB|7^2L3`iJ4nE0&#e?g|(r~);6RWF?eSIUW zt?G7vs?_bMjX2SJU?NbAayv^tlN1wD2x;U(#)>LE5G2eq-t-HHz<0}1DL3u`f8EwS zuMOHQ851|E)B0~5+Gz=2c}lQqKl6=v@P1{&2vauH=kQIhk$xU%nuR6gw$>@Os9Z&o z`Dn^k>wgpOz!;o2n!D;u>9m!#wM@yvH;J7ddx&Dq_0!Wlo>!Fq)kTLls_kV(*VFLV z(<1i`3YmDt;zhf}PMdRFEcqGy&tDWSn6$;x1~h#ZRcWW0rG?g{f~AHn5695skdr8i zzE32-RQl)zyaQ+xqY5ej3K%N8N0T@BCM&RBQFV3Q-NE@2|L$}Q{M%Gc(gmo*=IHT2 zH7MI!=JAv6Vv2Y}q0!^;b|~8<5fn(2JlCxS)UwIvf7Hi+7PcJ?M1=2=+|Xox`H3T+ z>tdpBo9A~ERzY@*p7K_o^uu#N89!!cN0Nta+baq%n^Jtpy{s`TAPuh5{@sZ)L?26%EHtZEA5JX`9j*=%?#*EAhsHMojnjx4M#*5`9lgDxlB(~UtALOYEAZbrt#!hxVNB$f zs(_ZHHj{it*!2J(Vove>LwH*p4@!qzU|7+y)3+f0L z+1EOty5)CBTc@hDvqh7(wh4x(5Qi~v)DUYQo}N~ZCwV_wQas|xae}S$1gZ=aT1oE6m;0V3*N5ZL1Bd;uGDF{IdEYISqZgvU>dYy*Yi;4At=$JV@CZp8UQ*6ro#t2}C!!h1YS8$ZwP#t`7Aq-j=c_>g$p7XH6A23ima@g3$qdQ^fC>)QI5gQMjO zZPQWe((uOS92lPr2_t~CfTqH4xSk=`odu<|L}id62`(~~Qik~u7+O9vgRJYWgB~oA z7{;t8#;6F9Nc_YuP&MjE9FNMcbSe*9(twBUr zuhK)6{pFACVY*V{QxNxvQcg{2~Z+B(7b<~lzKY2b1i>FkDGTkpLS?n5}ZGgzcpQ|CkXMmK`Rg;-( zcYhY~yJ_sbVdg(B?P!8)D?D^E;>!%LN1)el%!}l0igo6A$_N#CJFrFF-G)Y2yl9fY zu5WKiHG<;C7tSXbm34K?FnXAZ>!4svP>Kr9_n!2PMUPDI|Cp=)`C>;C_x2vrl<9MW zm?l4&QdmVL=WEsVw26dgYx@Cd5>(;@+?BcX-Yq@IPN=)mybme6+@2b`#%O9sEuaXUGdFsb z(!j6oQ2L@d0W`2i=d%|iQ99qTPK36l`YWUIbGs=Rg_U)8RBe*{#{tA=%clEb<3;g! zjkv)-Xa2?a+PMph|0So|ij2db(w-xn1N{gH@qbNT;g#v1AHAT$^B{l~(bpyphGt`! zvDekru3$)9zn>ASGI?htbcC(*9?Jkd&J-$Fd>IPvC2Mpg#RXtgV2~0^Eq?~SIH&h;_AnUv6kcKUs z89KU=Ao(&6N7Ax<&-rdy!gp1hfflu0HM)A#m7|Kx-;OW{3O~|8HQ~fQFtb+w>g(%3 z_~Q6G>B5oxuMJRx4|hefjw+gx9i?23@@PY_TUqM`yK@K4V30wH6ez=y4pRipILhuf zbdB5_z^;A0Q_=5zdeZxQ_~sTCwtx<8{lA2Z$Zi^ei#9?eu9acXmH;jp(92J9QWE$b zwoxD&QQ`k~E&1PIFm(R1Y5};76^5ar*JTxzmC&l#Os#Lk3yx{NUhTV2f+}BgiT8&6 zmFemH&z;%K7IyFLzl`v+BmP5lft=Z+vP9V-z&CA@l1HDocgC{^| zEcUxpjm-Uavy=0Ie1iT~Yrwnh)=NlK2JxO8MB)Ad(+nX@o^NDPXWl)0$ye>0j#*mq``HXg zySVb(dfv3e9KUD7pF$wok_PFrE=R!W)9>otSielWtXFR@3@IljeVVpBi68E%#OU&PRXMPNf#k{D?NG;wJGgMC|PowB&aqj3- zeG+!I8&oo7Wwh^3(vb|-424fN|Gggs@qYE~S;YenW~}fBngH2vP_RkO7iDX8u25XR zimJ{1EE{d@Pe$By<6YOUv9US#=QAadix7Xk4GBBWjWQbp8ouhyYns)+#L@nrPdrp9 z_0<`Ls8Wvx-!o#m%7AOe=MhPCJ;+UEBi{aL&v2yssk8d?gS$Wd>*7J|FOYu;>wtZC zrH^gWR~Jr0QmveoT;8$zMA^1pGWVKm-+LM}Bewg?969j)*{ER?{g(vDzODMi$cESk z{dXl_&BCoup7*85L%a9%MfPz>Nf~!V_G0w@_urd+rI(_S1g}e&6Tti%$>X4r^Q*wOU zWn&h8KJ{_F(?>N20cC&DFaRguk7YM<>GdIf`t{ph2l$$GP!FioVr;5kg}nYJ$^{g*g|9J z0GS1y>WWH`T1fb8MOw`;)va_Sk}(`Rr$t>jt&C> zHU0fnVe?!NuRNCKEH>sA*CH!12cW_8X&tI^s9BgnoZ7?EoS(nyQ@2tMEjbEJgi_h} z-J`w}{7r=XcZ3N&*uC$RRaD-NjC7%xhf5@8{UEC-qtKb$qET{ywVkROtA`|2`>4IV zeA`Hw%@IH12_W*(eYv!FE$_G}Xx>X%^WOc*)l{FiMw^tOy?ZdzaQei8_&p~%WiAoi z{W@b|*4VD`@{!ab$NLoV{-|9FQm*yJl(K2J81Xf8Bp34MWb`b#-aa$w5`7fr`6lNV z#}*ofiWwQDfCKHGID3xW12$xqta8RhWmnMbD(g%Y^WYeZ(yS~C*%?~13W}ZEdAYCO zh^H!T603Z;J3+pW@>RO=(*8|r^|W6Psh)U|Kh;+UOqXO|h1MzxF^dac$M`(Th$lC< zlgWSm=}WQGJuTUDz^0GK*1sq4SE7OX2$gfVCRhv(I%!Q)KcQ;ddr+)i0UPdDd|X`a z2F?RgfPPkE<8{+CXLB)TL%2BC zR8n~5NO5;#9+9$JV1pT&{cKX6fEE@m7_Ycv6DKUyDF2%T`9JQQb`uZoCD*epYi{c7 zpzDF+K3FL;f#bQ*bw?1>OyXrLC;VxhDl6%=yVD&zX1ndyw;N>&o)#0kQ{ppqpeZb# zQE)F*sbNse!ajE*V!G0{pDIT7WT^#@%*pA*G=(ZtXy|6V--5x97E#d-ak!apsg*d> z89jd07NM37Kez@qA_Ym7GXds1t&udgIqloE4fpGY;&zLgT1=9{Mw{uia;<8>^T|QQ zpk0M7I}6%)0>EZ1A+)=z-rRvI zbiMgJYmsFzy_qEV1WG!D?Jn1R2iV3u=zL;_=!7a&#DKJnOT0-ncM)ryXW3ajj0smW z+&4@7J>k(Mhc(gwn*{Ezu7MYVm4|(yZka-6 zq+TStX=#FkNTF#89{t*xLRN^GXoVINpH$4*k&ZT!mbk7zE0RiFe-+<;My|Q`U@2R_ z<8PoX%7rBPODXH$Yj$X08LE+HKj%_@w|^$Ku|4{*OeTYqb2L2Z&IfA4KSxD*xdwf! z-Ry!(d_8`ZsC-4Be6&9Ug$m#n2rC*5PoU9Gj*&jqZrS_*#Ha_|S`hgMh(c z$Ne!Yi)j?)F*rfN)*8vL`_l%OyCXjYfpUuc6HQ58AE3jULbF6{fYXJo4ETGL|9X^? zgpFu!mwMo=K?XNzmU*--^hZwWg=wKv4V4+=Z|g3G9i(*q8Om8C|7bVbe|MeCc6aR@ zYYZGwW1NVQd4Ld~JFO^jMsWqI0fvKkL0s&D*rB|@i&!PQ{&luVqn#@07KHZ^HYKbRH!RZw3$_nV)$;=|nCv+lLN}yT~uQxCEypDn=%tMA79@;QX0~m^) z%46YFAAPQgU_rd+AuOL7znPEPZyvHy739muwC?-bR1^I$mgUtm>;WoO_B~@0$WdUM zG&Ah7u~s8+aDW+W6BI%!B9HyU;^9L2NJ)RZd&v0~kMN+}_}47-)Tl}5VQg%w`9XG3 zcMmqcdba}FTySM&-D-sWo)F|yIl1zA#};K-94gTU2I+bS#R-g_M~i+D!z**FY#zsd zD5)J`)UPE-Wv}{5#E#3dso$ceWF!G&w%%c;-Fd_4^Fr-Y?zXvH=||8^*;D^W)ocGn zxQ16_yZ0R_9gEYTm;hq=q6lO15YssV*?_Anw29ji+fsF7r&J|5vd5H$@ES)3bmyU4 zQ~ye2QX6A6>pi~6#I=Wcd#jYkD=RCD>*!7zmEu2PS~;n2u~wZ{Qu4o+_U}idpNyMV z4Q_j1sO~aYc$2F9TxZZes!430RQZ#g92Zpn=;&d3U!@=F)41{t&5`A#KK(pW$udP7 z%s%4$btIjCs*4^bhl4RMX<<_)n3We(spDWUU4r^417LKzLEBXwuQ}qDr=z%CU;8jF z3LzeCUyNdqtZxL150!hb-T`nwxWa&`bfVHFP>Cv%eL;o-mGP+qz`m#%V7=+Joa%m& z@_MHwKTFcxQ2T|@5m=K6co1NLOu6icCbw9x)ECOIj_Yih6;=s%Fp;GZhSaYKyC3 z?0L>A2~Kc&*hRVO)DHLi2ETNF1VbpOXo{~nRnhkI9ba+PQ;2%>II49EJ?XyL~ITVVFV_rkC zRQ8pMlfeJ~fc`buPl3?1;qLzasL>;BlCaY*ql??!Uh^D6^c&u*wic)quw&a6fjRL+ z{m)#B>R33tC(a@gFejOR6&Sya8_UYm(*c!)ubn>#p+ES-SBI67eUTcsiFeP-V;@54 zgRW%%qq8DCR$}MFou*jq%St<~Bd&Wf~%Fz|^&6^_{X$7tr3okFB3P*m@;U5cLZ_WV* za-BoUo4;Q#-b)u1(p6k({(E zt%7^0p;F&l4QaQAxFxeClQkc{5)~rW zhV|h>4x`@|_Kb)1-d*hAdNwvP&=`BwD@#i5Vgnfn%vPxSb(hp^3?CJlniteXXL_*Ab?Aya;)2Cj70!EhmiZyw4ex0D;bxCaP~ ze6~h@FksgfaASS*b%(mmzu#KI1u;y7M9jNMa2r}Yehb;N)AN(;BazQYHUaHOYHGTD z%$}G+TV+LrGhP;2o!!$xr|Drgxqo+p>skwgZ|Ix z|BJ7~utJ18rTAr_A6!%f+FVQhrl7J3m5eZkC>jPZu#jQ0`Dl1R0xgsQ_gu`(?psu^ zR)Wl(^a-79`q?LB7wHU`htU*I%9Ld@k+tuuaqCr^Q0SXVPGUt+l-y9iq?qrt9!~bW zH!EfHro=Dl{@!60o8R!O=BaY+g}^DN{6l6pUK-Qn4)$cx*2_2FIx3phNQm;w?&Z&y zZTc0myp*s8IE<*z1re5E_)=RvS<+vnwo^!?OK$(C&_F59h`6kM6$O_+H=swC;puvtEn!pLiuLd$wJA2wuLs zX0WaMVQ%wqNTuSN57&My&qy&aky4b|8cyxj{UDINrV}dxMC^Jt^p8DS=uKK&o$9%` zz4*0&Z>TMHbLHrmVRoC97|$i!>g;Y;VUjOEI1T!5({1#d1qTBum!=5w`O@b(mNTGk zcwsxVyCO)=7@5QWp4j6w&>&c|dH+TK6Uzle5BrxfV~1u>D1XL{QU8PMUHnrehYuQ^ zr*!wH+(CGyDE!OOVm7lDXT7%org8Yyvz=PV_q%ntW#D?S2cdYcTXW+pH;mzq%D}XD z8W1URD^!0QMcux4`;5=n5G=>|=8EfN$T@b==!{A$&(e=;9bAuv4xvnG8DSaU2fc^7 zGa;&5aZU4)+4_EiK<9(7s>X8%@#crSe_auXnH)gDUv-g$-a7dDQmm|?)b?3j{Z>hR z&op!W$?kM2DjrA7T9jX%@Tb?Y#b>>11J<-=obnvqpqy7ADSIOyRI(U>S!~t51s=~s z|6&A{(7m{*l(G>n9@SEG__knMS#)zFmg;5Gz$0Y&A>FiH39I}BF3+oM#i{n?!rUV+ zC@J;@9ji=_IlN(J?^i}@aNnGOx{V*2KaNo*KL_HeR7DEWo#U@jg%1FFu{lPG2cn?x({FQe{7eq2bjSH{XC2bnhOtSOLqA2-UYJA6jaad>HHg?a zVg`R|u+-_4RyT32VcYu(I1R0aqJY3T;Gf-dnsr*L!y6>@D2|rpc zweYL#qe$eUXw2D!AIxj!yKIctC#1*_;j{H8e4Tc5Fu;cZpK2w%jA&*%*Jwv({^5vX z59JP2OIThrKqyfOCJS3V1f84jy!rF~NxQuBw|`hOoYeC7t8=mXhu{CKB8vkkU@Ny} z%+?Yob?>tx%-B5imW;a)R3I~KJeJB8Q+b`Qx#^}(9e#wp6UR?CchjOh;O~Mke%)T< zC?1#MMWkf^48!pPMD!W&?)?Ei-tv32viSjKV5`!ph}zkF+!R$GQHs6_Mf`PhHZ*xV zY&;^rc}SJmtM|%I308@Pa`E+A3BXNSxnFW?pvnP(!%5!j!YCwbNWgliN%V_S-3}h`5=BPF*YUkOIdO+7C%N&0r)Dcu&Euo~CvP-4 z99Cx&&pep`i0+&Ra}meTxWUf>QLpOWJ=dQt*%)6D(=#&Ynrg0Y4-5Zs=KZRHWLRN> zb<=4m0h2l6_Mn&u(m=5H??H}kh0H_RD+0*AVK+t{luh`JlGda<-ZDD&*R}q$$d0>l5LRyPyV86N> z_x|LrA3d44!ETeE^WsL$Q?Pv$y0s39+eiCYZ9I-wO;||D0kv=|I^flmVB?l^<<&Gg zq45c;?db40mMVCC9RT*iqD4huhmOfXMFc|tA7tPb&1m84w?Sv2Li&~RFb`TNE+cJW z7|wWXTPxnL9Y8a8*f*A5rGF?@&hPZuPOqHU*Y{@U=+7UR*NW2aZmNUHPeWgBWgpvx zgeyNygJTWCdyb1D`~5MW`Pkx9waVt*jG>$bLLFfpznoCTis&ARMx zlCo$GA9V@)kErq=$8a8sMoUL$GWS!(P}`1?kc7vam7Crwz*%a-%7^GnC1E=dVIY~B zZ9Viwj=jeRDt{#LUG4?mSF=o!;Pfz^5Ng;H3o1LZZ@@T>bD5!y2!!)-z>>J|qqq$h@& z>)`&pHF}f7YQ9`kbM89g7ZQ6hF_}H@W2M}-Qqn3~ae$92zv3K~gn|KC$9BTX+O7=E z;vzf?;K|*_$CT^Ef$@d;o8_SWwmuP;NUCp-iVesJ~TXg_Fby$)Gq4EkLNh$K-o(o)x$B;O~=2sl=fEs)X(?! zB2MgV*WVSc>P^hi>Ixz=o|E(O>ltK_>Is4;SKT~^gwEi_q6%7XoW){WMUkDZe)-xd zbi}e7Hf@0QCl9(WSDNff4*qsy|CzOc?$Vxl!f=@_xt<&5o#vQWzoNyY5Rrm=o7$iq zL7W`_WCDkj0;e@@({B)K5OeL70>{y<&A{xdy7}Q*xQwo*NB^ zh=LlTu1H8HfPBEF1;ueTs`i6Goz{@h?4C;!148B@*h|N4X+@`LxnVlC5j3mZcnr%* zyfGViWN>c&&3$Yi$WAVX-S0Z_M{oZ5y#E?)YPj-mD;|J5lV{CB;wQwM4k2BHiixSzJUJatn_xW60(6-v_`TL-*f_t4HIM$o zXoXJl+wXPr!%0+I>)ZCrP4?D!{K9ahzuQLAZ+!Iw2XEPH&9??3OrXe#q^jzS5wu_6 zR?ijb%}Fd(d2e)wk6=|z#!t=Ku)@KX>lPH_i7e45t8L@e^ofYQe9#^q@s0^{J*ujZ zuuyz*wpi*gX)H`S(+qoG;>!z*_0cV8xGA8?qqc)CaZ@Nrpxg3?0DUhb!$F7x9rdj& z1`?;_%Y#{3Kvi>zmXR)%^biJPz=+qQsX=oItWF&}G&*kL`>2Oc{r?4&ukHlKo9ngh)kA?HNH-5lD zP2&oefH!O$(&jJo1;B#x_0nQDtSQBJq|@~Z+VwtLCqSSzrnzvT{EMB~gV2SxlmTnc{Xebx>Jg7+ z54$vDhAkgYHpayLt7NMx<3B6pn3^+9foaqCL9Ob+0=V9s3|@7t&Znd%YvDiyd`2Vy zP&f7W*U<70vzjdi3DYgF>aQ~ZU~kwUFU)VocE({Mx6zq zs-RT8V>PPVFU5F{{ogLvh=gV8ZSW6l{|7E}!nJ2Y4V>JEDV}h>MvT4c_KUuC;y4ao z#8thxR&76MFV=X)0%jX8J3+ote{aKNkFMn*`&d6S7E+<>b+EkGiqYd8>BiAI-Q>wXJ5=?^okVM%CJA!%4OS z&U;qc26zK8!8#t7dr8~N3M&u4)Otpf&TYzjk2X3(-lddbv4L}j7p^SM3yg`G0p0`| zzC3X$20@s>=;sJ2YmtOHbo-{tA6{L$Li!qkbaX5>&n||Q^quqkr4j~fOxNw)S`UR` zP7i-(nN7`<8n4+f_IBoni~qJeT~PL@QEEZx(uI7SIX%0U7FB%A-2Gp+;tf6hig1=K zV%I*LusCYrGLyB!9}zm%#vn=E1}&eb~d3RVWmqOR$c^|zAV?Gm4IT#UiO z(>iW$d7UPi%0DPB*%w=Sy*w)pCUc~c3+mIV^iW+(zo%LDj!&4t83K*T=;bkjsjE!B z3FjqiXdQh#$0q}dBhP`_sDNvWKtQifqd#oLGn};dtH`{>7-GE!z|fg7fl5 zz!)Be=wtrkWm}9`1qEjNMN`Vg+5eHkiKaGNwxdRJEI=5=5dg`O#(A?W3B$==a2*Mm zuvbUKoQg$9!WtJXHIw3)} zoj_65afh&ZDfhm(xBFS&^LEu}`jJxB0Es7&nLIbV1sO2br-{n>RNs;<(s?|@9>36M z+sLn3;*(fOX3v9UyB6e6Zo=MO^h}SJvY05oYQUNDv3Ja}PszpdiO=G+LYs3g8FCNq zk?t8hz`n!2VuP@v`NL^!W+rJSg}jdzRK9|-#l{?xHct!B4}n;uL+wTRnJ}6;xGOk4 zgKVBUDO2CO(?8|$GJEg_R`1%??%Lq}1o!Xg4QTtfoMe;Ni!;Gl>K-wW+oXd7Y)<2X zJq};=DL4xrRe;kbQRG*}ZD!a~(`+g6f20UnV$eu7C=2H7Nh}&I%yQZM7x#p^QZo1K zhRtr6&YLsu$xhrv!pP?LtFgnrCnK6FyLS{RU6nU$JrKcNK)`S7!m^aaqVI^;2WLL$ zg~Ir#YU&`#5T%eW&}nwXjCy1VUrHhtEcA^r2M*5DRquGy%XV3hlvhs~-5ss0Dgwox z&h51uEaOj_Pfq4ufVSmG{flLZ>?P2{jv<36{rO-6rc#vy(7{M85ik%EF^XuK1H)FX z!61B}p8f{$%Sxqh`Ww-*A8|Od@(4A5)EnUB?F==pQBS)bDeF_yXP6U}f8Z?2H^>XQ zH6XdKH};IFss-sJD=1>=A>mriM!Fp}kn1f=TP+sK{;)Mlg-M$mv`*`fQPO=BU~^mc zD;XsGkb`PwBTTl9?y@L1wZd?&0jt%gb*~n{zM}p?@6qdMf{Gi#dC2W;E~t&wGofg$qtC8vME#2^ z#d*3hMt5^nuVjMaK7i8;&M_m4p3oc3+U(|FX@K71LNe&!us1N z3s=!tiA6I~5qz?!rD-IBeO?E_sVK_8t(}BDPgYx=85ms-H>PlM8n7yru8!e3GJ-K^ zGag|XIaX?g>JPrw99+q8G*LKPj|kTYoo4!i-lz3Rl`Do!3uVr>IO&dMR=im}StbMhr7v@+yAw6o)cM}W+N3?EjeUEb zg=D7X&BzOVz=+|>ADWw9EI61R^#$R#ZLZYBZv~KbrjC}=NrFY#*!pk&(2|s7xE@Og z*g31OUQe=T0@w6EoSU{9GU$q6PDys$>^k1Z)a%)j3#o^~!LBcOhfyltVHNS?0-f5G zs5vJ6Ca33xn;ZR{A>imU!{cU(<2)qAav<>83-Euj-axQgAXKF3ov<)?!O+#4awG+K zy}VDqYy|UzVng1rDmhQ*!7FepqaX$wYzPkBzAl$MEwi5h=rK2!E{&8&oxqoO|5@iH zd8vzB^V$Os8vTwYL0ffASws1=06bi@k4Ne^G?aqob0t_fT?k1u4BgQXc`W3<0hS^Y zYmz8zH96%`Q4q5tG>sZY8|dNY1-=zAZLN}jL;q~YGrLum>e(>l2nDMTcEfscQqqUPATwg&z^GW9iVEK6T-^w3< zbU&{Pqz9QLOl@Qsfr-3%r=MHHq{EEP`OAOSy7z6clafoIv%GNa)2$tHud@o*90Eky z*%tyjjn$ZWTHe)ER`W9szhzabGnQcpk6ILP6&)UmOiFVxSHqv|jos^O)N|TcHMuc) z1Su6*@AqqOrfBy^b;YViaQT!MFYO~ajtGq}h)6zL9u8bsBStaEqqGloGRDOo%%%_9 z7PKC_F3865tI7w+2x+Z`n9aUh2^byP!~jxWqLR%&+XYTYd%{__`fK=gYg4sL-nPTG za5*99j~KJDnHdiT#j^*6qNBHvM}!Cnu1{YaQJ$sj4P20Z#?e;j`B*N|FC>Um5X?O# zH-QAC zu^KFeoWHEeh}iom-nSQ4jJY>>$5EfR_PeX>8J;TjoYqyMQJ42pLRJssI2)j3y{|SM z0WM-Cg$60!RpEOc*fHw9KeMIwd*T+F+~!)#J*$O*m5-GeFIujPr-O({_>9EuWgva2G5nbq58yEK-b7a7r6*UUAomO?tPMH z>00nHE?>6!i|6|?>_&C6PlqcH>y@xSHZ*?{X&9L818=v6ZVb6-oVrjb@^4}2_1cs3 zTy!1qjHO#t&8qze`=YB2uHItu<%n!!NKbL10XwqmJGNOW|5~VOU?0D55pi|jQAVd) zXSbeeU_D-BY?ylgTPBmJEr;9(l7A((wUmt#dDdBvQw6v%G{%IMOQ|q>gbW1gMe@>k z*tssV9C6b46Y+%+#ueoejf?8Dvm!^cDg~8bSUg=q%PSnrvcV+DtB5~(-fTt%7De&u9~wT%D5-~RrFcaoTmZh1MI`>m`{I;t=JfG+2U z!CH;Ww|8*383px;*|WVjH+~g1o$+ z^j(p6NeA1aEtVN!r^(+tYU&@RU)T6lh{Uc8STB)t_F3&0Vz`DcbnK!+o)RnwHr~#e zsV2jkgG~#8($Z}b7J+rDR3!@B34Tv^j(7|!0bfLlHLHm!oa{^FeB9s{NQOyy`dCcf zC#d_Jv)ELN=;^StyAcRI6Hn6wOL#o3r3BYiA-gg_d-PytJrvqd9RWG|cEk!}Sh%dn zS2!N1wJ>g;_C)73cSL41?g`0PoAr8K#c1x}_Y#zC#4;Yegyy{i9MY@CJJ&T!Z^IM0 zBt$@q^SnLor4&}BrAImw+VkTUlYvBu?h)>o_(9H`5`!{S#JVT2K;P(#HC-NiEge2-*(~F2H9_ub?O#UD;xOYPOpnInff)he1iM(w81;; zD`jQE{gZn!sb@SGUo$qr{W}jAeIt)2qPzu)5d#iCe&<0$WOGnZS|~JZ^Ml-?p^DcH zBoE&~LZ)`uxHj&er`8wfuUCX^eT>JmSZh`~nsso`IN0?rZG@-(3liK@qZRPXRaprj zASA>@XS2-A{qaxu{839HgCK$(tql!l6Fq@qgFcaNfOqi|h%BTtq-k{>&K315hn&r9 z{Pt*SKybh!Og)@|!Z~x+%YFxR@%+Y&D1{%atUwd4$vhv}-UhZBT+Nm_Df(W9Tiw!KCJa1mai>tpU~4z2_G!t0C8O?YFqsZxd)?44C1xvpW3v;+e2L(GM*hRC|pP z9r7xP!QSwm5h|AH=&m53kg}cQr^>$QNFv#sX)jfCj5pMZzaw~?{OrHTd9E4dESb4E+QkmIB^`5gwrL2e|B9u>y)*eN{J}%9B0-Ln0&ea2@cpcao}sN zgtr4YwXzUmp+qGKUPD{X7*K=FvC?#3HQ3%7a4rT^6rY?`g@vi5iU`X2UZ%QUuIDzx zmAk%QgdV7u_s!G)>7N?lq+|mnKN>(BI3C)ql-%F!1v7fGJgpAnk1(!@!4|UQ4f9-4+eiJT}`(^Q25^Ne3?9K z9vN{4iG8+{$K=^95M;0oNjtx-3m_O8CDMIM(Hq?;FdDAFcsdEyw~iOF3mPb=Ea|a- zf4HKn$3+c}AtiHLTbW;un5c?D;S{kr%{of2S-`I>ScW>cETuktC0{C!Ym0NF?kJxj zS%nxv?l(~lyOgxUNx6(X#LKonwjRyNBD*3;(Y!vnr5nD6eJ2xtn?Hj((>f_`vE8Y} zf4rdXepCpjbV&LYodb*ZcOon*lM3rv1sJRO{sRid;JY&~>#s1s>hNq9uDf&b z7piN!-Ft?HE>^of@zT}rA4~Omt)}}Ah>2f}lMW}--%+w}BPO7er-)8l3-L*>rlVi+ zO5A*Y@AYPY%~QEGlE2v=UtrQ%m}W9y2_bN9kc~QfVSeG`@$cn&bldZ&nzZ388qHaA zV_%sV@}VsEbu;r)CXlKc@F$w}AW5g>b zjspSYj0+ggmx4i@%)=T9^W{IKf|*NrQkA>AVZyxQNzur*6rX#20Kph(TL}Hb0|h-n z?Zg=wWlSbAms!6K;?sW91=Qx32(373vgRGSf!oA&C7qQcy1Epuuhjnu?5djKo}OLz zUEog{Q(ZgD7p^gN5JfyLw%$~{UUJ*`Dg=}Vd<~ij@J4nb_Ey=rVRREu{I0;!auI@v zguUjMZMp-!09O0s$!F|)etJMjI)37K)$Qy;x z;l_ps4b2=YkY@VZzX@E1T7hI}VavU%45$2JTe` zOXrqQTGj+Ybx0i-oV6eY%>~i&h!Rj25h!JpT&r(&Q7W`YI;lB|ccj}}+4|)AX%4(0 zfN1He05p^|l=N0S^tw(Mpxb-;EI3&pJwn_BLpCIQauN^x5CCtGTWl^b^+h+`rR5u& z^fIavIv0>ZOz-v9m$1cq%UJK5=$2GR%iAXU#TG}r0H6^M2d){hJANB9`W>VC=nw_8{Gv+A>|*?LUPP7m&lxcM3@pEy1nDS`DXH#%JS}!Pu z^~6T-uFh?J37<*DiA)Bqb#nc-6fOuzJoIW;tEj^M1N@N+jySrnMskUeUSDv#LKdEL zD@X?qgVD2_Y=oxt>)U=@&6Qj35 zm>pd7@pd`%TRvw=U8V!At<~$HK!2LfQD(~;!zZcsc4Ii;X-+oh*xcJU5HE@Yk8h4W zK|HMCXeHGA->=_r9#7ALrC`^Er;Qc#kP}j6`T}jHk?IAZfu&LkEZf9KdosnJW8BlL zcKFnn?!Adj%fa&wn+JZLcC2kB9#DuYdKsFtDWB&Se!ORs>9JL4?sE@p6#btRj$J0) z(}b*?Tr7#U#c6zZ5xs??3Z=)L82OjOyISkQ5~WBX2Tw+dgYRNQhEd3Yckc_^qhGQE z4hUB3W{vbI{Th17wTUH`O@J4DhO2N9JGIc#E^6ls_6jRKUKHivi`#8?vbuRlm2d?NfYr3@~(>q#Zir769yX6YfuqSj&fmO*ObIs6KD-dQ>-d#mrv=X<=l??mGSr17 zBhe&k&o*t&N!wKst|+| z(a3$R^oYr%4qeBffAL*c9q7)OK_tuAKQ220sYdXOGaLrB> zUeRIjOPF6|bJQVg{Fe7?J=ap?nL`*a=lWuo9I@o(Dj?u8>yie`IbK95iwVkKwx$ua zOO4>07M#80dQ10*Tep&IB(=VlPkY2f*b{~_ zP_Fp7UuY##`=Q z+PZP$8t#3bYv@_Md7r-yujS=%Wcr;v1;gQoS@NEzMzHD7n}vCDl%9zRc2ea&H%Lc% z#6_3R0$P}-e6;s5LchgCW_-s*lRLGrzMATQUJwQjC%%CTKQHeWnICJs7Zy3bk*&@L zP`UtNEZLuLjk-w?k@s>K4s9<@^b4S!2HiMSPf5nvEwZ z+TAa{OcaXS4oudN`@)wup}A(h$w!N&PRKRphs-v59Wd*7Bkb#e;)H`V)a*6rhRnDU zC;c~d(k*qPxY~~xGw^^pubsFYTZ{%d4ufwJqk5K1z9SAM6t0s(mu^}Cc7+T|6CG>V zQq6|{zTW(RD-c`nlyY4Fv`VJ3)M)A$g#}cOkx>kVw91yvs=H#zb)h9in;+Dn z2DpxO9lONX9a~#s%9L-MR$=k-9>A9cx5Mwy7s@h_SL$NG$V=cbz@&0&KMBY&xCxW& z%pbIeU$WVbUONZ5P+LT_OQrxjTnfo(M8qE)u$>S&wbg>=b{ab56)=Z&YLn+F0yTN< zo;};b=}c>ilanve-mON~EUhRyXD4S(5R4~8)v7WmWpA@Gv%8oTc0?03yA93yvgPdH zv$2cO@Xe7ne}_YOhZgy{;_^5tIt~M2C{MfL*VYE8X~pw7Rpy#3uEmrc(+&m13xWk#M_dhL()rsuut*hpB!5iXigg4nPRRt_<-;Q!T(6SJKmcrJ8ZiS*XFo@9 zxyOW*a)uBsT};x_k{Gx?JdcbW&|(DN&nlNY?B={--sW+UU-z3-TnvMV6l?qG{t~a` z0SgM_X=-XR%2~5~6mvhVSXo~g>2+4t^XBeTc(dk-FL~+3jsJmW&7XncTfejeg{Y_{ zr)`r=b61B)- zA|!00aM_AmewugQNYQGaRq&68T9gXhvNCE-sPaZtvNH%3 zuVf$ca$J2{D(3FcAsBd8q8eNgZ{PGhHBc}7KLK$Uj_9q$|9s(fN4Ty4+#8P~Yu~l~ z=F6VH3i$3y{Cam57Wm%BlhTIw(!^*&EPr2+pClX0B_mDRBomj!MP9x6b^P$TLOii{ zK6Y#tBV*TFn7AR<6FQmI|b=RFjFipX&pkBm$aZH5VNLl-S>cX zQO%FDbTUV*)ET$E0?r@Bw1Nu=II$*n;L;MwS=L(SR-dOuaJ0_xd~rkVOtcQX?C9{O z2Kzs$z~X!DmQBOB_%%Yqs4gmIcxUSUcgB6)>8W@Oi^92Vrj&qt&YM6O6d5uJHna zLn&U~kKzOanN#hSm6!b8$jF*57Q5lH^n!8zTqEwBe~-Dj((BM?2T(NUE_F_+Ki|8j z+$RLoP7r9DsNgX{vd`y3tANqe^h|YbSdRGv{eHC#2X66PFt1xcDbGdS$#!*4)wz}O zJ>sUDaiUpP8?j-8Oz)kiRA&fLK~&MmAglo2k?rm6DwG5Vt}>(qUE&(QCHmB0K6>~Wlkml!v|2nuP19C}Do@5z z0jY$c0T|}F>`gE+DdG)l+`*Q(Yfvuumqx+X6z|HzlBIcAurGkj=V}mGy%HPR+*n>& zBefdesLKnpu;kC>*gd@jnOKIu*1c^9u;DSL)~ch=3jl7ft3*YOpkLBoaa+AW#<*6! zSP1XSZnPH%@oNFzPnOU%bRM2~^9@x`^_J&RxavW?_P}QBZQ6q()L^HZ$88=^v;lQ$ zQ~l2nP@tuyMM4@)u>H0f0*9p!K`WpY&y$7^7Dwt-u#4z?jgq`ZfQ$y8Hrz zJHRPBaVMroEJd;WrKN95TBcZKC8~M4a<(RR%F+^wP?#XNy}eZ+@C7tAO9yIl64-H` znwFtrud+jpA1>C8QEO+gwcg=9&yV?Q8(n&RbP6I6jFb4wmfCK16D+$nXXygcbR%x& z@yB9K&0)-+ztGGY(o@0?EAZgKvJ-saqR3I9w8-PVHQE)n(zAUVk=NaTQtUO7G1>pt51hjEmxv6Rg- zx=>=)J5x?BA*a2=ir^|^(qv~*BqmEdd+~~4P1Gha$sXgL^{D|dAqxrfT<|#P_So9OU?6mM*PcMZOv8mC!6mJm2~g>cW2{(G zo3XT&rw_3ro|u{{=ZDtK25|0`XL6rdLI))_vpUyuj%lqc92d2h&JUL3Ib_&~J-gmj zx1sRX@Q!V8Fu$Ztyp&UY!akDWSM<0G5va&qj~5A!)FVA{0Ee09N_8-}JF2*Kyjq)FlP z&G+%?GxfN`F%XP{Bzb-6fn5#}^`cflE1(r{D8TR{Y0|f#zEd6R^y2NKz_DY;Kubsd zCNPuryNlm1Y3XU|ThLs8wP|+YD&T=~_?{?KZl38XI*Zn}(!T-uyt4OR#fuwe;Kiy& ztj^1mL6%Z@U5VjpS*(Oxkc@QMEFj;K+%D*C#PU^i+sx#`g5qLSJeMYQlw*m@huzzO z-?Vx0#HI&u|JE9`OB;+7kF+fDKpk2#C$|2UP-cs`sdi@5`bKZUwD?`cPssPtZ*IPkw#W;Ef=@hVkvD&(xsx)5LJNp zP-bShpJ#|3rammKfL1^&pcVKM3VeQGmM>9}E_(Ybzz)l9v05SQRo1`KA!>kNzv}QL z%pD`~p*c;>fB!Ep7?_u9M-yRl_|hwvhS zkM$MEd+HS|N%o^+=MfaGSQ2&L&bEA=Wm?cigThTsjnc6zzrKb^iq;vDIVC&d=#!FM z%Jr>v1p!UDg7_gbT zSRu2i6TyxX+;Lrget}tJa60)aKjaIG<|)kv3(5=!Svd#F(2}CBPY%qH=yEw(Ky;$S zb2U>_(`mK66$~>rbF2VWGqDpcCMFi#zcbM)n)*AzRpPi7fyiOE-Q3PAVE_^Ypjj#K`+|U#e+Tye9Wx8(2v?IlId43tm&6rykDTA6B(aW`WrjxSQ`RH_bahB5 zii-x6=Jo{30dbw}ZE~ynj5-K!M_|ui-cudNBS#to37B`G<+M6)1j`Je!sj6e$~5$J z4nkz41P_SSRicuj~+2;J4$Z#yn(MgZvSl!=vVCLq^a*vcG8m5=~FaoufA97vEX zK#<32eXi4Ln#X6o#&`|0z0Sn8m9odDCiFYbrSR)}uhW+=_`7!wi_A`U4USkB6x7EzARLMtdX3vj>!uLbM< zMXUFA`MaaQ?oFgYzQs8x#hPfj&hMk)a1N};t>?7@T7jXXfY;liymB}_xj2uIAxiju zwT2jRmbo35o0}U|=oNm042Lvz>Qn`Wt;cGF34XVR+XhfuS&nU+-Ue2d<8P$|zybKSmEc8eL!q}A zzgum8Hy8ip7kFsvL40q6QGdWwh3z}`NR!G@U7UrYZ2mH;!K}MVu=kW$B7a}u?z|QC1!rGVL7NG3K%V|&H*%uF@Xz4nv zHZ}#^2jN|}ZZLMTI!OJ`kWqlYb@{D6Z{D3l=9u(>Xa%$aS^=%V*H>VKbht(K5`O)9 zbq%+$0{kfG?({3`s;&;7>d@?zX)w^O;vB}xFhRP9G$AlS@aPbLGUds*>!DN#sB#_Qu~8Qy?@2$ z)EmUspS~|3_hERpK8u43|2tMsH^8~C=>)2qgUDMn7rvd(; zD_9yV!y_N$;+@q62($`}Pt8TTe?NY>H5tEITYy>typ_!cOb*sbeQiL|q5=cdO1VuR zrQnGbxk5$+Ja0b$*TM&}H1z-`F4&KKRX;?2vI+5}oj>>u=Kt(r)NF4+$)aZbqW*5I zPdS3BloI&g+J)sjh7WhcjU1HTCv`HlR^Y|`ld*yO_?*<;*Z|M(e~EkleedU#`tqwh z5}!AkE6Fck)9~HGBUVhAQ>NPBgy&3yvXDx#fFA?YT#@@dY?(ZKRntd)J1RgpOu(k# zu>ym=A>eFG4OnQvNHtHZWx`38mG>>Dv;-u4WgW^YS(Z5^*fE!l`7mTw%b{{NQa8eL zf^4&cjr(G}a(WA3yk;};UH@s--?6y(+h&%U?kWHOFn#(AWKRu0&uLXl06M#HuB|LP za%o*`-Pf0KnH;Sw+eN@TW^6b%EO&bPbiG(>hTFuvvuB&s;FlC>gP91)4jrmegNO)M zX{F9-gA8O#nK)6jp}T7Xuy)9|Qcq8>42&8b0@KEMz8nZ*^hmK>mTQIEn!uS;bKsl_ zjCsCkwa(65^(XU$(EQG#b-OAjc?Q_+m+vx{fK(1JFa{p*7_zc+R7_~b>Sp5iRzNI~ zopAA^kM`hO-+DlmG5FI%x&80$PD@ zQh{^l&dGahyc#6)O}68k+IP$Ov+@idA9e82H`S&az26T%{F@4kV%-maU-BE2p+`Do zFdf10tfITEMXo*{@QD{@7hKmk5;Y)$-QvYl(6yxiT3Ui|rMn^ry2>|`X<_WFYv+>> zBmRYVvD7}!&RI;BeNum%e4|BgJip7F;WQ*m@}g9wvV7Qd|MMvR%NrOBH+;3Cl7G0W z0!vC(*aoP5PI0~J7Es{y=?3-tH7_s!7HG}QZNkx`)iRJ~vh+iTf7jmJ7U;cc1+)TM zfm>IB;W5PU*46)pwv4fVy959e{;EH*XyNpVSn(t#xSkL(d9^`9W?%VRkOIwYEs-l2=&)O`Mo2t|Y~Mj>JE-Ze!igaGM|FZ-)r~ z1&7^?>W(<9lv3IA7NSz1y7JT7x*I>=pMzKaA&5tQP=;3@pNpbk?x5vu+RPOEV&`FG z<(`%DMu&L3Kwc(OD<0;5p@SpMWpZ8(h%sI&Z z&SK2M2GrLkqk2&gW&crubkGG zA{rDvD3($47Yq-V(_d9L>vmQMWaiUtEjy;IiJ;{8(Ic35mt9+SXfPI|)#Ayzou1bU z+$stva4W#>>v*vs5LTdA?gztimq5{+m)K|mwKza)aGiiMV;ciJS|PCskQuUp(2>i= zpTK4{AD%M*i;~sK)GW)`xXwfiLnjnwnQ!0!59+(XTAt7_MqE5Q(}`o%NVw~6Bng-_ zQ{AarfwBF#V`kXWkt&IyQCnMwaxqn86j5K8m=Ehw;=0JiCLi@J8M$o0Z&sK37tP4zVbpL+$?Njz%; z%o0aNKQcQv4bH1E!Ty>=z;zLT<*Mtfj)`1Oh_$x{iM+HM=Nhy zSDA^HskHF6g5gg2u4J-;VKI!AIL|E+V0hF>T9w4-~p9qjq^-^&2L#Nm}XhJ=+4cxyL~1UWm~PC ztAxq+U?XPV^%lcJ@yXvd9&n5L=b*1gQ#VmDo zC=66=5i90*uMG;D_37#DrNG&nOfjYkOo6F$X;Bq!rK#Xa%$akqU%+ zyCT==oZCbJcK&gMWT*e4>R9gVka_t_N;W!n$BO&svEm{&ZF06)oQUf<>GZR9sPW_a z@B1oHyu@w=lql~1;vIoaCJM-LrcUWNYZVyW>OC(VnE|AxXCO0c8s^?<2SLv5hQqQ) z;CiOGEVg#m#Yt?%F9ySzC`vk@B=Q{J4a{Ap<^yeQh)7QTBnjcE&3Lelzj(fBQXt@_)U8 zbnzrg>njy2RKV@l4^P0|)P}P99Q^nDq)oX6D4O|w^?5_r%HBPhoEO?9G`HL&AI-8K7922 z3goR^kBs^M+04G~)7j#l)S04a9Xq&m7?KI}E^`0ZRbHY2i&z(6d@|n8izLJPTPfJTvZMCi- ze58A3XKHTph+AB{1u9)p`{g@?Zl}$}XGTLqomi0Mn^|gl@#2N3u+dg1v=GhulzGwe zoluxnSY2$J*1;*M8M6N#n{~5#7WR)2H_kb>X3*l9VAKlh{1UgB`E%wNZs2&Fybj!A z0h*a9&|BaxzX@seOsLr}ogjp>gvdSO@ufR7Kw&_(v068q^Ji*fC6q{~d@Itb*?`6u z&&wb|xh5F5Sy?Ts>1Y}J!PlmKbEJWdnXeX-rE%JO)*%{Z~RN zo1HbZgm$`BZxrtyjNNOG<2@h%vI8k8;qOs)4v$F~W8ICKpD6Q$oEs69;_~##U}wT_Us`T8p?%IfxuXm*t&1#00001_ diff --git a/develop/doc/_images/pprof_2.png b/develop/doc/_images/pprof_2.png deleted file mode 100644 index 172ba20399ba974d27f4c072425277b69b02520b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194000 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�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 bg1?qGymXmRYp`!_b>? z);h@X$>FMy4cl7c9TWo2+f(wV{#OU8LWGi#pl=ECjF8M#)7Ren@yGkG=ls`z7Ra*X z3JH6c)+WyaX86}=b`olFH|^scmMKr-Z=ZaESS2-zOojcq$&$K--;-Qf)k$~=Hd2LY zbVh07dgqR(&UqstPbuhz)p-~X=0`M6s3hd}6!Tm6n4Z`2qNUq2%j819gJj~@9MXc* z30y0v#s}0ENW5goOG`_P)V~w-Sp502t{m2%aZClH6=f{?E%mA*f;l(zKoTBTriP9k z(`4vxGrPD%nJ-UqKue|?)VT!Msv>(1Y@#q6h06g*TNx6(W6)_M5im z;$jSIv5zEnRg7@3-t<~_o8yzf$RhpGD)Emu9VVSoQDT|$11ts0wG)!03XSNyC~8+L zOHvw|lPkb;K>!rg-eG55g(Pa#H+xq%J@zx8WEuGkhjRJ)8imhnE0GvTX!1GjOS4fwxdbun6G!+Iiy8Vz@>NL`L5i8=KNW9A)fU5UF% z%H=X%fLtD{)=dVZi6wn~_QwUl>@1Y#{ba3fJmyGV>*Kb|N>sP8g8l&@145XL%*jmf zPbFBLjO!MzGg8_>W;dCkJ$kI)GWWX{3nxM4CKDNmZ-%uDaGh1q))cUVw z7M21EvN}B)3bQhiW|d##Z0Q0@oEzFcaq`0%PjRaR;_JN-1EtC4gSG}S^>0JONd=%Y~cn& zRQG4!wrxwn3F7<57d z8NlOa?lc}d7}_zHsyQ{&tyaHfF9(j zq{J33m+rTb5JuP;7mlmyTTmbuf`CX#oeg|`-8JDLU{ke0?LS{^eA>wuP1H{oYgVoD z9Q!J8k*ggDHYAs*-@1TRI;>cYX=Yl+Mc*m4y|kRkZh!bWAFEsP4cyjoo@mTd^) z+)ia%5!D_;lyr&+2fT`ACSEkm6*z_3e5>6yAA{~&WIta+;KO!k=-m&{YvG6%GS#&k zl5TQA4zi*OlDWQ)1C(8*CKbeRXwyX)OJ3t+F}|_${w1#uO%*{cw3Je4HLvt`N4cM^ z1HYT?ICZ>v;zqy@3{w2mJkM>bb5fX8mEtSh`nBvluISUv?o!iVrdKLYOm3|J8Ii%~ zQp08EroP!yIqk=Vl{b75p1aMCpB;hh%xhkreY+PpzJRC$IsW~LcTaiFKPtk!K-0xU zKV5RbQhd-wslF7L!JLtt>YU-E81A(l*K@vC^X*Tw5M)&fJa7)Mvx-Q_AOvPHV$o5ZWBT6AVk^xv*A{LGpm zEdP@52a07#oODB-3W2spDl))WzrqFxXS7%Hx_cc)mmja7m{~WpQS#oozc;8;SstPK zC1cVKMiWSoq=>uxR{t3b11e)k_3IWQ;CbZB`S!V1z7#&BmX+x{7q+NRye#aPF(riW zJ1{mBr(1i}kg&!{&SUcNm`A^^lrB$e3}9e4?)3J^ULI1SRG$uP8DRHzxVQ6Q&#;8D zs`-_+V&X2TNJ*BG^OU#Gl@gi>=uDa_;VQ->x;rP8pUNul!`HK%>?EUWpoVv;0sP*EB7=;7RjRw+FOnm=@@7+EZt)~Qy|2VVEW&62 zpB=Dc#4j}1JZu8TTTn6!qU&Wh;$)E;XLX(F0p@e62nJk_p?BrI8Pyl+HZ*rg z;4(Baf)X}jTB5g3g!v``>Dudt9@pXupX@p_Cy{uA?Jo_Od_|1I-Ffqj(DU9l5p^Apu|<5BjiV z;Ok=DX|V;t3~%9?Qk%}2P%&sV0L;$=CK8$Tl)!R1gWE1i$g-{XJMuaCHMIP!i_+2Q z&`lG;NRg=adgeB4#!AY0ij!cDBvZo&TvZerB;~=wFn=uz!GhTEjdzvFrJzM$FsJF7 z%9@A{Hqh}F()$qtNxH0A1N}_>m~C`vpD)H?cU-5z9sAaXp-_&4!EB ztI?*Xh(uXXuK#XP)*?$4Z#@!vUlmDZ!AmulYk$g{Z&o0x>WlyGJi6>4vSg!yc1hCt z<6#z1KQJr?pZS-nVB3Ee>}pN}2!FcJ$wYKe^g$T1s12MEiV8E6jcw~e+1li1XD(4i zZBSv`D*|SRz;LB0-s-Vmh^StAgU{AyxyD$wRgDt-7i*cgP-1}8)=ngg*YG4qU9k_WR$mZs(}lOHh>QE{4K0J33U0!1aOjKMW<~dH zh7HuOD&&%y7NNk^IK#hG3M0B7*1YslOHxJOxv$?P5Fc$hx^duL;z@$Pi%$~Meh-ZB zNX`9~;h5`ijK9=GASNrreh~NhI>ACP8CKZp&Zc=D8W|>`l+L-VA#up1Zg2lMHxG_Y zDUSdKsgbjFcRbsRhUn%BGVVYEtICH*_1lj6f>tRWiM?zBBdWHs6XqbimOEM1`2nZi z)p4SBYRHlzy<^xwuUj*zRo#E?kTrs)7S~4~Z5O0P7LOIAvuBwuU)U2Pln-E}!LQM2 z51pRnO9&3wktegCxVc2w>?C7Z-xkUxz1Sb?pmL4>0D8E3fO^waAk)4PS zq~ok#tnV`>tSbv9e4Lf4F+Z*kG2lSo(uhFisIgguqjRM}LQ2%Q5sl?%r(j!!n7OVD1VrbnM>$+@tZY&VZL@mJ|tJ3IMkRv`{J^o z8B6x2P@3RVB?$h;JA66!_BuMb4~s^j?UR=e1q#f;zW3vYS3)koQ|1r+zsc@Fk4)u-XLGWY zW_oVy4{68}DRDTXR6kA!&6-fcIQ$LY1ZvH={YN}U40Ro!Na~|)e>H3KMS&8-il5FU z-k-FrM3O&2T8$J6y&(i z)E3#H{IYRgpZ)W;L$QSzzc0Mt1+3AFtL&K?T^Ol`lEu4O!<7V>i0680bMz?72q!4ZuSsXX6bD^dNw$|Sr%`c;KZEjzs= z7SmGv7d+D%?RZ%63-y zJH-fHjRQ3kX^oly80B9iW$wJ0oQy@@lu@F<*wV(am@B3eYnSQmv*#r!bwa;8EV!`Z zqzmD*BQQ3u$WY~ATE4@!CHUQ(gzp~H)qu=Vae(9HZ85B7A%WT=NCTjg8zcPdaRT{} z@x$8-)9d)qh*ykOJLw&nutGCb6VUrxdZTCb2s1Ln@rxJ;3lJWeh1V4ipd19)uHze< zQ~`hNiqVD7xaKLt=uJEjDnGL&4X=at8GKkV09IF52k-NZ<>~+?bmS>U*RNP|f;jz2 z)s=)lghxka{}mHJ;yYweq@8M`oB`-T=AvG|JUiOW1d>1E40Jmb)s1&z4DaTIcL%{A zu9FDgy^M&?kH_9bjQoJdV#xL54@u95E#W1N!qJ8~+S*art}cN3ZSO}p0gl*YUo7IX z@T)sH|8h1IVn9UafCnC>fzA1AxumeH&Un~LUNr!1whC-G_{M6Fvv6x`89$~qu}y$q z%|?SUdZCirzkF$c%~iHktgrtQoR5mQL@%rIR6vz2h0hb3$R=#W)aPBi%TigGk3}}IX9fpP@2$Z zFcX>}!(@tJy0KYlJIdepdcUo{J57kZ0=F;N!le{OP$rwmUW!^W`?X0G_DI$GfX; zY{U%sGe5em;53&6!x&$1BlN}PRWI>g-Mtv*yf`=OgGb$-2^D^PBg`m_t$$!&2(1q0 zesSSb`@YLZ%eKqMuxlBU?#DVbHU3(1uW|863BJ9(UA=m~^Vlr78s{tn8O#FCgGJ&@ z^-ATH@L$aoUrgQw5dZ;(B^41hkDxtiZl}*0S@Cu^DX>v?a zqO_(WnjEYYp9|%AFvs;!`pnaCt8BN=H@Kd^FEFSNo`m}9xa-qWz?m?qBfPMARu6?k zCtHEz%Ea=tL5geAzq;Gxt^_U?Dd#Xf?;a+Vbs^DFZAu#;Efzr%7skyPX#=cF5it1@ zS}|}ua8VTXgabKvvTC$Q%sMfxr(aZZhkphKs|B4m*O#cJFo!G#20j+#_fY`MMTO20Q&y?^EIBEQ!dW zk&(T{GpI!P8C;VwM0DoT1CXUG@KHX^^` z{(=Q0EYMwgUD`(%o&YS;W?K2!6rO-4&x^2{BI4A%SdMk_-9jg7j786Axm+@v1u*^O zh28wx`s)#MsIe9co@`dCx#7l%XLhfHzy2a0dv)=i^;+aaF8p#C`SSt?=8OW>#dv$! z5D7k`K0NCFUyt>lq{dYLFEr*j3l?yq`WXatr|5Zyf&85{pT-Q3O#WBT2f+Fj7n}EL zn}$r9nabpeOfciJkn%7b1UMm){O8`ulUGJ;XA@tQ=J|mFcJh z8q(|3MYEKN)ETXjh%3N&e3DuI>MOZ=+nE|h4Sw?1K=Ol}^K#hzw7MD#Q&NjX`a#+- zdW{kS9T#>&43jH%qwW~)GZNDJ^|=Q6@B61zm$>P&(f)bbX1O_LK_P)Z%gTZ_hEKHr z0Jrg3j;j4_9DG;HN2q><;DVR?Dysj|ZgxhaUhE&b^(m44FA-#aB5#e5sv?{=uKG94 z3Qs=RN@hfaeNpdh0X$Sqb#fKnmhbf@DEe=S8COkCV^*`Mz2O|g6%3Ox*l58v6;nA= zlMq2*CQ*9$ekt1tj7yY+?yy~9&`ktZ5b9IbNkfXjf_;3yR~=TO{0vwgxr~Lwks&cG z>8C3x$NE;Iz)LhOC73a+miX;u0!wB2oJ}8j|5&OOWSH_;?1O_*60PGJgPpw(JT$_p zN0qe;`zFH|(UNuM zi2+{&H5(BiqR83NJ7A(zwh;6^pr;wxo!J-_!Q=@LuhNOgga-E_=`TCZr=KOKB9J5l ztdWMZ#tt487elcwm=?vfEM5uN`#zwH86?&^NMfc?;DPOqkplf5DdhTu{R>{UbpIF2 zzmn}=R{dA~#lk!Rh{H5HL$x1`DDe>scF|C#pZm?KWSupp_00>&Rko*w`kipahmP&2 z5*pF7jx~GFm+0nb!p!tv98i3$^4PzTleuWYPpNHe z{>gjM>{#4J`~EMq24jPxTvKS0w80*{byQb`Itr3nC-ZC{zwjAtnUeAkp&P2QTbvNo z!_D4;7SSt^O%it5tx6c|Bm7Iqpn{g?i+K!1@lnDOjU{y0&v7_NxCd_&U1mH22Uh&B z;TEYTR-*NH&aBYSZS#?%3AIw&+3g!4uox;}jwGO^x*bPl)xHu{uv=FD(DPIO&OA)V zBh;U0lKP$F_bEMaE*#CR!KW8s4wXD$!f7dPB%PRDKr>n?JXvD)Q1kCz44-xLK#c}a?ne+OPEFo=3*WZVB=5H z{r5x+K=5Ny8r?Z>T(v?Q|57JApL~6tPVZ63IxfQdXBeK;9Sd!wXm?yT{STU z3Nm!b;)35Cjo9hr0RGPhlms`!W;7?Fb2DiR+p$?k*-$b=f{^9Qq3Rup_4S=k>{Dnk zyyK^4RHAD1)m6rb`+3jsgfz@_fjswH^=AXMCv@p_@Y+$-egsL>bI92IE24i5b1TR! zf>sD{xjd{)1%!8(;n@iA5TOxn2Kek43xAP12>+sYN_Rs-Ab12&H#*)_7EdmR2O|mi z@4uNaU*cg3puh@d1Ticex-2GU?mK$=tA8wgn-!#YhzTphxa0h}7JdFVgzM(Qqu6aM zG8|+lxbkzbEJjxGJIvEEX}JzN*Kr{)@adQdIOT=(z-IoW3{@%@Y%tJO*dp1liMFD6 z+f|1AFv~`UvaI>9#j9^da+Q~}KcW9H7{;Tdh0SZjQkY+8FgkaP{i*?5?sXJ@KCBj* z!Gng!nZ{)6jan$H2|=D6E>FsK{PMS*N|p?dFvof{pX!WjhF=CBp=~6Ds>*us3=8N= zQGoH_h%hMkCmNbCT}lg|B3diDPc0ehIAAY(N+fVwaIu~$iMxV|k;xFyz)8x1$XX~j zxTcCh{Gr^WJR1kcCoS+j?0fG|){2Me#QJG=`$|b}WJ_B9t{iZ$Abf@t>nN6SKp>hHkO>-yHyYi@_YHTP3%0Dek1 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 z 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 UA!c8H>i_@%07*qoM6N<$f|2}Ij{pDw diff --git a/develop/doc/_images/trainer.png b/develop/doc/_images/trainer.png deleted file mode 100644 index 6537d3d56589ca9f19a77a50a970e4b5275e6ce0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 145107 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%0DrZVH_a1)FDYJ*0SAWQKe$b>$h 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 f -\ -Q -> f --> cost -B -> f -/ -``` - -The following program trains the topology including the cost, and then -use the sub-network in the trained topology in inference: - -```python -def f(in): - e = paddle.layer.embedding(in, parameter_name="embedding") - o = paddle.layer.softmax(e, parameter_name="semantic") - return o - -# Create 3 topologies (subnets), they share parameters because all -# correspoinding layers have the same parameter names. -fA = f(paddle.layer.data(input_name="A")) -fB = f(paddle.layer.data(input_name="B")) -fQ = f(paddle.layer.data(input_name="Q")) - -topology = paddle.layer.less_than( - paddle.layer.cross_entropy(fA, fQ), - paddle.layer.corss_entropy(fB, fQ)) - -# Derive parameters required in topology and create them in model. -parameters = paddle.parameters.create(topology) - -# Estimate parameters used in topology from data. -paddle.train(topology, parameters, reader=read_ranking_model_data) - -# Inference using fA (or fB or fC, as they share their parameters). -[testA, testB, testQ] = read_ranking_model_data() -print "The sematic-vector of testA: ", paddle.infer(fA, parameters, testA) -``` - - -### Example 2. Sharing Parameters between "Models" - -We use [GAN](https://github.com/PaddlePaddle/book/tree/develop/gan) in -this example. In the following example program, `d0` and `d1` -correspond to the two networks in the following figure: - - - -```python -def G(in): - # over-simplified example as G has only one layers: - return paddle.layer.fc(in, parameter_name="G") - -def D(in); - # again, over-simplified: - return paddle.layer.fc(in, parameter_name="D") - -# Construct the first topology, which contains both D and G. -# By learning this topology, we update parameters of G. -d0 = paddle.layer.should_be_false(D(G(paddle.layer.data()))) - -# Construct a second topology d1, which contains only D. By -# training this topology, we update parameters of D. Note -# that d1 share parameters with d0. -d1 = paddle.layer.should_be_true(D(paddle.layer.data())) - -# Create parameters from a list of multiple topologies (models) for -# the chance to share parameters between these topologies. -parameters = paddle.parameters.create([d0, d1]) - -# Iterative training of GAN. -for ...: - train(d0, parameters, reader=read_from_rng, immutable_parameters={"D"}) - train(d1, parameters, reader=read_from_realistic_images) - -# Use d1 for inference: -print "D thinks a batch of images are realistic ", infer(d1, parameters, read_mnist_images) -``` - - -### Summarization - - -Above two programs reveal some important design concerns: - -1. Users describe a topology as an expression of layers. Every layer - has a *parameter name*. If the users don't specify it explicitly, it's automatically generated as a unique name. By - specifying the parameter name, users can specify the sharing of - parameters between layers and even between topologies. - -1. `paddle.parameters.create` figures out parameters required by one - or more topologies from parameter names of layers. It creates these - parameters and returns a `ParameterSet` object, which is in essence - a map from *parameter names* to *parameters*. - -1. At training and inference time, `paddle.train` and `paddle.infer` - requires both a topology and the parameter set that holds the parameters of that topology. There are some reasons: - - 1. This prevents users from forgetting to call - `paddle.parameters.create`. - 1. `paddle.train` needs to know which parameter set to update. - 1. Users could load another (pre-trained) parameter set and use it - with a topology in `train.infer`. - -1. By specifying the `immutable_parameters` parameter of - `paddle.train`, we can forbid the update of these parameters. - - -## Reader - -Not all programming frameworks allow users to define I/O functions. -An example is Google MapReduce, which can only read from text, -SSTable, and RecordIO files. Hadoop MapReduce allows users to define -readers and writers by deriving from base classes `Reader` and -`Writer`. The former is less flexible but also less error-prone. We -decide to provide the flexibility to users to define their readers. - - -There are some open questions here: - -1. **Should a reader return a Python dictionary?** - -1. **How to map multiple outputs from a reader to multiple data layers?** - -1. **How to easily compose some existing readers to read more data and - feed a topology with more data layers?** - - -## Training - -The recommended way to training a model is to call `paddle.train`, -which simply calls `paddle.trainer.Default`, a global variable of -type `paddle.trainer.SGD`. Equivalently, we can do - -```python -opt = paddle.trainer.SGD(..., paddle.updater.Adam(...)) -opt.train(topology, parameters, reader=read, ...) -``` - -### Updater - -Please be aware that a trainer can accept an updater as its data -member, where an updater is a class derived from -`paddle.trainer.Updater`. This is to make it easier to customize -trainers, as discussed -[here](https://github.com/PaddlePaddle/Paddle/issues/1319). - -### Event Handler - -`paddle.train` and `paddle.trainer.XXX.train` take an optional -parameter `event_handler`, which should be either `None` or a function -that handle some events: - -1. BeginTraining -1. EndTraining -1. BeginIteration -1. EndIteration -1. BeginPass -1. EndPass - -where EndPass is sent if and only if the reader yields -`end_pass=True`. - -An example as follows: - -```python -def event_handler(event): - if ininstance(event, paddle.event.EndIteration): - print paddle.test(...) - -paddle.train(topology, parameters, reader, event_handler) -``` - -If we are writing a PaddlePaddle program in and for iPython/Jypyter, -we can use metaplotlib in the event handler to plot a curve of -cost/error versus iterations, as shown -[here](https://blog.dominodatalab.com/interactive-dashboards-in-jupyter/). - -### Distributed Training - -If users want to do distributed training on a cluster, s/he should -call `paddle.dist_train` and provides access tokens to the cluster as -a parameter. - -For example, if the user has a TLS certificate that allows him to -access a Kubernetes cluster, s/he should be able to call - -```python -paddle.dist_train(model, - trainer=paddle.trainer.SGD(..., - paddle.updater.Adam(...)), - reader=read, - k8s_user="yi", - k8s_token="kube_cluster_tls.pem", - k8s_job="hello", - num_parameter_servers=15) -``` - -The pseudo code of `paddle.dist_train` is as follows: - -```python -def dist_train(topology, parameters, trainer, reader, ...): - if os.getenv("KUBERNETES_SERVICE_HOST") == None: - image_name = k8s_user + '/' + k8s_job - docker_build(image_name) - docker_push() - kube_ctrl_start_job(image_name, k8s_user, k8s_token) - else: - rank = kube_list_containers_in_job_and_return_current_containers_rank() - if rank == 0: - master() - elif rank < 15: - parameter_server() - else: - trainer.train(model, reader=read) -``` - -Please be aware that if a process is running on the Kubernetes -cluster, it will have some environment variables pre-defined. - -If `dist_train` doesn't see these environment variables, it knows -that it's running on users' personal computer, and it should work as a -*launcher*. Otherwise, it knows that it's running on the cluster and -need to figure out its role as either the master, or a trainer, or a -parameter server. diff --git a/develop/doc/_sources/design/auto_gradient_check.md.txt b/develop/doc/_sources/design/auto_gradient_check.md.txt deleted file mode 100644 index 773b7b6a767..00000000000 --- a/develop/doc/_sources/design/auto_gradient_check.md.txt +++ /dev/null @@ -1,150 +0,0 @@ -## Auto Gradient Check Design - -## Background: -- Generally, it is easy to check whether the forward computation of an Operator is correct or not. However, backpropagation is a notoriously difficult algorithm to debug and get right because of the following challenges: - 1. The formula for backpropagation formula should be correct according to the forward computation. - 2. The Implementation of the above shoule be correct in CPP. - 3. It is difficult to prepare an unbiased test data. - -- Auto gradient checking gets a numerical gradient using forward Operator and uses it as a reference for the backward Operator's result. It has several advantages: - 1. Numerical gradient checker only needs the forward operator. - 2. The user only needs to prepare the input data for forward Operator and not worry about the backward Operator. - -## Mathematical Theory -The following documents from Stanford have a detailed explanation of how to compute the numerical gradient and why it is useful. - -- [Gradient checking and advanced optimization(en)](http://deeplearning.stanford.edu/wiki/index.php/Gradient_checking_and_advanced_optimization) -- [Gradient checking and advanced optimization(cn)](http://ufldl.stanford.edu/wiki/index.php/%E6%A2%AF%E5%BA%A6%E6%A3%80%E9%AA%8C%E4%B8%8E%E9%AB%98%E7%BA%A7%E4%BC%98%E5%8C%96) - - -## Numerical Gradient Implementation -### Python Interface -```python -def get_numerical_gradient(op, - input_values, - output_name, - input_to_check, - delta=0.005, - local_scope=None): - """ - Get Numerical Gradient for the input of an operator. - - :param op: C++ operator instance, could be an network. - :param input_values: The input variables. Should be an dictionary, whose key is - variable name, and value is a numpy array. - :param output_name: The final output variable name. - :param input_to_check: The input variable with respect to which the gradient has to be computed. - :param delta: The perturbation value for numerical gradient method. The - smaller the delta, the more accurate the result. But if the delta is too - small, it will suffer from the numerical stability problem. - :param local_scope: The local scope used for get_numeric_gradient. - :return: The gradient array in numpy format. - """ -``` - -### Explanation: - -- Why do we need an `output_name` - - An Operator may have multiple Outputs, one can compute an independent gradient from each Output. So the caller should specify the name of the output variable. - -- Why do we need `input_to_check` - - One operator can have multiple inputs. Gradient Op can calculate the gradient of these inputs at the same time. But Numerical Gradient needs to calculate them one by one. So `get_numeric_gradient` is designed to calculate the gradient for one input. If you need to compute multiple inputs, you can call `get_numeric_gradient` multiple times each with a different input. - - -### Core Algorithm Implementation - - -```python - # we only compute the gradient of one element a time. - # we use a for loop to compute the gradient of each element. - for i in xrange(tensor_size): - # get one input element using the index i. - original = tensor_to_check.get_float_element(i) - - # add delta to it, run the forward op and then - # get the new value of the result tensor. - x_pos = original + delta - tensor_to_check.set_float_element(i, x_pos) - y_pos = get_output() - - # Subtract delta from this element, run the op again - # and get the new value of the result tensor. - x_neg = original - delta - tensor_to_check.set_float_element(i, x_neg) - y_neg = get_output() - - # restore old value - tensor_to_check.set_float_element(i, original) - - # compute the gradient of this element and store - # it into a numpy array. - gradient_flat[i] = (y_pos - y_neg) / delta / 2 - - # reshape the gradient result to the shape of the source tensor. - return gradient_flat.reshape(tensor_to_check.get_dims()) -``` - -## Auto Gradient Check Framework - -Each Operator Kernel has three kinds of Gradient: - -1. Numerical gradient -2. CPU kernel gradient -3. GPU kernel gradient (if supported by the device) - -The numerical gradient only relies on the forward Operator, so we use the numerical gradient as the reference value. The gradient checking is performed in the following three steps: - -1. Calculate the numerical gradient -2. Calculate CPU kernel gradient with the backward Operator and compare it with the numerical gradient. -3. Calculate GPU kernel gradient with the backward Operator and compare it with the numeric gradient. (if supported) - -#### Python Interface - -```python - def check_grad(self, - forward_op, - input_vars, - inputs_to_check, - output_name, - no_grad_set=None, - only_cpu=False, - max_relative_error=0.005): - """ - :param forward_op: used to create backward_op - :param input_vars: numpy value of input variable. The following - computation will use these variables. - :param inputs_to_check: the input variable with respect to which the - gradient will be computed. - :param output_name: The final output variable name. - :param max_relative_error: The relative tolerance parameter. - :param no_grad_set: used to create backward ops - :param only_cpu: only compute and check gradient on cpu kernel. - :return: - """ -``` - -### How to check if two numpy arrays are close enough? -if `abs_numerical_grad` is nearly zero, then use absolute error for numerical_grad. - -```python -numerical_grad = ... -operator_grad = numpy.array(scope.find_var(grad_var_name(name)).get_tensor()) - -abs_numerical_grad = numpy.abs(numerical_grad) -# if abs_numerical_grad is nearly zero, then use abs error for -# numeric_grad, instead of relative error. -abs_numerical_grad[abs_numerical_grad < 1e-3] = 1 - -diff_mat = numpy.abs(abs_numerical_grad - operator_grad) / abs_numerical_grad -max_diff = numpy.max(diff_mat) -``` - - -#### Notes: -The Input data for auto gradient checker should be reasonable to avoid numerical stability problem. - - -#### References: - -- [Gradient checking and advanced optimization(en)](http://deeplearning.stanford.edu/wiki/index.php/Gradient_checking_and_advanced_optimization) -- [Gradient checking and advanced optimization(cn)](http://ufldl.stanford.edu/wiki/index.php/%E6%A2%AF%E5%BA%A6%E6%A3%80%E9%AA%8C%E4%B8%8E%E9%AB%98%E7%BA%A7%E4%BC%98%E5%8C%96) diff --git a/develop/doc/_sources/design/backward.md.txt b/develop/doc/_sources/design/backward.md.txt deleted file mode 100644 index 20fda7a98f5..00000000000 --- a/develop/doc/_sources/design/backward.md.txt +++ /dev/null @@ -1,158 +0,0 @@ -# Backward Building - -## Motivation - -In Neural Network, most models are solved by the backpropagation algorithm(known as **BP**) at present. Technically, BP calculates the gradient of the loss function, then propagates it back through the networks following the chain rule. However, when configuring the model structure, users do not need to define the backward part. So a mechanism is required by the framework which can complete the model's backward part automatically according to the given forward part. - -When implementing a specific `op`, the developer is also asked to implement its backward version, called `grad_op`. A `grad_op` takes gradients of its corresponding `op`'s outputs, and calculate gradients of the `op`'s inputs. During the building of a model's backward part, the framework creates each forward `op`'s `grad_op`, and then string them together in reverse order of forwarding part. In this way, gradients spread from the end to the beginning of the model, in another word, from the loss to parameters. - -## Challenges - -The motivation of backward building is apparent. However, implementation it correctly is not so easy. In the **Fluid** design, a deep learning model is described by `Program`, `Block`, `Op` and `Variable`. The `Block` itself can be nested. It means that the `op`s and `variable`s are scattered across different blocks rather than all be gathered in a single graph. Our backward building algorithm shall visit blocks in recursive order and be able to insert `grad_op`s and new created `variable`s into the right place. - -## Usage - -Although the whole algorithm is comprised of many functions, only one is exposed as API: - -```python -def append_backward(loss, parameter_list=None, no_grad_set=None): - """ - Append backward part to main_program - - Args: - loss(Variable): The variable generated by the cost function. - parameter_list(list): Parameters that need to be updated by optimizers. - If None, it means all parameters need to be updated. - - no_grad_set(set): Variables that have no gradients in Block 0. - If None, the set will be generated inside the function and - contains all variables with `step_gradient=True` from all blocks. - - Return: - (list[Variable]): list of (parameters, gradients) pair. - """ -``` - -By invoking this API, the framework appends backward part of the program where the `loss` is. It takes three arguments. `loss` means the final loss value. It must be a scalar and is usually the output of the loss layer. It is also where the gradient generated and backpropagation starts. `parameter_list` marks all parameters needs updating. If it's `None`, all parameter will be updated by optimizers. `no_grad_set` marks variables without gradient. if all outputs of some `grad_op` are in `no_grad_set`, the `grad_op` will not be run. - -This API will be invoked automatically before optimizer building. -As a result, in most cases, users do not need to invoke the API by themselves to append backward part. - -## Implementation - -The implementation of backward building algorithm is in `backward.py` file. The whole algorithm can be divided into two independent parts: creating `grad_op`s and creating new variables. - -### Creating `grad_op`s - -The creating of `grad_op`s is implemented by: - -```python -def _append_backward_ops_(target, - block, - target_block, - no_grad_dict, - grad_to_var): - """ - Create all grad ops, and insert them into given block - - Args: - target(Variable): the target variable of forward pass - block(Block): the block where forward ops are - target_block(Block): the block which is going to hold new generated grad ops - no_grad_dict(dict): - key(int) block index - val(set) a set of varibale names. These varibales have no gradient - grad_to_var(dict)(output argument): - key(str): grad variable name - val(str): corresponding forward variable name - """ -``` - -Given a `block`, the function will traverses all `op`s in this block in reverse order, gets corresponding `grad_op` from the C++ core via `core.get_grad_op_desc()`, then append it to `target_block`. - -However, some specific `op`(e.g. `while_op`, `if_else_op`) can hold its own sub-block. For these sub-blocks contains `op`s as well, the `grad_op` creating should be recursive. - -During the reverse traversal, we check each `op` whether it has an attribute named `sub_block`. If so, it means there is a sub-block and we need to deal with it first. After creating a new block whose father is the one in `op`'s attribute, we invoke `_append_backward_ops_()` recursively, assigning the new block to parameter `target_block` and the one in `op`'s attribute to `block`. The *pseudo-code* shows this process: - -``` -******* pseudo-code ******** -for op in reversed(block.ops): - if op has an attribute named 'sub_block': - Get the sub-block(`s_block`) from op's attribute. - Create a new block(`grad_s_block`), whose father is `s_block`. - Invoke _append_backward_ops_(), with `block=s_block` and `target_block=grad_s_block` - - Invoke `core.get_grad_op_desc()` to get op's grad_op. - Insert name correspondings between variables and their gradients of the grad_op to grad_to_var - Assign grad_s_block to grad_op as it's 'sub_block' attribute. - Append grad_op to current target_block. -``` - -The first invoking of `_append_backward_ops_()` is initiated by `append_backward()`, in which parameters `block` and `target_block` are all assigned with root block(the block with index 0). - -### Corner Cases of `grad_op` Creating - -In the previous section, we show the regular process of `grad_op` creating. However, in some corner cases, the conventional algorithm is not enough to get the correct result and appending handling is required. These additional processes run after the algorithm mentioned above and do some special adjusts on its output `grad_op`s. - -#### Shared Variables - -If a variable is read by more than one `op` in the forward pass, its gradient is likely to be written by more than one `grad_op`s in the next backward pass. To make the gradient result being the sum of all `grad_op`s' outputs instead of the last running one, we assign each output with a temporary variable and then add a `sum_op` to add them up. - -For the debug convenience, if the final gradient name is `w@GRAD`, it's corresponding temporary variables will be named as `w@GRAD@RENAME@0`, `w@GRAD@RENAME@1`... - -See function `_addup_repetitive_outputs_` in `backward.py` for implementation details. - -#### No Gradient Variables - -In our framework, variables can be marked as *no_gradient*, it means that the gradient of this variable is unnecessary and can be considered as zero in model training. Apparently, when all the outputs of some `grad_op` are marked as *no_gradient*, the `grad_op` itself can be skipped in backward pass. - -Another situation is all the gradient inputs of some `grad_op` are marked as *no_gradient*, which means all of them can be considered as zeros. For `grad_op`s are in essence the propagation of gradients, all the outputs are definitely zeros when all gradient inputs are zeros. Therefore the `grad_op` can also be skipped. - -It should be noted that all these zero gradients still need to be creating and initialized by something, otherwise following `grad_op`s who take these gradients as inputs take the risk of using uninitialized memory. In our code, we employ `fill_zeros_like_op` to initialize them as all zeros. - -This features are implemented in function `_remove_no_grad_branch_`. It checks new created `grad_op`s one-by-one, removes who can be skipped and inserts `fill_zeros_like_op` when its necessary. We can get the `no_grad_set` from the `_append_backward_ops_` argument `no_grad_dict` or generate it on the fly by scanning all variables' `no_gradient` attribute(True or False). - -### Creating Backward Variables - -Up to now, we have completed all creating and adjusting jobs of `grad_op`s. However, backward variables have not been created. Now they are only represented by `grad_op`'s input and output arguments. The backward variable creating job will be done by: - -```python -def _append_backward_vars_(block, - start_op_idx, - grad_to_var, - grad_info_map): - """ - Create new variables required by backward pass. - - Args: - block(Block): the block where new variables will be created - start_op_idx(int): Only variables required by ops in block.ops[start_op_idx : ] will be created - grad_to_var(dict): - key(str): grad variable name - val(str): corresponding forward variable name - In most cases, this dict is generated by _append_backward_ops_() - grad_info_map(dict)(output argument): - key(str): forward variable name - val(tuple): a tuple of (str, int), str is the corresponding grad name, int is the block index - """ -``` - -Given a `block`, this function traverses all the `grad_op`s in it(The argument `start_op_idx` indicates where the grad_op sequence starts.) and creates all the uncreated outputs. The *pseudo-code* shows this process: - -``` -for op in block.ops[start_op_idx : ]: - - if op has an attribute named 'sub_block': - Get the sub-block(`s_block`) from op's attribute. - Invoke _append_backward_vars_(), with `block=s_block` - - for var_name in op.all_output_names(): - if block.has_var_recursive(var_name) or var_name is the name of empty variable: - continue - create a new variable named 'var_name' in block - if grad_to_var.has_key(var_name): - set grad_info_map[grad_to_var[var_name]] as a tuple of (var_name. block) - - do op's var type inference - do op's shape inference -``` diff --git a/develop/doc/_sources/design/block.md.txt b/develop/doc/_sources/design/block.md.txt deleted file mode 100644 index 907a2def557..00000000000 --- a/develop/doc/_sources/design/block.md.txt +++ /dev/null @@ -1,336 +0,0 @@ -# Design Doc: Block and Scope - -## The Representation of Computation - -Both deep learning systems and programming languages help users describe computation procedures. These systems use various representations of computation: - -- Caffe, Torch, and Paddle: sequences of layers. -- TensorFlow, Caffe2, Mxnet: graph of operators. -- PaddlePaddle: nested blocks, like C++ and Java programs. - -## Block in Programming Languages and Deep Learning - -In programming languages, a block is a pair of curly braces that includes local variables definitions and a sequence of instructions or operators. - -Blocks work with control flow structures like `if`, `else`, and `for`, which have equivalents in deep learning: - -| programming languages | PaddlePaddle | -|-----------------------|-----------------------| -| for, while loop | RNN, WhileOp | -| if, if-else, switch | IfElseOp, SwitchOp | -| sequential execution | a sequence of layers | - -A key difference is that a C++ program describes a one pass computation, whereas a deep learning program describes both the forward and backward passes. - -## Stack Frames and the Scope Hierarchy - -The existence of the backward pass makes the execution of a block of PaddlePaddle different from traditional programs: - -| programming languages | PaddlePaddle | -|-----------------------|---------------------------------| -| stack | scope hierarchy | -| stack frame | scope | -| push at entering block| push at entering block | -| pop at leaving block | destroy when minibatch completes| - -1. In traditional programs: - - - When the execution enters the left curly brace of a block, the runtime pushes a frame into the stack, where it realizes local variables. - - After the execution leaves the right curly brace, the runtime pops the frame. - - The maximum number of frames in the stack is the maximum depth of nested blocks. - -1. In PaddlePaddle - - - When the execution enters a block, PaddlePaddle adds a new scope, where it realizes variables. - - PaddlePaddle doesn't pop a scope after the execution of the block because variables therein are used by the backward pass. So it has a stack forest known as a *scope hierarchy*. - - The height of the highest tree is the maximum depth of nested blocks. - - After the processing of a minibatch, PaddlePaddle destroys the scope hierarchy. - -## Use Blocks in C++ and PaddlePaddle Programs - -Let us consolidate the discussion by presenting some examples. - -### Blocks with `if-else` and `IfElseOp` - -The following C++ programs shows how blocks are used with the `if-else` structure: - -```c++ -namespace pd = paddle; - -int x = 10; -int y = 1; -int z = 10; -bool cond = false; -int o1, o2; -if (cond) { - int z = x + y; - o1 = z; - o2 = pd::layer::softmax(z); -} else { - int d = pd::layer::fc(z); - o1 = d; - o2 = d+1; -} - -``` - -An equivalent PaddlePaddle program from the design doc of the [IfElseOp operator](./if_else_op.md) is as follows: - -```python -import paddle as pd - -x = minibatch([10, 20, 30]) # shape=[None, 1] -y = var(1) # shape=[1], value=1 -z = minibatch([10, 20, 30]) # shape=[None, 1] -cond = larger_than(x, 15) # [false, true, true] - -ie = pd.ifelse() -with ie.true_block(): - d = pd.layer.add_scalar(x, y) - ie.output(d, pd.layer.softmax(d)) -with ie.false_block(): - d = pd.layer.fc(z) - ie.output(d, d+1) -o1, o2 = ie(cond) -``` - -In both examples, the left branch computes `x+y` and `softmax(x+y)`, the right branch computes `fc(x)` and `x+1` . - -The difference is that variables in the C++ program contain scalar values, whereas those in the PaddlePaddle programs are mini-batches of instances. - - -### Blocks with `for` and `RNNOp` - -The following RNN model in PaddlePaddle from the [RNN design doc](./rnn.md) : - -```python -x = sequence([10, 20, 30]) # shape=[None, 1] -m = var(0) # shape=[1] -W = var(0.314, param=true) # shape=[1] -U = var(0.375, param=true) # shape=[1] - -rnn = pd.rnn() -with rnn.step(): - h = rnn.memory(init = m) - h_prev = rnn.previous_memory(h) - a = layer.fc(W, x) - b = layer.fc(U, h_prev) - s = pd.add(a, b) - act = pd.sigmoid(s) - rnn.update_memory(h, act) - rnn.output(a, b) -o1, o2 = rnn() -``` -has its equivalent C++ program as follows - -```c++ -int* x = {10, 20, 30}; -int* m = {0}; -int* W = {0.314}; -int* U = {0.375}; - -int mem[sizeof(x) / sizeof(x[0]) + 1]; -int o1[sizeof(x) / sizeof(x[0]) + 1]; -int o2[sizeof(x) / sizeof(x[0]) + 1]; -for (int i = 1; i <= sizeof(x)/sizeof(x[0]); ++i) { - int x = x[i-1]; - if (i == 1) mem[0] = m; - int a = W * x; - int b = Y * mem[i-1]; - int s = fc_out + hidden_out; - int act = sigmoid(sum); - mem[i] = act; - o1[i] = act; - o2[i] = hidden_out; -} -``` - -## Compilation and Execution - -Like TensorFlow, a PaddlePaddle program is written in Python. The first part describes a neural network as a protobuf message, and the rest executes the message for training or inference. - -The generation of this protobuf message is similar to how a compiler generates a binary executable file. The execution of the message is similar to how the OS executes the binary file. - -## The "Binary Executable File Format" - -The definition of the protobuf message is as follows: - -```protobuf -message BlockDesc { - repeated VarDesc vars = 1; - repeated OpDesc ops = 2; -} -``` - -The step net in above RNN example would look like - -``` -BlockDesc { - vars = { - VarDesc {...} // x - VarDesc {...} // h - VarDesc {...} // fc_out - VarDesc {...} // hidden_out - VarDesc {...} // sum - VarDesc {...} // act - } - ops = { - OpDesc {...} // matmul - OpDesc {...} // add_two - OpDesc {...} // sigmoid - } -}; -``` - -Also, the RNN operator in above example is serialized into a protobuf message of type `OpDesc` and would look like: - -``` -OpDesc { - inputs = {0} // the index of x in vars of BlockDesc above - outputs = {5, 3} // indices of act and hidden_out in vars of BlockDesc above - attrs { - "states" : {1} // the index of h - "step_net" : - } -}; -``` - -This `OpDesc` value is in the `ops` field of the `BlockDesc` value representing the global block. - - -## The Compilation of Blocks - -During the generation of the Protobuf message, the Block should store VarDesc (the Protobuf message which describes Variable) and OpDesc (the Protobuf message which describes Operator). - -VarDesc in a block should have its name scope to avoid local variables affecting parent block's name scope. -Child block's name scopes should inherit the parent's so that OpDesc in child block can reference a VarDesc that is stored in the parent block. For example: - -```python -a = pd.Variable(shape=[20, 20]) -b = pd.fc(a, params=["fc.w", "fc.b"]) - -rnn = pd.create_rnn() -with rnn.stepnet(): - x = a.as_step_input() - # reuse fc's parameter - fc_without_b = pd.get_variable("fc.w") - rnn.output(fc_without_b) - -out = rnn() -``` -The method `pd.get_variable` can help retrieve a Variable by the name. The Variable may be stored in a parent block, but might be retrieved in a child block, so block should have a variable scope that supports inheritance. - -In compiler design, the symbol table is a data structure created and maintained by compilers to store information about the occurrence of various entities such as variable names, function names, classes, etc. - -To store the definition of variables and operators, we define a C++ class `SymbolTable`, like the one used in compilers. - -`SymbolTable` can do the following: - -- store the definitions (some names and attributes) of variables and operators, -- verify if a variable was declared, -- make it possible to implement type checking (offer Protobuf message pointers to `InferShape` handlers). - - -```c++ -// Information in SymbolTable is enough to trace the dependency graph. So maybe -// the Eval() interface takes a SymbolTable is enough. -class SymbolTable { - public: - SymbolTable(SymbolTable* parent) : parent_(parent) {} - - OpDesc* NewOp(const string& name=""); - - // TODO determine whether name is generated by python or C++. - // Currently assume that a unique name will be generated by C++ if the - // argument name is left default. - VarDesc* Var(const string& name=""); - - // find a VarDesc by name, if recursive is true, find parent's SymbolTable - // recursively. - // this interface is introduced to support InferShape, find protobuf messages - // of variables and operators, pass pointers into InferShape. - // - // NOTE maybe some C++ classes such as VarDescBuilder and OpDescBuilder should - // be proposed and embedded into pybind to enable python operation on C++ pointers. - VarDesc* FindVar(const string& name, bool recursive=true); - - OpDesc* FindOp(const string& name); - - BlockDesc Compile() const; - - private: - SymbolTable* parent_; - - map ops_; - map vars_; -}; -``` - -After all the description of variables and operators is added into SymbolTable, -the block has enough information to run. - -The `Block` class takes a `BlockDesc` as input, and provides `Run` and `InferShape` functions. - - -```c++ -namespace { - -class Block : OperatorBase { -public: - Block(const BlockDesc& desc) desc_(desc) {} - - void InferShape(const framework::Scope& scope) const override { - if (!symbols_ready_) { - CreateVariables(scope); - CreateOperators(); - } - // should run InferShape first. - for (auto& op : runtime_table_.ops()) { - op->InferShape(scope); - } - } - - void Run(const framework::Scope& scope, - const platform::Place& place) const override { - PADDLE_ENFORCE(symbols_ready_, "operators and variables should be created first."); - for (auto& op : runtime_table_.ops()) { - op->Run(scope, place); - } - } - - void CreateVariables(const framework::Scope& scope); - void CreateOperators(); - - // some other necessary interfaces of NetOp are listed below - // ... - -private: - BlockDesc desc_; - bool symbols_ready_{false}; -}; -``` - -## The Execution of Blocks - -Block inherits from OperatorBase, which has a Run method. -Block's Run method will run its operators sequentially. - -There is another important interface called `Eval`, which takes some arguments called targets and generates a minimal graph which treats targets as the end points and creates a new Block. After `Run`, `Eval` will get the latest value and return the targets. - -The definition of Eval is as follows: - -```c++ -// clean a block description by targets using the corresponding dependency graph. -// return a new BlockDesc with minimal number of operators. -// NOTE: The return type is not a Block but the block's description so that this can be distributed -// to a cluster. -BlockDesc Prune(const BlockDesc& desc, vector targets); - -void Block::Eval(const vector& targets, - const framework::Scope& scope, - const platform::DeviceContext& dev_ctx) { - BlockDesc min_desc = Prune(desc_, targets); - Block min_block(min_desc); - min_block.Run(scope, dev_ctx); -} -``` diff --git a/develop/doc/_sources/design/build_system/README.md.txt b/develop/doc/_sources/design/build_system/README.md.txt deleted file mode 100644 index bf0e4dddc1b..00000000000 --- a/develop/doc/_sources/design/build_system/README.md.txt +++ /dev/null @@ -1,152 +0,0 @@ -A few months ago when we were trying to replace CMake with Bazel, @emailweixu suggested that we rewrite those handy Bazel functions using CMake. Now it seems that it's the right time to get this done, as we are facing problems from the porting of Majel and the development of new the parameter server using Go and C++. - -Here are some initial thoughts. Your comments are welcome! - -### Required CMake Function - -I think we need only the following few CMake functions to make a project description mean and clean: - -| C++ | CUDA C++ | Go | -|---|---|---| -| cc_library | nv_library | go_library | -| cc_binary | nv_binary | go_binary | -| cc_test | nv_test | go_test | - -- The `_library` functions generate .a files from source code. -- The `_binary` functions generate executable binary files. -- The `_test` functions generate executable unit test files. They work like `_binary` but links `-lgtest` and `-lgtest_main`. - -The difference between `nv_` functions and `cc_` functions is that the former use `nvcc` instead of the system-default C++ compiler. - -Both `nv_` and `cc_` functions enables C++11 (-std=c++11). - -Also, - -- to describe external dependencies, we need `external_library`. -- to build shared libraries, we need `shared_library`. - -### An Example Project - -Suppose that we have aforementioned functions defined in our `/cmake` directory. The following example `CMakeLists.txt` describes a project including the following source files: - -- tensor.h -- tensor.cc -- tensor_test.cc -- ops.h -- ops.cu -- ops_test.cu -- api.go -- api_test.go - -Suppose that ops.cu depends on CUDNN. - -```cmake -# cc_binary parses tensor.cc and figures out that target also depend -# on tensor.h. -cc_binary(tensor - SRCS - tensor.cc) - -# The dependency to target tensor implies that if any of -# tensor{.h,.cc,_test.cc} is changed, tensor_test need to be re-built. -cc_test(tensor_test - SRCS - tensor_test.cc - DEPS - tensor) - -# I don't have a clear idea what parameters external_library need to -# have. @gangliao as a CMake expert would have better ideas. -external_library(cudnn - ....) - -# Suppose that ops.cu depends on external target CUDNN. Also, ops.cu -# include global functions that take Tensor as their parameters, so -# ops depend on tensor. This implies that if any of tensor.{h.cc}, -# ops.{h,cu} is changed, ops need to be re-built. -nv_library(ops - SRCS - ops.cu - DEPS - tensor - cudnn) # cudnn is defined later. - -nv_test(ops_test - SRCS - ops_test.cu - DEPS - ops) - -# Because api.go defines a GO wrapper to ops and tensor, it depends on -# both. This implies that if any of tensor.{h,cc}, ops.{h,cu}, or -# api.go is changed, api need to be re-built. -go_library(api - SRCS - api.go - DEPS - tensor # Because ops depend on tensor, this line is optional. - ops) - -go_test(api_test - SRCS - api_test.go - DEPS - api) - - -# This builds libapi.so. shared_library might use CMake target -# api_shared so to distinguish it from above target api. -shared_library(api - DEPS - api) - -``` - -### Implementation - -As above example CMakeLists.txt executes, each function invocation adds "nodes" to a dependency graph. It also use this graph to generate CMake commands including `add_executable`, `add_dependencies`, `target_link_libraries`, and `add_test`. - -### Using Package Manager For Go - -Building Go binaries and libraries need to satisfy their dependencies, generally -we can do `go get ./...` to download and compile all external dependencies. The -problems are: - -1. `go get` will always get the latest code from the default branch of the - remote repo, so changes of dependents might break the build. This is very - different with what we already have in `cmake/external` which download a - specific version or commit id of the dependency. -1. Some locations can not access external dependencies through the internet, as mentioned - in https://github.com/PaddlePaddle/Paddle/issues/2605. Using package management - tools can package the dependencies as a "vendor" package, which can be mirrored - at many cloud file hosting, so users what to compile paddle by themselves can - download this "vendor" package from a mirror site. - -#### Choose A Suitable Tool - -As mentioned by @wangkuiyi, [Here](https://github.com/golang/go/wiki/PackageManagementTools) -list dozens of Go package managers. We choose the tool using following principles: - -- Most "active" projects with more stars, more pull requests or commits -- Widely used project - -After comparing all these projects, we shall choose between the most popular -tools: Godep and Glide. - -Here's a brief comparison between Godep and Glide -: https://github.com/Masterminds/glide/wiki/Go-Package-Manager-Comparison. There are -also many complaints about using `Godep`. There's also a new "official" pakcage -management tool has been started at: https://github.com/golang/dep to resolve -such problems, but it's currently at Alpha stage. So the best choice now is -glide obviously. - -#### Manage Go Packages - -- Dependencies: `go/glide.yaml` will store the dependencies and their versions which - is directly imported by paddle. `go/glide.lock` will store all dependencies recursively - with their commit id. Builds will "lock" to these packages if we don't `glide up` - them -- Vendor package: `go/vendor` directory will generated when running `cmake` command. `cmake` - will download the code corresponding to `go/glide.lock`. If we put a vendor folder - under `go/`, cmake will just check the commit id to the packages under the folder, - if commit id matches, there will be no download at all. diff --git a/develop/doc/_sources/design/cluster_train/README.md.txt b/develop/doc/_sources/design/cluster_train/README.md.txt deleted file mode 100644 index 177a5f5d54b..00000000000 --- a/develop/doc/_sources/design/cluster_train/README.md.txt +++ /dev/null @@ -1,182 +0,0 @@ -# Design Doc: Distributed Training - -## Objective - -In [this slides](https://www.slideshare.net/cxwangyi/paddlepaddle-a-complete-solution-for-businesses), we explained that we'd like PaddlePaddle running on general-purpose clusters like those managed by Kubernetes, so to address demands for AI from both Internet and non-Internet industries. - -This poses technical challenges to PaddlePaddle: - -1. Support fault-recovery. -1. Support both offline and online training. -1. [Serverless computing](https://en.wikipedia.org/wiki/Serverless_computing) of distributed training. - - -## Training Job - -A training job will be created once user asks Paddle cloud to train a model. The training job is made up of different processes that collaboratively consume data and produce a trained model. There are three kinds of processes: - -1. the *master server process*, which dispatches tasks to -1. one or more *trainer processes*, which run distributed training and synchronize gradients/models via -1. one or more *parameter server processes*, where each holds a shard of the global model, and receive the uploaded gradients from every *trainer process*, so they can run the optimize functions to update their parameters. - -Their relation is illustrated in the following graph: - - - -By coordinating these processes, PaddlePaddle supports use both Synchronize Stochastic Gradient Descent (sync SGD) and Asynchronous Stochastic Gradient Descent (async SGD) to train user-defined neural network topologies. - -When training with sync SGD, parameter servers wait for all trainers to finish gradients update and then send the updated parameters to trainers, training can not proceed until the trainer received the updated parameters. This creates a synchronization point between trainers. When training with async SGD, each trainer upload gradient and download new parameters individually, without the synchronization with other trainers. Using asyc SGD will be faster in terms of time per pass, but have more noise in gradient since trainers are likely to have a stale model. - -### Master Server Process - -The master server process will: - -- Partition a dataset into [tasks](#task) and dispatch tasks to trainers. -- Keep track of training progress on the dataset with [task queue](#task-queue). A training job will iterate on the dataset for a full pass until it goes into next pass. - - -#### Task - -A task is a data shard to be trained. The total number of tasks will be much bigger than the total number of trainers. The number of data instances inside a task will be much bigger than the mini-batch size. - -#### Task Queue - -The master server has three task queues to track training progress. As illustrated in the graph below, Job A and Job B both have one master server. Each master server process has three task queues. - - - -- The todo queue holds tasks to be dispatched. When a job starts, the master server fills in the todo queue with all tasks. -- The pending queue holds tasks that are currently training by trainers. -- the done queue holds tasks that are already trained. - -The life cycle of a single task is illustrated below: - - - -1. When a new pass of training starts, all tasks will be placed in the todo queue. -1. Upon trainer requests for new task, the master server will dispatch a task from todo queue to it, put the task in the pending queue and wait for completion. -1. The trainer will work on its task and tell the master server once the task is completed and ask for new task. The master server will dispatch a new task to that trainer. -1. If a task fails for any reason in trainer, or takes longer than a specific period of time, the master server will move the task back to the todo queue. The timeout count for that task will increase by one. If the timeout count is above a threshold, the task is likely to cause a trainer to crash, then it will be discarded. -1. The master server will move completed task to the done queue. When the todo queue is empty, the master server will start a new pass by moving all tasks in the done queue to todo queue and reset the timeout counter of all tasks to zero. - -### Trainer Process - -The trainer process will: - -- Request tasks from the master. -- Work on the tasks -- Upload gradient to parameter servers, and update local model by downloading new parameters from parameter servers. - -### Parameter Server Process - -Parameter server processes hold the parameters collaboratively. The parameters are partitioned on different parameter servers. - -The parameter server will: - -- Receive gradient from the trainers, update its parameters, and give the trainers the latest parameters. -- Periodically save its parameters to distributed file system by overriding the previous save. - -### Optimization Algorithms - -The communication pattern between the trainers and the parameter servers depends on the category of optimization algorithm: - -- Synchronous Stochastic Gradient Descent (sync-SGD) - - Parameter server will wait for all trainer finish n-th mini-batch calculation and send their gradients before broadcasting new parameters to every trainer. Every trainer will wait for the new parameters before starting n+1-th mini-batch. - -- Asynchronous Stochastic Gradient Descent (async-SGD) - - There will no synchronization between different trainers, and parameter server updates its parameter as soon as it receives new gradient: - - - Each trainer uploads its accumulated gradient every n mini-batches. - - Every m mini-batches, the trainer downloads new parameters from parameter server. - - n and m do not have to be equal. - -## Fault Tolerant - -The training job will pause if the master server processes is dead, or any of the parameter server process is dead. They will be started by [Kubernetes](https://kubernetes.io/) and recover in few minutes. Please refer to [fault recovery](#fault-recovery). - -The training job will continue to make progress if there is at least one training process running. The strategy depends on the type of optimization algorithm: - -- sync-SGD - - TODO - -- async-SGD - - Since async-SGD does not require synchronization between mini-batches, the system will by definition make process if at least one trainer is running. - -## Fault Recovery - -PaddlePaddle uses [etcd](https://github.com/coreos/etcd) to keep track of the states of processes. Because etcd is a distributed reliable key-value store, the restarted process can recover its states from etcd. The model parameters are periodically saved into distributed file system, so a restarted parameter server can recover its parameters from the saved file. - -Now we will introduce how each process recovers from a failure, the graph below shows how etcd is used: - - - -### Master Server Process - -When the master is started by the Kubernetes, it executes the following steps at startup: - -1. Grabs a unique *master* lock in etcd, which prevents concurrent master instantiations. -1. Recovers the task queues from etcd if they already exist, otherwise, the master will create them. -1. Write its ip address to */master/addr* so that trainers can discover it. -1. Listens to trainers' request of task, dispatch one upon request, and updates task queue using an etcd transaction to ensure lock is held during the update. - -When the master server process is dead for any reason, Kubernetes will restart it. It will be online again with all states recovered from etcd in few minutes. - -### Trainer Process - -When the trainer is started by the Kubernetes, it executes the following steps at startup: - -1. Watches the available parameter server prefix keys `/ps/` on etcd and waits until the count of parameter servers reaches the desired count */ps_desired*. -1. Finds and watches */master/addr* to get master's address. -1. Requests for tasks from the master to start training. - -When a trainer fails, Kuberentes would try to restart it. The recovered trainer would fetch tasks from master and go on training. - -### Parameter Server Process - -When the parameter server is started by Kubernetes, it executes the following steps at startup: - -1. Read desired total number of parameter servers from etcd `/ps_desired` -1. Search through etcd keys `/ps/` (`/ps/0`, `/ps/1`, ...) to find the first non-existant key whose index is smaller than the total number of parameter servers. Set the key using a transaction to avoid concurrent writes. The parameter server's index is inferred from the key name. - - The desired number of parameter servers is 3: - - - - The third parameter server joined: - - - -1. The parameter server can load parameters if there are already saved parameters in the save path (inferred from its index). -1. Now the parameter server is ready for the trainers' requests. - -If the parameter server's etcd lease expires, the parameter server will kill itself. - - -## Parameter Server Checkpointing -See [here](./checkpointing.md) - -## Store and dispatching trainning data -See [here](./data_dispatch.md) - - -## Dynamic Scaling - -### Trainer Scaling - -TODO - -### Parameter Server Scaling - -Not planned for v1. - -## Training Dataset Format - -TODO - -## User Interface - -TODO diff --git a/develop/doc/_sources/design/cluster_train/checkpointing.md.txt b/develop/doc/_sources/design/cluster_train/checkpointing.md.txt deleted file mode 100644 index c87ef2c7d26..00000000000 --- a/develop/doc/_sources/design/cluster_train/checkpointing.md.txt +++ /dev/null @@ -1,44 +0,0 @@ -## 模型参数检查点(Checkpointing) -模型数据检查点的实现,可以有效的避免parameter server的单点或多点同时故障。模型参数检查点通过定期向磁盘上保存一份存储在parameter server内存中的模型数据的完整镜像,来保证训练过程可以从中间状态重新启动。在一个不可中断并缺少备份的训练任务中,可以通过阶段性的保存每个parameter server的数据快照(snapshot)到 ***分布式存储服务*** 达到容灾的目的,比如每隔10分钟最新的快照,并删除更早的快照。在出现单点故障时,只需要恢复这台节点,或者将这台节点迁移到另一个节点并启动即可恢复训练任务。 - - - -### 快照保存的设计如下: - -说明: - -* parameter server在集群中启动后,自动挂载分布式存储目录,并把快照保存到这个目录下。 -* ***注:每个parameter server的检查点各自独立保存,暂时不考虑多个parameter server同步的保存一个特定时间点的全局检查点,因为这样做也没法保证消除随机性。*** - -检查点保存程序流程: - -1. 如果满足条件"每隔10分钟"时,parameter server会获取parameters内存的`read_lock`,启动一个新的线程开始保存检查点。如果已经正在执行保存检查点的线程,则忽略。由于对parameters的更新需要获取parameters内存的`write_lock`,所以在写入快照的过程中,parameter server会暂停参数更新并等待。 -2. parameter server生成一个UUID,向指定的目录中一个新的文件(文件名为此UUID)写入快照数据。在快照写入完成后,计算这个文件的MD5 sum。然后在etcd的`/checkpoints/[pserver_id]`中写入json内容:`{"uuid": [UUID], "md5", "MD5 sum", "timestamp": xxxx}`。 -3. 删除磁盘目录中不是当前uuid的快照文件。 -4. 释放对paramters内存的锁定,停止保存检查点的线程。 - -这里需要用户额外注意,在您的实际环境中,训练任务的运行可能会占满trainer和parameter server之间的网络带宽,如果parameter server此时还需要通过网络访问分布式存储以保存快照,可能会造成网络拥塞,而出现阶段性的运行停滞。 - -### 从快照恢复 - -在parameter server第一次启动或任意时间parameter server故障后被Kubernetes重新启动,则需要回滚到上一个检查点: - - 1. 从etcd中读取节点:`/checkpoints/[pserver_id]`获取最新的检查点的文件uuid - 1. 从磁盘文件中加载uuid文件名的检查点快照文件,并加载其中的参数 - 1. 如果上面两步出现错误,则使用启动参数定义的初始化方法初始化参数 - 1. 开始提供服务 - -## TODO List -### 推测执行/加速执行(TODO) -在异构集群中,如果存在某些trainer执行速度过慢会影响整体集群的速度(如图中Trainer 1),此时master将负责启动一个新的Trainer(Accelerate Trainer 2),使用同样的训练数据block。哪个trainer先完成block的训练,则把另一个慢速的kill掉。 - -### 动态扩容/缩容 -目前只考虑动态扩容trainer数量,可以减小系统复杂性。 - -## 术语 -* model: 指深度学习训练之后得到的所有参数,使用这个神经网络可以完成对新数据的预测 -* parameters: 神经网络中的参数,包括权重w和偏置b。一个神经网络的模型由大量的参数组成 -* shard: 分片,通常指将一个整体拆分成多份的其中的一份。 -* model shard: 将一个神经网络参数拆分成多份,每个shard分别存储在其中一台parameter server之上 -* parameter block: 多个parameter block构成一个model shard -* 单点故障: 任意时刻只可能同时有一台服务器故障。由于集群中同时存在两台机器故障的概率极低((平均故障率*平均故障修复时间)^2)只对特殊在线系统考虑两台以上同时故障的容灾。 diff --git a/develop/doc/_sources/design/cluster_train/data_dispatch.md.txt b/develop/doc/_sources/design/cluster_train/data_dispatch.md.txt deleted file mode 100644 index 1f5d22ff5e6..00000000000 --- a/develop/doc/_sources/design/cluster_train/data_dispatch.md.txt +++ /dev/null @@ -1,160 +0,0 @@ -## 训练数据的存储和分发 - -### 概念解释 - -### 流程介绍 -生产环境中的训练数据集通常体积很大,并被存储在诸如Hadoop HDFS,Ceph,AWS S3之类的分布式存储之上。这些分布式存储服务通常会把数据切割成多个分片分布式的存储在多个节点之上。这样就可以在云端执行多种数据类计算任务,包括: - -* 数据预处理任务 -* Paddle训练任务 -* 在线模型预测服务 -

- -在上图中显示了在一个实际生产环境中的应用(人脸识别)的数据流图。生产环境的日志数据会通过实时流的方式(Kafka)和离线数据的方式(HDFS)存储,并在集群中运行多个分布式数据处理任务,比如流式数据处理(online data process),离线批处理(offline data process)完成数据的预处理,提供给paddle作为训练数据。用户也可以上传labeled data到分布式存储补充训练数据。在paddle之上运行的深度学习训练输出的模型会提供给在线人脸识别的应用使用。 - -### 训练数据存储 -我们选择[CephFS](http://docs.ceph.com/docs/master/cephfs/)作为存储系统。 - -- 无论是从[PFSClient](../file_manager/README.md)的角度,还是从[Pod](https://kubernetes.io/docs/concepts/workloads/pods/pod/)中运行任务的角度,统一用`/pfs/$DATACENTER/home/$USER`来访问用户自己的数据。 -- `/pfs/$DATACENTER/common`下存放公共数据集合 - - 做只读挂载 - -
- -
- -### 文件预处理 - - -在开始训练之前, 数据集需要预先被转换成PaddlePaddle分布式训练使用的存储格[RecordIO](https://github.com/PaddlePaddle/Paddle/issues/1947)。我们提供两个转换方式: - -1. 用户在本地转换好再上传 -1. 用户上传数据后,在机群上运行转换程序 - -转换生成的文件名会是以下格式: - -```text -name_prefix-aaaaa-of-bbbbb -``` - -"aaaaa"和"bbbbb"都是五位的数字,每一个文件是数据集的一个shard,"aaaaa"代表shard的index,"bbbbb"代表这个shard的最大index。 - -比如ImageNet这个数据集可能被分成1000个shard,它们的文件名是: -```text -imagenet-00000-of-00999 -imagenet-00001-of-00999 -... -imagenet-00999-of-00999 -``` - -#### 转换库 - -无论是在本地或是云端转换,我们都提供Python的转换库,接口是: -```python -def convert(output_path, reader, num_shards, name_prefix) -``` - -- `output_path`: directory in which output files will be saved. -- `reader`: a [data reader](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/reader/README.md#data-reader-interface), from which the convert program will read data instances. -- `num_shards`: the number of shards that the dataset will be partitioned into. -- `name_prefix`: the name prefix of generated files. - -`reader`每次输出一个data instance,这个instance可以是单个值,或者用tuple表示的多个值: - -```python -yield 1 # 单个值 -yield numpy.random.uniform(-1, 1, size=28*28) # 单个值 -yield numpy.random.uniform(-1, 1, size=28*28), 0 # 多个值 -``` - -每个值的类型可以是整形、浮点型数据、字符串,或者由它们组成的list,以及numpy.ndarray。如果是其它类型,会被Pickle序列化成字符串。 - -### 示例程序 - -#### 使用转换库 - -以下`reader_creator`生成的`reader`每次输出一个data instance,每个data instance包涵两个值:numpy.ndarray类型的值和整型的值: -```python -def reader_creator(): - def reader(): - for i in range(1000): - yield numpy.random.uniform(-1, 1, size=28*28), 0 # 多个值 - return reader -``` - -把`reader_creator`生成的`reader`传入`convert`函数即可完成转换: -```python -convert("./", reader_creator(), 100, random_images) -``` - -以上命令会在当前目录下生成100个文件: -```text -random_images-00000-of-00099 -random_images-00001-of-00099 -... -random_images-00099-of-00099 -``` - -#### 进行训练 - - -PaddlePaddle提供专用的[data reader creator](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/reader/README.md#python-data-reader-design-doc),生成给定`RecordIO`文件对应的data reader。**无论在本地还是在云端,reader的使用方式都是一致的**: - -```python -# ... -reader = paddle.reader.creator.RecordIO("/pfs/datacenter_name/home/user_name/random_images-*-of-*") -batch_reader = paddle.batch(paddle.dataset.mnist.train(), 128) -trainer.train(batch_reader, ...) -``` - -以上代码的reader输出的data instance与生成数据集时,reader输出的data instance是一模一样的。 - -### 上传训练文件 - -使用下面命令,可以把本地的数据上传到存储集群中。 - -```bash -paddle pfs cp filename /pfs/$DATACENTER/home/$USER/folder/ -``` - -比如,把之前示例中转换完毕的random_images数据集上传到云端的`/home/`可以用以下指令: - -```bash -paddle pfs cp random_images-*-of-* /pfs/$DATACENTER/home/$USER/folder/ -``` - -需要`$DATACENTER`的配置写到配置文件中,例如 - -``` -# config file -[datacenter_1] -username=user -usercert=user.pem -userkey=user-key.pem -endpoint=datacenter1.paddlepaddle.org - -[datacenter_2] -username=user -usercert=user.pem -userkey=user-key.pem -endpoint=datacenter2.paddlepaddle.org -``` -## TODO -### 文件访问的权限 -控制用户权限 - -- 用户可以把自己的数据分享给别人 - -### 文件访问方式 -不用mount的方式来访问数据,而是直接用API的接口远程访问 - -例如: - -``` -f = open('/pfs/datacenter_name/home/user_name/test1.dat') -``` - - -### 支持用户自定义的数据预处理job diff --git a/develop/doc/_sources/design/cluster_train/large_model_dist_train.md.txt b/develop/doc/_sources/design/cluster_train/large_model_dist_train.md.txt deleted file mode 100644 index 0c4b5bc24c8..00000000000 --- a/develop/doc/_sources/design/cluster_train/large_model_dist_train.md.txt +++ /dev/null @@ -1,101 +0,0 @@ -# Alalysis of large model distributed training in Paddle - -***NOTE: This is only some note for how we implemeted this scheme in V1, not a new design.*** - -## What is it - -We often encounter cases that the embedding layer parameters(sparse) are so large that we can not store it in the trainer's memory when training. So we need to put them to several servers, and fetch them row by row instead of fetch all of the parameters. - -## How to use - -Specify command-line argument like `--loadsave_parameters_in_pserver=true --ports_num_for_sparse=1 --use_old_updater=1` when starting the paddle trainer. And also add something like `--ports_num_for_sparse=1 --pserver_num_threads=5` when starting pserver processes. - -Accrodingly, configure your embedding layers like: - -```python -SPARSE_REMOTE=True - -w1 = data_layer(name="w1", size=dict_size) -emb1 = embedding_layer(input=w1, size=32, param_attr=ParameterAttribute(sparse_update=SPARSE_REMOTE)) -w2 = data_layer(name="w2", size=dict_size) -emb2 = embedding_layer(input=w2, size=32, param_attr=ParameterAttribute(sparse_update=SPARSE_REMOTE)) -... -``` - -## Implementation details - -```c++ -enum MatType { - MAT_NORMAL, - MAT_NORMAL_SHARED, - MAT_VALUE_SHARED, - MAT_SPARSE_ROW_IDS, - MAT_SPARSE_ROW_AUTO_GROW, - MAT_CACHE_ROW, - MAT_SPARSE_ROW, - MAT_SPARSE_ROW_PREFETCH, - MAT_SPARSE_ROW_PREFETCH_FULL_SIZE, -}; -``` - -`MAT_SPARSE_ROW_PREFETCH` is what we use when configured to fetch only row of matrix when training. - -In `trainer_internal.cpp:L93 trainOneBatch`: - -```c++ - if (config_->getOptConfig().use_sparse_remote_updater()) { - REGISTER_TIMER("prefetch"); - gradientMachine_->prefetch(inArgs); - parameterUpdater_->getParametersRemote(); - } -``` - -When doing actual network forward and backward, at the beginning of each batch, the trainer will try to download one row of data from pserver. - -In `trainer/RemoteParameterUpdater.cpp`: `parameterUpdater_->getParametersRemote();`: - -```c++ -if (fullSize) { - ... -} else { -getParams = [&] { - parameterClient_->getParameterSparse( - /* recvParameterType= */ PARAMETER_VALUE, sendBackParameterType); -}; -applyL1 = [](Parameter& para, real decayRate) { - para.getMat(PARAMETER_VALUE)->applyL1(/*lr=*/1.0f, decayRate); -}; -} -``` - -Calling `parameterClient_->getParameterSparse` will do remote call to pserver's `getParameterSparse`: - -```c++ -void ParameterServer2::getParameterSparse(const SendParameterRequest& request, - std::vector& inputBuffers, - SendParameterResponse* response, - std::vector* outputBuffers) { - (void)inputBuffers; - auto& buffer = *readWriteBuffer_; - size_t numReals = 0; - for (const auto& block : request.blocks()) { - numReals += getParameterConfig(block).dims(1); - } - buffer.resize(numReals); - - VLOG(3) << "pserver: getParameterSparse, numReals=" << numReals; - - ReadLockGuard guard(parameterMutex_); - size_t offset = 0; - for (const auto& block : request.blocks()) { - size_t width = getParameterConfig(block).dims(1); - Buffer buf = {buffer.data() + offset, width}; - int type = request.send_back_parameter_type(); - sendBackParameterSparse(block, type, response, &buf, width, outputBuffers); - offset += width; - } -} -``` - -`getParameterConfig(block).dims(1)` returns the width of the current "parameter block"(a shard of parameter object), -then `getParameterSparse` remote call returns only one row of data to the client. diff --git a/develop/doc/_sources/design/cluster_train/master_server.md.txt b/develop/doc/_sources/design/cluster_train/master_server.md.txt deleted file mode 100644 index 4bf3c506f10..00000000000 --- a/develop/doc/_sources/design/cluster_train/master_server.md.txt +++ /dev/null @@ -1,91 +0,0 @@ -# Design Doc: Master Server - -For an overview of master server's role, please refer to [distributed training design doc](./README.md). In this design doc we will discuss the master server in more details. The master will be implemented in [Go](https://golang.org/). - -## Dataset - - - -A dataset is a list of files in *RecordIO* format. A RecordIO file consists of chunks, whereas each chunk consists some records. - -## Task Queue - -As mentioned in [distributed training design doc](./README.md), a *task* is a data shard that the master server assigns to the trainer process to train on. A task consists of one or multiple *chunks* from one or multiple files. The master server maintains *task queues* to track the training progress. - -### Task Queue Creation - -1. Each trainer will make an RPC call (using Go's [rpc](https://golang.org/pkg/net/rpc/) package) to the master server, telling it the RecordIO files representing the dataset specified by the user. Since every trainer will tell the master server the same dataset, only the first RPC call will be honored. - - The RPC interface is: - ```go - func (m *RPCServer) ReportDataset(Paths []string, dummy *int) error { - } - ``` -1. The master server will scan through each RecordIO file to generate the *chunk index* and know how many chunks does each file have. A chunk can be referenced by the file path and the index of the chunk within the file. The chunk index is in memory data structure that enables fast access to each chunk, and the index of the chunk with the file is an integer start from 0, representing the n-th chunk within the file. - - The definition of the chunk is: - ```go - type Chunk struct { - Idx int // index of the chunk within the file - Path string - Index recordio.Index // chunk index - } - ``` -1. Chunks are grouped into tasks, and tasks are filled into the todo queue. The pending queue and the done queue are initialized with no element. - - The definition of the task is: - ```go - type Task struct { - Index int - Chunks []Chunk - } - ``` - - The elements in the tasks queues is of type `TaskEntry`, containing a timeout counter (described in [task retry logic](#task-retry-logic)), and a task: - ```go - type TaskEntry struct { - NumTimeout int - Task Task - } - ``` - - The definition of task queues is: - ```go - type TaskQueues struct { - Todo []TaskEntry - Pending map[int]TaskEntry // map from task index to task entry - Done []TaskEntry - } - ``` - -### Task Queue Persistence - -The task queues need to be persisted on [etcd](https://github.com/coreos/etcd) for fault recovery. Since the task queues only change once a task is completed or timed out, which is not very frequent, we can afford to synchronize with etcd every time the task queues change. - -We will serialize the task queues data structure with [gob encoding](https://golang.org/pkg/encoding/gob/), compress with gzip, and save into etcd synchronously under key `/task_queues`. - -### Task Dispatch - -The trainer will make an RPC call to master to get a new task when: - -- the trainer first started, or -- the trainer finishes a task. - -The RPC interface is: -```go -func (m *RPCServer) GetTask(finished *Task, result *Task) error { -} -``` -Argument `finished` will be `nil` when the trainer is just started. - -During the RPC call the master will do the following: - -- Make a copy of the task queues, and update the copy reflecting the finished tasks and the new pending tasks. -- Synchronize the copy of task queues with etcd using a transaction conditioned on holding the master lock. -- Replace the task queues with the copy and report to the trainer with the new tasks if succeeded, or discard the copy and report the error to the trainer if failed. - -### Task Retry Logic - -When a task is dispatched to the trainer, the master will schedule a function for execution after the timeout duration (based on the moving average of task completion time). If the task entry in still in the pending queue, its timeout counter will increase by one, and the task will be moved to todo queue. If the timeout counter is above the threshold, the master will log the error and discard the task. - -Please note that since a timed out task could be completed after it has been dispatched for retry, so it is possible for a task to be processed multiple times. We do not try to prevent it from happening since it's fine to train on the same task multiple times due to the stochastic nature of the stochastic gradient decent algorithm. diff --git a/develop/doc/_sources/design/cluster_train/pserver_client.md.txt b/develop/doc/_sources/design/cluster_train/pserver_client.md.txt deleted file mode 100644 index 474b8c572cd..00000000000 --- a/develop/doc/_sources/design/cluster_train/pserver_client.md.txt +++ /dev/null @@ -1,171 +0,0 @@ -# Design Doc: The Client Library of Parameter Server - -For an overview of trainer's role, please refer to [distributed training design doc](README.md). In this design doc, we will discuss the parameter server's client library, which will manage communication with parameter servers. The library will be implemented in [Go](https://golang.org/) and made available as a static or dynamic library with a C header file. - -## Parameter Partition - -Each parameter will be partitioned into parameter blocks to make the parameters evenly distributed on parameter servers. The partition is done automatically by the client library. The *sparse parameter* require a little different treatment: - -### Sparse Parameter - -The sparse parameter is a parameter that is updated sparsely. The name is somewhat misleading, it does not have a sparse representation, it has the same representation as a dense vector. - -Because a sparse parameter is updated sparsely, the trainer will have to partition the sparse parameter. Because the parameter server will merge all sparse parameter shard into the same file when saving the parameter. It needs special naming convention: - -If a sparse parameter is partitioned into n shards, they should be named as: - -```text -name:sparse-0 -name:sparse-1 -... -name:sparse-n-1 -``` - -The library is unaware of the partition, and treat each parameter independently. Only when saving parameters, the parameter servers will merge the sparse parameters according to the naming convention. - -## Model Optimization Using Gradients - -There are two ways to perform model optimization using gradients: - -- On Client - - The client does multiple steps of forward and backward update. In each step, the gradients are calculated and a new model is generated. After some steps, the client will calculate the difference between the newest model and the old model at step 0. The difference will be updated to parameter servers. Parameter servers will just update parameters using the difference without any optimization using gradients (such as Adam and L1 regularization). - -- On Parameter Server - - The client will send accumulated gradients to parameter servers, the parameter server will do the optimization using gradients. - -## L1 and L2 Regularization - -PaddlePaddle allows L1 or L2 regularizations to be specified per parameter, so when the trainer initializes the parameter it needs include a parameter configuration when L1 or L2 regularization is necessary. - -## Parameter Initialization - -The parameters on parameter servers need to be initialized. To provide maximum flexibility, the trainer will initialize the parameters. Only one trainer will do the initialization, the other trainers will wait for the completion of initialization and get the parameters from the parameter servers. - -### Trainer Selection - -To select the trainer for initialization, every trainer will try to get a distributed lock, whoever owns the lock will do the initialization. As illustrated below: - - - -### Trainer Selection Process - -The trainer select process is encapsulated in the C API function: -```c -int paddle_begin_init_params(paddle_pserver_client* client, const char* config_proto); -``` -The selected trainer's call to `paddle_begin_init_params` will return with 1, and the other trainers' call to `paddle_begin_init_params` will return 0. `paddle_get_params` will be blocked until initialization is completed. As illustrated below: - - - -## C Interface - -```c -typedef enum { - PADDLE_ELEMENT_TYPE_INT32 = 0, - PADDLE_ELEMENT_TYPE_UINT32 = 1, - PADDLE_ELEMENT_TYPE_INT64 = 2, - PADDLE_ELEMENT_TYPE_UINT64 = 3, - PADDLE_ELEMENT_TYPE_FLOAT32 = 4, - PADDLE_ELEMENT_TYPE_FLOAT64 = 5, -} paddle_element_type; - -typedef struct { - char* name; - paddle_element_type element_type; - unsigned char* content; - int content_len; -} paddle_parameter, paddle_gradient; - -typedef int paddle_pserver_client; - -/** - * @brief creates a pserver client that talks to etcd for coordination. - */ -paddle_pserver_client paddle_new_etcd_pserver_client(char* etcd_addr); - -/** - * @brief creates a pserver client given pserver addresses. - * - * @param pserver_addrs comma-separated pserver addresses. - * @param selected if current pserver client is selected to initialize all parameter servers. - */ -paddle_pserver_client paddle_new_pserver_client(char* pserver_addrs, int selected); -void paddle_pserver_client_release(paddle_pserver_client c); - -/** - * @brief paddle_begin_init_params begins to initialize parameters on - * parameter servers. - * - * paddle_begin_init_params will be called from multiple trainers, - * only one trainer will be selected to initialize the parameters on - * parameter servers. Other trainers need to get the initialized - * parameters from parameter servers using @paddle_get_params. - * - * @return 1 if the trainer is selected to initialize parameter - * servers, otherwise 0. - */ -int paddle_begin_init_params(paddle_pserver_client client); - -/** - * @brief paddle_init_param initializes the parameter on parameter - * servers. - * - * @param param the parameter to initialize. - * @param param_config_proto the configuration for the parameter. - * @param config_len the length of param_config_proto - * @return 0 if successful, otherwise -1. On failure, the trainer - * needs to restart the entire initialization process (starting from - * @paddle_begin_init_param). Or simply exit the program and wait for - * the cluster management system to restart the trainer. - */ -int paddle_init_param(paddle_pserver_client client, paddle_parameter param, const unsigned char* param_config_proto, int config_len); - -/** - * @brief paddle_finish_init_params tells parameter servers client has - * sent all parameters to parameter servers as initialization. - * - * @return 0 if successful, otherwise -1. On failure, the trainer - * needs to restart the entire initialization process (starting from - * @paddle_begin_init_param). Or simply exit the program and wait for - * the cluster management system to restart the trainer. - */ -int paddle_finish_init_params(paddle_pserver_client client); - -/** - * @brief paddle_send_grads sends gradients to parameter servers for - * updating parameters. - * - * @param grads the array of gradients to send. - * @param len the length of the gradient array. - * @param learning_rate the learning rate for the gradients. - * @return 0 if successful, otherwise -1. - */ -int paddle_send_grads(paddle_pserver_client client, const paddle_gradient* grads, int len); - -/** - * @brief paddle_get_params gets parameters from parameter servers. - * - * paddle_get_params will block until parameters are initialized on - * the parameter servers. - * - * @param dst the destination array of parameter pointers to save to. - * The parameter pointer must be pre-popullated with required parameter name, - * and the content of parameter must be pre-allocated of the size of required - * parameter on pserver. - * @param len the length of the names array and the paddle_parameter - * array. - * @return 0 if successful, otherwise -1. - */ -int paddle_get_params(paddle_pserver_client client, paddle_parameter** dst, int len); - -/** - * @brief paddle_save_model indicates parameters to save the parameter - * to the given path - * - * @param path the path to save parameters. - * @return 0 if successful, otherwise -1. - */ -int paddle_save_model(paddle_pserver_client client, const char* path); -``` diff --git a/develop/doc/_sources/design/cluster_train/remote_parameter_updater.md.txt b/develop/doc/_sources/design/cluster_train/remote_parameter_updater.md.txt deleted file mode 100644 index 6e8e5938455..00000000000 --- a/develop/doc/_sources/design/cluster_train/remote_parameter_updater.md.txt +++ /dev/null @@ -1,21 +0,0 @@ -# Design Doc: Remote Parameter Updater for Cluster Train - -For an overview of distribute training, please refer to [distributed training design doc](README.md). In this design doc, we will discuss the parameter updater that will use parameter server cclient [The Client Library of Parameter Server Design Doc](pserver_client.md) to manage and update parameters. - -## Parameter Updater - -Parameter Updater is used by trainer to manage and update parameter, there are mainly two kind of parameter updater: local and remote, since this design is for cluster train, we will only discuss remote parameter updater here. - -### Remote Parameter Updater - -Remote Parameter Updater manage parameters through remote parameter server with the client that communicate with pserver([The Client Library of Parameter Server Design Doc](pserver_client.md)) - -In PaddlePaddle Python V2 API, trainer is implemented in python, and the trainer will hold a instance of parameter updater and call it's functions directly. In this design, we will also expose the api of RemoteParameterUpdater to python with swig. - -#### Sparse Remote Parameter Updater - -Since we will only implement dense parameter management new, the mechanism for sparse parameter will be discussed in next stage. - -### Interface Design - -TBD diff --git a/develop/doc/_sources/design/cluster_train/save_model.md.txt b/develop/doc/_sources/design/cluster_train/save_model.md.txt deleted file mode 100644 index b755185c81a..00000000000 --- a/develop/doc/_sources/design/cluster_train/save_model.md.txt +++ /dev/null @@ -1,111 +0,0 @@ -# Design Doc: Save Model - -## Overview - -The model is the output of the training process. There are two -ways from which user can obtain a model: - -- Save model triggered by user code: user code asks PaddlePaddle to - save a model. -- Convert model from the checkpoint: model being converted from - pservers' periodic checkpoint. In this way, the user can cancel a - job at any time, and still have a relatively fresh model (we - checkpoint around every 5 minutes). - -### Trainer Saving Model vs. Pservers Saving Model - -Both trainers and pservers have access to the model. So the model can -be saved from a trainer or pservers. We need to decide where the model -is saved from. - -#### Dense Update vs. Sparse Update - -There are two types of model update methods: dense update and sparse -update (when the model parameter is configured to be sparse). - -- Dense update - - Every trainer has it's own full copy of the model. Every model - update will update the entire model. - -- Sparse update - - The training input is sparse, and the trainer does not have the - entire model. It will only download the sub-model necessary related - to the input. When updating the model, only the sub-model related to - the training input is updated. - - -#### Pservers Saving Model - -The benefit of letting pservers save model is they have the entire -model all the time. However, since pservers are on different nodes, it -requires a merging process to merge model shards into the same -model. Thus requires the pservers to write models to a distributed -filesystem, making the checkpoint shards visible to the merge program. - -#### Trainer Saving Model - -The benefit of letting one trainer to save the model is it does not -require a distributed filesystem. And it's reusing the same save model -logic when training locally - except when doing sparse update, the -trainer needs to download the entire model during the saving process. - -#### Conclusion - -Given trainer saving model does not require a distributed filesystem, -and is an intuitive extension to trainer saving model when training -locally, we decide to let the trainer save the model when doing -distributed training. - - -### Convert Model from Checkpoint - -TODO - - -## Timeline - -We first implement trainer save the model. Converting the latest -snapshot to a model will be a TODO for future. - - -## Trainer Save Model - -### Trainer Election - -One trainer will be elected as the one to save the model. When using -etcd, trainer ID is a randomly generated UUID, the trainer will -contact the master server requesting to save the model, and find out -if itself is elected. When the master server is not used, unique -trainer IDs will be given by the administrator, the trainer whose ID -is "0" is elected to save the model. - -### Model Save Path - -Each trainer will be given the directory to save the model. The -elected trainer will save the model to -`given-directory/trainerID`. Since the trainer ID is unique, this -would prevent concurrent save to the same file when multiple trainers -are elected to save the model when split-brain problem happens. - -### What Happens When Model Is Saving - -It takes some time to save model, we need to define what will happen -when save model is taking place. - -When doing dense update, the trainer uses the local model. Pservers -does not need to pause model update. - -When doing sparse update. The trainer needs to download the entire -model while saving. To get the most accurate model, the model update -needs to be paused before the download starts and resumed after the -download finishes. Otherwise, the trainer gets a model that is -"polluted": some part of the model is old, some part of the model is -new. - -It's unclear that the "polluted" model will be inferior due to the -stochastic nature of deep learning, and pausing the model update will -add more complexity to the system. Since supporting sparse update is a -TODO item. We defer the evaluation of pause the model update or not -during saving model to the future. diff --git a/develop/doc/_sources/design/cluster_train/submit-job.md.txt b/develop/doc/_sources/design/cluster_train/submit-job.md.txt deleted file mode 100644 index 8377d5489dc..00000000000 --- a/develop/doc/_sources/design/cluster_train/submit-job.md.txt +++ /dev/null @@ -1,127 +0,0 @@ -# Submit a Distributed Training Job - -The user can submit a distributed training job with Python code, rather than with a command-line interface. - -## Runtime Environment On Kubernetes - -For a distributed training job, there is two Docker image called *runtime Docker image* and *base Docker image*. The runtime Docker image is the Docker image that gets scheduled by Kubernetes to run during training. The base Docker image is for building the runtime Docker image. - -### Base Docker Image - -Usually, the base Docker image is PaddlePaddle product Docker image including paddle binary files and python package. And of course, users can specify any image name hosted on any docker registry which users have the access right. - -### Runtime Docker Image - -The trainer package which user upload and some Python dependencies are packaged into a runtime Docker image based on base Docker image. - -- Handle Python Dependencies - - You need to provide requirements.txt file in your `trainer-package` folder. Example: - - ```txt - pillow - protobuf==3.1.0 - ``` - More [details](https://pip.readthedocs.io/en/1.1/requirements.html) about requirements, an example project looks like: - ```bash - paddle_example - |-quick_start - |-trainer.py - |-dataset.py - |-requirements.txt - ``` - -## Submit Distributed Training Job With Python Code - - -- `paddle.job.dist_train()` will call the Job Server API `/v1/packages` to upload the trainer package and save them on CephFS, and then call `/v1/trainer/job` to submit the PaddlePaddle distributed job. -- `/v1/trainer/job` will start a building job for preparing the runtime Docker image. When the building job is finished, Job Server will submit the PaddlePaddle distributed job to Kubernetes. -- *NOTE*: For the first version, we will not prepare the runtime Docker image, instead, the package is uploaded to Paddle Cloud, and Paddle Cloud will mount the package in a temporary folder into the base Docker image. We will not support custom Python dependencies in the first version as well. - -You can call `paddle.job.dist_train` and provide distributed training configuration as the parameters: -```python -paddle.job.dist_train( - trainer=dist_trainer(), - paddle_job=PaddleJob( - job_name = "paddle-cloud", - entry_point = "python %s"%__file__, - trainer_package = "/example/word2vec", - image = "yancey1989/paddle-job", - trainers = 10, - pservers = 3, - trainer_cpu = 1, - trainer_gpu = 1, - trainer_mem = "10G", - pserver_cpu = 1, - pserver_mem = "2G" - )) -``` - -The parameter `trainer` of `paddle.job.dist_train` is a function and you can implement it as follows: -```python -def dist_trainer(): - def trainer_creator(): - trainer = paddle.v2.trainer.SGD(...) - trainer.train(...) - return trainer_creator -``` - -The pseudo code of `paddle.job.dist_train` is as follows: -```python -def dist_train(trainer, paddle_job): - # if the code is running on cloud, set PADDLE_ON_CLOUD=YES - if os.getenv("RUNNING_ON_CLOUD", "NO") == "NO": - #submit the paddle job - paddle_job.submit() - else: - #start the training - trainer() -``` -### PaddleJob Parameters -parameter | type | explanation - --- | --- | --- -job_name | str | the unique name for the training job -entry_point | str | entry point for startup trainer process -trainer_package | str | trainer package file path which user have the access right -image|str|the [base image](#base-docker-image) for building the [runtime image](#runtime-docker-image) -pservers|int| Parameter Server process count -trainers|int| Trainer process count -pserver_cpu|int| CPU count for each Parameter Server process -pserver_mem|str| memory allocated for each Parameter Server process, a plain integer using one of these suffixes: E, P, T, G, M, K -trainer_cpu|int| CPU count for each Trainer process -trainer_mem|str| memory allocated for each Trainer process, a plain integer using one of these suffixes: E, P, T, G, M, K -trainer_gpu|int| GPU count for each Trainer process, if you only want CPU, do not set this parameter - -### Deploy Parameter Server, Trainer and Master Process - - Deploy PaddlePaddle Parameter Server processes, it's a Kubernetes ReplicaSet. - - Deploy PaddlePaddle Trainer processes, it's a Kubernetes Job. - - Deploy PaddlePaddle Master processes, it's a Kubernetes ReplicaSet. - -## Job Server - -- RESTful API - - Job server provides RESTful HTTP API for receiving the trainer package and displaying - PaddlePaddle job related informations. - - `POST /v1/package` receive the trainer package and save them on CephFS - - `POST /v1/trainer/job` submit a trainer job - - `GET /v1/jobs/` list all jobs - - `GET /v1/jobs/` the status of a job - - `DELETE /v1/jobs/` delete a job - - `GET /v1/version` job server version - -- Build Runtime Docker Image on Kubernetes - - `paddle.job.dist_train` will upload the trainer package to Job Server, save them on the distributed filesystem, and then start up a job for building the runtime Docker image that gets scheduled by Kubernetes to run during training. - - There are some benefits for building runtime Docker image on JobServer: - - On Paddle Cloud, users will run the trainer code in a Jupyter Notebook which is a Kubernetes Pod, if we want to execute `docker build` in the Pod, we should mount the host's `docker.sock` to the Pod, user's code will connect the host's Docker Engine directly, it's not safe. - - Users only need to upload the training package files, does not need to install docker engine, docker registry as dependencies. - - If we want to change another image type, such as RKT, users do not need to care about it. - -- Deploy Parameter Server, Trainer and Master Processes - - `POST /v1/trainer/job` receives the distributed training parameters, and deploy the job as follows: - - Deploy PaddlePaddle Parameter Server processes, it's a Kubernetes ReplicaSet. - - Deploy PaddlePaddle Trainer processes, it's a Kubernetes Job. - - Deploy PaddlePaddle Master processes, it's a Kubernetes ReplicaSet. diff --git a/develop/doc/_sources/design/concurrent_programming.md.txt b/develop/doc/_sources/design/concurrent_programming.md.txt deleted file mode 100644 index f022e67fd3a..00000000000 --- a/develop/doc/_sources/design/concurrent_programming.md.txt +++ /dev/null @@ -1,163 +0,0 @@ -# Design Doc: Concurrent Programming with Fluid - -With PaddlePaddle Fluid, users describe a program other than a model. The program is a [`ProgramDesc`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto) protobuf message. TensorFlow/MxNet/Caffe2 applications generate protobuf messages too, but their protobuf messages represent the model, a graph of operators, but not the program that trains/uses the model. - -Many know that when we program TensorFlow, we can specify the device on which each operator runs. This allows us to create a concurrent/parallel AI application. An interesting questions is **how does a `ProgramDesc` represents a concurrent program?** - -The answer relies on the fact that a `ProgramDesc` is similar to an abstract syntax tree (AST) that describes a program. So users just program a concurrent program that they do with any concurrent programming language, e.g., [Go](https://golang.org). - -## An Analogy - -The following table compares concepts in Fluid and Go - -| Go | Fluid | -|----|-------| -|user-defined functions | [layers](https://github.com/PaddlePaddle/Paddle/tree/develop/python/paddle/fluid) | -| control-flow and built-in functions | [intrinsics/operators](https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/operators) | -| goroutines, channels | [class ThreadPool](https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/framework/thread_pool.h) | -| runtime | [class Executor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/executor.h) | - -## An Example Concurrent Program - -To review all above concepts in an example, let us take a simple program and writes its distributed version. - -Suppose that we want to parallelize a naive Fluid program (written in Go and calling Fluid's Go binding) that multiplies two tensors. - -```go -import "fluid" - -func paddlepaddle() { - X = fluid.read(...) - W = fluid.Tensor(...) - Y = fluid.mult(X, W) -} -``` - -Please be aware that the Fluid's Go binding provides the default `main` function, which calls the `paddlepaddle` function, which, in this case, is defined in above program and creates the following `ProgramDesc` message. - -```protobuf -message ProgramDesc { - block[0] = Block { - vars = [X, W, Y], - ops = [ - read(output = X) - assign(input = ..., output = W) - mult(input = {X, W}, output = Y) - ], - } -} -``` - -Then, the default `main` function calls `fluid.run()`, which creates an instance of the [`class Executor`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/executor.h) and calls `Executor.Run(block[0])`, where `block[0]` is the first and only block defined in above `ProgramDesc` message. - -The default `main` function is defined as follows: - -```go -func main() { - paddlepaddle() - fluid.run() -} -``` - -## The Concurrent Version - -By parallelizing the above program, we could support very big tensor X by splitting into small pieces {x_1, x_2, ...} and sent each piece to worker process/node for parallel multiplication. - -In this case, we can write a transpiler that takes a `ProgramDesc` message that represents the above example program and outputs two `ProgramDesc` messages, one for running on the master process/node, and the other one for worker processes/nodes. - -### The Master Program - -The master program could look like the following: - -```protobuf -message ProgramDesc { - block[0] = Block { - vars = [X, L, Y], - ops = [ - read(output = X) - kube_get_workers_addrs(output = L) - Y = tensor_array(len(L)) - parallel_for(input = X, output = Y, - attrs = {L, block_id(1)}) # referring to block 1 - ] - } - - block[1] = Block { - parent = 0, - vars = [x, y, index], - ops = [ - slice(input = [X, index], output = x) # index is initialized by parallel_for - send(input = x, attrs = L[index]) - recv(outputs = y, attrs = L[index]) - assign(input = y, output = Y[index]) - ] - } -} -``` - -The equivalent Fluid program (calling the Go binding) is: - -```go -func main() { //// block 0 - X = fluid.read(...) - L = fluid.k8s.get_worker_addrs() - Y = fluid.tensor_array(len(L)) - fluid.parallel_for(X, L, - func(index int) { //// block 1 - x = X[index] - fluid.send(L[index], x) - y = fluid.recv(L[index]) - Y[index] = y - }) -} -``` - -An explanation of the above program: - -- `fluid.k8s` is a package that provides access to Kubernetes API. -- `fluid.k8s.get_worker_addrs` returns the list of IP and ports of all pods of the current job except for the current one (the master pod). -- `fluid.tensor_array` creates a [tensor array](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/lod_tensor_array.h). `fluid.parallel_for` creates a `ParallelFor` intrinsic, which, when executed, - - 1. creates `len(L)` scopes, each for the concurrent running of the sub-block (block 1 in this case), and initializes a variable named "index" in the scope to an integer value in the range `[0, len(L)-1]`, and - 2. creates `len(L)` threads by calling into the `ThreadPool` singleton, each thread - 1. creates an Executor instance, and - 2. calls `Executor.Run(block)`, where `block` is block 1 as explained above. -1. Please be aware that block 1 is a sub-block of block 0, so ops in block 1 could refer to variables defined in block 0. - -### The Worker Program - -The worker program looks like - -```go -func main() { - W = Tensor(...) - x = fluid.listen_and_do( - fluid.k8s.self_addr(), - func(input Tensor) { - output = fluid.mult(input, W) - }) -} -``` - -where - -- `fluid.listen_and_do` creates a `ListenAndDo` intrinsic, which, when executed, - 1. listens on the current pod's IP address, as returned by `fliud.k8s.self_addr()`, - 2. once a connection is established, - 1. creates a scope of two parameters, "input" and "output", - 2. reads a [Fluid variable](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/variable.h) and saves it into "input", - 3. creates an Executor instance and calls `Executor.Run(block)`, where the block is generated by running the lambda specified as the second parameter of `fluid.listen_and_do`. - -## Summarization - -From the above example, we see that: - -1. Fluid enables the imperative programming paradigm by: - 1. letting users describe a program, but not a model (a sequence of layers, or a graph of operators), and - 2. call the `fluid.run` function that runs the program implicitly. -1. The program is described as a `ProgramDesc` protobuf message. -2. Function `Executor.Run` takes a block, instead of a `ProgramDesc`, as its parameter. -3. `fluid.run` calls `Executor.Run` to run the first block in the `ProgramDesc` message. -4. `Executor.Run`'s implementation is extremely simple -- it doesn't plan the execution nor create threads; instead, it runs on the current thread and execute intrinsics/operators' `Run` method sequentially as they appear in the `Block.ops` array. -5. Intrinsics/operators' `Run` method might create threads. For example, the `ListenAndDo` operator creates a thread to handle each incoming request. -6. Threads are not necessarily OS thread; instead, they could be [green threads](https://en.wikipedia.org/wiki/Green_threads) managed by ThreadPool. Multiple green threads might run on the same OS thread. An example green threads is Go's [goroutines](https://tour.golang.org/concurrency/1). diff --git a/develop/doc/_sources/design/cpp_data_feeding.md.txt b/develop/doc/_sources/design/cpp_data_feeding.md.txt deleted file mode 100644 index 40205350f99..00000000000 --- a/develop/doc/_sources/design/cpp_data_feeding.md.txt +++ /dev/null @@ -1,79 +0,0 @@ -# C++ Data Feeding - -In training with Paddle V2 API, data feeding wholly dependents on Python code. To get rid of the Python environment and achieve the goal of "wrapping the whole training by a while loop op" in Paddle Fluid, a C++ data feeding mechanism is required. - -In this document we show the fundamental design of C++ data feeding process, which includes the data reading, shuffling and batching. - -## Reader - -A new concept named 'Reader' is introduced. `Reader` is a series of inherited classes which can be hold by our `Variable` and they are used to read or process file data. - - -### `ReaderBase` - -`ReaderBase` is the abstract base class of all readers. It defines the all readers' interfaces. - -```cpp -class ReaderBase { - public: - explicit ReaderBase(const std::vector& shapes) : shapes_(shapes) { - PADDLE_ENFORCE(!shapes_.empty()); - } - // Read the next batch of data. (A 'batch' can be only one instance) - virtual void ReadNext(std::vector* out) = 0; - // Show whether the next bacth exists. - virtual bool HasNext() const = 0; - - // Reinitialize the reader and read the file from the begin. - virtual void ReInit() = 0; - - // Get a certain read in data's shape. - DDim shape(size_t idx) const; - // Get shapes of all read in data. - std::vector shapes() const { return shapes_; } - // Set shapes of read in data. - void set_shapes(const std::vector& shapes) { shapes_ = shapes; } - - virtual ~ReaderBase() {} - - protected: - std::vector shapes_; -}; -``` - -### `FileReader` and `DecoratedReader` - -These two classes are derived from the `ReaderBase` and will further be derived by respective specific readers. That is to say, in our design, there are two kinds of readers: file readers and decorated readers. A file reader reads from a file of some specific format, and yield only one instance of data at a time. e.g. RecordIO reader, jpg reader, .... A decorated reader takes another reader(both file reader and decorated reader are OK) as its 'underlying reader'. It gets data from its underlying reader, does some process on them(shuffling, or batching), then yields processed data. The output data of a decorated reader can be a single instance or a batch. `ShuffleReader` and `BatchReader` are both decorated readers. - -All the readers share exactly the same interfaces defined in `ReaderBase`. So they can be decorated for more than one time: We can **shuffle** a reader's outputs and then **batch** the shuffle outputs. The interface consistency also allows related ops use readers without knowing what they are exactly. - - -### `ReaderHolder` - -Different readers belong to different class types. It leads to a problem: How can we drop them into `Variable`s and fetch them out by a unified method? For example, if a Variable holds a `BatchReader`, we can not get it by the following code: - -```cpp -var->Get("batch_reader"); -``` - -we have to write: - -```cpp -var->Get("batch_reader"); -``` - -This requires each time getting a reader from a variable we must know the reader's type exactly. It is nearly impossible. - -To solve this problem, we introduce `ReaderHolder` as a wrapper. It acts as an empty decorator of `ReaderBase`, which erases reader's type. With `ReaderHolder` we are able to fetch all types of readers by `var->Get("...")` and regard the obtained object as a reader. - -## Related Operators - -To create and invoke readers, some now ops are introduced: - -### `CreateReaderOp` - -Each reader has its creating op. File readers' creating ops have no input and yield the created file reader as its output. Decorated readers' creating ops take the underlying readers as inputs and then yield new decorated readers. - -### `ReadOp` - -A reader is only a Variable. It cannot trigger the reading process by itself. So we add the `ReadOp` to execute it. A `ReadOp` takes a reader Variable as its input. Each time it runs, it invokes the reader‘s `ReadNext()` function and gets a new batch of data(or only one instance of data, if we use file reader directly). The output data of a reader are in the form of `std::vector`, so the `ReadOp` also needs to split the vector and move LoDTensors to their respective output Variables. diff --git a/develop/doc/_sources/design/csp.md.txt b/develop/doc/_sources/design/csp.md.txt deleted file mode 100644 index 10d936860fa..00000000000 --- a/develop/doc/_sources/design/csp.md.txt +++ /dev/null @@ -1,224 +0,0 @@ -# Design Doc: CSP in PaddlePaddle Fluid - -## Motivation - -Concurrent programming is important for deep learning. Few example applications are: - -1. The main thread keeps reading the next mini-batch while another thread uses the GPU for computing. -2. The main thread performs the computation while another thread uploads the local gradients from each trainer to the parameter server. - -Most DL systems, including TensorFlow, Caffe2, and MxNet, can asynchronously execute operators in a graph. However, Fluid doesn't have the concept of a graph at all, as the design goal of Fluid is that of a programming language. - -## Concurrent Programming Models - -There were many concurrent programming models, implemented in various forms: - -| concurrent programming model | implementation | -|-----|-----| -| mutex | types and functions in standard libraries | -| semaphore | types and functions in standard libraries | -| communicating sequential processes (CSP) | Go programming language | -| actor model | Erlang programming language | -| message passing | MPI | -| bulk synchronous parallel (BSP) | Pregel distributed programming framework | - -Since Fluid was designed to be a programming language, we would like to implement CSP in Fluid. - -### CSP v.s. Actor Model - -A well-known implementation of Actor Model is the Erlang programming language. In Actor Model, *processes* could send messages to another process and receive messages from another process given the process IDs. We can find the three ingredients, process with ID, send, and recv, in MPI too. Indeed, we can rewrite Erlang programs in Python + MPI with possibly fewer lines of code. Our concern with Actor Model is that it doesn't seem reasonable to implement process management in a programming language's runtime library; instead, it should be the operating systems' responsibility to manage processes and libraries like MPI for send/recv. - -## CSP in Fluid - -Fluid has two fundamental control-flows: *if-else* and *while*. If we are to implement CSP, we need the following: - -1. a new data type: *channel* and operators *send* and *recv*, -1. *goroutine* or thread, and -1. a new control-flow: select. - -We also need Python wrappers for the above components. - -The type *channel* is conceptually the blocking queue. In Go, its implemented is a [blocking circular queue](https://github.com/golang/go/blob/68ce117cf17b8debf5754bfd476345779b5b6616/src/runtime/chan.go#L31-L50), which supports send and recv. - -The `select` operation has been in OS kernels long before Go language. All Unix kernels implement system calls *poll* and *select*. They monitor multiple file descriptors to see if I/O is possible on any of them. This takes O(N) time. Since Linux 2.6, a new system call, *epoll*, can do the same in O(1) time. In BSD systems, there is a similar system call *kqueue*. Go's Linux implementation uses epoll. - -It might be a good idea to implement Fluid's select using epoll too. In this design doc, we start from the O(N) way so that we could focus on Python binding and the syntax. - -### Type Channel - -Fluid supports many data types: - -1. Tensor, -1. Row-sparse Tensor -1. LoD Tensor, -1. Tensor array, etc - -Each data type is registered in the [`framework.proto`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto#L117-L127) as an enum value. To add a new type channel, we need to add a new type enum. - -To expose a C++ type to Python, we need to edit the [`pybind.cc`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/pybind/pybind.cc) file. [Here](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/pybind/pybind.cc#L120-L164) is an example how we expose C++ class LoDTensor. - -## Syntax Design - -### Create Channel - -In Go, we create a channel by specifying the element type and buffer size: - -```go -ch := make(chan int) // a channel without buffer -ch1 := make(chan int, 100) // a channel that can buffer 100 ints. -``` - -In Fluid, we should be able to do the same: - -```python -ch = fluid.make_channel(dtype=INT) -ch1 = fluid.make_channel(dtype=INT, 100) -``` - -In addition to that, we want channels that can hold more complex element types, e.g., Tensors of float16: - -```python -ch = fluid.make_channel(dtype=Tensor, etype=float16) -``` - -or Tensors of Tensors of float16 etc. - -The point here is that we need a consistent way to compose types, like in C++ we can have `Tensor...> >`. - -### Send and Recv - -Go's CSP implementation depends on data type *channel*. There are two types of channels: - -1. The unblocked channel, or buffered channel, is a blocking queue with a non-zero sized buffer. The sending to buffered channel blocks if the buffer is full, and the receive operation blocks if the buffer is empty. -1. blocked channel, or unbuffered channel, is a blocking queue with no buffer. Both sending and receiving block with unbuffered channels. - -There are four types of actions with a channel: - -1. Create a channel - - ```go - ch := make(chan int) // this is an unbuffered channel - ch := make(chan int, 100) // this is a buffered channel of 100 ints. - ``` - -1. Send - - ```go - ch <- 111 - ``` - -1. Recv - - ```go - y, ok <- ch - ``` - -1. Close - - ```go - close(ch) - ``` - - Please be aware that a closed channel is not a nil channel, which is `var ch chan int`. - -There are some [axioms with channels](https://dave.cheney.net/2014/03/19/channel-axioms): - -1. A send to a nil channel blocks forever - -1. A receive from a nil channel blocks forever - -1. A send to a closed channel panics - -1. A receive from a closed channel returns the residual values and then zeros. - -In Fluid, we have [buffered channels](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/details/buffered_channel.h) and [unbuffered channels](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/details/unbuffered_channel.h) - -The following program illustrates the Python syntax for accessing Fluid buffers. - -```python -import fluid - -buffer_size = 10 -ch = fluid.make_channel(dtype=INT, buffer_size) - -# Now write three elements to the channel -with fluid.while(steps=buffer_size): - fluid.send(ch, step) - -fluid.close_channel(ch) - -with fluid.while(steps=buffer_size): - fluid.print(fluid.recv(ch)) -``` - -The following example shows that to avoid the always-blocking behavior of unbuffered channels, we need to use Fluid's goroutines. - -```python -import fluid - -ch = fluid.make_channel(dtype=INT) - -with fluid.go(): - fluid.send(ch) - -y = fluid.recv(ch) - -fluid.close_channel(ch) -``` - -### Select - -In Go, the `select` statement lets a goroutine wait on multiple communication operations. A `select` blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready. - -```go - -ch1 := make(chan int) -ch2 := make(chan int, 100) - -x := 0 - -for { - select { - case ch1 <- x: - x := x + 1 - case y <- ch2: - fmt.Println("Received on channel") - default: - fmt.Println("Default") - } - } - -``` - -In Fluid, we should be able to do the same: - -```python -ch1 = fluid.make_chan(dtype=INT) -ch2 = fluid.make_chan(dtype=INT, 100) - -sel = fluid.select() - -with sel.case(ch1, 'w', X): - fluid.layers.increment(X) - -with sel.case(ch2, 'r', Y): - fluid.print("Received on Channel") - -with sel.default(): - fluid.print("Default") - -``` - -In the above code snippet, `X` and `Y` are variables. Now let us look at each of these statements one by one. - -- `sel.case(ch1, 'w', X)` : This specifies that we are writing to `ch1` and we want to write the integer in variable `X` to the channel. The character `w` is used here to make the syntax familiar to write syntax in Python I/O. - -- `sel.case(ch2, 'r', Y)` : This specifies that we would like to read the result from `ch2` into variable `Y`. The character `r` is used here to make the syntax familiar to read syntax in Python I/O. - -- `sel.default()` : This is equivalent to the default in Go `select`. If none of the channels are ready for read or write, then the fluid code in the default block will be executed. - -## Example Programs - -### 1. RPC between Trainers and Parameter Servers - -### 2. Concurrent Minibatch Loading diff --git a/develop/doc/_sources/design/dist_refactor/distributed_architecture.md.txt b/develop/doc/_sources/design/dist_refactor/distributed_architecture.md.txt deleted file mode 100644 index 9368c5780dc..00000000000 --- a/develop/doc/_sources/design/dist_refactor/distributed_architecture.md.txt +++ /dev/null @@ -1,197 +0,0 @@ -# Design Doc: Distributed Training Architecture - -## Abstract - -PaddlePaddle version 0.10.0 uses the "trainer-parameter server" architecture. We run multiple instances of trainers (where each trainer runs the same model) and parameter servers for distributed training. This architecture serves well, but has few limitations: - -1. There is a need to write special code that handles tasks which should only be run on a single trainer. E.g., initializing the model, saving the model etc. - -2. Model parallelism is hard: It would need all the if-else branches conditioned on the trainer ID to partition the model onto the trainers, and eventually manually writing out the inter-model-shard communication code to communicate between different trainers. - -3. The user can not directly specify the parameter update rule: This would need to modify the parameter server code and compile a new binary. This makes things more complicated for researchers: A lot of extra effort is required to make this work. Besides, the training job submission program may not allow running arbitrary binaries. - -This design doc discusses PaddlePaddle's new distributed training architecture that addresses the above mentioned limitations. - -## Analysis - -The assumption is that the user writes the trainer program in either Python or C++. - -### Limitation 1 - -There are two basic functionalities in the trainer program: - -1. The training logic such as loading / saving the model and printing out the logs. -2. The neural network definition such as the definition of the data layer, the fully connected layer, the cost function and the - optimizer. - -When we train using PaddlePaddle v0.10.0 in a distributed fashion, multiple instances of the same Python code are run on different nodes, hence both: the -training logic as well as the neural network computation logic, is replicated. - -The tasks that only need to be run once belong to the training logic. Hence if we only replicate the neural network computation part, and do **not** -replicate the training logic, the limitation mentioned above can be avoided. - -### Limitation 2 - -Model parallelism means that a single model is partitioned into different components and each node runs one of the component separately. This comes at the extra cost of managing the -inter-model-shard communication between nodes. - -PaddlePaddle should ideally be able to modify the neural network computation and figure out the support for model parallelism automatically. However, the -computation is only specified in Python code which sits outside of PaddlePaddle, hence PaddlePaddle can not support the feature in this setup. - -Similar to how a compiler uses an intermediate representation (IR) so that the programmer does not need to manually optimize their code for most of the cases, we can have an intermediate representation in PaddlePaddle as well. The compiler optimizes the IR as follows: - - - -PaddlePaddle can support model parallelism by converting the IR so that the user no longer needs to manually perform the computation and operations in the Python component: - - - -The IR for PaddlePaddle after refactoring is called a `Block`, it specifies the computation dependency graph and the variables used in the computation. - -### Limitation 3 - -The user can not directly specify the parameter update rule for the parameter server in the Python module, since the parameter server does not use the same computation definition as the trainer. Instead, the update rule is baked inside the parameter server. The user can not specify the update rule explicitly. - -This could be fixed by making the parameter server also run an IR, which can be different to the trainer side -For a detailed explanation, refer to this document - -[Design Doc: Parameter Server](./parameter_server.md) - -## Distributed Training Architecture - -The revamped distributed training architecture can address the above discussed limitations. Below is the illustration of how it does so: - - - -The major components are: *Python API*, *Distribute Transpiler* and *Remote Executor*. - -### Python API - -Python API is the Python library that user's Python code invokes, to read the data, build the neural network topology, and start training, etc. - -```Python -images = fluid.layers.data(name='pixel', shape=[1, 28, 28], dtype='float32') -label = fluid.layers.data(name='label', shape=[1], dtype='int64') -... -predict = fluid.layers.fc(input=conv_pool_2, size=10, act="softmax") -cost = fluid.layers.cross_entropy(input=predict, label=label) -avg_cost = fluid.layers.mean(x=cost) -optimizer = fluid.optimizer.Adam(learning_rate=0.01) -optimizer.minimize(avg_cost) - -train_reader = paddle.batch( - paddle.reader.shuffle( - paddle.dataset.mnist.train(), buf_size=500), - batch_size=BATCH_SIZE) - -place = fluid.CPUPlace() -exe = fluid.Executor(place) - -for pass_id in range(10): - for data in train_reader(): - loss, acc = exe.run(trainer_prog, - feed=feeder.feed(data), - fetch_list=[avg_cost]) -``` - -The code above is a typical local training program, the "Training Program" is built using helper functions such as -`fluid.layer.fc`. The training is done by calling `Executor.run` -iteratively. - -For more details, the implementation of IR is [Program](../program.md), and `ProgramDesc` is the protobuf type. - -[Executor](../executor.md) simply runs the `ProgramDesc`. For local training you generally use -`Executor` to run the program locally. For any kind of distributed training, you can use -`RemoteExecutor` to specify desired distributed training method with some optional arguments. - -### Distributed Transpiler - -The Distributed Transpiler automatically converts the IR (in protobuf format) to partitioned IRs. Then -the Remote Executor dispatches the new IRs to Remote Executors across the cluster. -Below are the steps that are followed : - -1. User only need to change `Executor` to `RemoteExecutor` to change local program to distributed program. -1. `RemoteExecutor` calls `Distributed Transpiler` to "transpile" user's program to several IRs representing a - distributed training program: - 1. Parse configurations from `RemoteExecutor`. - 1. Determine the type of distributed program, can be DataParallelism, ModelParallelism or Streaming. - 1. Partition the `ProgramDesc` according to type and add `send` / `recv` OP pair on the boundaries. Take - DataParallelism type for example, it removes the optimization operators and add a `send` OP to the - "trainer" role, then add the optimization operators to the parameter server role within the `recv` OP. -1. Dispatch the partitioned graph to different `RemoteExecutor` in the cluster. -1. `RemoteExecutor` on each node run the received `ProgramDesc` utill the end. - - -### RemoteExecutor - -As shown in the graph, `RemoteExecutor.run` sends the IR to the cluster for Execution. -You can also use parameter `fetch_list` to interactively fetch variable back to local for -log printing. - -The Python `RemoteExecutor` is derived from `Executor` class. - -```python -exe = RemoteExecutor( - feed=feeder.feed(data), - fetch_list=[avg_cost], - job_desc=JobDesc( - jobname, - num_trainer, - num_pserver, - cpu_per_trainer, - gpu_per_trainer, - mem_per_trainer, - cpu_per_pserver, - mem_per_pserver - )) -for data in train_reader(): - loss, acc = exe.run(trainer_prog, - feed=feeder.feed(data), - fetch_list=[avg_cost]) -``` - -`JobDesc` object describe the distributed job resource specification to run on -Cluster environment. - - - -`RemoteExecutor.run` sends the `ProgramDesc` and -[TrainingJob](https://github.com/PaddlePaddle/cloud/blob/develop/doc/autoscale/README.md#training-job-resource) -to a server in the cluster which executes `RemoteExecutor.listen`. This server is responsible -to start the final Kubernetes Jobs to run the different role of `ProgramDesc` from `ConfigMap`. - - -### Placement Algorithm - -Our first implementation will only support "trainer-parameter server" placement: the parameters, initializers, and optimizers are all placed on the PaddlePaddle runtimes with the parameter server role. Everything else will be placed on the PaddlePaddle runtimes with the trainer role. This has the same functionality as the "trainer-parameter server" architecture of PaddlePaddle v0.10.0, but is more generic and flexible. - -In the future, a more general placement algorithm should be implemented, which makes placements according to the input IR, and a model of device computation time and device communication time. Model parallelism requires the generic placement algorithm. - - -### Local Training Architecture - -The local training architecture will be the same as the distributed training architecture, the difference is that everything runs locally, and there is just one PaddlePaddle runtime: - - - - -### Training Data - -In PaddlePaddle v0.10.0, training data is typically read -with [data reader](../reader/README.md) from Python. This approach is -no longer efficient when training distributedly since the Python -process no longer runs on the same node with the trainer processes, -the Python reader will need to read from the distributed filesystem -(assuming it has the access) and send to the trainers, doubling the -network traffic. - -When doing distributed training, the user can still use Python data -reader: the training data are sent with `Executor.run`. However, should -be used for debugging purpose only. The users are encouraged to use -the read data OPs. - - -## References: - -[1] [TensorFlow: Large-Scale Machine Learning on Heterogeneous Distributed Systems](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45166.pdf) - -[2] [TensorFlow: A System for Large-Scale Machine Learning](https://www.usenix.org/system/files/conference/osdi16/osdi16-abadi.pdf) diff --git a/develop/doc/_sources/design/dist_refactor/multi_cpu.md.txt b/develop/doc/_sources/design/dist_refactor/multi_cpu.md.txt deleted file mode 100644 index a8d8ee0422a..00000000000 --- a/develop/doc/_sources/design/dist_refactor/multi_cpu.md.txt +++ /dev/null @@ -1,43 +0,0 @@ -# Design Doc: Execute the Program with Multi CPU - -## Abstract - -This Design Doc propose an approach to make the user-defined Op graph -running with multi-CPU, we will use an auto transpiler to convert the user-defined -Op graph to a multi-CPU Op graph, and run `ParallelDo` Op to run the graph. - -## Transpiler - - - -After converted: - - - -## Implement - -- `Multi-CPU Transpiler` will convert the graph to a multi-CPU graph - which would be executed with multi-threads. -- `BlockingCounter` will `Init/Decrement` an atomic counter, and Blocking `Wait` - for the atomic counter become `0`: - ```cpp - BlockingCounter bc(thread_count); - for (int i = 0; i < thread_count; ++i) { - thread_pool->Start([&bc] {bc.DecrementCount(); }) - } - bc.Wait(); - ``` -- `ParallelDo` Operator - - Initialize a thread pool which is a Singleton. - - Use a block id as the input, and create run the specify Block on independent scope - with multi-threads. - - Initialize a `BlockingCounter` instance and wait until all threads are done. -- `Split` Operator will split the Input Tensor into a TensorArray. -- `Merge` merge all the gradients which calculated in different threads - with `mean/sum/max/min...` method, and then run the Optimizer Op to optimize `W`. - -## TODO - -- Improve the optimizer stage with multi-threads, since we could - assign the parameters to the different threads and execute - optimizer with multi-threads. diff --git a/develop/doc/_sources/design/dist_refactor/parameter_server.md.txt b/develop/doc/_sources/design/dist_refactor/parameter_server.md.txt deleted file mode 100644 index 805dd13048d..00000000000 --- a/develop/doc/_sources/design/dist_refactor/parameter_server.md.txt +++ /dev/null @@ -1,96 +0,0 @@ -# Design Doc: Parameter Server - -## Abstract - -We propose an approach to implement the parameter server. In this -approach, there is no fundamental difference between the trainer and -the parameter server: they both run subgraphs, but subgraphs of -different purposes. - -## Background - -The previous implementations of the parameter server do not run a -fluid sub-program. Parameter initialization, optimizer computation, network -communication and checkpointing are implemented twice on both the -trainer as well as the parameter server. - -It would be great if we can write code once and use them on both: the -trainer and the parameter server, since this reduces code duplication and -improves extensibility. Given that after the current refactoring, we are -representing everything as a computation graph on the -trainer. Representing everything as a computation graph on the parameter -server becomes a natural extension. - -## Design - -### Distributed Transpiler - -The *Distributed Transpiler* converts the user-defined fluid program -into sub-programs to be scheduled on different nodes with the following -steps: - -1. OP placement: the OPs will be placed on different nodes according - to a heuristic that minimizes the estimated total computation - time. Currently we will use a simple heuristic that puts parameter - variable on parameter server workers and everything else on trainer - workers. -1. Add communication OPs to enable the communication between nodes. - -We will need these OPs: *Send*, *Recv*, *Enqueue*, *Dequeue*. - -Below is an example of converting the user defined graph to the -subgraphs for the trainer and the parameter server: - - - -After converting: - - - -1. The parameter variable W and its optimizer program are placed on the parameter server. -1. Operators are added to the program. - - *Send* sends data to the connected *Recv* operator. The - scheduler on the receive node will only schedule *Recv* operator - to run when the *Send* operator has ran (the *Send* OP will mark - the *Recv* OP runnable automatically). - - *Enqueue* enqueues the input variable, it can block until space - become available in the queue. - - *Dequeue* outputs configurable numbers of tensors from the - queue. It will block until the queue has the required number of - tensors. - - -### Benefits - -- Model parallelism becomes easier to implement: it is an extension to - the trainer - parameter server approach. We can have several "Transpilers" - to achieve different goals. -- User-defined optimizer is easier to add - user can now express it as - a sub-program. -- No more duplication logic inside the trainer and the parameter - server mentioned in the background section. - -### Challenges - -- It is important to balance the parameter shards on multiple - parameter servers. If a single parameter is very big (for example: some - word-embedding, fully connected, softmax layer), we need to - automatically partition the single parameter onto different - parameter servers when possible (only element-wise optimizer depends - on the parameter variable). -- In the "Async SGD" figure, the "W" variable on the parameter server - could be read and written concurrently. See - [here](https://github.com/PaddlePaddle/Paddle/pull/6394) for more - details about concurrent program in Fluid. - -### Discussion - -- Can the Enqueue OP be implemented under our current tensor design - (put the input tensor into the queue tensor)? -- *Dequeue* OP will have variable numbers of output (depending on the - `min_count` attribute), does our current design support it? (similar - question for the *Add* OP) - - -### References: -[1] [TensorFlow: Large-Scale Machine Learning on Heterogeneous Distributed Systems](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45166.pdf) diff --git a/develop/doc/_sources/design/error_clip.md.txt b/develop/doc/_sources/design/error_clip.md.txt deleted file mode 100644 index 58aa73b8cd3..00000000000 --- a/develop/doc/_sources/design/error_clip.md.txt +++ /dev/null @@ -1,92 +0,0 @@ -# Error Clip - -## Overview - -Error clip is widely used in model training to prevent gradient exploding. It takes some specific rules to adjust variables' gradients and prevent them from being too large. With it, values of a gradient will be checked before they are taken by the next `grad_op` and be shrunk if necessary. -## Usage - -Users are allowed to assign different error clip methods or attributes to different `Variable`s. Users can specify it as a parameter of `Variable`'s constructor: - -```python -var = framework.Variable(..., error_clip=myErrorClip, ...) -``` - -The default value of `error_clip` is `None`, which means no error clip is employed. When it's not `None`, it should take an object of `BaseErrorClipAttr`'s derived class. So far, `BaseErrorClipAttr` has only one derived class: `ErrorClipByValue`, whose constructor is: - -```python -ErrorClipByValue(max, min=None) -``` - -`max` and `min` represent the maximal and minimal clip threshold respectively. In backward pass, all values of `var`'s gradient greater than `max` or less than `min` will be clipped to `max` and `min` respectively. When the `min` is None, the minimal threshold will be assigned with `-max` automatically. - -So we can enable the error clip with threshold `[-5.0, 5.0]` for variable `var` by: - -```python -var = framework.Variable(..., error_clip=ErrorClipByValue(max=5.0), ...) -``` - -## Implementation - -The `BaseErrorClipAttr` and its derived class `ErrorClipByValue` are defined in *clip.py*. - -```python -class BaseErrorClipAttr(object): - def append_clip_op(self, block, grad_name): - raise NotImplementedError() - - -class ErrorClipByValue(BaseErrorClipAttr): - def __init__(self, max, min=None): - max = float(max) - if min is None: - min = -max - else: - min = float(min) - self.max = max - self.min = min - - def append_clip_op(self, block, grad_name): - clip_op_desc = block.desc.append_op() - clip_op_desc.set_type("clip") - clip_op_desc.set_input("X", [grad_name]) - clip_op_desc.set_output("Out", [grad_name]) - clip_op_desc.set_attr("min", self.min) - clip_op_desc.set_attr("max", self.max) -``` - -The `BaseErrorClipAttr` have one main member functions: `append_clip_op(self, block, grad_name)`. - -This function is used to create a `clip_op` and append it to the end of given `block`. For different error clip algorithm require different `clip_op`, the function is defined as virtual in the base class. All derived classes must implement their own versions of this function. - -These `clip_op`s should be inserted after `grad_op`s whose output gradients need to be clipped. It is equivalent to appending some `clip_op`s to the end of the target block every time a new `grad_op` is added. - -```python -for op_desc in grad_op_descs: - new_op_desc = target_block.desc.append_op() - new_op_desc.copy_from(op_desc) - callback(block=target_block, context=grad_to_var) -``` - -Here we employ a callback function to complete this kind of jobs. In `_append_backward_ops_` function, each time after a `grad_op` is added to the `target_block`, a callback function is invoked. The logic of `clip_op` appending can be implemented inside the callback function. - -The callback function for `clip_op` appending is defined in *clip.py*: - -```python -def error_clip_callback(block, context): - # the context is a grad_to_var map - grad_to_var = context - op_desc = block.desc.op(block.desc.op_size() - 1) - for grad_n in filter(lambda n: grad_to_var.has_key(n), - op_desc.output_arg_names()): - fwd_var = block.var_recursive(grad_to_var[grad_n]) - error_clip = getattr(fwd_var, "error_clip", None) - if not (error_clip is None or isinstance(error_clip, - BaseErrorClipAttr)): - raise TypeError( - "Variable's error_clip should be an instance of BaseErrorClipAttr or None." - ) - if error_clip is not None: - error_clip.append_clip_op(block, grad_n) -``` - -This function takes a `block` and a `context`(which is actually a grad\_to\_var map) as inputs. It checks each output of the last `OpDesc` in the `block`. Notice that the last `OpDesc` of the `block` must be a `grad_op` and its outputs must be some forward variables' gradients. If an output gradient's corresponding forward variable has an attribute of `error_clip`, `error_clip_callback` will call the `error_clip`'s `append_clip_op` function to append the required `clip_op` into the `block`. diff --git a/develop/doc/_sources/design/evaluator.md.txt b/develop/doc/_sources/design/evaluator.md.txt deleted file mode 100644 index 11cc129d569..00000000000 --- a/develop/doc/_sources/design/evaluator.md.txt +++ /dev/null @@ -1,58 +0,0 @@ -## Evaluator Design - -### Problem Statement - -During training or inference, we provide an evaluation function to measure the model performance, for example, accuracy, precision, etc. In the operator based framework design, the data passes through the network pipeline batch by batch. As a result, inside the operator, we only calculate the metrics for one minibatch. Thus, we need to provide a mechanism to calculate the metrics for each N pass/batch the user wants. - -### Evaluator Design -Currently, every operation is expressed in the graph. We divide the evaluator process into three steps. - -1. Initialize the metric state and add it into the block. - -2. Calculate the concerned metrics for every mini-batch. The single evaluator operator is only responsible for calculating the necessary statistics for one mini-batch. For example, the accuracy operator only calculates the accuracy for a minibatch data if run once. - - -3. Merge the mini-batch statistics to form the evaluation result for multiple mini-batches. When it comes to distributed training/Multi-GPU training, aggregate the value from different devices. - -### Implementation -This design is shown in the Python API. -Each metric operator needs to caculate the metric statistic and return the batch-aware states. Python side is responsible for accumulating the states for each pass. - - -```python -class Evaluator(object): - """ - Evaluator Base class. - """ - def __init__(self, name, **kwargs): - """ - Different evaluator may has different metric states. E.g, Accuracy need two variables, total and right sample counts. - Auc need four variables, `true_positives`, - `true_negatives`, `false_positives` and `false_negatives`. So every evaluator should create its needed variables and append to main_program - - The initialization of Evaluator should be responsible for: - create metric states and append to the main_program - """ - pass - - def _update_ops(self, input, label, **kwargs) - """ - Add mini-batch evaluator caculate operators to the main_program. - Add increment operator to accumulate the metric states. - """ - - - def reset(self, executor, reset_program=None): - """ - Reset metric states at the begin of each pass/user specified batch number. - Execute the reset_program to reset the states. - """ - - - def eval(self, executor, eval_program=None): - """ - Merge the mini-batch statistics to form the evaluation result for multiple mini-batches. - Execute the eval_program and return the result. - """ - return eval_result -``` diff --git a/develop/doc/_sources/design/executor.md.txt b/develop/doc/_sources/design/executor.md.txt deleted file mode 100644 index 2d4b371cc56..00000000000 --- a/develop/doc/_sources/design/executor.md.txt +++ /dev/null @@ -1,29 +0,0 @@ -# Executor Design Doc - -## Motivation -In [fluid](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/fluid.md), we encourage the user to use deep learning programming paradigms to describe the training process. When the user-written Python program is executed, it will first create a protobuf message -[`ProgramDesc`](https://github.com/PaddlePaddle/Paddle/blob/a91efdde6910ce92a78e3aa7157412c4c88d9ee8/paddle/framework/framework.proto#L145) that describes the process and is conceptually like an [abstract syntax tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree). - -The executor runs the `ProgramDesc` like an interpreter. `ProgramDesc` contains the intrinsics (operators in this case) and variables which will be used, executor explicitly executes the stored precompiled code. - -## Overview - -An executor takes a `ProgramDesc`, a `block_id` and a `Scope`. The `ProgramDesc` is a list of blocks and each block contains the protobuf definition of all the parameters and operators in the block. The `block_id` specifies the entrance block. And the `Scope` is the container of all the variable instances, which is persistent throughout different runs. - -## Executor - -The `Executor` explicitly executes all the intrinsics (operators here) in the `block_id`th block of a `ProgramDesc`. Essentially, it instantiates Variables and Operators, then runs all the operators in sequence one-by-one. -It is very similar to how a push stack frame works when entering a block, following which it cleans up all the temporary variables when a mini-batch is finished. It does not however, have the stack frame pop process. - -### The interface -```c++ - Executor(places); -``` -A executor does not own any computing resources, a user can only construct an executor using the specified places. - -### Running an Executor - -``` - void Run(ProgramDesc, Scope, block_id, create_local_scope); -``` -An `Executor` only provides a unified way to execute `ProgramDesc`. `ProgramDesc` is the target that will be executed, the `Scope` specifies the variable container, the `block_id` indicates the entrance block and `create_local_scope` is a boolean that states whether it will destroy the temporary variables after the execution is finished. diff --git a/develop/doc/_sources/design/file_manager/README.md.txt b/develop/doc/_sources/design/file_manager/README.md.txt deleted file mode 100644 index 3df10d801e5..00000000000 --- a/develop/doc/_sources/design/file_manager/README.md.txt +++ /dev/null @@ -1,87 +0,0 @@ -# FileManager设计文档 -## 目标 -在本文档中,我们设计说明了名为FileManager系统,方便用户上传自己的训练数据以进行分布式训练 - -主要功能包括: - -- 提供常用的命令行管理命令管理文件和目录 -- 支持大文件的断点上传、下载 - -## 名词解释 -- PFS:是`Paddlepaddle cloud File System`的缩写,是对用户文件存储空间的抽象,与之相对的是local filesystem。目前我们用CephFS来搭建。 -- [CephFS](http://docs.ceph.com/docs/master/cephfs/):一个POSIX兼容的文件系统。 -- Chunk:逻辑划上文件分块的单位。 - -## 模块 -### 架构图 - - -### PFSClient -- 功能: 详细设计[link](./pfs/pfsclient.md) - - 提供用户管理文件的命令 - - 需要可以跨平台执行 - -- 双向验证 - PFSClient需要和Ingress之间做双向验证[tls](#tls),所以用户需要首先在`cloud.paddlepaddle.org`上注册一下,申请用户空间,并且把系统生成的CA(certificate authority)、Key、CRT(CA signed certificate)下载到本地,然后才能使用PFSClient。 - -### [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) -- 功能: - 提供七层协议的反向代理、基于粘性会话的负载均衡功能。 - -- 透传用户身份的办法 - Ingress需要把PFSClient的身份信息传给PFSServer,配置的方法参考[link](http://www.integralist.co.uk/posts/clientcertauth.html#3) - -### PFSServer -PFSServer提供RESTful API接口,接收处理PFSClient端的文件管理请求,并且把结果返回PFSClient端。 - -RESTful API - -- /api/v1/files - - `GET /api/v1/files`: Get metadata of files or directories. - - `POST /api/v1/files`: Create files or directories. - - `PATCH /api/v1/files`: Update files or directories. - - `DELETE /api/v1/files`: Delete files or directories. - -- /api/v1/file/chunks - - `GET /api/v1/storage/file/chunks`: Get chunks's metadata of a file. - -- /api/v1/storage/files - - `GET /api/v1/storage/files`: Download files or directories. - - `POST /api/v1/storage/files`: Upload files or directories. - -- /api/v1/storage/file/chunks - - `GET /api/v1/storage/file/chunks`: Download chunks's data. - - `POST /api/v1/storage/file/chunks`: Upload chunks's data. - -## 文件传输优化 - -### 分块文件传输 -用户文件可能是比较大的,上传到Cloud或者下载到本地的时间可能比较长,而且在传输的过程中也可能出现网络不稳定的情况。为了应对以上的问题,我们提出了Chunk的概念,一个Chunk由所在的文件偏移、数据、数据长度及校验值组成。文件的上传和下载都是通过对Chunk的操作来实现的。由于Chunk比较小(默认256K),完成一个传输动作完成的时间也比较短,不容易出错。PFSClient需要在传输完毕最后一个Chunk的时候检查destination文件的MD5值是否和source文件一致。 - -一个典型的Chunk如下所示: - -``` -type Chunk struct { - fileOffset int64 - checksum uint32 - len uint32 - data []byte -} -``` - -### 生成sparse文件 -当destination文件不存在或者大小和source文件不一致时,可以用[Fallocate](https://Go.org/pkg/syscall/#Fallocate)生成sparse文件,然后就可以并发写入多个Chunk。 - -### 覆盖不一致的部分 -文件传输的的关键在于需要PFSClient端对比source和destination的文件Chunks的checksum是否保持一致,不一致的由PFSClient下载或者传输Chunk完成。这样已经传输成功的部分就不用重新传输了。 - -## 用户使用流程 -参考[link](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/cluster_train/data_dispatch.md) - -## 框架生成 -用[swagger](https://github.com/swagger-api/swagger-codegen)生成PFSClient和PFSServer的框架部分,以便我们可以把更多的精力放到逻辑本身上。 - -## 参考文档 --
[TLS complete guide](https://github.com/k8sp/tls/blob/master/tls.md) -- [aws.s3](http://docs.aws.amazon.com/cli/latest/reference/s3/) -- [linux man document](https://linux.die.net/man/) diff --git a/develop/doc/_sources/design/file_manager/pfs/pfsclient.md.txt b/develop/doc/_sources/design/file_manager/pfs/pfsclient.md.txt deleted file mode 100644 index 56bc70c54bb..00000000000 --- a/develop/doc/_sources/design/file_manager/pfs/pfsclient.md.txt +++ /dev/null @@ -1,129 +0,0 @@ -# PFSClient - -## Description -The `pfs` command is a Command Line Interface to manage your files on PaddlePaddle Cloud - -## Synopsis -``` -paddle [options] pfs [parameters] -``` - -## Options -``` ---profile (string) - Use a specific profile from your credential file. - ---help (string) - Display more information about command - ---version - Output version information and exit - ---debug - Show detailed debugging log - ---only-show-errors (boolean) - Only errors and warnings are displayed. All other output is suppressed. -``` - -## Path Arguments -When using a command, we need to specify path arguments. There are two path argument type: `localpath` and `pfspath`. - -A `pfspath` begin with `/pfs`, eg: `/pfs/$DATACENTER/home/$USER/folder`. - -[Here](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/cluster_train/data_dispatch.md#上传训练文件) is how to config datacenters. - -## order of Path Arguments -Commonly, if there are two path arguments, the first is the source, and the second is the destination. - -## Subcommonds -- rm - remove files or directories - -``` -Synopsis: - rm [-r] [-v] ... - -Options: - -r - Remove directories and their contents recursively - -v - Cause rm to be verbose, showing files after they are removed. - -Examples: - paddle pfs rm /pfs/$DATACENTER/home/$USER/file - paddle pfs rm -r /pfs/$DATACENTER/home/$USER/folder -``` -- mv - move (rename) files - -``` -Synopsis: - mv [-f | -n] [-v] - mv [-f | -n] [-v] ... - mv [-f | -n] [-v] - mv [-f | -n] [-v] ... - mv [-f | -n] [-v] - mv [-f | -n] [-v] ... - -Options: - -f - Do not prompt for confirmation before overwriting the destination path. (The -f option overrides previous -n options.) - -n - Do not overwrite an existing file. (The -n option overrides previous -f options.) - -v - Cause mv to be verbose, showing files after they are moved. - -Examples: - paddle pfs mv ./text1.txt /pfs/$DATACENTER/home/$USER/text1.txt -``` -- cp - copy files or directories - -``` -Synopsis: - cp [-r] [-f | -n] [-v] [--preserve--links] - cp [-r] [-f | -n] [-v] [--preserve--links] ... - cp [-r] [-f | -n] [-v] [--preserve--links] - cp [-r] [-f | -n] [-v] [--preserve--links] ... - cp [-r] [-f | -n] [-v] [--preserve--links] - cp [-r] [-f | -n] [-v] [--preserve--links] ... - -Options: - -r - Copy directories recursively - -f - Do not prompt for confirmation before overwriting the destination path. (The -f option overrides previous -n options.) - -n - Do not overwrite an existing file. (The -n option overrides previous -f options.) - -v - Cause cp to be verbose, showing files after they are copied. - --preserve--links - Reserve links when copy links - -Examples: - paddle pfs cp ./file /pfs/$DATACENTER/home/$USER/file - paddle pfs cp /pfs/$DATACENTER/home/$USER/file ./file -``` -- ls- list files - -``` -Synopsis: - ls [-r] ... - -Options: - -R - List directory(ies) recursively - -Examples: - paddle pfs ls /pfs/$DATACENTER/home/$USER/file - paddle pfs ls /pfs/$DATACENTER/home/$USER/folder -``` - -- mkdir - mkdir directory(ies) -Create intermediate directory(ies) as required. - -``` -Synopsis: - mkdir ... - -Examples: - paddle pfs mkdir /pfs/$DATACENTER/home/$USER/folder -``` diff --git a/develop/doc/_sources/design/float16.md.txt b/develop/doc/_sources/design/float16.md.txt deleted file mode 100644 index 1ea95ed6b5d..00000000000 --- a/develop/doc/_sources/design/float16.md.txt +++ /dev/null @@ -1,105 +0,0 @@ -# Design Doc: float16 - -## Why float16 -Half precision (float16) is a binary floating-point format that occupies 16 bits in memory. float16 is half the size of traditional 32-bit single precision format (float) and has lower precision and smaller range. - -When high precision computation is not required, using float16 data type could potentially - -- reduce storage space, memory bandwidth, and power usages; -- increase the chance of data fitting into a smaller cache of lower latency; -- provide arithmetic speed up if supported by hardware. - -## Survey of current float16 support -A brief survey of float16 support on different compilers, hardwares, and libraries can be found below. Interested readers can refer to [link1](https://github.com/PaddlePaddle/Paddle/issues/4853) and [link2](https://github.com/Xreki/Xreki.github.io/blob/master/multi_data_types_in_dl_framework/ppt/float16_and_quantized_type.md) for more info. - -The goal of float16 is to serve as a key for the executor to find and run the correct version of compute method specialized for float16 in operator kernel. It should be compatible with various natively supported float16 implementations including `__half` for cuda, `float16_t` for ARM, and `Eigen::half` for Eigen to make writing customized float16 kernels easier. - -### Compiler -- nvcc supports `__half` data type after CUDA 7.5. -- `__fp16` or `float16_t` is supported as storage type for gcc >= 6.1 and clang >= 3.4. -- `__fp16` or `float16_t` is supported as arithmetic type for gcc >= 7.1 and clang >= 3.9. - -### Hardware -- `__half` is supported on GPU with compute capability >= 5.3. -- `__fp16` is supported as storage type for ARMv7-A, ARMv8-A, and above. -- `__fp16` is supported as arithmetic type after ARMv8.2-A (currently, the only microarchitecture implementing ARMv8.2-A is ARM Cortex-A75, which is announced in May 2017. There seems to be no application processors currently available on market that adopts this architecture. It is reported that Qualcomm Snapdragon 845 uses Cortex-A75 design and will be available in mobile devices in early 2018). - -### Libraries -- [Eigen](https://github.com/RLovelett/eigen) >= 3.3 supports float16 calculation on both GPU and CPU using the `Eigen::half` class. It is mostly useful for Nvidia GPUs because of the overloaded arithmetic operators using cuda intrinsics. It falls back to using software emulation on CPU for calculation and there is no special treatment to ARM processors. -- [ARM compute library](https://github.com/ARM-software/ComputeLibrary) >= 17.02.01 supports NEON FP16 kernels (requires ARMv8.2-A CPU). - -### CUDA version issue -There are currently three versions of CUDA that supports `__half` data type, namely, CUDA 7.5, 8.0, and 9.0. -CUDA 7.5 and 8.0 define `__half` as a simple struct that has a `uint16_t` data (see [`cuda_fp16.h`](https://github.com/ptillet/isaac/blob/9212ab5a3ddbe48f30ef373f9c1fb546804c7a8c/include/isaac/external/CUDA/cuda_fp16.h)) as follows: -``` -typedef struct __align__(2) { - unsigned short x; -} __half; - -typedef __half half; -``` -This struct does not define any overloaded arithmetic operators. So you have to directly use `__hadd` instead of `+` to correctly add two half types: -``` -__global__ void Add() { - half a, b, c; - c = __hadd(a, b); // correct - c = a + b; // compiler error: no operator "+" matches these operands -} -``` -CUDA 9.0 provides a major update to the half data type. The related code can be found in the updated [`cuda_fp16.h`](https://github.com/ptillet/isaac/blob/master/include/isaac/external/CUDA/cuda_fp16.h) and the newly added [`cuda_fp16.hpp`](https://github.com/ptillet/isaac/blob/master/include/isaac/external/CUDA/cuda_fp16.hpp). - -Essentially, CUDA 9.0 renames the original `__half` type in 7.5 and 8.0 as `__half_raw`, and defines a new `__half` class type that has constructors, conversion operators, and also provides overloaded arithmetic operators such as follows: -``` -typedef struct __CUDA_ALIGN__(2) { - unsigned short x; -} __half_raw; - - -struct __CUDA_ALIGN__(2) __half { -protected: - unsigned short __x; -public: - // constructors and conversion operators from/to - // __half_raw and other built-in data types -} - -typedef __half half; - -__device__ __forceinline__ -__half operator+(const __half &lh, const __half &rh) { - return __hadd(lh, rh); -} - -// Other overloaded operators -``` -This new design makes `c = a + b` work correctly for CUDA half data type. - -## Implementation -The float16 class holds a 16-bit `uint16_t` data internally. -``` -struct float16 { - uint16_t x; -}; -``` - -float16 supports the following features: - - constructors / assignment operators that take input from primitive data types including bool, integers of various length, float, and double. - - constructors / assignment operators that take input from `__half` on cuda, `float16_t` on ARM, and `Eigen::half` on Eigen. - - conversion operators to primitive data types and half precision data types on cuda, ARM and Eigen. - - overloaded arithmetic operators for cuda, arm, and non-arm cpu, respectively. These operators will take advantage of the cuda and ARM intrinsics on the corresponding hardware. - -To support the above features, two fundamental conversion functions are provided: -``` -float16 float_to_half_rn(float f); // convert to half precision in round-to-nearest-even mode -float half_to_float(float16 h); -``` -which provides one-to-one conversion between float32 and float16. These twos functions will do different conversion routines based on the current hardware. CUDA/ARM instrinsics will be used when the corresonding hardware is available. If the hardware or compiler level does not support float32 to float16 conversion, software emulation will be performed to do the conversion. - -## To do -After float16 class is available, some of the future items are below: - -- Update pybind/tensor_py.h to bind c++ float16 with numpy float16. - -- Modify `GetKernelType()` method in `framework/operator.h` to make it compatible with float16. - -- Create a type-casting operator that can convert the data type in tensor between float16 and other types. diff --git a/develop/doc/_sources/design/fluid.md.txt b/develop/doc/_sources/design/fluid.md.txt deleted file mode 100644 index f78fa8c1914..00000000000 --- a/develop/doc/_sources/design/fluid.md.txt +++ /dev/null @@ -1,114 +0,0 @@ -# Design Doc: PaddlePaddle Fluid - -## Why Fluid - -When Baidu developed PaddlePaddle in 2013, the only well-known open source deep learning system at the time was Caffe. However, when PaddlePaddle was open-sourced in 2016, many other choices were available. There was a challenge -- what is the need for open sourcing yet another deep learning framework? - -Fluid is the answer. Fluid is similar to PyTorch and TensorFlow Eager Execution, which describes the "process" of training or inference using the concept of a model. In fact in PyTorch, TensorFlow Eager Execution and Fluid, there is no concept of a model at all. The details are covered in the sections below. Fluid is currently more extreme in the above mentioned idea than PyTorch and Eager Execution, and we are trying to push Fluid towards the directions of a compiler and a new programming language for deep learning. - -## The Evolution of Deep Learning Systems - -Deep learning infrastructure is one of the fastest evolving technologies. Within four years, there have already been three generations of technologies invented. - -| Existed since | model as sequence of layers | model as graph of operators | No model | -|--|--|--|--| -| 2013 | Caffe, Theano, Torch, PaddlePaddle | | | -| 2015 | | TensorFlow, MxNet, Caffe2, ONNX, n-graph | | -| 2016 | | | PyTorch, TensorFlow Eager Execution, PaddlePaddle Fluid | - -From the above table, we see that the deep learning technology is evolving towards getting rid of the concept of a model. To understand the reasons behind this direction, a comparison of the *programming paradigms* or the ways to program deep learning applications using these systems, would be helpful. The following section goes over these. - -## Deep Learning Programming Paradigms - -With the systems listed as the first or second generation, e.g., Caffe or TensorFlow, an AI application training program looks like the following: - -```python -x = layer.data("image") -l = layer.data("label") -f = layer.fc(x, W) -s = layer.softmax(f) -c = layer.mse(l, s) - -for i in xrange(1000): # train for 1000 iterations - m = read_minibatch() - forward({input=x, data=m}, minimize=c) - backward(...) - -print W # print the trained model parameters. -``` - -The above program includes two parts: - -1. The first part describes the model, and -2. The second part describes the training process (or inference process) for the model. - -This paradigm has a well-known problem that limits the productivity of programmers. If the programmer made a mistake in configuring the model, the error messages wouldn't show up until the second part is executed and `forward` and `backward` propagations are performed. This makes it difficult for the programmer to debug and locate a mistake that is located blocks away from the actual error prompt. - -This problem of being hard to debug and re-iterate fast on a program is the primary reason that programmers, in general, prefer PyTorch over the older systems. Using PyTorch, we would write the above program as following: - -```python -W = tensor(...) - -for i in xrange(1000): # train for 1000 iterations - m = read_minibatch() - x = m["image"] - l = m["label"] - f = layer.fc(x, W) - s = layer.softmax(f) - c = layer.mse(l, s) - backward() - -print W # print the trained model parameters. -``` - -We can see that the main difference is the moving the model configuration part (the first step) into the training loop. This change would allow the mistakes in model configuration to be reported where they actually appear in the programming block. This change also represents the model better, or its forward pass, by keeping the configuration process in the training loop. - -## Describe Arbitrary Models for the Future - -Describing the process instead of the model also brings Fluid, the flexibility to define different non-standard models that haven't been invented yet. - -As we write out the program for the process, we can write an RNN as a loop, instead of an RNN as a layer or as an operator. A PyTorch example would look like the following: - -```python -for i in xrange(1000): - m = read_minibatch() - x = m["sentence"] - for t in xrange x.len(): - h[t] = the_step(x[t]) -``` - -With Fluid, the training loop and the RNN in the above program are not really Python loops, but just a "loop structure" provided by Fluid and implemented in C++ as the following: - -```python -train_loop = layers.While(cond) -with train_loop.block(): - m = read_minibatch() - x = m["sentence"] - rnn = layers.While(...) - with rnn.block(): - h[t] = the_step(input[t]) -``` - -An actual Fluid example is described [here](https://github.com/PaddlePaddle/Paddle/blob/bde090a97564b9c61a6aaa38b72ccc4889d102d9/python/paddle/fluid/tests/unittests/test_while_op.py#L50-L58). - -From the example, the Fluid programs look very similar to their PyTorch equivalent programs, except that Fluid's loop structure, wrapped with Python's `with` statement, could run much faster than just a Python loop. - -We have more examples of the [`if-then-else`](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/if_else_op.md) structure of Fluid. - -## Turing Completeness - -In computability theory, a system of data-manipulation rules, such as a programming language, is said to be Turing complete if it can be used to simulate any Turing machine. For a programming language, if it provides if-then-else and loop, it is Turing complete. From the above examples, Fluid seems to be Turing complete; however, it is noteworthy to notice that there is a slight difference between the `if-then-else` of Fluid and that of a programming language. The difference being that the former runs both of its branches and splits the input mini-batch into two -- one for the True condition and another for the False condition. This hasn't been researched in depth if this is equivalent to the `if-then-else` in programming languages that makes them Turing-complete. Based on a conversation with [Yuang Yu](https://research.google.com/pubs/104812.html), it seems to be the case but this needs to be looked into in-depth. - -## The Execution of a Fluid Program - -There are two ways to execute a Fluid program. When a program is executed, it creates a protobuf message [`ProgramDesc`](https://github.com/PaddlePaddle/Paddle/blob/a91efdde6910ce92a78e3aa7157412c4c88d9ee8/paddle/framework/framework.proto#L145) that describes the process and is conceptually like an [abstract syntax tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree). - -There is a C++ class [`Executor`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/executor.h), which runs a `ProgramDesc`, similar to how an interpreter runs a Python program. - -Fluid is moving towards the direction of a compiler, which is explain in [fluid_compiler.md](fluid_compiler.md). - -## Backward Compatibility of Fluid - -Given all the advantages from the removal of the concept of a *model*, hardware manufacturers might still prefer the existence of the concept of a model, so it would be easier for them to support multiple frameworks all at once and could run a trained model during inference. For example, Nervana, a startup company acquired by Intel, has been working on an XPU that reads the models in the format known as [n-graph](https://github.com/NervanaSystems/ngraph). Similarly, [Movidius](https://www.movidius.com/) is producing a mobile deep learning chip that reads and runs graphs of operators. The well-known [ONNX](https://github.com/onnx/onnx) is also a file format of graphs of operators. - -For Fluid, we can write a converter that extracts the parts in the `ProgramDesc` protobuf message, converts them into a graph of operators, and exports the graph into the ONNX or n-graph format. diff --git a/develop/doc/_sources/design/fluid_compiler.md.txt b/develop/doc/_sources/design/fluid_compiler.md.txt deleted file mode 100644 index 2a6beafc52e..00000000000 --- a/develop/doc/_sources/design/fluid_compiler.md.txt +++ /dev/null @@ -1,110 +0,0 @@ -# PaddlePaddle Fluid: Towards a Compiled Programming Language - -As described in [fluid.md](fluid.md), when a Fluid application program -runs, it generates a `ProgramDesc` protobuf message as an intermediate -representation of itself. The C++ class `Executor` can run this -protobuf message as an interpreter. This article describes the Fluid -compiler. - -![](fluid-compiler.png) - -## ProgramDesc - -Before we go deeper into the idea of compiled language, let us take a -look at a simple example Fluid application. - -```python -import "fluid" - -func paddlepaddle() { - X = fluid.read(...) - W = fluid.Tensor(...) - Y = fluid.mult(X, W) -} -``` - -This program consists of a [block](block.md) of three operators -- -`read`, `assign`, and `mult`. Its `ProgramDesc` message looks like -the following - -```protobuf -message ProgramDesc { - block[0] = Block { - vars = [X, W, Y], - ops = [ - read(output = X) - assign(input = ..., output = W) - mult(input = {X, W}, output = Y) - ], - } -} -``` - -## Transpilers - -We can write a transpiler program that takes a `ProgramDesc`, e.g., -the above one, and outputs another `ProgramDesc`. Let us take some -examples: - -1. *Memory optimization transpiler*: We can write a transpiler that - inserts some `FreeMemoryOp`s in the above example `ProgramDesc` so - to free memory early, before the end of an iteration, so to keep a - small memory footprint. - -1. *Distributed training transpiler*: We can write a transpiler that - converts a`ProgramDesc` into its distributed version of two - `ProgramDesc`s -- one for running by the trainer processes and the - other for the parameter server. - -In the rest of this article, we talk about a special kind of -transpiler, *Native code generator*, which takes a `ProgramDesc` and -generates a `.cu` (or `.cc`) file, which could be built by C++ -compilers (gcc, nvcc, icc) into binaries. - -## Native Code Generator - -For the above example, the native code generator transpiler, say, the -CUDA code generator, should generate a `main` function: - -```c++ -void main() { - auto X = fluid_cuda_read(...); - auto W = fluid_cuda_create_tensor(...); - auto Y = fluid_cuda_mult(X, W); -} -``` - -and the definitions of functions `fluid_cuda_read`, -`fluid_cuda_create_tensor`, and `fluid_cuda_mult`. Please be aware -that each function could just define a C++ instance of an operator and -run it. For example - -```c++ -paddle::Tensor fluid_cuda_read(...) { - paddle::Tensor t; - paddle::operator::Read r(&t, ...); - r.Run(); - return t; -} -``` - -For computational operators that have multiple *kernels*, each for a -specific hardware platform, for example, the `mult` operator, the -generated code should call its CUDA kernel: - -```c++ -paddle::Tensor fluid_cuda_mult(const paddle::Tensor& a, - const paddle::Tensor& b) { - paddle::Tensor t; - paddle::operator::Mult m(a, b, ...); - Mult.Run(cuda_context); -} -``` - -where `cuda_context` could be a global variable of type -`paddle::CUDADeviceContext`. - -## Multi-Block Code Generation - -Most Fluid application programs may have more than one blocks. To -execute them, we need to trace [scopes](scope.md). diff --git a/develop/doc/_sources/design/functions_operators_layers.md.txt b/develop/doc/_sources/design/functions_operators_layers.md.txt deleted file mode 100644 index 984b59f4c69..00000000000 --- a/develop/doc/_sources/design/functions_operators_layers.md.txt +++ /dev/null @@ -1,100 +0,0 @@ -# Design Doc: Functions, Operators, and Layers - -In a DL system, we can compose one or more fine grained operators into a coarse grained one. For example, the FC layer can be composed of a multiplication operator and an add operator. - -Historically, some fine grained operations are known as operators, and some coarse level ones are known as layers. But we need a well-defined separation. - -In general, operators are those very fine grained operations, e.g., mul and add. In the implementation, we can write them as C++ functions: - -```c++ -template T add(T x, T y) { return x + y; } -template T mul(T x, T y) { return x * y; } -``` - -Then we can wrap them into operators which are C++ classes and can be created from Python bindings by name. A C macro can do this. For example, the following macro invocation - -```c++ -#define MAKE_FUNCTION_OPERATOR(mul); -``` - -generates - -```c++ -template class mulOp : public OperatorBase {...}; -REGISTER_OP(mulOp, "mul"); -``` - -so that in Python we can create operator mul by: - -```python -X1 = Var() -X2 = Var() -Y = Var() -paddle.cpp.create_operator("mul", input=[X1, X2], output=Y) -``` - -Also, at the same time, we can compose a coarse level C++ operator class by composing functions `mul` and `add`: - -```c++ -template -class FCOp : public OperatorBase { - public: - void Run(...) { - add(mul(Input("X"), Input("W")), Input("b"); - } -}; -REGISTER_OP(FCOp, "fc"); -``` - -We need to support such composition in Python as well. To do so, we need a higher level Python wrapping of operator creation than `paddle.cpp.create_operator`. This higher level operator API should be compatible with the layer API. - -Let's explain using an example. Suppose that we are going to compose the FC using mul and add in Python, we'd like to have Python functions `mul` and `add` defined in module `operator`: - -```python -def operator.mul(X1, X2): - O = Var() - paddle.cpp.create_operator("mul", input={X1, Y1}, output=O) - return O - -def operator.add(X1, X2): - O = Var() - paddle.cpp.create_operator("add", input={X1, X2}, output=O) - return O -``` - -Above code snippets are automatically generated. Given them, users can define - -```python -def layer.fc(X): - W = Var() - b = Var() - return operator.add(operator.mul(X, W), b) -``` - -If we don't have `operator.mul` and `operator.add`, the definiton of `layer.fc` would be complicated: - -```python -def layer.fc(X): - W = Var() - b = Var() - O1 = Var() - paddle.cpp.create_operator("mul", input=[X, W], output=O1) - O2 = Var() - paddle.cpp.create_operator("add", input=[O1, b], output=O2) - return O2 -``` - -We'd like to have Python bindings to operators in package `paddle.operator`, and Python compositions of operators in package `paddle.layer`. So we have the following concepts in above illustrative example: - - -| C++ functions/functors | mul | add | | | -|------------------------|--------------|--------------|-------------|----------| -| C++ operator class | mulOp | addOp | FCOp | | -| Python binding | operator.mul | operator.add | operator.fc | | -| Python function | | | | layer.fc | - - -This is how we differentiate layer and operators in PaddlePaddle: - -- those defined in C++ and have a lightweighted Python wrapper in module `operators` are operators; whereas -- those who don't have C++ implementations but a Python implementation that compose C++ operators are known as layers. diff --git a/develop/doc/_sources/design/gan_api.md.txt b/develop/doc/_sources/design/gan_api.md.txt deleted file mode 100644 index fb41df8615f..00000000000 --- a/develop/doc/_sources/design/gan_api.md.txt +++ /dev/null @@ -1,253 +0,0 @@ -# Design for GAN - -GAN (General Adversarial Net [https://arxiv.org/abs/1406.2661]) is an important model for unsupervised learning and widely used in many areas. - -It applies several important concepts in machine learning system design, including building and running subgraphs, dependency tracing, different optimizers in one executor and so forth. - -In our GAN design, we wrap it as a user-friendly easily customized python API to design different models. We take the conditional DC-GAN (Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks [https://arxiv.org/abs/1511.06434]) as an example due to its good performance on image generation. - -

-
-Figure 1. The overall running logic of GAN. The black solid arrows indicate the forward pass; the green dashed arrows indicate the backward pass of generator training; the red dashed arrows indicate the backward pass of the discriminator training. The BP pass of the green (red) arrow should only update the parameters in the green (red) boxes. The diamonds indicate the data providers. d\_loss and g\_loss marked in red and green are the two targets we would like to run. -

- -The operators, layers and functions required/optional to build a GAN demo is summarized in https://github.com/PaddlePaddle/Paddle/issues/4563. - -

-
-Figure 2. Photo borrowed from the original DC-GAN paper. -

- -## The Conditional-GAN might be a class. -This design we adopt the popular open source design in https://github.com/carpedm20/DCGAN-tensorflow and https://github.com/rajathkmp/DCGAN. It contains following data structure: - -- DCGAN(object): which contains everything required to build a GAN model. It provides following member functions methods as API: - -- __init__(...): Initialize hyper-parameters (like conv dimension and so forth), and declare model parameters of discriminator and generator as well. - -- generator(z, y=None): Generate a fake image from input noise z. If the label y is provided, the conditional GAN model will be chosen. -Returns a generated image. - -- discriminator(image): -Given an image, decide if it is from a real source or a fake one. -Returns a 0/1 binary label. - -- build_model(self): -build the whole GAN model, define training loss for both generator and discrimator. - -## Discussion on Engine Functions required to build GAN -- Trace the tensor and variable dependency in the engine executor. (Very critical, otherwise GAN can'be be trained correctly) -- Different optimizers responsible for optimizing different loss. - -To be more detailed, we introduce our design of DCGAN as following: - -### Class member Function: Initializer -- Set up hyper-parameters, including condtional dimension, noise dimension, batch size and so forth. -- Declare and define all the model variables. All the discriminator parameters are included in the list self.theta_D and all the generator parameters are included in the list self.theta_G. -```python -class DCGAN(object): - def __init__(self, y_dim=None): - - # hyper parameters - self.y_dim = y_dim # conditional gan or not - self.batch_size = 100 - self.z_dim = z_dim # input noise dimension - - # define parameters of discriminators - self.D_W0 = pd.Variable(shape=[3,3, 1, 128], data=pd.gaussian_normal_randomizer()) - self.D_b0 = pd.Variable(np.zeros(128)) # variable also support initialization using a numpy data - self.D_W1 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer()) - self.D_b1 = pd.Variable(np.zeros(128)) # variable also support initialization using a numpy data - self.D_W2 = pd.Varialble(np.random.rand(128, 1)) - self.D_b2 = pd.Variable(np.zeros(128)) - self.theta_D = [self.D_W0, self.D_b0, self.D_W1, self.D_b1, self.D_W2, self.D_b2] - - # define parameters of generators - self.G_W0 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer()) - self.G_b0 = pd.Variable(np.zeros(128)) # variable also support initialization using a numpy data - self.G_W1 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer()) - self.G_b1 = pd.Variable(np.zeros(128)) # variable also support initialization using a numpy data - self.G_W2 = pd.Varialble(np.random.rand(128, 1)) - self.G_b2 = pd.Variable(np.zeros(128)) - self.theta_G = [self.G_W0, self.G_b0, self.G_W1, self.G_b1, self.G_W2, self.G_b2] -``` - -### Class member Function: Generator -- Given a noisy input z, returns a fake image. -- Concatenation, batch-norm, FC operations required; -- Deconv layer required, which is missing now... -```python -class DCGAN(object): - def generator(self, z, y = None): - # input z: the random noise - # input y: input data label (optional) - # output G_im: generated fake images - - if not self.y_dim: - z = pd.layer.concat(1, [z, y]) - - G_h0 = pd.layer.fc(z, self.G_w0, self.G_b0) - G_h0_bn = pd.layer.batch_norm(G_h0) - G_h0_relu = pd.layer.relu(G_h0_bn) - - G_h1 = pd.layer.deconv(G_h0_relu, self.G_w1, self.G_b1) - G_h1_bn = pd.layer.batch_norm(G_h1) - G_h1_relu = pd.layer.relu(G_h1_bn) - - G_h2 = pd.layer.deconv(G_h1_relu, self.G_W2, self.G_b2)) - G_im = pd.layer.tanh(G_im) - return G_im -``` - -### Class member function: Discriminator -- Given a noisy input z, returns a fake image. -- Concatenation, Convolution, batch-norm, FC, Leaky-ReLU operations required; -```python -class DCGAN(object): - def discriminator(self, image): - # input image: either generated images or real ones - # output D_h2: binary logit of the label - - D_h0 = pd.layer.conv2d(image, w=self.D_w0, b=self.D_b0) - D_h0_bn = pd.layer.batchnorm(h0) - D_h0_relu = pd.layer.lrelu(h0_bn) - - D_h1 = pd.layer.conv2d(D_h0_relu, w=self.D_w1, b=self.D_b1) - D_h1_bn = pd.layer.batchnorm(D_h1) - D_h1_relu = pd.layer.lrelu(D_h1_bn) - - D_h2 = pd.layer.fc(D_h1_relu, w=self.D_w2, b=self.D_b2) - return D_h2 -``` - -### Class member function: Build the model -- Define data readers as placeholders to hold the data; -- Build generator and discriminators; -- Define two training losses for discriminator and generator, respectively. -If we have execution dependency engine to back-trace all tensors, the module building our GAN model will be like this: -```python -class DCGAN(object): - def build_model(self): - if self.y_dim: - self.y = pd.data(pd.float32, [self.batch_size, self.y_dim]) - self.images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size]) - self.faked_images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size]) - self.z = pd.data(tf.float32, [None, self.z_size]) - - # step 1: generate images by generator, classify real/fake images with discriminator - if self.y_dim: # if conditional GAN, includes label - self.G = self.generator(self.z, self.y) - self.D_t = self.discriminator(self.images) - # generated fake images - self.sampled = self.sampler(self.z, self.y) - self.D_f = self.discriminator(self.G) - else: # original version of GAN - self.G = self.generator(self.z) - self.D_t = self.discriminator(self.images) - # generate fake images - self.sampled = self.sampler(self.z) - self.D_f = self.discriminator(self.images) - - # step 2: define the two losses - self.d_loss_real = pd.reduce_mean(pd.cross_entropy(self.D_t, np.ones(self.batch_size)) - self.d_loss_fake = pd.reduce_mean(pd.cross_entropy(self.D_f, np.zeros(self.batch_size)) - self.d_loss = self.d_loss_real + self.d_loss_fake - - self.g_loss = pd.reduce_mean(pd.cross_entropy(self.D_f, np.ones(self.batch_szie)) -``` - -If we do not have dependency engine but blocks, the module building our GAN model will be like this: -```python -class DCGAN(object): - def build_model(self, default_block): - # input data in the default block - if self.y_dim: - self.y = pd.data(pd.float32, [self.batch_size, self.y_dim]) - self.images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size]) - # self.faked_images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size]) - self.z = pd.data(tf.float32, [None, self.z_size]) - - # step 1: generate images by generator, classify real/fake images with discriminator - with pd.default_block().g_block(): - if self.y_dim: # if conditional GAN, includes label - self.G = self.generator(self.z, self.y) - self.D_g = self.discriminator(self.G, self.y) - else: # original version of GAN - self.G = self.generator(self.z) - self.D_g = self.discriminator(self.G, self.y) - self.g_loss = pd.reduce_mean(pd.cross_entropy(self.D_g, np.ones(self.batch_szie)) - - with pd.default_block().d_block(): - if self.y_dim: # if conditional GAN, includes label - self.D_t = self.discriminator(self.images, self.y) - self.D_f = self.discriminator(self.G, self.y) - else: # original version of GAN - self.D_t = self.discriminator(self.images) - self.D_f = self.discriminator(self.G) - - # step 2: define the two losses - self.d_loss_real = pd.reduce_mean(pd.cross_entropy(self.D_t, np.ones(self.batch_size)) - self.d_loss_fake = pd.reduce_mean(pd.cross_entropy(self.D_f, np.zeros(self.batch_size)) - self.d_loss = self.d_loss_real + self.d_loss_fake -``` -Some small confusion and problems with this design: -- D\_g and D\_f are actually the same thing, but has to be written twice; i.e., if we want to run two sub-graphs conceptually, the same codes have to be written twice if they are shared by the graph. -- Requires ability to create a block anytime, rather than in if-else or rnn only; - -## Main function for the demo: -Generally, the user of GAN just need to the following things: -- Define an object as DCGAN class; -- Build the DCGAN model; -- Specify two optimizers for two different losses with respect to different parameters. -```python -# pd for short, should be more concise. -from paddle.v2 as pd -import numpy as np -import logging - -if __name__ == "__main__": - # dcgan class in the default graph/block - # if we use dependency engine as tensorflow - # the codes, will be slightly different like: - # dcgan = DCGAN() - # dcgan.build_model() - with pd.block() as def_block: - dcgan = DCGAN() - dcgan.build_model(def_block) - - # load mnist data - data_X, data_y = self.load_mnist() - - # Two subgraphs required!!! - with pd.block().d_block(): - d_optim = pd.train.Adam(lr = .001, beta= .1) - d_step = d_optim.minimize(dcgan.d_loss, dcgan.theta_D) - with pd.block.g_block(): - g_optim = pd.train.Adam(lr = .001, beta= .1) - g_step = pd.minimize(dcgan.g_loss, dcgan.theta_G) - - # executor - sess = pd.executor() - - # training - for epoch in xrange(10000): - for batch_id in range(N / batch_size): - idx = ... - # sample a batch - batch_im, batch_label = data_X[idx:idx+batch_size], data_y[idx:idx+batch_size] - # sample z - batch_z = np.random.uniform(-1., 1., [batch_size, z_dim]) - - if batch_id % 2 == 0: - sess.run(d_step, - feed_dict = {dcgan.images: batch_im, - dcgan.y: batch_label, - dcgan.z: batch_z}) - else: - sess.run(g_step, - feed_dict = {dcgan.z: batch_z}) -``` - -# More thinking about dependency engine v.s. block design: -- What if we just want to run an intermediate result? Do we need to run the whole block/graph? -- Should we call eval() to get the fake images in the first stage? And then train the discriminator in the second stage? diff --git a/develop/doc/_sources/design/graph.md.txt b/develop/doc/_sources/design/graph.md.txt deleted file mode 100644 index 7519a65df83..00000000000 --- a/develop/doc/_sources/design/graph.md.txt +++ /dev/null @@ -1,70 +0,0 @@ -# Design Doc: Computations as a Graph - -A primary goal of the refactorization of PaddlePaddle is a more flexible representation of deep learning computation, in particular, a graph of operators and variables, instead of sequences of layers as before. - -This document explains that the construction of a graph as three steps: - -- construct the forward part -- construct the backward part -- construct the optimization part - -## The Construction of a Graph - -Let us take the problem of image classification as a simple example. The application program that trains the model looks like: - -```python -x = layer.data("images") -l = layer.data("label") -y = layer.fc(x) -cost = layer.mse(y, l) -optimize(cost) -train(cost, reader=mnist.train()) -``` - -### Forward Part - -The first four lines of above program build the forward part of the graph. - -![](images/graph_construction_example_forward_only.png) - -In particular, the first line `x = layer.data("images")` creates variable x and a Feed operator that copies a column from the minibatch to x. `y = layer.fc(x)` creates not only the FC operator and output variable y, but also two parameters, W and b, and the initialization operators. - -Initialization operators are kind of "run-once" operators -- the `Run` method increments a class data member counter so to run at most once. By doing so, a parameter wouldn't be initialized repeatedly, say, in every minibatch. - -In this example, all operators are created as `OpDesc` protobuf messages, and all variables are `VarDesc`. These protobuf messages are saved in a `BlockDesc` protobuf message. - -### Backward Part - -The fifth line `optimize(cost)` calls two functions, `ConstructBackwardGraph` and `ConstructOptimizationGraph`. - -`ConstructBackwardGraph` traverses the forward graph in the `BlockDesc` protobuf message and builds the backward part. - -![](images/graph_construction_example_forward_backward.png) - -According to the chain rule of gradient computation, `ConstructBackwardGraph` would - -1. create a gradient operator G for each operator F, -1. make all inputs, outputs, and outputs' gradient of F as inputs of G, -1. create gradients for all inputs of F, except for those who don't have gradients, like x and l, and -1. make all these gradients as outputs of G. - -### Optimization Part - -For each parameter, like W and b created by `layer.fc`, marked as double circles in above graphs, `ConstructOptimizationGraph` creates an optimization operator to apply its gradient. Here results in the complete graph: - -![](images/graph_construction_example_all.png) - -## Block and Graph - -The word block and graph are interchangable in the desgin of PaddlePaddle. A [Block](https://github.com/PaddlePaddle/Paddle/pull/3708) is a metaphore of the code and local variables in a pair of curly braces in programming languages, where operators are like statements or instructions. A graph of operators and variables is a representation of the block. - -A Block keeps operators in an array `BlockDesc::ops` - -```protobuf -message BlockDesc { - repeated OpDesc ops = 1; - repeated VarDesc vars = 2; -} -``` - -in the order that they appear in user programs, like the Python program at the beginning of this article. We can imagine that in `ops`, we have some forward operators, followed by some gradient operators, and then some optimization operators. diff --git a/develop/doc/_sources/design/graph_survey.md.txt b/develop/doc/_sources/design/graph_survey.md.txt deleted file mode 100644 index 6c6db08f463..00000000000 --- a/develop/doc/_sources/design/graph_survey.md.txt +++ /dev/null @@ -1,232 +0,0 @@ -## Survey on Graph - -Neural network framework often provides symbolic API for users to write network topology conveniently. This doc manily focus on symbolic API in most popular neural network frameworks, and try to find out how to parse symbolic configuration to a portable file, such as protobuf or json. - -### Mxnet - -The core concept of symbolic API is `Symbol`. Mxnet implements `Symbol` class in C++, and export to Python using C-API. Please refer to the comments in Mxnet: - - -`Symbol` is help class used to represent the operator node in Graph. -`Symbol` acts as an interface for building graphs from different components like Variable, Functor and Group. `Symbol` is also exported to python front-end (while Graph is not) to enable quick test and deployment. Conceptually, symbol is the final operation of a graph and thus including all the information required (the graph) to evaluate its output value. - - -A simple network topology wrote by Symbol is as follows: - -```python -def get_symbol(num_classes=10, **kwargs): - data = mx.symbol.Variable('data') - data = mx.symbol.Flatten(data=data) - fc1 = mx.symbol.FullyConnected(data = data, name='fc1', num_hidden=128) - act1 = mx.symbol.Activation(data = fc1, name='relu1', act_type="relu") - fc2 = mx.symbol.FullyConnected(data = act1, name = 'fc2', num_hidden = 64) - act2 = mx.symbol.Activation(data = fc2, name='relu2', act_type="relu") - fc3 = mx.symbol.FullyConnected(data = act2, name='fc3', num_hidden=num_classes) - mlp = mx.symbol.SoftmaxOutput(data = fc3, name = 'softmax') - return mlp -``` - - - -Varible here is actually a Symbol. Every basic Symbol will correspond to one Node, and every Node has its own NodeAttr. There is a op field in NodeAttr class, when a Symbol represents Variable(often input data), the op field is null. - -Symbol contains a data member, std::vector outputs, and NodeEntry cantains a poniter to Node. We can follow the Node pointer to get all the Graph. - -And Symbol can be saved to a Json file. - -Here is a detailed example: - -``` ->>> import mxnet as mx ->>> data = mx.symbol.Variable('data') ->>> print data.debug_str() -Variable:data - ->>> data = mx.symbol.Flatten(data=data) ->>> print data.debug_str() -Symbol Outputs: - output[0]=flatten0(0) -Variable:data --------------------- -Op:Flatten, Name=flatten0 -Inputs: - arg[0]=data(0) version=0 - ->>> fc1 = mx.symbol.FullyConnected(data = data, name='fc1', num_hidden=128) ->>> print fc1.debug_str() -Symbol Outputs: - output[0]=fc1(0) -Variable:data --------------------- -Op:Flatten, Name=flatten0 -Inputs: - arg[0]=data(0) version=0 -Variable:fc1_weight -Variable:fc1_bias --------------------- -Op:FullyConnected, Name=fc1 -Inputs: - arg[0]=flatten0(0) - arg[1]=fc1_weight(0) version=0 - arg[2]=fc1_bias(0) version=0 -Attrs: - num_hidden=128 - -``` - - -### TensorFlow - - -The core concept of symbolic API is `Tensor`. Tensorflow defines `Tensor` in Python. Please refer to the comments in TensorFlow: - -A `Tensor` is a symbolic handle to one of the outputs of an `Operation`. It does not hold the values of that operation's output, but instead provides a means of computing those values in a TensorFlow [Session](https://www.tensorflow.org/api_docs/python/tf/Session). - -A simple example is as follows: - -```python - # Build a dataflow graph. - c = tf.constant([[1.0, 2.0], [3.0, 4.0]]) - d = tf.constant([[1.0, 1.0], [0.0, 1.0]]) - e = tf.matmul(c, d) - - # Construct a `Session` to execute the graph. - sess = tf.Session() - - # Execute the graph and store the value that `e` represents in `result`. - result = sess.run(e) -``` - - -The main method of `Tensor` is as follows: - - -```python -@property -def op(self): - """The `Operation` that produces this tensor as an output.""" - return self._op - -@property -def dtype(self): - """The `DType` of elements in this tensor.""" - return self._dtype - -@property -def graph(self): - """The `Graph` that contains this tensor.""" - return self._op.graph - -@property -def name(self): - """The string name of this tensor.""" - if not self._op.name: - raise ValueError("Operation was not named: %s" % self._op) - return "%s:%d" % (self._op.name, self._value_index) - -@property -def device(self): - """The name of the device on which this tensor will be produced, or None.""" - return self._op.device -``` - - -Tensor can be taken as target to run by session. Tensor contains all the information of Graph, and tracks data dependency. - - -Here is a detailed example: - - -``` ->>> import tensorflow as tf ->>> c = tf.constant([[1.0, 2.0], [3.0, 4.0]]) ->>> print c.graph - ->>> d = tf.constant([[1.0, 1.0], [0.0, 1.0]]) ->>> print d.graph - ->>> e = tf.matmul(c, d) ->>> print e.graph - -``` - -### Dynet - - -The core concept of symbolic API is `Expression`, and Dynet defines `Expression` class in C++. - - -A simple example is as follows: - -```cpp -ComputationGraph cg; -Expression W = parameter(cg, pW); - -Expression in = input(cg, xs[i]); -Expression label = input(cg, ys[i]); -Expression pred = W * in; -Expression loss = square(pred - label); -``` - -The input data and parameter are also represented by Expression. Every basci Expression corresponds to a Node. And input data is also a Node. - -Expression has a data member ComputationGraph, and ComputationGraph will be modified in users' configuring process. Expression can be a running target, beacuse Expression contains all dependency. - - -Here is a detailed example: - -write topology in C++ - -``` -ComputationGraph cg; -Expression W = parameter(cg, pW); -cg.print_graphviz(); - -Expression pred = W * xs[i]; -cg.print_graphviz(); - -Expression loss = square(pred - ys[i]); -cg.print_graphviz(); -``` - -compile and print - -``` -# first print -digraph G { - rankdir=LR; - nodesep=.05; - N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"]; -} -# second print -digraph G { - rankdir=LR; - nodesep=.05; - N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"]; - N1 [label="v1 = v0 * -0.98"]; - N0 -> N1; -} -# third print -digraph G { - rankdir=LR; - nodesep=.05; - N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"]; - N1 [label="v1 = v0 * -0.98"]; - N0 -> N1; - N2 [label="v2 = -1.88387 - v1"]; - N1 -> N2; - N3 [label="v3 = -v2"]; - N2 -> N3; - N4 [label="v4 = square(v3)"]; - N3 -> N4; -} -``` - -### Conclusion - - -Actually, Symbol/Tensor/Expression in Mxnet/TensorFlow/Dynet are the same level concepts. We use a unified name Expression here, this level concept has following features: - -- Users wirte topoloy with symbolic API, and all return value is Expression, including input data and parameter. -- Expression corresponds with a global Graph, and Expression can also be composed. -- Expression tracks all dependency and can be taken as a run target diff --git a/develop/doc/_sources/design/if_else_op.md.txt b/develop/doc/_sources/design/if_else_op.md.txt deleted file mode 100644 index 26d140f06db..00000000000 --- a/develop/doc/_sources/design/if_else_op.md.txt +++ /dev/null @@ -1,51 +0,0 @@ -# The `IfElse` Operator - -PaddlePaddle's `IfElse` operator differs from TensorFlow's: - -- the TensorFlow version takes a scalar boolean value as the condition so that the whole mini-batch goes to either the true or the false branch, whereas -- the PaddlePaddle version takes a vector of boolean value as the condition, and instances corresponding to true values go to the true branch, those corresponding to false values go to the false branch. - -## Example - -The following PaddlePaddle program shows the usage of the IfElse operator: - -```python -import paddle as pd - -x = minibatch([10, 20, 30]) # shape=[None, 1] -y = var(1) # shape=[1], value=1 -z = minibatch([10, 20, 30]) # shape=[None, 1] -cond = larger_than(x, 15) # [false, true, true] - -ie = pd.ifelse() -with ie.true_block(): - d = pd.layer.add(x, y) - ie.output(d, pd.layer.softmax(d)) -with ie.false_block(): - d = pd.layer.fc(z) - ie.output(d, d+1) -o1, o2 = ie(cond) -``` - -A challenge to implement the `IfElse` operator is to infer those variables to be split, or, say, to identify the variable of the mini-batch or those derived from the mini-batch. - -An equivalent C++ program is as follows: - -```c++ -namespace pd = paddle; - -int x = 10; -int y = 1; -int z = 10; -bool cond = false; -int o1, o2; -if (cond) { - int d = x + y; - o1 = z; - o2 = pd::layer::softmax(z); -} else { - int d = pd::layer::fc(z); - o1 = d; - o2 = d+1; -} -``` diff --git a/develop/doc/_sources/design/infer_var_type.md.txt b/develop/doc/_sources/design/infer_var_type.md.txt deleted file mode 100644 index d9d5397becb..00000000000 --- a/develop/doc/_sources/design/infer_var_type.md.txt +++ /dev/null @@ -1,78 +0,0 @@ -# Design Doc: InferVarType - -## The Problem Posed - -The variable in our design can hold variant types. Such as `LoDTensor` and `SelectedRows`. An operator should be able to inference the variable types of its output. - -For example, a `lookup table` operator takes two `LoDTensor`; one is a float tensor as the embedding table, the other is an int tensor as word ID. The gradient operator of `lookup table` will generate a `SelectedRows` as its output. A `sum` operator can take both `LoDTensor` and `SelectedRows` as its inputs and will generate a `LoDTensor` if any of its inputs is `LoDTensor`, otherwise, the `sum` operator will generate `SelectedRows` as its output. - -The variable type will be constant at runtime. Every variable's type can either be set by the user (input data and parameter) or be inferred by the operator in compile time. - -## Proposed Solution - -The `InferVarType` is a compile-time function which is registered to each operator. The inferface of that function is: - - -```c++ -using InferVarTypeFN = std::function< - void (const OpDescBind& /*op_desc*/, BlockDescBind* /*block*/)>; -``` - -It takes an operator description as its input and will write the output variable type and store them in block description. - -The `InferVarTypeFN` will be registered in `OpInfo`, to replace `infer_var_type_` field. The `OpInfo` should be - -```cpp -struct OpInfo { - InferVarTypeFN infer_var_type_; - ... -}; -``` - -The default `InferVarType` will set output type as `LoDTensor`. It can be done by `GetInferVarType()`. - -```cpp -void DefaultInferVarType(const OpDescBind& op_desc, BlockDescBind* block) { - // set the output type of variable as `LoDTensor`. - // ... -} - -struct OpInfo { - InferVarTypeFN infer_var_type_; - InferVarTypeFN GetInferVarType() const { - if (infer_var_type_) { - return infer_var_type_; - } else { - return DefaultInferVarType; - } - } -}; -``` - -## Register InferVarType - -We provide a thin base class for registering an `InferVarTypeFN`. To use a base class will ease the implementation of registry since we can detect the registry entry is an `InferVarTypeFN` or not. - -```cpp -class VarTypeInferer { -public: - virtual void operator()(const OpDescBind& op_desc, BlockDescBind* block) const = 0; -} -``` - -Operator developers can write the specialize `VarTypeInferer` as follow. - -```cpp -class SpecialVarTypeInferer : public VarTypeInferer { -public: - virtual void operator()(const OpDescBind& op_desc, BlockDescBind* block) const { - // .. own logic - } -} -``` - -Then user can register the `InferVarType` just like `GradOpDescMaker` and `OpInfoMaker`. - -``` -REGISTER_OPERATOR(some_op, OpType, SpecialVarTypeInferer, ...); -``` diff --git a/develop/doc/_sources/design/kernel_hint_design.md.txt b/develop/doc/_sources/design/kernel_hint_design.md.txt deleted file mode 100644 index a54b7da045e..00000000000 --- a/develop/doc/_sources/design/kernel_hint_design.md.txt +++ /dev/null @@ -1,57 +0,0 @@ -## Problem -In PaddlePaddle's [Design](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/switch_kernel.md), one Operator may have multiple kernels. Users may have some personal preference to choose a certain type of kernel for an operator, such as `force_cpu` to choose a CPU kernel, `use_cudnn` to choose a CUDNN kernel, we need to provide a way for users to do this. - -In the current design, we use KernelType to describe one kernel. - -```cpp -struct KernelType { - Place place_; - DataType data_type_; - LayoutType layout_; -}; -``` - `place_` `data_type_` and `layout_` can be got from the input tensors of the operator, `GetActualKernelType(inputs)` use inputs to infer the proper kernel key that fit the incoming data, but users can not directly configure it. - -The [design](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/switch_kernel.md) also provides a virtual method `GetExpectedKernelType` that user can overload and use to choose the KernelType they want to use. - -So we should send the information user defined in proto to `GetExpectedKernelType` for choosing a kernel. - -The problem is, how should we define and send the information for `GetExpectedKernelType` to use? - -## Solution - -### Potential choice -1. Do nothing, let the user add the information they want to operator‘s attribute and get them inside `GetExpectedKernelType`, this can work properly. But there is a little problem that users may define many kinds of hints for the same purpose, such as `force_cpu`, `use_cpu`, `cpu_kernel` to choose CPU kernel, and `use_cudnn`, `force_cudnn`, `cudnn_kernel` to choose CUDNN kernel. - -2. Pre-define all the needed option and use a single attr key such as `kernel_hint` for the user, this is not so flexible if the user wants to define some more kind of hint. - -### Final choice -To provide enough flexibility while avoiding confusion definition, we can define some global constants for these attribute names, such as `force_cpu`, `use_cudnn`, `use_mkldnn` for a user to choose. - -In C++ - -```cpp -const std::string kForceCPU = "force_cpu"; -const std::string kUseCUDNN = "use_cudnn"; -const std::string kUseMKLDNN = "use_mkldnn"; - -KernelType GetExpectedKernelType() { - if (Attr(kForceCPU)) { - return KernelType(CPUPlace, ...) - } else { - ... - } -} -``` - -In Python code - -```python -FORCE_CPU = core.kForceCPU() - -def xx_layer(..., force_cpu=false): - layer_helper = LayerHelper(...) - layer_helper.append_op( - type="xx", - attr={FORCE_CPU: force_cpu}) -``` diff --git a/develop/doc/_sources/design/kernel_selection.md.txt b/develop/doc/_sources/design/kernel_selection.md.txt deleted file mode 100644 index 9719e031c70..00000000000 --- a/develop/doc/_sources/design/kernel_selection.md.txt +++ /dev/null @@ -1,99 +0,0 @@ -## Background -Every operator has many kernels because there are multiple data types, places, data layout, library type that Fluid supports. We use the `OpKernelType ` to describe kernel types that operators can hold. - -The `OpKernelType ` is as follows: - -```cpp -struct OpKernelType { - Place place_; - DataType data_type_; - DataLayout data_layout_; - LibraryType library_type_; -}; -``` - -- The `place_` is a descriptor of the device, e.g., CPUPlace, CUDAPlace. - -- The `data_type_` is the data type that this kernel performs on, e.g., `FP32`, `INT64`. Note that one kernel may have inputs with different data types. However, it will be a major `data_type`. For example, the `cross_entropy` takes `int64` as it label, and `double`/`float` as its input logit and output cost. The major `data_type` of `cross_entropy` is `float` or `double`. - -- The `data_layout_ ` is useful for some computational library. One example is that MKLDNN uses many kinds of layout, such as `nChw8c`. Each kind of layout will invoke the different kernel. - -- The `library_type_` describes the computational library, e.g., `MKLDNN`, `CUDNN`. - -## Problem - -We register a kernel for every operator and every kernel type ideally. However, it is impracticable for the following situations. - -1. Some operators, like CRF, are complicated and inefficient to be implemented on GPU. The CRF operator will only have a CPU kernel. -2. Some operators will take too many memory. It is better to force them into CPU. However, the rest of operators in this neural network will be performed on GPU, i.e., model parallel problem. -3. Some layout and place are particular. One example is that MKLDNN uses `nChw8` and there is no other library uses `nChw8c`. - -Take one situation to give a detailed explanation, if we have two Operators: OP1 and OP2, OP1 has one output `op1_to_op2`, and `op1_to_op2` is the input of OP2. - -If OP1 and OP2 run on the same place(for example CPUPlace), then `op1_2_op2` can be used directly by OP2. - -``` -OP1(CPUPlace) - | - op1_2_op2 - | -OP2(CPUPlace) -``` - -If OP1 and OP2 run one different place, then OP2 cannot `use op1_2_op2` directly. - -Problems under these situations are similar. We can formalize this problem as follow. - -We register kernels with types $KT = \{kt_1, kt_2, kt_3, ...\}$ for one operator. The inputs of this operator should be run on kernel type $kt_{?}$, which the $kt_{?} \notin KT$. How to cast the input of this operator from $kt_{?}$ to any of kernel type in $KT$. - -## Solution: data transform - -It is clear that transforming inputs of an operator to adapt another kernel type is not related to the particular operator. So we should register these transformation methods as global methods. - -We can infer kernel type for each input of an operator. We let this kernel type as `actual kernel type for var`, which means this kernel type is the kernel type that can process this input variable. - -We can get a kernel type by 1) The configuration of operator description. (Users may want to force use `MKL` for `conv` operator). 2) The place of the current executor. (Executor is running on GPU). This kernel type is what we expect the operator will be performed on. We let this kernel type as `expect kernel type`. - -We transform the input data from `actual` to `expect` if the actual kernel type is not as same as expect kernel type. - -The algorithm is described as following - -```cpp -void OperatorWithKernel::Run( - const Scope& scope, - const platform::Place& place) const { - ExecutionContext ctx(...); - auto expected_kernel_key = this->GetExpectedKernelType(ctx); - - Scope& new_scope = scope.NewScope(); - - for (auto& var_name : this->Inputs()) { - auto* tensor_in = GetTensor(var_name); - auto kernel_type_for_var = this->GetKernelTypeForVar(...); - if (kernel_type_for_var.place_ != expected_kernel_key.place_) { - auto* trans_var = new_scope.Var(var_name); - auto* out = DataTransform(expected_kernel_key, - kernel_type_for_var, - *tensor_in); - CopyVariableWithTensor(...); - } - } - - auto kernel = kernels.find(expected_kernel_key); - kernel->Compute(ExecutionContext(...)); -} -``` - -then the actual process for the multi-device above will be: - -``` -OP1(CPUPlace) - | -op1_2_op2(on CPU) - | -[transform](from CPU to GPU) - | -op1_2_op2(on GPU) - | -OP2(CUDAPlace) -``` diff --git a/develop/doc/_sources/design/memory_optimization.md.txt b/develop/doc/_sources/design/memory_optimization.md.txt deleted file mode 100644 index 285464ada72..00000000000 --- a/develop/doc/_sources/design/memory_optimization.md.txt +++ /dev/null @@ -1,217 +0,0 @@ -# Memory Optimization - - -## Problem - -In a lecture from Andrew Ng, he attributes the recent sucess of AI due to a combination of these: - -- Availability of Big Data -- Supercomputing power to process this Big Data over very large neural networks -- Modern algorithms - -Following graph shows the details: - -![](images/deep_learning.png) - -Larger model usually bring better performance. However, GPU memory is limited. For example, the memory size of a GTX TITAN X is only 12GB. To train complex and large models, we have to take care of memory usage. Besides, memory optimization is also necessary in both online/mobile inference. - -## Solution - -### Basic Strategy - -There are some basic strategies to improve memory usage, including in-place operations and memory sharing. - -#### In-place Operation -In a relu activation operator: - -$y = \max(x, 0)$ - -If the variable x is not used in any other operator, we can make an in-place operation. In other words, the memory block of variable y and variable x will be the same. In-place operations will save 50% memory occupancy immediately. - -#### Memory Sharing - -Not all operators support in-place operations. Memory sharing is a more general strategy. - -Following is an example: - -``` -a = op1(b, c); -d = op2(a) -e = op3(d, f) -``` - -In this case, variable a is no longer used, and op2 does not support in-place operation. After op2 finishes, we can put the memory of variable a to a memory pool. Then, variable e can share the memory of variable a from the pool. - - -### Live Variable Analysis - -It's not enough to only have some basic strategies. The pre-requisite of memory optimization is to know if a variable is still "live" after an operation. - -In our design, the neural network topology is defined as a program. Luckily, [live variable analysis](https://en.wikipedia.org/wiki/Live_variable_analysis) is a classic problem in compilers which can be used in many stages, such as register allocation. - -In compilers, the front end of the compiler translates programs into an intermediate language with an unbounded number of temporary variables. This program must run on a machine with a bounded number of registers. Two temporary variables a and b can fit into the same register, if a and b are never "in use" at the same time. Thus, many temporary variables can fit in few registers; if they don't all fit, the excess tempory variables can be kept in memory. - -Therefore, the compiler needs to analyze the intermediate-representation program to determine which temporary variables are in use at the same time. We say a variable is "live" if it holds a value that may be needed in the future, so this analysis is called liveness analysis. - -We can leran these techniques from compilers. There are mainly two stages to make live variable analysis: - -- construct a control flow graph -- solve the dataflow equations - - -#### Control Flow Graph -To perform analysis on a program, it is often useful to make a control flow graph. A [control flow graph](https://en.wikipedia.org/wiki/Control_flow_graph) (CFG) in computer science is a representation, using graph notation, of all paths that might be traversed through a program during its execution. Each statement in the program is a node in the flow graph; if statemment x can be followed by statement y, there is an egde from x to y. - -Following is the flow graph for a simple loop. - -![](images/control_flow_graph.png) - -#### Dataflow Analysis - -Liveness of variable "flows" around the edges of the control flow graph; determining the live range of each variable is an example of a dataflow problem. [Dataflow analysis](https://en.wikipedia.org/wiki/Data-flow_analysis) is a technique for gathering information about the possible set of values calculated at various points in a computer program. - -A simple way to perform data-flow analysis of programs is to set up dataflow equations for each node of the control flow graph and solve them by repeatedly calculating the output from the input locally at each node until the whole system stabilizes. - -- Flow Graph Terminology - -A flow graph node has out-edges that lead to sucessor nodes, and in-edges that come from predecessor nodes. The set *pred[n]* is all the predecessors of node n, and *succ[n]* is the set of sucessors. -In former control flow graph, the out-edges of node 5 are 5 --> 6 and 5 --> 2, and *succ[5]* = {2, 6}. The in-edges of 2 are 5 --> 2 and 1 --> 2, and *pred[2]* = {1, 5}. - -- Uses and Defs - -An assignmemt to a variable or temporary defines that variable. An occurence of a variable on the right-hand side of an assginment(or in other expressions) uses the variable. We can define the *def* of a variable as the set of graph nodes that define it; or the *def* of a graph node as the set of variables that it defines; and the similarly for the *use* of a variable or graph node. In former control flow graph, *def(3)* = {c}, *use(3)* = {b, c}. - -- Liveness - -A variable is *live* on an edge if there is a directed path from that edge to a *use* of the variable that does not go through any *def*. A variable is *live-in* at a node if it is live on any of the in-edges of that node; it is *live-out* at a node if it is live on any of the out-edges of the node. - - -The calcution of liveness can be solved by iteration until a fixed pointer is reached. Following is the recursive formula: - -![](images/dataflow_equations.png) - -### Memory optimization transpiler - -At last, we take basic strategy and liveness analysis techniques learning from compilers to implement our memory optimization transpiler. - -#### add in-place attribute - -In-place is a built-in attribute of an operator. Since we treat in-place and other operators differently, we have to add an in-place attribute for every operator. - - -#### contruct control flow graph - -Following is the ProgramDesc protobuf of [machine translation](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/tests/book/test_machine_translation.py) example. - -- Block0: - -``` -lookup_table -mul -... -while(sub-block idx 1) -... -array_to_lod_tensor -cross_entropy -... -while_grad(sub-block idx 2) -read_from_array -array_to_lod_tensor -... -``` - -- Block1 - -``` -read_from_array -read_from_array -... -write_to_array -increment -write_to_array -less_than -``` - -- Block2 - -``` -read_from_array -increment -... -write_to_array -write_to_array -``` - -We can transfer all the operators and variables in ProgramDesc to build a control flow graph. - -```python -class ControlFlowGraph(object): - def __init__(self, Program): - self._sucessors = defaultdict(set) - self._presucessors = defaultdict(set) - self._uses = defaultdict(set) - self._defs = defaultdict(set) - self._live_in = defaultdict(set) - self._live_out = defaultdict(set) - self._program = Program - - def build(self): - pass - - def dataflow_analysis(self): - pass - - def memory_optimization(self): - pass - - def get_program(self): - return self._program -``` - -#### Make dataflow analysis - -We follow the guide from compilers and try to solve the dataflow equation to get liveness of every variable. If the live-in of an operator node is different from the live-out, then we can make memory sharing. - -For example: - -``` -a = op1(b, c); -d = op2(a) -e = op3(d, f) -``` - -The dataflow analysis result is: - -``` -live_in(op1) = {b, c, f} -live_out(op1) = {a, f} - -live_in(op2) = {a, f} -live_out(op2) = {d, f} - -live_in(op3) = {d, f} -live_out(op3) = {} -``` - -After op1, we can process variable b and variable c; After op2, we can process variable a. After op3, we can process variable d and variable f. - -#### memory sharing policy - -A memory pool will be mantained in the stage of memory optimization. Each operator node will be scanned to determine memory optimization is done or not. If an operator satifies the requirement, following policy will be taken to handle input/output variables. - -``` -if op.support_inplace(): - i --> pool - pool --> o -else: - pool --> o - i --> pool -``` - - - -## Reference - -- [Lecture Notes From Artificial Intelligence Is The New Electricity By Andrew Ng](https://manavsehgal.com/lecture-notes-from-artificial-intelligence-is-the-new-electricity-by-andrew-ng-4712dcbf26e5) -- Modern compiler implementation in ML, by Andrew W. Appel -- [Optimizing Memory Consumption in Deep learning](https://mxnet.incubator.apache.org/architecture/note_memory.html) diff --git a/develop/doc/_sources/design/mkl/mkl_packed.md.txt b/develop/doc/_sources/design/mkl/mkl_packed.md.txt deleted file mode 100644 index 0123315ad43..00000000000 --- a/develop/doc/_sources/design/mkl/mkl_packed.md.txt +++ /dev/null @@ -1,108 +0,0 @@ -# Intel® MKL Packed on PaddlePaddle: Design Doc - - -## Contents - -- [Overview](#overview) -- [Key Points](#key-points) - - [Background](#background) - - [Solution](#solution) -- [Actions](#actions) - - [CMake](#cmake) - - [Layers](#layers) - - [Unit Tests](#unit-tests) - - [Python API](#python-api) - - [Benchmarking](#benchmarking) - - -## Overview -我们计划将 Intel® MKL 中引入的 GEMM Packed APIs\[[1](#references)\] 集成到 PaddlePaddle 中,充分发挥英特尔平台的优势,有效提升PaddlePaddle在英特尔架构上的性能。 -现阶段的优化主要针对 Recurrent Neural Network(以下简称RNN)相关层(包括`RecurrentLayer`, `GatedRecurrentLayer`和`LstmLayer`), 以及 PaddlePaddle V1 API。 - -## Key Points - -### Background -目前PaddlePaddle采用了 Intel® MKL库的[cblas_?gemm](https://software.intel.com/en-us/mkl-developer-reference-c-cblas-gemm)函数,这个函数本身会在计算前将原数据转换为更适合英特尔平台的内部格式。 - -1. 转换耗时 \ -这一数据格式的转换操作(Packing),在问题本身的计算量比较小的时候,显得相对来说较为耗时。例如在DeepSpeech2 \[[2](#references)\] 的Vanilla RNN部分中,矩阵大小是`batch_size * 2048`。 -2. 转换冗余 \ -由于在现有的某些情况下(例如RNN),多次调用 cblas_?gemm 会使用相同的原数据,因此,每次调用时对原数据的重复Packing便成为了冗余。 - -为了最大程度减少多次调用 cblas_?gemm 在Packing上的耗时,Intel® MKL 引入了以下四个API: - * [cblas_?gemm_alloc](https://software.intel.com/en-us/mkl-developer-reference-c-cblas-gemm-alloc) - * [cblas_?gemm_pack](https://software.intel.com/en-us/mkl-developer-reference-c-cblas-gemm-pack) - * [cblas_?gemm_compute](https://software.intel.com/en-us/mkl-developer-reference-c-cblas-gemm-compute) - * [cblas_?gemm_free](https://software.intel.com/en-us/mkl-developer-reference-c-cblas-gemm-free) - -通过使用这些API,我们可以先完成对原数据的Packing操作,再把已转换为Packed格式的数据传递给那些复用同一数据的gemm_compute函数,从而避免了Packing冗余。 - -### Solution -在RNN的情况下,同一次前向、后向(forward/backward)过程中所有时间步(time step)共享同一个权重(weight)。当只做推断(inference)时,各次前向之间也都使用了相同的权重,没有必要在每次前向中每个时间步的计算时对权重进行重复的Packing操作。 - -我们通过使用新引入的GEMM Packed APIs,在层初始化的时候,先完成对权重的Packing操作,然后在前向,后向时复用已经转换过的权重,并在每次权重更新后,对新的权重进行转换用于下次迭代。 - -* 优化前,对于序列长度(sequence length)为`T`的网络模型(model), `N`次迭代执行的转换次数为: - - `inference`: `N * T` - - `training`: `2 * N * T` -* 优化后,对于同样设置的网络模型,其转换次数减少至: - - `inference`: `1` - - `training`: `2 * N` - -## Actions - -添加的相关文件和目录结构如下: - -```txt -PaddlePaddle/Paddle -├── ... -└── paddle/ - ├── ... - └── gserver/ - ├── ... - ├── layers/ - │ ├── ... - │ ├── MKLPackedRecurrentLayer.* - | ├── MKLPackedGatedRecurrentLayer.* - | ├── MKLPackedLstmLayer.* - | └── MKLPackedGemm.h - └── tests/ - ├── ... - └── test_MKLPacked.cpp -``` - -### CMake -在对应的`CMakeLists.txt`中根据`WITH_MKL`是否打开,来决定是否开启MKL Packed相关功能。 - -### Layers -所有的`MKLPacked*Layer`都继承于PaddlePaddle的基类`Layer`, 并添加头文件 `MKLPackedGemm.h`,该文件对相关GEMM Packed APIs做了封装。 - -### Unit Tests -我们会添加`test_MKLPacked.cpp`用于MKL Packed优化后layer的测试。 -对于每一个新加的RNN layer,我们会对比如下2个方面: -1. 对比优化后layer自身,sequence mode(`rnn_use_batch=false`)与batch mode(`rnn_use_batch=true`)的结果。 -2. 对比优化后layer与相对应的PaddlePaddle原有layer, 在batch mode下的结果。 - -### Python API -计划在`paddle/utils.Flags`中添加`use_mkl_packed`的flag,用于选择是否使用相关功能,并且当编译时`WITH_MKL=ON`的情况下,默认设置为`true`。 - -同时,在`python/paddle/trainer/config_parser.py`中对应的layer处,添加`use_mkl_packed`这个选择,方便用户在Python端选择是否启用这个功能。 - -具体实现方式比如: - -```python -use_mkl_packed = bool(int(g_command_config_args.get("use_mkl_packed", 0))) -if use_mkl_packed: - self.layer_type = mkl_packed_* -``` - -所有相关的`layer_type`会以*mkl_packed_*开头,这些会在`MKLPacked*Layer`注册layer的时候保证,以示区分。 - - -### Benchmarking -会添加相应的脚本用于测试和对比在使用MKL Packed recurrent layers 前后的网络性能。 - -## References -1. [Introducing the new Packed APIs for GEMM](https://software.intel.com/en-us/articles/introducing-the-new-packed-apis-for-gemm) -2. [DeepSpeech2 on PaddlePaddle](https://github.com/PaddlePaddle/DeepSpeech#deepspeech2-on-paddlepaddle) - diff --git a/develop/doc/_sources/design/mkl/mkldnn.md.txt b/develop/doc/_sources/design/mkl/mkldnn.md.txt deleted file mode 100644 index e2fe1e6b26f..00000000000 --- a/develop/doc/_sources/design/mkl/mkldnn.md.txt +++ /dev/null @@ -1,210 +0,0 @@ -# Intel® MKL-DNN on PaddlePaddle: Design Doc - -我们计划将英特尔深度神经网络数学库[Intel MKL-DNN](https://github.com/01org/mkl-dnn) -(Intel Math Kernel Library for Deep Neural Networks)集成到PaddlePaddle, -充分展现英特尔平台的优势,有效提升PaddlePaddle在英特尔架构上的性能。 - -
-
-Figure 1. PaddlePaddle on IA -
- -近期目标 - -- 完成常用Layer的MKL-DNN实现。 -- 完成常见深度神经网络VGG,GoogLeNet 和 ResNet的MKL-DNN实现。 - -目前的优化,主要针对PaddlePaddle在重构之前的代码框架以及V1的API。 -具体的完成状态可以参见[这里](https://github.com/PaddlePaddle/Paddle/projects/21)。 - -## Contents - -- [Overview](#overview) -- [Actions](#actions) - - [CMake](#cmake) - - [Matrix](#matrix) - - [Layers](#layers) - - [Activations](#activations) - - [Parameters](#parameters) - - [Gradients](#gradients) - - [Unit Tests](#unit-tests) - - [Python API](#python-api) - - [Benchmarking](#benchmarking) - - [Others](#others) -- [Design Concerns](#design-concerns) - -## Overview - -我们会把MKL-DNN会作为第三方库集成进PaddlePaddle,与其他第三方库一样,会在编译PaddlePaddle的时候下载并编译MKL-DNN。 - -同时,为了进一步提升PaddlePaddle在基本数学运算的计算速度,我们也将MKLML即(MKL small library\[[1](#references)\]) -作为另一个第三方库集成进PaddlePaddle,它只会包括生成好的动态库和头文件。 - -MKL,MKLML以及MKL-DNN三者关系如下表: - -| Name | Open Source | License | Descriptions | -| :---------- | :--------------- | :---------- | :------------ | -| MKL | No | Proprietary | Accelerate math processing routines | -| MKLML | No | Proprietary | Small package of MKL, especially for Machine Learning | -| MKL-DNN | Yes | Apache 2.0 | Accelerate primitives processing routines especially for Deep Neural Networks | - -MKLML可以与MKL-DNN共同使用,以此达到最好的性能。 - -
-
-Figure 2. PaddlePaddle with MKL Engines -
- -## Actions - -添加的相关文件和目录结构如下: - -```txt -PaddlePaddle/Paddle -├── ... -├── cmake/ -│ ├── external/ -│ │ ├── ... -│ │ ├── mkldnn.cmake -│ │ └── mklml.cmake -└── paddle/ - ├── ... - ├── math/ - │ ├── ... - │ └── MKLDNNMatrix.* - └── gserver/ - ├── ... - ├── layers/ - │ ├── ... - │ └── MKLDNN*Layer.* - ├── activations/ - │ ├── ... - │ └── MKLDNNActivations.* - └── tests/ - ├── ... - ├── MKLDNNTester.* - └── test_MKLDNN.cpp -``` - -### CMake -在`CMakeLists.txt`中提供一个与MKL有关的总开关:`WITH_MKL`,它负责决定编译时是否使用MKLML和MKL-DNN - -- `WITH_MKLML` 控制是否使用MKLML库。 -当打开`WITH_MKL`时,会自动使用MKLML库作为PaddlePaddle的CBLAS和LAPACK库,同时会开启Intel OpenMP用于提高MKLML的性能。 -编译时会把对应的头文件和库放在`build/third_party/install/mklml/*`目录下对应的地方。 -MKLML的库目前都是动态库,主要包括`libiomp5.so`和`libmklml_intel.so`。 -- `WITH_MKLDNN` 控制是否使用MKL-DNN。 -当开启`WITH_MKL`时,会自动根据硬件配置[[2](#references)]选择是否编译MKL-DNN。 -编译时会把对应的头文件和库放在`build/third_party/install/mkldnn/*`目录下对应的地方。 -MKL-DNN的库目前只有动态库`libmkldnn.so`。 - -### Matrix -目前在PaddlePaddle中数据都是以`NCHW`的格式存储,但是在MKL-DNN中的排列方式不止这一种。 -所以我们定义了一个`MKLDNNMatrix`用于管理MKL-DNN数据的不同格式以及相互之间的转换。 - -
-
-Figure 3. MKLDNNMatrix -
- -### Layers -所有MKL-DNN的Layers都会继承于`MKLDNNLayer`,该类继承于PaddlePaddle的基类`Layer`。 -在`MKLDNNLayer`中会提供一些必要的接口和函数,并且会写好`forward`和`backward`的基本逻辑, -子类只需要使用定义好的接口,实现具体的函数功能即可。 - -
-
-Figure 4. MKLDNNLayer -
- -每个MKLDNNLayer都包含用于内部存储和外部存储的一系列MKLDNNMatrix: - -- 内部存储(internel memory):`inVal_`,`inGrad_`,`outVal_`和`outGrad_`,分别代表输入数据,输入梯度,输出数据和输出梯度。 -- 外部存储(external memory):都是以ext开头,比如`extInVal_`和`extInGrad_`,它们主要是用于, -当数据格式与PaddlePaddle默认的`NCHW`格式不匹配时,转换内存的工作。 -需要注意的是,PaddlePaddle的activation会直接使用`output_.value`和`output_.grad`, -所以`extOutVal_`和`extOutGrad_`必须分别与`output_.value`和`output_.grad`共享内存, -如果不需要外部存储用于转换,那么对应的内部存储也会与它们共享内存。 -- 转换函数(resetXXX): 包括`resetInValue`,`resetInGrad`,`resetOutValue`和`resetOutGrad`, -表示对输入数据,输入梯度,输出数据和输出梯度的转换。 -这些函数会根据输入参数重新设置内部和外部存储,当然这两者也可以相等,即表示不需要转换。 - -注意:每个`MKLDNNlayer`的子类只需要使用内部存储就可以了,所有外部的转换工作都会在reset系列函数中都准备好。 - -### Activations -在重构前的PaddlePaddle中,激活函数是独立于`Layer`的概念,并且输入输出都是共用一块内存, -所以添加了对应的`MKLDNNActivation`来实现,方式类似于`MKLDNNLayer`。 - -### Parameters -对于有参数的层,我们会保证`MKLDNNLayer`使用的参数与PaddlePaddle申请的buffer共用一块内存。 -如果存在数据排列格式不一样的情况时,我们会在网络训练之前把格式转换为MKL-DNN希望的格式, -在训练结束的时候再保存为PaddlePaddle的格式,但是整个训练过程中不需要任何转换。 -这样既使得最终保存的参数格式与PaddlePaddle一致,又可以避免不必要的转换。 - -### Gradients -由于MKL-DNN的操作都是直接覆盖的形式,也就是说输出的结果不会在原来的数据上累加, -这样带来的好处就是不需要一直清空memory,节省了不必要的操作。 -但是注意的是,当网络出现分支且在`backward`的时候,需要累加不同Layer传过来的梯度。 -所以在`MKLDNNlayer`中实现了一个merge的方法,此时每个小分支的`Input Gradient` -会先临时保存在`MKLDNNMatrix`中,由分支处的Layer负责求和,并把结果放到当前层的`output_.grad`中。 -所以整体上,在实现每个子类的时候就不需要关心分支的事情了。 - -
-
-Figure 5. Merge Gradients -
- -### Unit Tests -我们会添加`test_MKLDNN.cpp`和`MKLDNNTester.*`用于MKL-DNN的测试。 -测试分为每个Layer(或Activation)的单元测试和简单网络的整体测试。 -每个测试会对比PaddlePaddle中CPU算出的结果与MKL-DNN的结果,小于某个比较小的阈值认为通过。 - -### Python API -目前只考虑**v1 API**。 - -计划在`python/paddle/trainer/config_parser.py`里面添加`use_mkldnn`这个选择,方便用户选择使用MKL-DNN的layers。 - -具体实现方式比如: - -```python -use_mkldnn = bool(int(g_command_config_args.get("use_mkldnn", 0))) -if use_mkldnn - self.layer_type = mkldnn_* -``` - -所有MKL-DNN的`layer_type`会以*mkldnn_*开头,这些会在`MKLDNN*Layer`注册layer的时候保证,以示区分。 - -同时,会在`paddle/utils.Flags`中添加一个`use_mkldnn`的flag,用于选择是否使用MKL-DNN的相关功能。 - -### Benchmarking -会添加相应的脚本在[这里](https://github.com/PaddlePaddle/Paddle/tree/develop/benchmark/paddle/image),用于测试和对比在使用MKL-DNN前后的CNN网络性能。 -测试的性能对比结果会在[IntelOptimizedPaddle.md](https://github.com/PaddlePaddle/Paddle/blob/develop/benchmark/IntelOptimizedPaddle.md) - -### Others -1. 如果在使用MKL-DNN的情况下,会把CPU的Buffer对齐为4096,具体可以参考MKL-DNN中的[memory](https://github.com/01org/mkl-dnn/blob/master/include/mkldnn.hpp#L673)。 -2. 深入PaddlePaddle,寻找有没有其他可以优化的可能,进一步优化。比如可能会用OpenMP改进SGD的更新性能。 - -## Design Concerns - -为了更好的符合PaddlePaddle的代码风格\[[3](#references)\],同时又尽可能少的牺牲MKL-DNN的性能\[[4](#references)\]。 - -我们总结出一些特别需要注意的点: - -1. 使用**deviceId_**。为了尽可能少的在父类Layer中添加变量或者函数, -我们决定使用已有的`deviceId_`变量来区分layer的属性,定义`-2`为`MKLDNNLayer`特有的设备ID。 -2. 重写父类Layer的**init**函数,修改`deviceId_`为`-2`,代表这个layer是用于跑在MKL-DNN的环境下。 -3. 创建`MKLDNNBase`,定义一些除了layer和memory相关的类和函数。 -包括MKL-DNN会用到`MKLDNNStream`和`CPUEngine`,和未来可能还会用到`FPGAEngine`等。 -4. 如果MKL-DNN layer的后面接有cpu device,那么就会使`output_.value`与`extOutVal_`共享内存, -同时数据格式就是`NCHW`,这样下一个cpu device就能拿到正确的数据。 -在有普通的CPU layer时, `extOutVal_`和`extOutGrad_`的格式始终是`NCHW`或者`NC`。 - -## References -1. [MKL small library](https://github.com/01org/mkl-dnn#linking-your-application)是[Intel MKL](https://software.intel.com/en-us/mkl)的一个子集。 -主要包括了深度学习相关的数学原语与操作,一般由MKL-DNN在发布[新版本](https://github.com/01org/mkl-dnn/releases)时一起更新。 -2. [MKL-DNN System Requirements](https://github.com/01org/mkl-dnn#system-requirements)。 -目前在PaddlePaddle中,仅会在支持AVX2指令集及以上的机器才使用MKL-DNN。 -3. [原来的方案](https://github.com/PaddlePaddle/Paddle/pull/3096)会引入**nextLayer**的信息。 -但是在PaddlePaddle中,无论是重构前的layer还是重构后的op,都不会想要知道next layer/op的信息。 -4. MKL-DNN的高性能格式与PaddlePaddle原有的`NCHW`不同(PaddlePaddle中的cuDNN部分使用的也是`NCHW`,所以不存在这个问题)。 -所以需要引入一个转换方法,并且只需要在必要的时候转换这种格式,才能更好的发挥MKL-DNN的性能。 diff --git a/develop/doc/_sources/design/mkl/mkldnn_fluid.md.txt b/develop/doc/_sources/design/mkl/mkldnn_fluid.md.txt deleted file mode 100644 index bef126f3f05..00000000000 --- a/develop/doc/_sources/design/mkl/mkldnn_fluid.md.txt +++ /dev/null @@ -1,149 +0,0 @@ -# Design Doc: Add MKLDNN Kernel in Fluid Operator - -## Principles - -First of all, we should follow some basical principles like: -1. [How to write a new operator](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/dev/new_op_en.md). We are trying to add a new kind of kernel into operators, so basically we should follow this doc. -2. [Supporting new Device/Library](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/support_new_device.md). Since MKLDNN is a new library to fluid, we should add `MKLDNNDeviceContext` and maybe `mkldnn_helper.h`, just like [cudnn_helper.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/cudnn_helper.h). -3. [Switch Kernel](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/switch_kernel.md). Another important point is that we should ensure the data synchronization between different kernel types, which is this [topic](https://github.com/PaddlePaddle/Paddle/issues/6549). So basically we should override `GetExpectedKernelType` and `trans` functions to support switching kernels. -4. [The Keys of Operator Kernel Type](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/operator_kernel_type.md). Kernel Type is a pivotal conception which can record the `Place`, `Library`, `DataType` and `Layout`. - -## Sulution - -In general, there are four parts we should follow to run a MKL-DNN primitive. -- Create a primitive descriptor that describe this operator -- Create a primitive itself by primitive descriptor and the engine -- Create all memory buffers that primitive needed -- Launch a stream to execute the primitive created -More details can refer to [here](http://01org.github.io/mkl-dnn). - -It's better to avoid reinitialization of primitives and memory handles in the first three stages in every iteration. \ -So we plan to create a map to record all the `primitive` and `memory`, which should not take too much memories as discussed [here](https://github.com/PaddlePaddle/Paddle/issues/6822). - -It's assumed that following three conditions should be satisfied. -1. there is a unique key for each operator instance. May be the actual name of `Output Tensor`. -2. the `Input Tensor` inside `Compute` function is the one after converted. -3. we can get the phase(eg. `is_test`) inside `Compute` function, otherwise we need to expose this attribue to user. - -### Compute -The algorithm of `Compute` would be described as follow, let's take conv like an example. - -```c++ - - PADDLE_ENFORCE(platform::is_cpu_place(ctx.GetPlace()), "It must use CPUPlace."); - PADDLE_ENFORCE(platform::is_mkldnn_library(ctx.GetLibrary()), "It must use MKLDNN Library."); - - auto& dev_ctx = ctx.template device_context(); - - // find primitive by unique key from mkldnn context - // the op_key should be a unique name of this op instance - auto& p = dev_ctx.findPrimitive(op_key + "_fwd"); - - // assuming the input tensor inside this compute function is the one after converted - // this point should be guarantee by another mechanism - auto& i = dev_ctx.findMemory(op_key + "_input"); - - if (p == nullptr || i == nullptr || inputSizeChanged(p, i)) { - auto fwd_primitive_desc = createPrimitiveDesc(ctx); - auto* input = ctx.Input("Input"); - auto* filter = ctx.Input("Filter"); - auto* output = ctx.Output("Output"); - shared_ptr in(new mkldnn::memory(fwd_primitive_desc->src_primitive_desc(), input->data())); - shared_ptr wgt(new mkldnn::memory(fwd_primitive_desc->weights_primitive_desc(), filter->data())); - shared_ptr out(new mkldnn::memory(fwd_primitive_desc->dst_primitive_desc(), output->mutable_data(ctx.GetPlace()))); - shared_ptr fwd_primitive(new mkldnn::conv_fwd(*fwd_primitive_desc, *in, *wgt, *out)); - - dev_ctx.addMemory(op_key+"_input", in); - dev_ctx.addMemory(op_key+"_output", out); - dev_ctx.addMemory(op_key+"_filer", wgt); - dev_ctx.addPrimitive(op_key+"_fwd", fwd_primitive); - dev_ctx.addPrimitiveDesc(op_key+"_fwd_PD", fwd_primitive_desc); - } - - p = dev_ctx.findPrimitive(op_key + "_fwd"); - - PADDLE_ENFORCE(p, "Should have forward Primitive"); - PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_input"), "Should have input memory"); - PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_output"), "Should have output memory"); - PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_filter"), "Should have filter memory"); - PADDLE_ENFORCE(dev_ctx.findPrimitiveDesc(op_unique_key+"_fwd_PD"), "Should have forward PrimitiveDesc"); - dev_ctx.submit(p); - dev_ctx.execute(); // the convert primitive should have already contained. - -``` - -The `createPrimitiveDesc` returns the primitive descripotor of this operator, would be like this: -```c++ - auto* input = ctx.Input("Input"); - auto* filter = ctx.Input("Filter"); - auto* output = ctx.Output("Output"); - std::vector strides = ctx.Attr>("strides"); - std::vector paddings = ctx.Attr>("paddings"); - std::vector dilations = ctx.Attr>("dilations"); - int groups = ctx.Attr("groups"); - algorithm algo = static_cast(ctx.Attr("convolution_algorithm_option")); - prop_kind pk = ctx.Attr("is_test") ? prop_kind::forward_inference : prop_kind::forward_training; - - auto fwd_desc = mkldnn::conv_fwd::desc(/* all the setting above*/); - shared_ptr fwd_primitive_desc(new mkldnn::conv_fwd::primitive_desc(fwd_desc, ctx.getEngine())); - - return fwd_primitive_desc; - } -``` - -### MKLDNNDeviceContext -`MKLDNNDeviceContext`, which is very straightforward, should contain some base information like: `stream`, `engine` and the map needed. - - -### mkldnn_helper -Some functions would be put in `paddle/platform/mkldnn_helper.h`. -- create MKLDNN memories -- create MKLDNN primitives -- error check function -- etc - - -### Kernel Switch -We should `reorder` the different Layout from other device or to other device. `GetExpectedKernelType` and `trans` functions can help us to implement it. - -`GetExpectedKernelType` should get the context, and this operator can return the best `KernelType`. -`trans` would be like this: - -```c++ -void trans(inputs, ctx) override { - if (NoNeedTrans()) { - return; - } - // find reorder primitive by op_key from context - auto& dev_ctx = ctx.template device_context(); - auto& p = dev_ctx.findPrimitive(op_key + "_reorder_input"); - auto& i = dev_ctx.findMemory(op_key + "_src_input"); - - if (p == nullptr || i == nullptr || changeSized(i, input)) { - auto prim = createPrimitiveDesc(ctx); - auto src = createMemory(memoryDesc(input->dims(), actual_layout), input->data); - auto newbuffer = paddle::memory::Alloc(ctx.GetPlace(), input->size_in_bytes()); - auto dst = createMemory(p->expected_desc(), newbuffer->data); - auto reorder_primitive(new mkldnn::reorder(src, dst)); - - dev_ctx.addMemory(op_key+"_src_input", src); - dev_ctx.addMemory(op_key+"_input", dst); - dev_ctx.addPrimitive(op_key+"_reorder_input", reorder_primitive); - } - - p = dev_ctx.findPrimitive(op_key + "_reorder_input"); - PADDLE_ENFORCE(p, "Should have Reorder Primitive"); - dev_ctx.submit(p); - if (! this->isMKLDNNKernel()) { - // execute immediately only if this is not mkldnn kernel function. - // otherwise, it can be executed with the operator primitive in Compute - dev_ctx.stream(); - } - // after submit, the input tensor in ExecutionContext should be changed as the converted one - // there should be another mechanism to ensure this -} -``` - -### Unit Test -All the functions should be tested corresponding. -TBD diff --git a/develop/doc/_sources/design/model_format.md.txt b/develop/doc/_sources/design/model_format.md.txt deleted file mode 100644 index e29129fddf7..00000000000 --- a/develop/doc/_sources/design/model_format.md.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Design Doc: Model Format - -## Motivation - -A model is an output of the training process. One complete model consists of two parts, the **topology** and the **parameters**. In order to support industrial deployment, the model format must be self-complete and must not expose any training source code. - -As a result, In PaddlePaddle, the **topology** is represented as a [ProgramDesc](https://github.com/PaddlePaddle/Paddle/blob/1c0a4c901c9fc881d120249c703b15d1c50dae7d/doc/design/program.md), which describes the model structure. The **parameters** contain all the trainable weights in the model. We must support large size parameters and efficient serialization/deserialization of parameters. - -## Implementation - -The topology is saved as a plain text in a detailed self-contain protobuf file. - -The parameters are saved as a binary file. As we all know, the protobuf message has a limit of [64M size](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.io.coded_stream#CodedInputStream.SetTotalBytesLimit.details). We have done a [benchmark experiment](https://github.com/PaddlePaddle/Paddle/pull/4610), which shows that protobuf is not fit for the task. - -As a result, we design a particular format for tensor serialization. By default, an arbitrary tensor in Paddle is a [LoDTensor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/lod_tensor.md), and has a description information proto of [LoDTensorDesc](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto#L99). We save the DescProto as the byte string header. It contains all the necessary information, such as the `dims`, and the `LoD` information in [LoDTensor](https://github.com/PaddlePaddle/Paddle/blob/1c0a4c901c9fc881d120249c703b15d1c50dae7d/paddle/framework/lod_tensor.md). A tensor stores values in a continuous memory buffer. For speed we dump the raw memory to disk and save it as the byte string content. So, the binary format of one tensor is, - -The table below shows a tensor's byte view in detail. Note that all the signed values are written in the little-endian format. - -|field name | type | description | -| --- | --- | --- | -| version | uint32_t | Version of saved file. Always 0 now. | -| tensor desc length | uint32_t | TensorDesc(Protobuf message) length in bytes. | -| tensor desc | void* | TensorDesc protobuf binary message | -| tensor data | void* | Tensor's data in binary format. The length of `tensor_data` is decided by `TensorDesc.dims()` and `TensorDesc.data_type()` | -| lod_level | uint64_t | Level of LoD | -| length of lod[0] | uint64_t | [Optional] length of lod[0] in bytes. | -| data of lod[0] | uint64_t* | [Optional] lod[0].data() | -| ... | ... | ... | - - - -## Summary - -- We introduce a model format. -- The model represented by its forward-pass computation procedure is saved in a **ProgramDesc** protobuf message. -- A bunch of specified format binary tensors describe the **parameters**. diff --git a/develop/doc/_sources/design/multi_language_interface/00.why_plain_c.md.txt b/develop/doc/_sources/design/multi_language_interface/00.why_plain_c.md.txt deleted file mode 100644 index a1443093342..00000000000 --- a/develop/doc/_sources/design/multi_language_interface/00.why_plain_c.md.txt +++ /dev/null @@ -1,118 +0,0 @@ -# Paddle多语言接口实现 -## 背景 - -Paddle需要一个多语言接口,这个接口需要做到: - -* 有标准的,良好的文档 - * 例如Python可以使用[Sphinx](http://www.sphinx-doc.org/en/stable/)生成API文档,golang可以使用[GoDoc](https://godoc.org/golang.org/x/tools/cmd/godoc)生成文档。这都需要这个接口按照约定俗成的规则来注释完备。 -* 不同语言的接口适应不同语言的特性 - * 例如Java与Python的错误处理是直接扔出来Exception,而对于golang错误处理应该使用返回值。 - -## 基本要求 - -Paddle的多语言接口实现包括一下几个方面: - -* 我们使用动态库来分发Paddle。在这个动态库中不嵌入任何其他语言的解释器,也不使用其他动态库。 -* 这个动态库使用C99标准的头文件导出一些函数,不使用/导出C++符号。 -* 不导出Paddle内部的结构体、类,仅仅使用`void*`指针作为类型的句柄(handler)。 -* 不使用SWIG这种代码生成器,而是手写多语言绑定。 - - -## 原因 - -### 使用动态库来分发Paddle - -* Paddle的链接方式比较复杂 - * 如果用户要把Paddle的静态库(libpaddle.a)链接到自己的程序里,得使用 `--whole-archive` (for GCC) 或者 `--force_load` (for Clang) 参数,来确保把 libpaddle.a 里所有的符号都写入自己的程序的二进制文件里。这是因为 Paddle 的源码里使用了[object factory design pattern](http://stackoverflow.com/a/1310326/724872)。 -* 编译型语言,例如C/C++使用静态库和动态库难度差不多。但是解释性语言,例如[Python](http://stackoverflow.com/questions/19560594/how-to-import-static-library-in-python)或者[Java](http://stackoverflow.com/questions/24493337/linking-static-library-with-jni),只能调用Paddle的动态库,否则得把Paddle静态库链接到解释器里。 - * 解释性语言实际运行的二进制是解释器本身,如果调用静态库只能将静态库与解释器链接。例如对于Java来说,便是将静态库加入JVM中。这对于通常的Java的开发者来说,是不常见的做法。 - -### 动态库中不嵌入任何其他语言的解释器 - -* 目前Paddle的进程模型是C++内部驱动Python解释器进行模型配置解析和数据读取 -* 我们最终的动态库中不嵌入Python或者其他任何语言的解释器。模型配置解析,数据读取均交由其他语言完成 - -现阶段Paddle有一个问题是,Paddle内嵌的Python解释器和外部使用的Python如果版本不同,会直接报错退出。 - -### Paddle动态库中,不引用其他动态库 - -* 即这个动态库是不依赖于其他任何文件的,可以在任何机器上执行的。 - -### 这个动态库使用C99标准的头文件导出一些函数,不使用/导出C++符号 - -* 由于C++编译器没有[名字修饰](https://en.wikipedia.org/wiki/Name_mangling#C.2B.2B)的规范,不同版本的编译器之间,对于同一段C++代码生成的符号可能不一致。而多语言接口需要直接读取生成的二进制(动态库),需要有稳定的导出符号。 -* C语言是有导出符号的标准的,并且在常见的平台上,都是ABI调用标准的。 -* 大多数语言都支持使用C语言API -* 使用C99而不使用C89,是因为C99支持[Fixed-width integer types](https://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types)和[Boolean type](https://en.wikipedia.org/wiki/C_data_types#Boolean_type)。 -* 使用C99而不使用C11的原因是,[C11](https://en.wikipedia.org/wiki/C11_(C_standard_revision))并没有Paddle特别需要的特性,且C99相对于C11使用更加广泛。 - -### 不导出Paddle内部的结构体、类,仅仅使用`void*`指针作为类型的句柄(handler) - -* Paddle内部的类为C++书写,直接导出到C的接口比较困难。 -* 在C-API中使用`void*`来表示Paddle内部类。再在每一个API中自己检查类型。 - -在C的头文件 `paddle_matrix.h` 中: - -```C -typedef void* paddle_matrix; -typedef int paddle_error; - -extern "C" -paddle_error paddle_matrix_get_shape(paddle_matrix matrix, - uint64_t* width, - uint64_t* height); -``` -而在CPP里面实现这个C的接口,文件 `paddle_matrix.cpp` - -```cpp -#include "paddle/math/matrix.h" -extern "C" -paddle_error paddle_matrix_shape(paddle_matrix matrix, - uint64_t *width, - uint64_t *height) { - auto m = (paddle::capi::CMatrix*)(matrix); - *width = m->width(); - *height = m->height(); -} -``` - -其中`paddle/capi/CMatrix.hpp`文件内容为: - -```cpp -namespace paddle { -namespace math { - -class CMatrix { - std::shared_ptr mat; -}; - -} // namespace math -} // namespace paddle -``` - -### 不使用SWIG这种代码生成器,而是手写多语言绑定 - -* [SWIG](http://www.swig.org/)是一个多语言接口的代码生成器。他的目标是使用C/C++写代码,SWIG直接读取C/C++的头文件,生成各种语言的绑定代码。 - * 对于多语言接口,SWIG需要写一个interface文件。这个文件具有独特的语法,学习成本高。且增加一个第三方语言,就需要对这个第三方语言增加一些定义。有的时候,interface文件的写法非常[tricky](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/api/Paddle.swig#L36)。社区贡献代码学习成本高。 - * SWIG暴露的接口保留了C++的接口样式,很难保证多语言代码风格的一致性。(函数命名,错误处理) - * 因为SWIG在第三方语言中暴露的函数名,类名和C++中完全一致。C++的命名风格并不能适应其他第三方语言。如果使用SWIG我们需要将在interface文件里,将大量的`SomeCppClass`重命名成`some_python_class`,或者`SomeGoTypes`。 - * 对于不同语言,错误处理的方式也不尽相同。例如对于Java或者Python,最常见的错误处理方式是Exception,而对于Golang,错误处理方式是返回值。而SWIG只能简单的暴露C++接口,无法做到对于各种语言错误处理方式的适配。 - * 对于大多数语言,直接使用C语言的.h并不困难。例如Python的[cffi](https://cffi.readthedocs.io/en/latest/overview.html#simple-example-abi-level-in-line)或者[Cython](http://cython.org/), golang的[cgo](https://golang.org/cmd/cgo/)。 - * SWIG支持的语言或者解释器有局限。例如对于Python,使用SWIG只支持CPython解释器,而不支持PyPy解释器。 - - -## 原因列表 - -| 结论 | 对比 | 原因 | -|---| --- | --- | -| 使用动态库 | 不使用静态库 | 解释型语言只能调用动态库,Paddle静态库链接复杂 | -| 不嵌入其他语言解释器 | 不嵌入Python解释器 | Paddle C++目前嵌入Python解释器,会导致不同版本Python在一个进程里的bug | -| 不引用其他动态库 | | Paddle一个动态库可以在任何Linux系统上运行 | -| 使用C99做接口 | 不使用C++做接口 | C有标准的ABI,C99是目前C最广泛的使用标准,且C99支持bool类型和定长整数(uint64_t等)类型 | -| 使用void*作为类句柄 | 不显示的写每个类具体包含什么| 实现简单,并且让接口脱离实现细节 | -| 手写多语言绑定 | 不使用SWIG | 使用SWIG需要多语言绑定的开发人员熟练掌握SWIG配置,社区参与困难。SWIG生成的代码不能保证多语言代码风格的一致性 | - - -## 实现 - -参考[Inference implementation](01.inference_implementation.md) diff --git a/develop/doc/_sources/design/multi_language_interface/01.inference_implementation.md.txt b/develop/doc/_sources/design/multi_language_interface/01.inference_implementation.md.txt deleted file mode 100644 index 98202845232..00000000000 --- a/develop/doc/_sources/design/multi_language_interface/01.inference_implementation.md.txt +++ /dev/null @@ -1,131 +0,0 @@ -# C-API 模型推断实现文档 - -本文档描述Paddle C-API的实现细节。Paddle C-API是多语言API的基础部分。Paddle需要暴露的API很多。先实现模型推断的API,通过模型推断API的实现作为一个样例,来进行讨论。至于为什么需要C-API,请参考[Why Plain C](./00.why_plain_c.md)。 - -## Table of Contents - * [C-API 模型推断实现文档](#c-api-模型推断实现文档) - * [暴露接口原则](#暴露接口原则) - * [目录结构](#目录结构) - * [实现方式](#实现方式) - * [capi.h](#capih) - * [具体某种类型的头文件](#具体某种类型的头文件) - * [capi_private.h](#capi_privateh) - * [具体某种类型的实现文件](#具体某种类型的实现文件) - * [libpaddle_capi_shared.{so, dylib}](#libpaddle_capi_sharedso-dylib) - * [libpaddle_capi_whole.a](#libpaddle_capi_wholea) - * [examples](#examples) - * [编译选项](#编译选项) - - -## 暴露接口原则 - -1. 所有的接口均为C接口。即使用`extern "C"` -2. 除构造某种类型的函数(`paddle_matrix_create`等),其他函数均返回`paddle_error`。且调用时不能抛出异常或出现运行时错误。 -3. 所有类型名为`paddle_类型名`,所有与类型相关的函数,函数名为`paddle_类型名_函数名` -4. 如果某一个Paddle Core概念(GradientMachine/Matrix)需要被暴露到其他语言,那么 - * 为了暴露的接口尽量简单。只暴露概念的接口,而不暴露概念的实现。即暴露`GradientMachine`或者`Matrix`但不暴露`RecurrentGradientMachine`和`CpuSparseMatrix`。 - * 暴露这个概念必要函数。`必要`是指,即完成某一个任务的最少函数。 -5. 不在`capi`接口层做过多封装。 - * 如果某一个Paddle概念必须要暴露,但是又过于琐碎。不在`capi`这一层进行封装,而是直接修改Paddle Core。让Paddle核心中,这一概念不再琐碎。 - - -## 目录结构 - -```text -Paddle - `-- paddle - `-- capi - `-- examples # The example project for C-API. - `-- tests # unittests for C-API - `-- capi.h # C-API header file. - `-- capi_private.h # The shared header file between implementation sources. - `-- matrix.{h, cpp} - `-- gradient_machine.{h, cpp} - `-- ... -``` - - -Paddle的C-API目录结构如上图表所示。这个目录中除了`capi_private.h`之外的所有头文件,均会被安装到include/paddle路径下。C-API生成的二进制文件会被安装到`lib`目录下。即,安装后的目录结构为 - -```text -`-- include - `-- paddle - `-- capi.h - `-- matrix.h - `-- gradient_machine.h - `-- ... -`-- lib - `-- libpaddle_capi_shared.{so, dylib} # In mac, dynamic libary's file name extention is `dylib` - `-- libpaddle_capi_whole.a # static library for all symbols of Paddle. -``` - -## 实现方式 - -下面分别介绍某一类文件的实现方式。 - -### capi.h - -`capi.h`是用户使用C-API时所唯一需要引入的头文件。在`capi.h`中,引入了类型的头文件,`matrix.h`, `gradient_machine.h`。在引入其他类型的头文件时,使用相对路径的引用方式。即`#include "matrix.h"` - -### 具体某种类型的头文件 - -具体某种类型的头文件,即例如`matrix.h`,`gradient_machine.h`等。在这些头文件中,包含了某种类型的类型定义和暴露的全部函数。 - -这个头文件不假设其他文件的引用顺序,即使用户直接引用某种类型的头文件,也不应该报错(虽然不鼓励这样)。如果某一个类型需要引用另一个类型,例如`gradient_machine`需要引用`matrix`,则直接引入另一种类型的头文件,即`#include "matrix.h"`。 - -### capi_private.h - -`capi_prviate.h`是各个实现中共享的头文件,他主要包含了实际暴露的类型结构。在用户使用C-API时,Paddle的类型全部退化成`void *`,即`typedef paddle_matrix void*`。但,对于每种C-API暴露的类型,均是在`capi_private.h`中实现的结构体。 - -```cpp -struct CMatrix { - int type = MatrixType; - std::shared_ptr mat; -}; -``` - -通常,这个结构体包含两个项目。 - -* `type`是一个类型的标志。对于每种类型,type字段均不尽相同。这样,即使C-API接受的类型全是`void *`,我们也可以确定每一个参数的类型。 - - ```cpp - void some_c_api_function(void* some_instance) { - int* type = (int *) some_instance; - switch (*type) { - case MatrixType: - CMatrix* mat = (CMatrix *) some_instance; - ... - ... - } - } - ``` -* 这个结构体中的另一个项目是,Paddle Core中这一类型接口的智能指针(shared_ptr)。 - * 使用智能指针的原因是: 用户可以安全的释放某个C-API的实例,而不必在意Paddle Core是否还在使用这个实例。 - * 例如,用户通过C-API获得了神经网络的参数实例。当用户使用完这个参数后,直接删除这个参数即可。即便Paddle Core中的模型还在使用这个参数,这个参数也不会一并删除。 - -### 具体某种类型的实现文件 - -具体某种类型的实现文件,即`matrix.cpp`, `gradient_machine.cpp`等文件。在这些文件中,使用C++ 11实现了C-API的接口,并且使用`extern "C"`导出这些接口。在实现过程中,对输入参数的安全性进行了必要的判断,并将C-API接口的参数转发给`Paddle Core`。 - -### libpaddle\_capi_shared.{so, dylib} - -`libpaddle_capi_shared`是C-API导出的动态库。这个动态库的连接参数与Paddle的其他二进制(例如`paddle_trainer`)类似。用户可以直接使用这个动态库来引入Paddle C-API。具体使用方法为`-lpaddle_capi_shared`。 - -### libpaddle\_capi_whole.a - -`libpaddle_capi_whole`是C-API导出的静态库。这个静态库包含了Paddle的全部符号。他是将`libpaddle_gserver.a`, `libpaddle_math.a`, `libpaddle_capi.a`等全部静态库中的目标文件全部打包后产生的文件。具体使用方法为`--whole-archive -lpaddle_capi_whole --no-whole-archive`。 - - -### examples - -在样例中,使用`C99`开发了模型预测的样例代码。具体请参考[example/README.md](../../../paddle/capi/examples/README.md)。 - -## 编译选项 - -C-API的编译选项默认关闭,打开这个编译选项,需要在cmake的时候,设置 - -```bash -cmake ${YOUR_SOURCE_ROOT} -DWITH_C_API=ON -DWITH_PYTHON=OFF -DWITH_SWIG_PY=OFF -``` - -编译C-API的时候推荐Paddle不嵌入Python解释器,也不生成`SWIG`接口,具体原因参考[Why Plain C](./00.why_plain_c.md)。 diff --git a/develop/doc/_sources/design/operator_kernel_type.md.txt b/develop/doc/_sources/design/operator_kernel_type.md.txt deleted file mode 100644 index f86e6b7a564..00000000000 --- a/develop/doc/_sources/design/operator_kernel_type.md.txt +++ /dev/null @@ -1,91 +0,0 @@ -# Design Doc: The Keys of Operator Kernel Type -## Problem -An operator can have different kernel implementations, and each operator will have a map to store the related kernels. Fluid uses `OpKernelType` as a key to identify a unique kernel. Before an operator runs, a certain type of kernel must be chosen via a key of `OpKernelType`. Currently, `OpKernelType` is defined as follows: - -```cpp -struct OpKernelType { - platform::Place place_; - proto::DataType data_type_; -}; -``` -For more details, please refer to [codes](https://github.com/PaddlePaddle/Paddle/blob/2d5ec16bc8a09fb8e0f62c89b116b0cd1d333907/paddle/framework/operator.h#L348-L374) in github. - -It contains two keys, `Place` and `DataType`. And these two keys will be hashed to a unique key to represent a certain type of kernel. However, these two keys do not provide enough information. We need a more complete representation of `OpKernelType`. - -We often implement a kernel of an operator with some computing library on certain device(place). Please note that computing library and device do not have a one-to-one correspondence. A device can have a lot of computing libraries and a computing library can also support different devices. - -For example, Eigen library supports Nvidia GPU/AMD GPU/CPU and MKLDNN library supports Intel CPU/Intel FPGA. Both `Place` and `Library` should be a key of `OpKernelType`. - -Different DataTypes, such as fp64/fp32/int8, will obviously have different kernels. But different data layout of a Tensor will also lead to different implementations. Please refer to the batch norm operator [kernels](https://github.com/PaddlePaddle/Paddle/blob/a948fac4d0ad7e0412d373b8aabeb711c2899563/paddle/operators/batch_norm_op.cc#L180-L209) as an example. Data layout should also be taken into consideration. - -## Solution - -There are four keys to determine a kernel type of an operator: `Place`/`Library`/`DataType`/`Layout`. - -```cpp -struct OpKernelType { - platform::Place place_; - platform::Library library_; - proto::DataType data_type_; - framework::Layout layout_; -}; -``` - -The details are as follows: - -### Place - -`Place` is defined as: - -```cpp -typedef boost::variant Place; -``` - -`Place` represents the device memory where data is located. - - -### Library - -One operator kernel is usually implemented based on one library. `Library` is defined as a enum variable: - -```cpp -enum Library { Plain, MKLDNN, CUDNN }; -``` - -We use `Plain` enumerator to represent default library. Since most operators in Fluid are implemented based on the `Eigen` library, we take `Eigen` library as the `Plain` enumerator. -A library usually has a corresponding `DeviceContext` which contains some handles needed for computation. Fluid now has two default DeviceContexts for CPU and CUDA, namely, `CPUDeviceContext` and `CUDADeviceContext`. `CPUDeviceContext` contains an Eigen library handle and `CDUADeviceContext` contains an Eigen library handle and a cuBLAS handle. - -If we want to support new library, a new enumerator need to be added to `Library` and a corresponding new `LibraryDeviceContext` need to be created. - - -### DataType - - -`DataType` is defined in [framework.proto](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto). Currently, int32/int64/fp32/fp64 are supported. - -### Layout - -Actually, a Tensor is a view of a block of memory. Besides a pointer to the memory, we also have to get some other descriptions of this block of memory, such as shape(ddim), stride, and layout. - -Different layout leads to different implementation of the operator kernel. There are mainly 4 principles we have to follow to support layout in our Fluid framework. - -- We take layout as a data member of Tensor. Layout is actually a enum variable. If Fluid is built with MKLDNN, then the memory format in MKLDNN will also be added into this enum variable. - -- Users have to set layout for input data. And some operators like fill_constant/random, also have to set layout for generating data. Of course, we can have some default layout, like NCHW. - -- The inference of Layout is at run-time, not at compile-time. - -- Every operator has to implement different kernels for different layouts. Let's take MKLDNN as an example. If we want to implement an MKLDNN convolution operator, we have to implement all the kernels for different layouts, which are listed [here](http://01org.github.io/mkl-dnn/structmkldnn_1_1memory.html). And we will have a special macro to register kernels for MKLDNN operators. - -`Layout` is also defined as a enum variable: - -```cpp -enum Layout { - kNCHW, - kNHWC, -#ifdef PADDLE_WITH_MKLDNN - knChw8c - ... -#endif -}; -``` diff --git a/develop/doc/_sources/design/ops/rnn.md.txt b/develop/doc/_sources/design/ops/rnn.md.txt deleted file mode 100644 index 2f4854793fa..00000000000 --- a/develop/doc/_sources/design/ops/rnn.md.txt +++ /dev/null @@ -1,153 +0,0 @@ -# RNNOp design - -This document describes the RNN (Recurrent Neural Network) operator and how it is implemented in PaddlePaddle. The RNN op requires that all instances in a mini-batch have the same length. We will have a more flexible dynamic RNN operator in the future. - -## RNN Algorithm Implementation - -

- -

- -The above diagram shows an RNN unrolled into a full network. - -There are several important concepts here: - -- *step-net*: the sub-graph that runs at each step. -- *memory*, $h_t$, the state of the current step. -- *ex-memory*, $h_{t-1}$, the state of the previous step. -- *initial memory value*, the memory of the first (initial) step. - -### Step-scope - -There could be local variables defined in each step-net. PaddlePaddle runtime realizes these variables in *step-scopes* which are created for each step. - -

-
-Figure 2 illustrates the RNN's data flow -

- -Please be aware that every step runs the same step-net. Each step does the following: - -1. Creates the step-scope. -2. Initializes the local variables including step-outputs, in the step-scope. -3. Runs the step-net, which uses the above mentioned variables. - -The RNN operator will compose its output from step outputs in each of the step scopes. - -### Memory and Ex-memory - -Let's give more details about memory and ex-memory using a simple example: - -$$ -h_t = U h_{t-1} + W x_t -$$, - -where $h_t$ and $h_{t-1}$ are the memory and ex-memory (previous memory) of step $t$ respectively. - -In the implementation, we can make an ex-memory variable either "refer to" the memory variable of the previous step, -or copy the memory value of the previous step to the current ex-memory variable. - -### Usage in Python - -For more information on Block, please refer to the [design doc](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/block.md). - -We can define an RNN's step-net using a Block: - -```python -import paddle as pd - -X = some_op() # x is some operator's output and is a LoDTensor -a = some_op() - -# declare parameters -W = pd.Variable(shape=[20, 30]) -U = pd.Variable(shape=[20, 30]) - -rnn = pd.create_rnn_op(output_num=1) -with rnn.stepnet(): - x = rnn.add_input(X) - # declare a memory (rnn's step) - h = rnn.add_memory(init=a) - # h.pre_state(), the previous memory of rnn - new_state = pd.add_two( pd.matmul(W, x) + pd.matmul(U, h.pre_state())) - # update current memory - h.update(new_state) - # indicate that h variables in all step scopes should be merged - rnn.add_outputs(h) - -out = rnn() -``` - -Python API functions in above example: - -- `rnn.add_input`: indicates that the parameter is a variable that will be segmented into step-inputs. -- `rnn.add_memory`: creates a variable used as the memory. -- `rnn.add_outputs`: marks the variables that will be concatenated across steps into the RNN output. - -### Nested RNN and LoDTensor - -An RNN whose step-net includes other RNN operators is known as an *nested RNN*. - -For example, we could have a 2-level RNN, where the top level corresponds to paragraphs, and the lower level corresponds to sentences. Each step of the higher level RNN also receives an input from the corresponding step of the lower level, and additionally the output from the previous time step at the same level. - -The following figure illustrates feeding in text into the lower level, one sentence at a step, and the feeding in step outputs to the top level. The final top level output is about the whole text. - -

- -

- -```python -import paddle as pd - -W = pd.Variable(shape=[20, 30]) -U = pd.Variable(shape=[20, 30]) - -W0 = pd.Variable(shape=[20, 30]) -U0 = pd.Variable(shape=[20, 30]) - -# a is output of some op -a = some_op() - -# chapter_data is a set of 128-dim word vectors -# the first level of LoD is sentence -# the second level of LoD is a chapter -chapter_data = pd.Variable(shape=[None, 128], type=pd.lod_tensor, level=2) - -def lower_level_rnn(paragraph): - ''' - x: the input - ''' - rnn = pd.create_rnn_op(output_num=1) - with rnn.stepnet(): - sentence = rnn.add_input(paragraph, level=0) - h = rnn.add_memory(shape=[20, 30]) - h.update( - pd.matmul(W, sentence) + pd.matmul(U, h.pre_state())) - # get the last state as sentence's info - rnn.add_outputs(h) - return rnn - -top_level_rnn = pd.create_rnn_op(output_num=1) -with top_level_rnn.stepnet(): - paragraph_data = rnn.add_input(chapter_data, level=1) - low_rnn = lower_level_rnn(paragraph_data) - paragraph_out = low_rnn() - - h = rnn.add_memory(init=a) - h.update( - pd.matmul(W0, paragraph_data) + pd.matmul(U0, h.pre_state())) - top_level_rnn.add_outputs(h) - -# output the last step -chapter_out = top_level_rnn(output_all_steps=False) -``` - -In the above example, the construction of the `top_level_rnn` calls `lower_level_rnn`. The input is an LoD Tensor. The top level RNN segments input text data into paragraphs, and the lower level RNN segments each paragraph into sentences. - -By default, the `RNNOp` will concatenate the outputs from all the time steps. -If the `output_all_steps` is set to False, it will only output the final time step. - - -

- -

diff --git a/develop/doc/_sources/design/ops/sequence_decoder.md.txt b/develop/doc/_sources/design/ops/sequence_decoder.md.txt deleted file mode 100644 index c4a9bbeeefc..00000000000 --- a/develop/doc/_sources/design/ops/sequence_decoder.md.txt +++ /dev/null @@ -1,229 +0,0 @@ -# Design: Sequence Decoder Generating LoDTensors -In tasks such as machine translation and visual captioning, -a [sequence decoder](https://github.com/PaddlePaddle/book/blob/develop/08.machine_translation/README.md) is necessary to generate sequences, one word at a time. - -This documentation describes how to implement the sequence decoder as an operator. - -## Beam Search based Decoder -The [beam search algorithm](https://en.wikipedia.org/wiki/Beam_search) is necessary when generating sequences. It is a heuristic search algorithm that explores the paths by expanding the most promising node in a limited set. - -In the old version of PaddlePaddle, the C++ class `RecurrentGradientMachine` implements the general sequence decoder based on beam search, due to the complexity involved, the implementation relies on a lot of special data structures that are quite trivial and hard to be customized by users. - -There are a lot of heuristic tricks in the sequence generation tasks, so the flexibility of sequence decoder is very important to users. - -During the refactoring of PaddlePaddle, some new concepts are proposed such as: [LoDTensor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/lod_tensor.md) and [TensorArray](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/tensor_array.md) that can better support the sequence usage, and they can also help make the implementation of beam search based sequence decoder **more transparent and modular** . - -For example, the RNN states, candidates IDs and probabilities of beam search can be represented all as `LoDTensors`; -the selected candidate's IDs in each time step can be stored in a `TensorArray`, and `Packed` to the sentences translated. - -## Changing LoD's absolute offset to relative offsets -The current `LoDTensor` is designed to store levels of variable-length sequences. It stores several arrays of integers where each represents a level. - -The integers in each level represent the begin and end (not inclusive) offset of a sequence **in the underlying tensor**, -let's call this format the **absolute-offset LoD** for clarity. - -The absolute-offset LoD can retrieve any sequence very quickly but fails to represent empty sequences, for example, a two-level LoD is as follows -```python -[[0, 3, 9] - [0, 2, 3, 3, 3, 9]] -``` -The first level tells that there are two sequences: -- the first's offset is `[0, 3)` -- the second's offset is `[3, 9)` - -while on the second level, there are several empty sequences that both begin and end at `3`. -It is impossible to tell how many empty second-level sequences exist in the first-level sequences. - -There are many scenarios that rely on empty sequence representation, for example in machine translation or visual captioning, one instance has no translation or the empty candidate set for a prefix. - -So let's introduce another format of LoD, -it stores **the offsets of the lower level sequences** and is called **relative-offset** LoD. - -For example, to represent the same sequences of the above data - -```python -[[0, 3, 6] - [0, 2, 3, 3, 3, 9]] -``` - -the first level represents that there are two sequences, -their offsets in the second-level LoD is `[0, 3)` and `[3, 5)`. - -The second level is the same with the relative offset example because the lower level is a tensor. -It is easy to find out the second sequence in the first-level LoD has two empty sequences. - -The following examples are based on relative-offset LoD. - -## Usage in a simple machine translation model -Let's start from a simple machine translation model that is simplified from the [machine translation chapter](https://github.com/PaddlePaddle/book/tree/develop/08.machine_translation) to draw a blueprint of what a sequence decoder can do and how to use it. - -The model has an encoder that learns the semantic vector from a sequence, and a decoder which uses the sequence encoder to generate new sentences. - -**Encoder** -```python -import paddle as pd - -dict_size = 8000 -source_dict_size = dict_size -target_dict_size = dict_size -word_vector_dim = 128 -encoder_dim = 128 -decoder_dim = 128 -beam_size = 5 -max_length = 120 - -# encoder -src_word_id = pd.data( - name='source_language_word', - type=pd.data.integer_value_sequence(source_dict_dim)) -src_embedding = pd.embedding(size=source_dict_size, size=word_vector_dim) - -src_word_vec = pd.lookup(src_embedding, src_word_id) - -encoder_out_seq = pd.gru(input=src_word_vec, size=encoder_dim) - -encoder_ctx = pd.last_seq(encoder_out_seq) -# encoder_ctx_proj is the learned semantic vector -encoder_ctx_proj = pd.fc( - encoder_ctx, size=decoder_dim, act=pd.activation.Tanh(), bias=None) -``` - -**Decoder** - -```python -def generate(): - decoder = pd.while_loop() - with decoder.step(): - decoder_mem = decoder.memory(init=encoder_ctx) # mark the memory - generated_ids = decoder.memory() # TODO init to batch_size s - generated_scores = decoder.memory() # TODO init to batch_size 1s or 0s - - target_word = pd.lookup(trg_embedding, gendrated_ids) - # expand encoder_ctx's batch to fit target_word's lod - # for example - # decoder_mem.lod is - # [[0 1 3], - # [0 1 3 6]] - # its tensor content is [a1 a2 a3 a4 a5] - # which means there are 2 sentences to translate - # - the first sentence has 1 translation prefixes, the offsets are [0, 1) - # - the second sentence has 2 translation prefixes, the offsets are [1, 3) and [3, 6) - # the target_word.lod is - # [[0, 1, 6] - # [0, 2, 4, 7, 9 12]] - # which means 2 sentences to translate, each has 1 and 5 prefixes - # the first prefix has 2 candidates - # the following has 2, 3, 2, 3 candidates - # the encoder_ctx_expanded's content will be - # [a1 a1 a2 a2 a3 a3 a3 a4 a4 a5 a5 a5] - encoder_ctx_expanded = pd.lod_expand(encoder_ctx, target_word) - decoder_input = pd.fc( - act=pd.activation.Linear(), - input=[target_word, encoder_ctx_expanded], - size=3 * decoder_dim) - gru_out, cur_mem = pd.gru_step( - decoder_input, mem=decoder_mem, size=decoder_dim) - scores = pd.fc( - gru_out, - size=trg_dic_size, - bias=None, - act=pd.activation.Softmax()) - # K is an config - topk_scores, topk_ids = pd.top_k(scores, K) - topk_generated_scores = pd.add_scalar(topk_scores, generated_scores) - - selected_ids, selected_generation_scores = decoder.beam_search( - topk_ids, topk_generated_scores) - - # update the states - decoder_mem.update(cur_mem) # tells how to update state - generated_ids.update(selected_ids) - generated_scores.update(selected_generation_scores) - - decoder.output(selected_ids) - decoder.output(selected_generation_scores) - -translation_ids, translation_scores = decoder() -``` -The `decoder.beam_search` is an operator that, given the candidates and the scores of translations including the candidates, -returns the result of the beam search algorithm. - -In this way, users can customize anything on the input or output of beam search, for example: - -1. Make the corresponding elements in `topk_generated_scores` zero or some small values, beam_search will discard this candidate. -2. Remove some specific candidate in `selected_ids`. -3. Get the final `translation_ids`, remove the translation sequence in it. - -The implementation of sequence decoder can reuse the C++ class: [RNNAlgorithm](https://github.com/Superjom/Paddle/blob/68cac3c0f8451fe62a4cdf156747d6dc0ee000b3/paddle/operators/dynamic_recurrent_op.h#L30), -so the python syntax is quite similar to that of an [RNN](https://github.com/Superjom/Paddle/blob/68cac3c0f8451fe62a4cdf156747d6dc0ee000b3/doc/design/block.md#blocks-with-for-and-rnnop). - -Both of them are two-level `LoDTensors`: - -- The first level represents `batch_size` of (source) sentences. -- The second level represents the candidate ID sets for translation prefix. - -For example, 3 source sentences to translate, and has 2, 3, 1 candidates. - -Unlike an RNN, in sequence decoder, the previous state and the current state have different LoD and shape, and an `lod_expand` operator is used to expand the LoD of the previous state to fit the current state. - -For example, the previous state: - -* LoD is `[0, 1, 3][0, 2, 5, 6]` -* content of tensor is `a1 a2 b1 b2 b3 c1` - -the current state is stored in `encoder_ctx_expanded`: - -* LoD is `[0, 2, 7][0 3 5 8 9 11 11]` -* the content is - - a1 a1 a1 (a1 has 3 candidates, so the state should be copied 3 times for each candidates) - - a2 a2 - - b1 b1 b1 - - b2 - - b3 b3 - - None (c1 has 0 candidates, so c1 is dropped) - -The benefit from the relative offset LoD is that the empty candidate set can be represented naturally. - -The status in each time step can be stored in `TensorArray`, and `Pack`ed to a final LoDTensor. The corresponding syntax is: - -```python -decoder.output(selected_ids) -decoder.output(selected_generation_scores) -``` - -The `selected_ids` are the candidate ids for the prefixes, and will be `Packed` by `TensorArray` to a two-level `LoDTensor`, where the first level represents the source sequences and the second level represents generated sequences. - -Packing the `selected_scores` will get a `LoDTensor` that stores scores of each translation candidate. - -Packing the `selected_generation_scores` will get a `LoDTensor`, and each tail is the probability of the translation. - -## LoD and shape changes during decoding -

- -

- -According to the image above, the only phase that changes the LoD is beam search. - -## Beam search design -The beam search algorithm will be implemented as one method of the sequence decoder and has 3 inputs: - -1. `topk_ids`, the top K candidate ids for each prefix. -2. `topk_scores`, the corresponding scores for `topk_ids` -3. `generated_scores`, the score of the prefixes. - -All of these are LoDTensors, so that the sequence affiliation is clear. Beam search will keep a beam for each prefix and select a smaller candidate set for each prefix. - -It will return three variables: - -1. `selected_ids`, the final candidate beam search function selected for the next step. -2. `selected_scores`, the scores for the candidates. -3. `generated_scores`, the updated scores for each prefix (with the new candidates appended). - -## Introducing the LoD-based `Pack` and `Unpack` methods in `TensorArray` -The `selected_ids`, `selected_scores` and `generated_scores` are LoDTensors that exist at each time step, -so it is natural to store them in arrays. - -Currently, PaddlePaddle has a module called `TensorArray` which can store an array of tensors. It is better to store the results of beam search in a `TensorArray`. - -The `Pack` and `UnPack` in `TensorArray` are used to pack tensors in the array to an `LoDTensor` or split the `LoDTensor` to an array of tensors. -It needs some extensions to support the packing or unpacking an array of `LoDTensors`. diff --git a/develop/doc/_sources/design/optimizer.md.txt b/develop/doc/_sources/design/optimizer.md.txt deleted file mode 100644 index 691081c268b..00000000000 --- a/develop/doc/_sources/design/optimizer.md.txt +++ /dev/null @@ -1,91 +0,0 @@ -## Optimizer Design - -### The Problem - -A PaddlePaddle program, or a block, is a sequence of operators operating variables. A training program needs to do three kinds of works: - -1. the forward pass, which computes intermediate results and the cost(s), -1. the backward pass, which derives gradients from intermediate results and costs, and -1. the optimization pass, which update model parameters to optimize the cost(s). - -These works rely on three kinds of operators: - -1. forward operators, -1. gradient operators, and -1. optimization operators. - -It's true that users should be able to create all these operators manually by calling some low-level API, but it would be much more convenient if they could only describe the forward pass and let PaddlePaddle create the backward and optimization operators automatically. - -In this design, we propose a high-level API that automatically derives the optimisation pass and operators from the forward pass. - - -### High-level Python API to describe the training process - -1. User write code to describe the network: - - ```python - images = layer.data("images") - labels = layer.data("labels") - w1 = pd.var("w1") - b1 = pd.var("b1") - hidden = layer.fc(images, w=w1, b=b1) - cost = layer.mse(hidden, labels) - ``` - - The above code snippet will create forward operators in [Block](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/block.md). - - -2. Users create a certain kind of Optimizer with some argument. - - ```python - optimizer = AdagradOptimizer(learing_rate=0.001) - ``` - -3. Users use the optimizer to `minimize` a certain `cost` through updating parameters in parameter_list. - - ```python - opt_op_list = optimizer.minimize(cost, parameter_list=[w1, b1]) - ``` - The above code snippet will create gradient and optimization operators in Block. The return value of `minimize()` is list of optimization operators that will be run by session. - -4. Users use Session/Executor to run this opt_op_list as target to do training. - - ```python - sess.run(target= opt_op_list, ...) - ``` - -#### Optimizer Python interface: - -```python -class Optimizer(object): - """Optimizer Base class. - - """ - - def __init__(self): - pass - - def create_optimization_pass(self, parameters_and_grads): - """Add optimization operators to update gradients to variables. - - Args: - parameters_and_grads: a list of (variable, gradient) pair to update. - - Returns: - optmization_op_list: a list of optimization operator that will update parameter using gradient. - """ - return None - - def minimize(self, loss, parameter_list): - """Add operations to minimize `loss` by updating `parameter_list`. - - This method combines interface `append_backward()` and - `create_optimization_pass()` into one. - """ - params_grads = self.create_backward_pass(loss, parameter_list) - update_ops = self.create_optimization_pass(params_grads) - return update_ops - -``` - -Users can inherit the Optimizer above to create their own Optimizer with some special logic, such as AdagradOptimizer. diff --git a/develop/doc/_sources/design/paddle_nccl.md.txt b/develop/doc/_sources/design/paddle_nccl.md.txt deleted file mode 100644 index c7dac70998a..00000000000 --- a/develop/doc/_sources/design/paddle_nccl.md.txt +++ /dev/null @@ -1,65 +0,0 @@ -# Design Doc: NCCL support in Paddle Fluid - -## Abstract - -This Design Doc refers to the NCCL feature in paddle. We propose an approach to support NCCL library both on a single machine and multiple machines. We wrapper the NCCL primitives `Broadcast`, `Allreduce`, `Reduce` as operators to utilize Multi-GPU powers in one script. - - -## Motivation - -[NCCL](https://developer.nvidia.com/nccl) is a NVIDIA library support Multi-GPU communicating and optimized for NVIDIA GPUs, it provides routines such as all-gather, all-reduce, broadcast, reduce, reduce-scatter, that can achieve high bandwidth over PCIe and NVLink high-speed interconnect. With NCCL library, we can easily accelerate the training in parallel. - -- Pros -1. easily plug-in with [NCCL2](https://developer.nvidia.com/nccl) library. -1. high performance in NVIDIA GPUs. -1. MPI like primitives, which have low learning cost for users. - -- Cons -1. Only design for NVIDIA GPUs, not a general multi-device solution. -1. Although NCCL1 is opensourced under BSD license, but NCCL2 is not opensourced anymore. - -At the beginning of training, the framework needs to distribute the same parameters to every GPU, and merge the gradients at any time user interests. - -As a result, during training, we need the operations of peer to peer copy between different GPUs, aggregating gradients/parameters from GPUs, and broadcasting parameters to GPUs. Every GPU only need to run the operator with correct place information. - -Besides, it needs interfaces to synchronize model update with each different GPU Cards. - -## Implementation - -As mentioned above, we wrap the NCCL routines as several kinds of operators. Need to note that NCCL need to create Communicator between gpu at the beginning, so there is a NCCLInit operator created. - -### Transpiler - -To be compatible with [parameter server design doc](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/ops/dist_train.md), the transpiler compiles the user defined operation graph into sub-graphs to be executed on different devices. - -1. The user-defined model will be a single device program - -2. Broadcast/Reduce operators between GPUs will be inserted into the program, even for the multi-node, may insert the `Send`, `Recv` operator. - - *Broadcast, AllReduce in a single machine. And Broadcast, AllReduce, [Send, Recv](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/ops/dist_train.md#graph-converter) in multiple machines* - - - -After compiling, the graph as shows - - - -Operators are added to the sub-graphs. Every GPU assigned a role of `rank0`, `rank1` etc. - -- **Broadcast**. Broadcast operator distribute initialized parameter to all the GPUs from the GPU who owns it. e.g. from`rank0` GPU. -- **AllReduce**. AllReduce operator synchronizes parameters/gradients between GPUs. AllReduce implemented in the Ring-Based communicating method, avoid of the bottle neck in a single GPU. - -Need to notice that AllReduce operator force GPUs synchronized at that point. The whole training process in asynchronous or synchronous mode depends on the AllReduce point in the graph. - -As it shown in the picture, when each GPU compute the gradient of `W`, followed with a `AllReduce` operator, accumulate the `dW` to full batch of data, then run the optimize process individually and apply the gradient to its `W`. - -- **AllReduce** - Need to note that our AllReduce operator is a ring-base AllReduce implementation. If we use the NCCL2 AllReduce primitive, every GPU optimized full batch of data, wasted (n-1) GPU compute resources. In addition, NCCL2 built-in AllReduce will only utilize the communicating resource during synchronization, then update the gradient will be a subsequent phase. In fact, we can amortize the update gradient time cost into the communicating phase. The process is -1. Every parameter has its root card. That card will responsible for aggregating the gradients from GPUs. -2. The whole model's parameter will be hashed to different root card, ensure the load balance between GPUs. -3. Logically neighberhood card will start send parameter to the next one. After one round, the parameter main card will aggregate the full gradients. -4. Then the root card will optimize the parameter. -5. This parameter card will send its optimized result to its neighberhood, then the neighberhood will send parameter to its next one. -6. Finish the sychronization round. - -The total time cost will be 2 * (n-1) * per-parameter-send-time, we reach the goal of amortize the upgrade time into communicating phase. diff --git a/develop/doc/_sources/design/parallel_do.md.txt b/develop/doc/_sources/design/parallel_do.md.txt deleted file mode 100644 index 42bd136f825..00000000000 --- a/develop/doc/_sources/design/parallel_do.md.txt +++ /dev/null @@ -1,163 +0,0 @@ -# Design Doc: Parallel_Do in PaddlePaddle - -In PaddlePaddle, we use parallel_do primitive to represent multithread data parallel processing. - -## Design overview - -The definition of a parallel_do op looks like the following - -```c++ -AddInput(kInputs, "Inputs needed to be split onto different devices").AsDuplicable(); -AddInput(kParameters, "Parameters are duplicated over different devices") - .AsDuplicable(); -AddInput(kPlaces, "Devices used for parallel processing"); -AddOutput(kOutputs, "Outputs needed to be merged from different devices").AsDuplicable(); -AddOutput(kParallelScopes, - "Scopes for all local variables in forward pass. One scope for each device"); -AddAttr(kParallelBlock, - "List of operaters to be executed in parallel"); -``` - -A vanilla implementation of parallel_do can be shown as the following (`|` means single thread and -`||||` means multiple threads) - -``` -In the forward pass - | Split input onto different devices - | Copy parameter onto different devices - |||| Compute forward pass in parallel - | Merge output from different devices - -In the backward pass - | Split output@grad onto different devices - |||| Compute backward pass in parallel - | accumulate param@grad from different devices to the first device - | Merge input@grad from different devices -  | Copy param@grad to the place of parallel_do_op -``` - -This implementation allows to write mixed device program like this - -```python -W1 = fluid.tensor(size=[100,20], parameter=true) -W2 = fluid.tensor(size=[20,15], parameter=true) - -data = layers.data() - -gpu_places = layers.get_place(use_gpu=True) -# parallel processing on multiple GPUs -pd = ParallelDo(gpu_places) -with pd.do(input=data): - prediction = softmax(fc(fc(data, W1), W2)) - write_output(prediction) -prediction = pd() -loss = cross_entropy(prediction, label) -``` - -And the programDesc are like the following - -``` -# start_program will be run by executor(CPUPlace), all w1, w2 will be allocated on CPU -start_program -{ - vars: w1, w2 - ops: init(w1), init(w2) -} - -main_program -{ -block0 { - vars: data, places, w1, w2, w1_grad, w2_grad, - ops: data, get_place, parallel_do(block1), - parallel_do_grad(block2), - sgd(w2, w2_grad), - sgd(w1, w1_grad) -} -block1 { # the forward pass - parent_block: 0 - vars: data, h1, h2, loss - ops: fc, fc, softmax -} -block2 { # the backward pass - parent_block: 1 - vars: data_grad, h1_grad, h2_grad, loss_gard, local_w1_grad, local_w2_grad - ops: softmax_grad, - fc_grad - fc_grad -} -} -``` - -## Performance Imporvement - -There are serial places we can make this parallel_do faster. - -### forward: split input onto different devices - -If the input of the parallel_do is independent from any prior opeartors, we can avoid this step by -prefetching the input onto different devices in a seperate background thread. And the python code -looks like this. -```python -pd = ParallelDo(gpu_places) -with pd.do(): -    feature = get_data_from_prefetch_queue(gpu_places) - prediction = my_net(feature) - write_output(activation) -``` - -### forward: Copy parameter to onto different devices - -We can avoid this step by making each device have a copy of the parameter. This requires: - -1. `fluid.default_start_up_program()` to be run on all devices -1. In the backward, allreduce param@grad at different devices, this requires - 1. `backward.py` add `allreduce` operators at parallel_do_grad - 1. `allreduce` operators need to be called in async mode to achieve maximum throughput -1. apply gradients related op(i.e. cliping, normalization, decay, sgd) on different devices in parallel - -By doing so, we also avoided "backward: accumulate param@grad from different devices to the first device". -And the ProgramDesc looks like the following - -``` -# w1, w2 will be allocated on all GPUs -start_program -{ -block0 { - parallel_do(block1) -} -block1 { - parent_block: 0 - vars: w1, w2 - ops: init(w1), init(w2) -} -} - -main_program -{ -block0 { - vars: data, places, w1, w2 - ops: data, get_place, parallel_do(block1), - parallel_do_grad(block2), # append_backward - parallel_do(block3) # append_optimization - -} -block1 { - parent_block: 0 - vars: data, h1, h2, loss - ops: fc, fc, softmax -} -block2 { - parent_block: 1 - vars: data_grad, h1_grad, h2_grad, loss_gard, w1_grad, w2_grad - ops: softmax_grad, - fc_grad, allreduce(places, scopes, w1_grad), - fc_grad, allreduce(places, scopes, w2_grad) -} -block3 { - parent_block: 0 - vars: lr - ops: sgd(w2, w2_grad), - sgd(w1, w1_grad) -} -} -``` diff --git a/develop/doc/_sources/design/parameter_average.md.txt b/develop/doc/_sources/design/parameter_average.md.txt deleted file mode 100644 index 2c4edee9fe3..00000000000 --- a/develop/doc/_sources/design/parameter_average.md.txt +++ /dev/null @@ -1,72 +0,0 @@ -# Averaging Parameter in PaddlePaddle - -## Why Averaging -In a large scale machine learning setup where the size of the training data is huge, it could take us a large number of iterations over the training data before we can achieve the optimal values of parameters of our model. Looking at the problem setup, it is desirable if we can obtain the optimal values of parameters by going through the data in as few passes as we can. - -Polyak and Juditsky (1992) showed that the test performance of simple average of parameters obtained by Stochastic Gradient Descent (SGD) is as good as that of parameter values that are obtained by training the model over and over again, over the training dataset. - -Hence, to accelerate the speed of Stochastic Gradient Descent, Averaged Stochastic Gradient Descent (ASGD) was proposed in Polyak and Juditsky (1992). For ASGD, the running average of parameters obtained by SGD, is used as the estimator for
. The averaging is done as follows: - -
- -We propose averaging for any optimizer similar to how ASGD performs it, as mentioned above. - -### How to perform Parameter Averaging in PaddlePaddle - -Parameter Averaging in PaddlePaddle works in the following way during training : -1. It will take in an instance of a normal optimizer as an input, e.g. RMSPropOptimizer -2. The optimizer itself is responsible for updating the parameters. -3. The ParameterAverageOptimizer maintains a separate copy of the parameters for itself: - 1. In concept, the values of this copy are the average of the values of the parameters in the most recent N batches. - 2. However, saving all the N instances of the parameters in memory is not feasible. - 3. Therefore, an approximation algorithm is used. - -Hence, overall we have have two copies of the parameters: one for the optimizer itself, and one for the ParameterAverageOptimizer. The former should be used in back propagation, while the latter should be used during testing and should be saved. - -During the testing/ saving the model phase, we perform the following steps: -1. Perform the delayed operations. -2. Save current values of the parameters to a temporary variable. -3. Replace the values of the parameters with the averaged values. -4. Perform testing and/or save the parameters. -5. Restore the values of the parameters once done. - -### How to implement Averaging of Parameter in PaddlePaddle - -We can add the ParameterAverageOptimizer op to the graph through Python API. Using this approach, we manually add this op to the graph and direct the output of the optimizer op to this op during training. - - **Advantages**: - - Allows for greater flexibility to the users of PaddlePaddle. Using this approach, the users can plug different optimizers into ParameterAverageOptimizer by passing in the optimizer to the op. - - Makes it easy for the users to customize and extend the framework. - - **Disadvantages**: - - Implementation requires re-writing the averaging methodology in Python. - -### Low-Level implementation - -In the new design, we propose to create a new operation for averaging parameter updates (ParameterAverageOptimizer). For now, we can add an op that takes in the following as input: -- the optimizer -- the window_size to keep the updates - -The ParameterAverageOptimizer op can be like any other operator with its own CPU/GPU implementation either using Eigen or separate CPU and GPU kernels. As the initial implementation, we can implement the kernel using Eigen following the abstraction pattern implemented for [Operators](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/rmsprop_op.h). We also want to support the case when the Trainer/Optimizer runs on the GPU while ParameterAverageOptimizer runs on a CPU. - -The idea of building an op for averaging is in sync with the refactored PaddlePaddle philosophy of using operators to represent any computation unit. The way the op will be added to the computation graph will be decided by the [layer functions](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md#layer-function) in Python API. - -### Python API implementation for ParameterAverageOptimizer - -Based on Polyak and Juditsky (1992), we can generalize the averaging of updates to any optimizer. The input to the op would be the following: -- Any optimizer (RMSProp , AdaGrad etc.) -- A window size. The op keeps accumulating updated parameter values over a window of N batches and takes an average. Move the averaged value to a buffer when window is full to avoid loss of precision. - -Using the ParameterAverageOptimizer op, any user can add the operation to their computation graphs. However, this will require a lot of lines of code and we should design Python APIs that support averaging. As per the PaddlePaddle [Python API design](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md), the layer functions are responsible for creating operators, operator parameters and variables. Since ParameterAverageOptimizer will be an operator, it makes sense to create it in the layer functions. -We will have a wrapper written in Python that will support the functionality and implement the actual core computation in C++ core as we have done for other [Optimizers](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/rmsprop_op.cc) - -#### Creation of the ParameterAverageOptimizer operator -There are two ways for creating the ParameterAverageOptimizer op: -1. We create the op immediately while building the computation graph. -2. We add the op in a lazy manner, just before the backward pass, similar to the way the optimization ops are added. - -The proposal is to add the op immediately while building the computation graph. - -#### High-level API - -In PaddlePaddle Python API, users will primarily rely on [layer functions](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md#layer-function) to create neural network layers. Hence, we also need to provide parameter average functionality in layer functions. diff --git a/develop/doc/_sources/design/parameters_in_cpp.md.txt b/develop/doc/_sources/design/parameters_in_cpp.md.txt deleted file mode 100644 index a7ac3f17c44..00000000000 --- a/develop/doc/_sources/design/parameters_in_cpp.md.txt +++ /dev/null @@ -1,41 +0,0 @@ -# Design Doc: The C++ Class `Parameters` - -`Parameters` is a concept we designed in PaddlePaddle V2 API. `Parameters` is a container of parameters, which makes PaddlePaddle capable of sharing parameter between topologies. We described usages of `Parameter` in [api.md](./api.md). - -We used Python to implement Parameters when designing V2 API before. There are several defects for the current implementation: -* We just use `memcpy` to share Parameters between topologies, but this is very inefficient. -* We did not support sharing Parameters while training. We just trigger `memcpy` when start training. - -It is necessary that we implement Parameters in CPP side. However, it could result a code refactoring for PaddlePaddle, because PaddlePaddle was designed for training only one topology before, i.e., each GradientMachine contains its Parameter as a data member. In current PaddlePaddle implementation, there are three concepts associated with `Parameters`: - -1. `paddle::Parameter`. A `Parameters` is a container for `paddle::Parameter`. -It is evident that we should use `paddle::Parameter` when developing `Parameters`. -However, the `Parameter` class contains many functions and does not have a clear interface. -It contains `create/store Parameter`, `serialize/deserialize`, `optimize(i.e SGD)`, `randomize/zero`. -When we developing `Parameters`, we only use `create/store Parameter` functionality. -We should extract functionalities of Parameter into many classes to clean PaddlePaddle CPP implementation. - -2. `paddle::GradientMachine` and its sub-classes, e.g., `paddle::MultiGradientMachine`, `paddle::NeuralNetwork`. -We should pass `Parameters` to `paddle::GradientMachine` when `forward/backward` to avoid `memcpy` between topologies. -Also, we should handle multi-GPU/CPU training, because `forward` and `backward` would perform on multi-GPUs and multi-CPUs. -`Parameters` should dispatch the parameter value to each device, and gather the parameter gradient from each device. - -3. `paddle::ParameterUpdater`. The ParameterUpdater is used to update parameters in Paddle. -So `Parameters` should be used by `paddle::ParameterUpdater`, and `paddle::ParameterUpdater` should optimize `Parameters` (by SGD). - - -The step by step approach for implementation Parameters in PaddlePaddle C++ core is listed below. Each step should be a PR and could be merged into PaddlePaddle one by one. - -1. Clean `paddle::Parameter` interface. Extract the functionalities of `paddle::Parameter` to prepare for the implementation of Parameters. - -2. Implementation a `Parameters` class. It just stores the `paddle::Parameter` inside. Make `GradientMachine` uses `Parameters` as a class member. - -3. Make `Parameters` support Multi-CPU and Multi-GPU training to prepare for sharing `Parameter` between topologies. -Because we need share `Parameters` between topologies, it is `Parameters`'s response to exchange Parameters between GPUs. -`GradientMachine` should not handle how to exchange Parameters because `GradientMachine` only used to train one topology and we need to support train many topologies in Paddle, i.e., there could be many GradientMachines use one `Parameters`. - * We should use a global function to exchange Parameters between GPUs, not a member function in `Parameters`. The `MultiGradientMachine` invoke this function, which uses `Parameters` as this function inputs. - * The MultiGradientMachine contains many functionalities. Extracting the Parameters exchanging logic could make MultiGradientMachine clearer and simpler. - -4. Make `Parameters` as an argument for `forward/backward` function, not a data member for `GradientMachine`. For example, `forward` could be `forward(const Parameters& params, ...)` and `backward` could be `backward(Parameters* params, ...)`. After this step, Paddle could share `Parameters` between topologies. - -5. `ParameterUpdater` is invoked by `GradientMachine` and `Trainer`, but it updates `Parameters`. In the end of this code refactoring, we could change `ParameterUpdater` directly uses `Parameters` to make `ParameterUpdater`'s implementation clear. diff --git a/develop/doc/_sources/design/profiler.md.txt b/develop/doc/_sources/design/profiler.md.txt deleted file mode 100644 index b20b5efdc1f..00000000000 --- a/develop/doc/_sources/design/profiler.md.txt +++ /dev/null @@ -1,97 +0,0 @@ -## Introduction - -There are many performance analysis tools for [different programming languages and different software frameworks](https://en.wikipedia.org/wiki/List_of_performance_analysis_tools). For most popular deep learning frameworks, they use several programming languages and adapt to heterogeneous platforms. Similar to most of the deep learning frameworks, PaddlePaddle also uses C++, CUDA and Python as the basic programming languages to adapt to run on CPU and GPU devices. The [`nvprof` tools](http://docs.nvidia.com/cuda/profiler-users-guide/index.html#nvprof-overview) is usually used to analyse the CUDA program. We have [a document](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/optimization/cpu_profiling.md) to profile CPU and Python program by [yep](https://pypi.python.org/pypi/yep) and [Google's perftools](https://github.com/google/pprof) to profile only the CPU and Python program. But for [PaddlePaddle fluid](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/fluid.md), the operator is the basic computing unit. The developers usually want to collect the time of each operator and locate bottlenecks. The `nvprof` usually collect the timeline of CUDA-related activities on both CPU and GPU, including kernel execution, memory transfers, memory set and CUDA API calls and events or metrics for CUDA kernels. And the `yep` and `Google's perftools` can't collect the timeline for CUDA program. All these tools can't collect time in the operator level. So we design this profiling tool. - -## Architecture - -The work flow for most task is as follows. Each operator will run many times in the all iterations. So the profiler must collect the total time of each operator during the iteration. For more, sometimes, the developers may want to collect more detailed time span inside the operator or record time span for elsewhere, this requires that the profiler must support to record the nested time span. And in order to speedup training, all the deep learning frameworks support parallel computing, including multiple threads on CPU and multiple GPUs. So the profiler must be able to collect the timeline for each thread. In addition, the profiler also occupies certain resources. It must can be easily to be enabled or disabled by the developers. At last, the profiler should present a human-readable report. - -```python -for i in xrange(M): # M is the iteration number - for op in operator_lists: # The `operator_lists` contains all the operators in the network. - op.run(); -``` - -In summary, the proflier should have following features: - -- records time span in loop. -- supports nested time span. -- supports multiple threads/multiple GPUs. -- supports to be enabled and disabled by users. - -But how to record the time for the mixed C++ and CUDA program? There many C++ APIs to get the current calendar time in host program. But for GPU, the CUDA kernels may be executed concurrently if they are in different [streams](http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#streams) and the CUDA kernels is asynchronous with the host program if there is no the synchronous aftern the CUDA kernels. CUDA provides [event](http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#events) to monitor the device and perform accurate timing. Inspired by PyTorch and CUDA event, we also design and apply the events to record the timeline. Then summarize and present statistics based on these events. - -The overall flow is shown as the following figure. - -
- -### Event - -In above work flow, a pair of events are needed before and after the piece of code to collect time. So the event has a flag to mark whether it is a starting event or an ending event. Except this two kinds of event, sometime, a only marker with a text message is needed, for example, a marker to specify the profiling start or end. There are three kinds of event: - -```c++ -enum EventKind { - kMark, - kPushRange, - kPopRange}; -``` -- kMark: only a marker without time range. -- kPushRange: mark the starting event for time range. -- kPopRange: mark the ending event for time range. - -For the CPU code, the events only need to record the current time. For the CUDA code, the [event management functions of CUDA](http://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__EVENT.html#group__CUDART__EVENT) are used. For many pieces of code, an event lists are used to record each piece. - -```c++ -class Event { - public: - // The DeviceContext is used to get current CUDA stream. - Event(EventKind kind, std::string name, uint32_t thread_id, - const platform::DeviceContext* dev_ctx = nullptr); - double CpuElapsedUs(const Event& e) const; - double CudaElapsedUs(const Event& e) const; - - private: - EventKind kind_; - std::string name_; - uint32_t thread_id_; - int64_t cpu_ns_; -#ifdef PADDLE_WITH_CUDA - cudaEvent_t event_ = nullptr; - int device_ = -1; -#endif -}; - -struct EventList { - std::forward_list> event_blocks; -}; -``` - -As mentioned above, there is no need to record the timeline when disabling the profiler. So there is a global state to enable or disable the profiler. - -```c++ -enum ProfilerState { - kDisabled, - kCPU, - kCUDA -}; -ProfilerState g_state; -``` -- kDisabled: the disabled state. -- kCPU: CPU profiling state. -- kCUDA: GPU profiling state. - -A pair of starting and ending events are pushed to event lists in constructor and destructor of `RecordEvent`. So the timeline is recorded for the code in the lifecycle of an object of `RecordEvent`. - -```c++ -struct RecordEvent { - explicit RecordEvent(const std::string name, - platform::DeviceContext* dev_ctx = nullptr) { - if (kState == ProfilerState::kDisabled) return; - // push the starting event to the event lists. - } - ~RecordEvent() { - if (kState == ProfilerState::kDisabled) return; - // push the ending event to the event lists. - } -}; -``` diff --git a/develop/doc/_sources/design/program.md.txt b/develop/doc/_sources/design/program.md.txt deleted file mode 100644 index bd2456787c4..00000000000 --- a/develop/doc/_sources/design/program.md.txt +++ /dev/null @@ -1,139 +0,0 @@ -# Design Doc: PaddlePaddle Programs - -## Compile and Execution - -A PaddlePaddle program consists of two parts -- the first generates a `ProgramDesc` protobuf message that describes the program, and the second runs this message using a C++ class `Executor`. - -A simple example PaddlePaddle program can be found in [graph.md](./graph.md): - -```python -x = layer.data("images") -l = layer.data("label") -y = layer.fc(x) -cost = layer.mse(y, l) -optimize(cost) -train(cost, reader=mnist.train()) -``` - -The first five lines of the following PaddlePaddle program generates, or, compiles, the `ProgramDesc` message. The last line runs it. - -## Programs and Blocks - -The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program. - -- program: some nested blocks -- [block](./block.md): - - some local variable definitions, and - - a sequence of operators - -The concept of block comes from usual programs. For example, the following C++ program has three blocks: - -```c++ -int main() { // block 0 - int i = 0; - if (i < 10) { // block 1 - for (int j = 0; j < 10; j++) { // block 2 - } - } - return 0; -} -``` - -The following PaddlePaddle program has three blocks: - -```python -import paddle as pd // block 0 - -x = minibatch([10, 20, 30]) # shape=[None, 1] -y = var(1) # shape=[1], value=1 -z = minibatch([10, 20, 30]) # shape=[None, 1] -cond = larger_than(x, 15) # [false, true, true] - -ie = pd.ifelse() -with ie.true_block(): // block 1 - d = pd.layer.add_scalar(x, y) - ie.output(d, pd.layer.softmax(d)) -with ie.false_block(): // block 2 - d = pd.layer.fc(z) - ie.output(d, d+1) -o1, o2 = ie(cond) -``` - -## `BlockDesc` and `ProgramDesc` - -All protobuf messages are defined in `framework.proto`. - -`BlockDesc` is straight-forward -- it includes local variable definitions, `vars`, and a sequence of operators, `ops`. - -```protobuf -message BlockDesc { - required int32 parent = 1; - repeated VarDesc vars = 2; - repeated OpDesc ops = 3; -} -``` - -The parent ID indicates the parent block so that operators in a block can refer to variables defined locally and also those defined in their ancestor blocks. - -All hierarchical blocks in a program are flattened and stored in an array. The block ID is the index of the block in this array. - -```protobuf -message ProgramDesc { - repeated BlockDesc blocks = 1; -} -``` - - -### Global Block - -The global block is the first one in the above array. - -## Operators that Use Blocks - -In the above example, the operator `IfElseOp` has two blocks -- the true branch and the false branch. - -The definition of `OpDesc` shows that an operator could have some attributes: - -```protobuf -message OpDesc { - AttrDesc attrs = 1; - ... -} -``` - -and an attribute could be of type block, which is, in fact, a block ID as described above: - -``` -message AttrDesc { - required string name = 1; - - enum AttrType { - INT = 1, - STRING = 2, - ... - BLOCK = ... - } - required AttrType type = 2; - - optional int32 block = 10; // when type == BLOCK - ... -} -``` - -## InferShape - -With this design, the InferShape function should take the following parameters: - -```c++ -void InferShape(int current_block, - int current_operator, - ProgramDesc* program // might change VarDesc values. - ) { - ... -} -``` - -where - -- `current_block` indices into `ProgramDesc::blocks`, -- `current_operator` indices into `BlockDesc::ops`. diff --git a/develop/doc/_sources/design/prune.md.txt b/develop/doc/_sources/design/prune.md.txt deleted file mode 100644 index 4a5cf10c79a..00000000000 --- a/develop/doc/_sources/design/prune.md.txt +++ /dev/null @@ -1,63 +0,0 @@ -# Prune - -## Motivation - -We want to support running inference, training and checkpointing in one `ProgramDesc`. We implement -`void Prune(const ProgramDesc* input, ProgramDesc* output)` function, which takes a `ProgramDesc` -and generate a pruned `ProgramDesc`. - -## Challenge - -Pruning need to support both variables and operators being evaluation targets. Consider the following -different situations. - -```python -# Case 1: run foward pass. -cost_np = session.run(target=cost) -# Case 2: run backward passing. -opts_np, _ = session.run(target=[cost, opt]) -# Case 3: run checkpointing -_ = session.run(target=checkpoint) -``` - -## Solution - -To support evaluation of operators, we add `is_target` field in the `OpDesc`. - -```c++ -message OpDesc { - required string type = 3; - repeated Var inputs = 1; - repeated Var outputs = 2; - repeated Attr attrs = 4; - optional bool is_target = 5 [ default = false ]; -}; -``` - -To support evaluation of variables, we add [fetch_op](https://github.com/PaddlePaddle/Paddle/pull/4599). -For each variable in the `target`, we insert a `fetch_op` into the `ProgramDesc` with `variable` being -`fetch_op`'s input. Then we also set `fetch_op` is a target. - -### Algorithm - -If an operator needs to be run, it must fall into one of the following cases: - -1. It is the target. -2. It is depended by some other ops, meaning its output is some other op's input. - -The first case can be checked by `op_desc.is_traget()` . The second case can be implement as - -```c++ -bool HasDependentVar(const OpDesc& op_desc, const std::set& dependent_vars) { - for (auto& var : op_desc.outputs()) { - for (auto& argu : var.arguments()) { - if (dependent_vars.count(argu) != 0) { - return true; - } - } - } - return false; -} -``` - -Then the whole algorithm can be implemented as the following [code](https://github.com/tonyyang-svail/Paddle/blob/prune_impl/paddle/framework/prune.cc). diff --git a/develop/doc/_sources/design/python_api.md.txt b/develop/doc/_sources/design/python_api.md.txt deleted file mode 100644 index 73f6d7b90c7..00000000000 --- a/develop/doc/_sources/design/python_api.md.txt +++ /dev/null @@ -1,304 +0,0 @@ -# Design Doc: Python API - -Due to the refactorization of the PaddlePaddle core, we need Python classes to construct corresponding protobuf messages that describe a DL program. - -| Python classes | Protobuf messages | -| --- | --- | -| Program | ProgramDesc | -| Block | BlockDesc | -| Operator | OpDesc | -| Variable | VarDesc | - -Please be aware that these Python classes need to maintain some construction-time information, which are not part of the protobuf messages. - -## Core Concepts - -### Program - -A `ProgramDesc` describes a [DL program](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/program.md), which is composed of an array of `BlockDesc`s. The `BlockDesc`s in a `ProgramDesc` can have a tree-like hierarchical structure. However, the `ProgramDesc` onlys stores a flattened array of `BlockDesc`s. A `BlockDesc` refers to its parent block by its index in the array. For example, operators in the step block of an RNN operator need to be able to access variables in its ancestor blocks. - -Whenever we create a block, we need to set its parent block to the current block, hence the Python class `Program` needs to maintain a data member `current_block`. - -```python -class Program(objects): - def __init__(self): - self.desc = core.NewProgram() # a C++ ProgramDesc pointer. - self.blocks = vector() - self.blocks.append(Block(self, -1)) # the global block - self.current_block = 0 # initialized to the global block - - def global_block(): - return self.blocks[0] - - def current_block(): - return self.get_block(self.current_block) - - def rollback(): - self.current_block = self.current_block().parent_idx - - def create_block(): - new_block_idx = len(self.block) - self.blocks.append(Block(self, self.current_block)) - self.current_block = new_block_idx - return current_block() -``` - -`Program` is an accessor to the protobuf message `ProgramDesc`, which is created in C++ space, because the InferShape function is in C++, which manipulates `VarDesc` messages, which are in turn members of `BlockDesc`, which is a member of `ProgramDesc`. - -`Program` creates the first block as the global block in its constructor. All parameters and their initializer operators are in the global block. - -### Block - -A [Block](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/block.md) includes - -1. a map from variable names to an instance of the Python `Variable` class, and -1. a list of `Operator` instances. - -```python -class Block(objects): - def __init__(self, program, parent_idx): - self.desc = core.NewBlock(program.desc) - self.program = program - self.vars = map() - self.ops = vector() - self.parent_idx = parent_idx - - def create_var(self, ...): - return Variable(self, ...) - - def _create_global_var(self, ...): - program.global_block().create_var(...) - - def create_parameter(self, name, ...): - # Parameter is a subclass of variable. See Parameter section for details. - self.vars[name] = Parameter(self._create_global_var(...), ...) - return self.vars[name] - - def append_operator(self, ...): - self.ops.append(Operator(self, ...)) - - def prepend_operator(self, ...): # Parameter's ctor prepands initialize operators. - self.ops.prepend(Operator(self, ...)) -``` - -`create_parameter` is necessary because parameters are global variables, defined in the global block, but can be created in some sub-blocks. For example, an FC layer in the step block of an RNN operator. - -`prepend_operator` is necessary because the constructor of `Parameter` needs to create the initialize (or load) operator of the parameter, and would like to put it in the *preamble* of the global block. - -### Operator - -The `Operator` class fills in the `OpDesc` message and calls the C++ function `InferShape` to infer the output shapes from the input shapes. - -```python -class Operator(object): - def __init__(self, - block, # Block - type, # string - inputs, # dict - outputs,# dict - attrs # dict - ): - self.desc = core.NewOpDesc(block.desc, type, inputs, outputs, attrs) - core.infer_shape(self.desc, inputs, outputs) - - def type(self): - return self.desc.type() -``` - -`Operator` creates the `OpDesc` message in C++ space, so that it can call the `InferShape` function, which is in C++. - -### Variable - -Operators take Variables as its inputs and outputs. - -```python -class Variable(object): - def __init__(self, - block=None, # Block - name=None, # string - shape, # tuple - dtype="float32", # string - lod_level=None # int - ): - if name is None: - name = unique_name_generator() - self.name = name - self.block = block - self.desc = core.NewVarDesc(block.desc, name, shape, lod_level) - self.writer = None -``` - -Please be aware of `self.writer`, that tracks operator who creates the variable. It possible that there are more than one operators who write a variable, but in Python space, each write to a variable is represented by a Variable class. This is guaranteed by the fact that **`core.NewVarDesc` must NOT create a new `VarDesc` message if its name already exists in the specified block**. - -### Parameter - -A parameter is a global variable with an initializer (or load) operator. - -```python -class Parameter(Variable): - def __init__(self, - block=None, # Block - name=None, # string - shape, # tuple - dtype="float32", # string - lod_level=None # int - trainable, # bool - initialize_op_attrs, - optimize_op_attrs): - super(Parameter, self).__init__(block, name, shape, dtype, lod_level) - self.trainable = trainable - self.optimize_op_attrs = optimize_op_attrs - block.prepend(Operator(block, # Block - initialize_op_attrs['type'], # string - None, # no inputs - self, # output is the parameter - initialize_op_attrs) -``` - -When users create a parameter, they can call - -```python -program.create_parameter( - ..., - init_attr={ - type: "uniform_random", - min: -1.0, - max: 1.0, - }) -) -``` - -In above example, `init_attr.type` names an initialize operator. It can also name the load operator - -```python -init_attr={ - type: "load", - filename: "something.numpy", -} -``` - -`optimize_op_attrs` is not in the `VarDesc` message, but kept in the Python instance, as it will be used in the Python space when creating the optimize operator's `OpDesc`, and will be in the `OpDesc` message. - -## Layer Function - -A layer is a Python function that creates some operators and variables. Layers simplify the work of application programmers. - -Layer functions take `Variable` and configuration parameters as its input and return the output variable(s). - -For example, `FullyConnected` take one or more variable as its input. The input could be input data or another layer's output. There are many configuration options for a `FullyConnected` layer, such as layer size, activation, parameter names, initialization strategies of parameters, and so on. The `FullyConnected` layer will return an output variable. - - -### Necessity for reusing code between layer functions - -There are a lot of code that can be reused. Such as - -* Give the default value of configuration. e.g., default initialize strategy for parameters is uniform random with `min = -1.0`, `max = 1.0`. and default initialize strategy for bias is to fill zero. -* Append the activation operator. -* Create a temporary variable. -* Create parameter. -* Generate a unique name. -* Add a bias. -* ... - -A mechanism to reuse code between layer functions is necessary. It will be around [150 lines of code](https://github.com/PaddlePaddle/Paddle/pull/4724/files#diff-823b27e07e93914ada859232ae23f846R12) if we write a `FullyConnected` layer without any helper functions. - - - -### Comparision between global functions and helper class - -The `FullyConnected` layer will be as follow when we provide global functions: - -```python -def fc_layer(input, size, param_attr=None, bias_attr=None, act=None, name=None): - if name is None: - name = unique_name("fc") - input = multiple_input(input) - param_attr = default_param_attr(param_attr) - param_attr = multiple_param_attr(param_attr, len(input)) - - # mul - mul_results = [] - for ipt, attr in zip(input, param_attr): - shape = ipt.shape[1:] + [size] - w = g_program.global_block().create_parameter(shape, ipt.dtype, name, attr) - tmp = create_tmp_var(name) - g_program.current_block().append_op("mul", {ipt, w}, {tmp}) - mul_results.append(tmp) - - # add sum - ... - # add bias - ... - # add activation - ... - return out -``` - -We can provide many helpers functions for layer developers. However, there are several disadvantages for global helper functions: - -1. We need a namespace for these methods, then layer developers can quickly figure out what method they can use. -2. Global functions will force layer developers to pass its parameter time by time. - -So we provide a helper class, `LayerHelper`, to share code between layer functions. The `FullyConnected` Layer will be as follow. - -```python -def fc_layer(input, size, param_attr=None, bias_attr=None, act=None, name=None): - helper = LayerHelper(locals()) # pass all parameter to LayerHelper - - mul_results = [] - for ipt, param in helper.iter_multiple_input_and_param(): - w = helper.create_parameter(shape=ipt.shape[1:] + [size], dtype = ipt.dtype) - tmp = helper.create_tmp_variable() - helper.append_op('mul', {ipt, w}, {tmp}) - mul_results.append(tmp) - - pre_bias = helper.add_sum(mul_results) - pre_activation = helper.add_bias(pre_bias) - return helper.add_activation(pre_activation) -``` - -We not only use the fewer lines of code to write `fc_layer` but also make the code clearer to understand. At the same time, layer developers can figure out what function they can invoke by typing `helper.` in a python editor. - - -### Implementation of layer helper - -We just keep all parameters of a layer function as a dictionary in layer helper as a private data member. Every method of layer helper will look up the dictionary after it is invoked. In that way, we can implement a layer helper for all layer functions even some layer does not contain some operator. For example, The `activation` is used by the FullyConnected layer or convolution layers, but a cross-entropy layer does not use it. The example code of `add_activation` are: - -```python -class LayerHelper(object): - def __init__(self, **kwargs): # kwargs is short for `keyword arguments` - self.kwargs = kwargs - - def add_activation(self, input_var): - act = self.kwargs.get("act", None) # default value is None - if act is None: # do nothing if no act - return input_var - - tmp = self.create_tmp_var(self) - self.append_op(type=act, input=input_var, output=tmp) - return tmp -``` - -### Return value of layer functions - -The layer will return a Variable, which is also the output of an operator. However, outputs of a layer function have more attributes than an operator. There are parameter variables, and their gradient variables need to return. To return them is useful. For example, - -1. Users can debug the network by printing parameter gradients. -2. Users can append attributes to a parameter, such as, `param.stop_gradient=True` will make a parameter stop generate the gradient. We can fix the parameter value during training by using this attribute. - -However, it is good to return a Variable for layers, since all layers and operators use Variables as their parameters. We can just append a `param` field and a `grad` field for layer function since the Python is dynamic typing. - -The sample usage is - -```python -data = fluid.layers.data(...) -hidden = fluid.layers.fc(data, ...) -... - -executor.run(fetch_list=[hidden.param, hidden.param.grad], ...) -``` - - -## Optimizer - -[Optimizer Design Doc](./optimizer.md) diff --git a/develop/doc/_sources/design/reader/README.md.txt b/develop/doc/_sources/design/reader/README.md.txt deleted file mode 100644 index 2cd4b6225b6..00000000000 --- a/develop/doc/_sources/design/reader/README.md.txt +++ /dev/null @@ -1,206 +0,0 @@ -# Python Data Reader Design Doc - -During the training and testing phases, PaddlePaddle programs need to read data. To help the users write code that performs reading input data, we define the following: - -- A *reader*: A function that reads data (from file, network, random number generator, etc) and yields the data items. -- A *reader creator*: A function that returns a reader function. -- A *reader decorator*: A function, which takes in one or more readers, and returns a reader. -- A *batch reader*: A function that reads data (from *reader*, file, network, random number generator, etc) and yields a batch of data items. - -and also provide a function which can convert a reader to a batch reader, frequently used reader creators and reader decorators. - -## Data Reader Interface - -*Data reader* doesn't have to be a function that reads and yields data items. It can just be any function without any parameters that creates an iterable (anything can be used in `for x in iterable`) as follows: - -``` -iterable = data_reader() -``` - -The item produced from the iterable should be a **single** entry of data and **not** a mini batch. The entry of data could be a single item or a tuple of items. Item should be of one of the [supported types](http://www.paddlepaddle.org/doc/ui/data_provider/pydataprovider2.html?highlight=dense_vector#input-types) (e.g., numpy 1d array of float32, int, list of int etc.) - -An example implementation for single item data reader creator is as follows: - -```python -def reader_creator_random_image(width, height): - def reader(): - while True: - yield numpy.random.uniform(-1, 1, size=width*height) - return reader -``` - -An example implementation for multiple item data reader creator is as follows: -```python -def reader_creator_random_image_and_label(width, height, label): - def reader(): - while True: - yield numpy.random.uniform(-1, 1, size=width*height), label - return reader -``` - -## Batch Reader Interface - -*Batch reader* can be any function without any parameters that creates an iterable (anything can be used in `for x in iterable`). The output of the iterable should be a batch (list) of data items. Each item inside the list should be a tuple. - -Here are some valid outputs: - -```python -# a mini batch of three data items. Each data item consist three columns of data, each of which is 1. -[(1, 1, 1), -(2, 2, 2), -(3, 3, 3)] - -# a mini batch of three data items, each data item is a list (single column). -[([1,1,1],), -([2,2,2],), -([3,3,3],)] -``` - -Please note that each item inside the list must be a tuple, below is an invalid output: -```python - # wrong, [1,1,1] needs to be inside a tuple: ([1,1,1],). - # Otherwise it is ambiguous whether [1,1,1] means a single column of data [1, 1, 1], - # or three columns of data, each of which is 1. -[[1,1,1], -[2,2,2], -[3,3,3]] -``` - -It is easy to convert from a reader to a batch reader: - -```python -mnist_train = paddle.dataset.mnist.train() -mnist_train_batch_reader = paddle.batch(mnist_train, 128) -``` - -It is also straight forward to create a custom batch reader: - -```python -def custom_batch_reader(): - while True: - batch = [] - for i in xrange(128): - batch.append((numpy.random.uniform(-1, 1, 28*28),)) # note that it's a tuple being appended. - yield batch - -mnist_random_image_batch_reader = custom_batch_reader -``` - -## Usage - -Following is how we can use the reader with PaddlePaddle: -The batch reader, a mapping from item(s) to data layer, the batch size and the number of total passes will be passed into `paddle.train` as follows: - -```python -# two data layer is created: -image_layer = paddle.layer.data("image", ...) -label_layer = paddle.layer.data("label", ...) - -# ... -batch_reader = paddle.batch(paddle.dataset.mnist.train(), 128) -paddle.train(batch_reader, {"image":0, "label":1}, 128, 10, ...) -``` - -## Data Reader Decorator - -The *Data reader decorator* takes in a single reader or multiple data readers and returns a new data reader. It is similar to a [python decorator](https://wiki.python.org/moin/PythonDecorators), but it does not use `@` in the syntax. - -Since we have a strict interface for data readers (no parameters and return a single data item), a data reader can be used in a flexible way using data reader decorators. Following are a few examples: - -### Prefetch Data - -Since reading data may take some time and training can not proceed without data, it is generally a good idea to prefetch the data. - -Use `paddle.reader.buffered` to prefetch data: - -```python -buffered_reader = paddle.reader.buffered(paddle.dataset.mnist.train(), 100) -``` - -`buffered_reader` will try to buffer (prefetch) `100` data entries. - -### Compose Multiple Data Readers - -For example, if we want to use a source of real images (say reusing mnist dataset), and a source of random images as input for [Generative Adversarial Networks](https://arxiv.org/abs/1406.2661). - -We can do the following : - -```python -def reader_creator_random_image(width, height): - def reader(): - while True: - yield numpy.random.uniform(-1, 1, size=width*height) - return reader - -def reader_creator_bool(t): - def reader: - while True: - yield t - return reader - -true_reader = reader_creator_bool(True) -false_reader = reader_creator_bool(False) - -reader = paddle.reader.compose(paddle.dataset.mnist.train(), data_reader_creator_random_image(20, 20), true_reader, false_reader) -# Skipped 1 because paddle.dataset.mnist.train() produces two items per data entry. -# And we don't care about the second item at this time. -paddle.train(paddle.batch(reader, 128), {"true_image":0, "fake_image": 2, "true_label": 3, "false_label": 4}, ...) -``` - -### Shuffle - -Given the shuffle buffer size `n`, `paddle.reader.shuffle` returns a data reader that buffers `n` data entries and shuffles them before a data entry is read. - -Example: -```python -reader = paddle.reader.shuffle(paddle.dataset.mnist.train(), 512) -``` - -## Q & A - -### Why does a reader return only a single entry, and not a mini batch? - -Returning a single entry makes reusing existing data readers much easier (for example, if an existing reader returns 3 entries instead if a single entry, the training code will be more complicated because it need to handle cases like a batch size 2). - -We provide a function: `paddle.batch` to turn (a single entry) reader into a batch reader. - -### Why do we need a batch reader, isn't is sufficient to give the reader and batch_size as arguments during training ? - -In most of the cases, it would be sufficient to give the reader and batch_size as arguments to the train method. However sometimes the user wants to customize the order of data entries inside a mini batch, or even change the batch size dynamically. For these cases using a batch reader is very efficient and helpful. - -### Why use a dictionary instead of a list to provide mapping? - -Using a dictionary (`{"image":0, "label":1}`) instead of a list (`["image", "label"]`) gives the advantage that the user can easily reuse the items (e.g., using `{"image_a":0, "image_b":0, "label":1}`) or even skip an item (e.g., using `{"image_a":0, "label":2}`). - -### How to create a custom data reader creator ? - -```python -def image_reader_creator(image_path, label_path, n): - def reader(): - f = open(image_path) - l = open(label_path) - images = numpy.fromfile( - f, 'ubyte', count=n * 28 * 28).reshape((n, 28 * 28)).astype('float32') - images = images / 255.0 * 2.0 - 1.0 - labels = numpy.fromfile(l, 'ubyte', count=n).astype("int") - for i in xrange(n): - yield images[i, :], labels[i] # a single entry of data is created each time - f.close() - l.close() - return reader - -# images_reader_creator creates a reader -reader = image_reader_creator("/path/to/image_file", "/path/to/label_file", 1024) -paddle.train(paddle.batch(reader, 128), {"image":0, "label":1}, ...) -``` - -### How is `paddle.train` implemented - -An example implementation of paddle.train is: - -```python -def train(batch_reader, mapping, batch_size, total_pass): - for pass_idx in range(total_pass): - for mini_batch in batch_reader(): # this loop will never end in online learning. - do_forward_backward(mini_batch, mapping) -``` diff --git a/develop/doc/_sources/design/refactorization.md.txt b/develop/doc/_sources/design/refactorization.md.txt deleted file mode 100644 index f93d6155e17..00000000000 --- a/develop/doc/_sources/design/refactorization.md.txt +++ /dev/null @@ -1,249 +0,0 @@ -# Design Doc: Refactorization Overview - -The goals of refactoring include: - -1. Making it easy for external contributors to write new elementary computation operations. -1. Making the codebase clean and readable. -1. Designing a new computation representation -- a computation graph of operators and variables. -1. Implementing auto-scalability and auto fault recoverable distributed computing with the help of computation graphs. - -## Computation Graphs - -1. PaddlePaddle represents the computation, training and inference of Deep Learning models, by computation graphs. - - 1. Please refer to [computation graphs](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/graph.md) for a concrete example. - -1. Users write Python programs to describe the graphs and run them (locally or remotely). - -1. A graph is composed of *variables* and *operators*. - -1. The description of graphs must be serializable/deserializable, so that: - - 1. It can be sent to the cloud for distributed execution, and - 1. It can be sent to clients for mobile or enterprise deployment. - -1. The Python program does two things - - 1. *Compilation* runs a Python program to generate a protobuf message representation of the graph and send it to - 1. the C++ library `libpaddle.so` for local execution, - 1. the master process of a distributed training job for training, or - 1. the server process of a Kubernetes serving job for distributed serving. - 1. *Execution* executes the graph by constructing instances of class [`Variable`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/variable.h#L24) and [`OperatorBase`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/operator.h#L70), according to the protobuf message. - -## Description and Realization of Computation Graph - -At compile time, the Python program generates a protobuf message representation of the graph, or a description of the graph. - -At runtime, the C++ program realizes the graph and runs it. - -| | Representation (protobuf messages) | Realization (C++ class objects) | -|---|---|---| -|Data|[VarDesc](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto#L107)|[Variable](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/variable.h#L24)| -|Operation|[OpDesc](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto#L35)|[Operator](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/operator.h#L64)| -|Block|BlockDesc|Block| - -The word *graph* is interchangeable with *block* in this document. A graph consists of computation steps and local variables similar to a C++/Java program block, or a pair of parentheses(`{` and `}`). - -## Compilation and Execution - -1. Run a Python program to describe the graph. In particular, the Python application program does the following: - - 1. Create `VarDesc` to represent local/intermediate variables, - 1. Create operators and set attributes, - 1. Validate attribute values, - 1. Infer the type and the shape of variables, - 1. Plan memory-reuse for variables, - 1. Generate the backward graph - 1. Add optimization operators to the computation graph. - 1. Optionally, split the graph for distributed training. - -1. The invocation of `train` or [`infer`](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/v2/inference.py#L108) methods in the Python program does the following: - - 1. Create a new Scope instance in the [scope hierarchy](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/scope.md) for each run of a block, - 1. realize local variables defined in the BlockDesc message in the new scope, - 1. a scope is similar to the stack frame in programming languages, - - 1. Create an instance of class `Block`, in which, - 1. realize operators in the BlockDesc message, - - 1. Run the Block by calling - 1. `Block::Eval(vector* targets)` for forward and backward computations, or - 1. `Block::Eval(vector* targets)` for optimization. - - -## Intermediate Representation (IR) - -```text -Compile Time -> IR -> Runtime -``` - -### Benefits of IR - -- Optimization - ```text - Compile Time -> IR -> Optimized IR -> Runtime - ``` -- Automatically send partitioned IR to different nodes. - - Automatic Data Parallelism - ```text - Compile Time - |-> Single GPU IR - |-> [trainer-IR-0, trainer-IR-1, pserver-IR] - |-> Node-0 (runs trainer-IR-0) - |-> Node-1 (runs trainer-IR-1) - |-> Node-2 (runs pserver-IR) - ``` - - Automatic Model Parallelism (planned for future) - ---- - -# Operator/OpWithKernel/OpKernel - -![class_diagram](http://api.paddlepaddle.org/graphviz?dot=https://gist.githubusercontent.com/reyoung/53df507f6749762675dff3e7ce53372f/raw/49caf1fb70820fb4a6c217634317c9306f361f36/op_op_with_kern_class_diagram.dot) - ---- - -# Operator -![class_diagram](http://api.paddlepaddle.org/graphviz?dot=https://gist.githubusercontent.com/reyoung/53df507f6749762675dff3e7ce53372f/raw/dd598e8f1976f5759f58af5e5ef94738a6b2e661/op.dot) - -* `Operator` is the fundamental building block of the user interface. - * Operator stores input/output variable names and attributes. - * The `InferShape` interface is used to infer the shape of the output variables based on the shapes of the input variables. - * Use `Run` to compute the `output` variables from the `input` variables. - ---- - -# OpWithKernel/Kernel - -![class_diagram](http://api.paddlepaddle.org/graphviz?dot=https://gist.githubusercontent.com/reyoung/53df507f6749762675dff3e7ce53372f/raw/9d7f4eba185cf41c8e2fbfb40ae21890dbddcd39/op_with_kernel.dot) - -* `OpWithKernel` inherits `Operator`. -* `OpWithKernel` contains a Kernel map. - * `OpWithKernel::Run` get device's kernel, and invoke `OpKernel::Compute`. - * `OpKernelKey` is the map key. Only device place now, but may be data type later. - ---- - -# Why separate Kernel and Operator - -* Separate GPU and CPU code. - * Make Paddle capable of running without GPU. -* Make one operator (which is a user interface) and create many implementations. - * For example, same multiplication op can have different implementations kernels such as FP16 kernel, FP32 kernel, MKL, eigen kernel. ---- - -# Libraries for Kernel development - -* `Eigen::Tensor` contains basic math and element-wise functions. - * Note that `Eigen::Tensor` has broadcast implementation. - * Limit the number of `tensor.device(dev) = ` in your code. -* `thrust::transform` and `std::transform`. - * `thrust` has the same API as C++ standard library. Using `transform`, one can quickly implement customized element-wise kernels. - * `thrust`, in addition, supports more complex APIs, like `scan`, `reduce`, `reduce_by_key`. -* Hand-writing `GPUKernel` and `CPU` code - * Do not write in header (`.h`) files. CPU Kernel should be in cpp source (`.cc`) and GPU kernels should be in cuda (`.cu`) files. (GCC cannot compile GPU code.) ---- -# Operator Registration - -## Why is registration necessary? -We need a method to build mappings between Op type names and Op classes. - -## How is registration implemented? -Maintaining a map, whose key is the type name and the value is the corresponding Op constructor. - ---- -# The Registry Map - -### `OpInfoMap` - -`op_type(string)` -> `OpInfo` - -`OpInfo`: - -- **`creator`**: The Op constructor. -- **`grad_op_type`**: The type of the gradient Op. -- **`proto`**: The Op's Protobuf, including inputs, outputs and required attributes. -- **`checker`**: Used to check attributes. - ---- -# Related Concepts - -### Op_Maker -It's constructor takes `proto` and `checker`. They are completed during Op_Maker's construction. ([ScaleOpMaker](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/scale_op.cc#L37)) - -### Register Macros -```cpp -REGISTER_OP(op_type, op_class, op_maker_class, grad_op_type, grad_op_class) -REGISTER_OP_WITHOUT_GRADIENT(op_type, op_class, op_maker_class) -``` - ---- -# Registration Process -1. Write an Op class and its gradient Op class, if required. -2. Write an Op maker class. In the constructor of this class, describe the inputs, outputs and attributes of the operator. -3. Invoke the macro `REGISTER_OP`. This macro will - 1. Call maker class to complete `proto` and `checker` - 2. Using the completed `proto` and `checker`, it will add a new key-value pair to the `OpInfoMap` - ---- -# Backward Module (1/2) -### Create Backward Operator -- Mapping from forward Op to backward Op -![backward](https://gist.githubusercontent.com/dzhwinter/a6fbd4623ee76c459f7f94591fd1abf0/raw/61026ab6e518e66bde66a889bc42557a1fccff33/backward.png) - ---- -# Backward Module (2/2) -### Build Backward Network -- **Input**: a graph of forward operators -- **Output**: a graph of backward operators -- **Corner cases in construction** - - Shared Variables => insert an `Add` operator to combine gradients - - No Gradient => insert a `fill_zero_grad` operator - - Recursive NetOp => call `Backward` recursively - - RNN Op => recursively call `Backward` on stepnet - - RNN Op => recursively call `Backward` on stepnet - - ---- -# Scope, Variable, Tensor - -* `Tensor` is an n-dimension array with type. - * Only dims and data pointers are stored in `Tensor`. - * All operations on `Tensor` are written in `Operator` or global functions. - * Variable length Tensor design [LoDTensor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/lod_tensor.md) -* `Variable` instances are the inputs and the outputs of an operator, not just `Tensor`. - * `step_scopes` in RNN is a variable and not a tensor. -* `Scope` is where variables are stored. - * map - * `Scope` has a hierarchical structure. The local scope can get variables from its parent scope. - ---- -# Block (in design) -## the difference between original RNNOp and Block -- As an operator is more intuitive than `RNNOp`, -- Offers a new interface `Eval(targets)` to deduce the minimal block to `Run`, -- Fits the compile-time/ runtime separation design paradigm. - - During the compilation, `SymbolTable` stores `VarDesc`s and `OpDesc`s and serialize to a `BlockDesc` - - When graph executes, a Block with `BlockDesc` is passed. It then creates `Op` and `Var` instances and then invokes `Run`. - ---- -# Milestone -- Take Paddle/books as the main line, the requirement of the models motivates framework refactoring, -- Model migration - - Framework development gives **priority support** to model migration, for example, - - the MNIST demo needs a Python interface, - - the RNN models require the framework to support `LoDTensor`. - - Determine some timelines, - - Frequently used Ops need to be migrated first, - - Different models can be migrated in parallel. -- Improve the framework at the same time -- Accept imperfection, concentrate on solving the specific problem at the right price. - ---- -# Control the migration quality -- Compare the performance of migrated models with old ones. -- Follow the google C++ style guide. -- Build the automatic workflow of generating Python/C++ documentations. - - The documentation of layers and ops should be written inside the code. - - Take the documentation quality into account when submitting pull requests. - - Preview the documentations, read and improve them from a user's perspective. diff --git a/develop/doc/_sources/design/register_grad_op.md.txt b/develop/doc/_sources/design/register_grad_op.md.txt deleted file mode 100644 index 8d973eb5317..00000000000 --- a/develop/doc/_sources/design/register_grad_op.md.txt +++ /dev/null @@ -1,92 +0,0 @@ -# Design Doc: Gradient Operators Registration - - -## The Problem Posed - -Currently, for each C++ operator class definition, a *gradient operator creator* function is registered, which takes as input a C++ operator instance and returns the corresponding gradient operator instance. - -However, we noticed two problems with the current design: - -1. As we decided to separate the *compilation* and the *execution* phases, we need to change the creator to take an `OpDesc` protobuf message in a `ProgramDesc` and inserts corresponding `OpDesc` messages into the `ProgramDesc` message. - -1. For some operators, the gradient computation can be written in terms of existing operators. For example, the gradient of *minus* operator consists of two operators -- an *identity* operator followed by a *scale* operator. Hence the registration mechanism needs to support mapping from an operator to a set of operators for the gradient computation. - -## The Current Implementation - -Instances of the C++ class `OpInfo` are stored an associative map whose key is the operator type. The `grad_op_type` indicates the associated gradient operator type. An operator can create the gradient operator by invoking `OpInfo::creator_` of the gradient operator. The pseudo code is as follows - -```cpp -struct OpInfo { - std::function creator_; - std::string grad_op_type_; - ... -}; - -map OpInfoMap; - -OperatorBase* CreateGradientOperator(const OperatorBase& op) { - return OpInfoMap.at(op.Type()).creator_(...); -} -``` - -## Proposed Solution - -The mapping relationship between an operator and its gradient operators is a function. The interface of this function is: - -```cpp -// (OpDesc) --> vector -std::function(const OpDescBind&)>; -``` - -The function takes an `OpDescBind` of the forward operator and returns one or many gradient operator descriptions. `OpDescBind` is a C++ wrapper for the protobuf message `OpDesc` for rapid manipulation of `OpDesc`. - -The `GradOpDescMaker` will be registered in `OpInfo` and will replace the `grad_op_type_` field. The `OpInfo` should look like - -```cpp -struct OpInfo { - std::function>(const OpDescBind&)> grad_op_maker_; - ... -}; -``` - -The `grad_op_maker_ ` is a `nullptr` if the operator does not have any associated gradient operators. - -We propose a base class called `GradOpDescMakerBase` to let operator developers generate `Gradient Operators` easily. The public interface of that class is - -```cpp -class GradOpDescMakerBase { -public: - GradOpDescMakerBase(const OpDescBind& ); - virtual std::vector> operator()()const = 0; -}; -``` - -We can convert `GradOpDescMakerBase` to `std::function>(const OpDescBind&)>` by - -```cpp -using GradOpMaker = ...; -std::function(const OpDescBind&)> func; -func = [] (const OpDescBind& fwd_op) { - GradOpMaker maker(fwd_op); - return maker(); -}; -``` - -We can write many helper functions since the `GradOpDescMakerBase` is a class now. The basic helper functions get the variables of `Input`, `Output`, `InputGradient` and `OutputGradient` in the forwarding operator. - -We should change register macros at the same time. In the current solution, there is no difference between forwarding operators and backward operators. So `REGISTER_OP` just register one operator. If the `REGISTER_OPERATOR ` contains `OpProtoAndCheckerMaker` and `GradOpDescMaker`, we just list them in the same macro. It can be done by a macro contains `__VA_ARGS__`. - -The user interface should be - -```cpp -vector MinusOpGradMaker(OpDesc) {...} -REGISTER_OPERATOR(minus, MinusOp, MinusOpProtoAndCheckerMaker, SumOpGradMaker); -// Developers can still manually implement gradient operator. -REGISTER_OPERATOR(minus_grad, MinusGradOp); -``` - -The interface of current `REGISTER_OP` macro could not be changed. In `REGISTER_OP`, it will invoke `REGISTER_OPERATOR` two times and generate GradOpDescMaker inside. - -```cpp -REGISTER_OP(minus, MinusOp, MinusOpProtoAndCheckerMaker, minus_grad, MinusGradOp); -``` diff --git a/develop/doc/_sources/design/regularization.md.txt b/develop/doc/_sources/design/regularization.md.txt deleted file mode 100644 index 21280ac898f..00000000000 --- a/develop/doc/_sources/design/regularization.md.txt +++ /dev/null @@ -1,72 +0,0 @@ -# Regularization in PaddlePaddle - -## Introduction to Regularization -A central problem in machine learning is how to design an algorithm that will perform well not just on the training data, but also on new data. A frequently faced problem is the problem of **overfitting**, where the model does not make reliable predictions on new unseen data. **Regularization** is the process of introducing additional information in order to prevent overfitting. This is usually done by adding extra penalties to the loss function that restricts the parameter spaces that an optimization algorithm can explore. - -### Parameter Norm Penalties -Most common regularization approaches in deep learning are based on limiting the capacity of the models by adding a parameter norm penalty to the objective function `J`. This is given as follows: - -
- -The parameter `alpha` is a hyperparameter that weights the relative contribution of the norm penalty term, `omega`, relative to the standard objective function `J`. - -The most commonly used norm penalties are the L2 norm penalty and the L1 norm penalty. These are given as follows: - -##### L2 Regularization: -
- -##### L1 Regularization -
- -A much more detailed mathematical background of regularization can be found [here](http://www.deeplearningbook.org/contents/regularization.html). - -## Regularization Survey - -A detailed survey of regularization in various deep learning frameworks can be found [here](https://github.com/PaddlePaddle/Paddle/wiki/Regularization-Survey). - -## Proposal for Regularization in PaddlePaddle - -### Low-Level implementation - -In the new design, we propose to create new operations for regularization. For now, we can add 2 ops that correspond to the most frequently used regularizations: -- L2_regularization_op -- L1_regularization_op - -These ops can be like any other ops with their own CPU/GPU implementations either using Eigen or separate CPU and GPU kernels. As the initial implementation, we can implement their kernels using Eigen following the abstraction pattern implemented for [Activation Ops](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/accuracy_op.h). This abstraction pattern can make it very easy to implement new regularization schemes other than L1 and L2 norm penalties. - -The idea of building ops for regularization is in sync with the refactored Paddle philosophy of using operators to represent any computation unit. The way these ops will be added to the computation graph, will be decided by the [layer functions](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md#layer-function) in Python API. - -### Computation Graph - -Below is an example of a really simple feed forward neural network. - -
- -The Python API will modify this computation graph to add regularization operators. The modified computation graph will look as follows: - -
-    -### Python API implementation for Regularization - -Using the low level ops, `L2_regularization_op` and `L1_regularization_op`, any user can add regularization to their computation graphs. However, this will require a lot of lines of code and we should design Python APIs that support regularization. An example of such an API can be seen in [Keras](https://keras.io/regularizers/). As per the PaddlePaddle [Python API design](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md), the layer functions are responsible for creating operators, operator parameters and variables. Since regularization is a property of parameters, it makes sense to create these in the layer functions. - -#### Creation of Regularization ops -There are two possibilities for creating the regularization ops: -1. We create these ops immediately while building the computation graph. -2. We add these ops in a lazy manner, just before the backward, similar to the way the optimization ops are added. - -The proposal is to add these ops in a lazy manner just before the backward pass. - -#### Storage of Regularization attributes - -Since we want to create the regularization ops in a lazy manner, the regularization attributes (type of regularization and weight of regularization penalty) can be stored as attributes of the [`Parameter`](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/v2/framework/framework.py#L421) class. This is because regularization is a property of the parameters and storing regularization properties with Parameters also allows for shared parameters. - -#### High-level API - -In PaddlePaddle Python API, users will primarily rely on [layer functions](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md#layer-function) to create neural network layers. Hence, we also need to provide regularization functionality in layer functions. The design of these APIs can be postponed for later right now. A good reference for these APIs can be found in [Keras](https://keras.io/regularizers/) and also by looking at Tensorflow in [`tf.contrib.layers`](https://www.tensorflow.org/api_guides/python/contrib.layers). - - - - - - diff --git a/develop/doc/_sources/design/releasing_process.md.txt b/develop/doc/_sources/design/releasing_process.md.txt deleted file mode 100644 index b9787261092..00000000000 --- a/develop/doc/_sources/design/releasing_process.md.txt +++ /dev/null @@ -1,90 +0,0 @@ -# PaddlePaddle发行规范 - -PaddlePaddle使用git-flow branching model做分支管理,使用[Semantic Versioning](http://semver.org/)标准表示PaddlePaddle版本号。 - -PaddlePaddle每次发新的版本,遵循以下流程: - -1. 从`develop`分支派生出新的分支,分支名为`release/版本号`。例如,`release/0.10.0` -1. 将新分支的版本打上tag,tag为`版本号rc.Patch号`。第一个tag为`0.10.0rc1`,第二个为`0.10.0rc2`,依次类推。 -1. 对这个版本的提交,做如下几个操作: - * 使用Regression Test List作为检查列表,测试本次release的正确性。 - * 如果失败,记录下所有失败的例子,在这个`release/版本号`分支中,修复所有bug后,Patch号加一,到第二步 - * 修改`python/setup.py.in`中的版本信息,并将`istaged`字段设为`True`。 - * 编译这个版本的python wheel包,并发布到pypi。 - * 由于pypi.python.org目前遵循[严格的命名规范PEP 513](https://www.python.org/dev/peps/pep-0513),在使用twine上传之前,需要重命名wheel包中platform相关的后缀,比如将`linux_x86_64`修改成`manylinux1_x86_64`。 - * pypi上的package名称为paddlepaddle和paddlepaddle_gpu,如果要上传GPU版本的包,需要修改build/python/setup.py中,name: "paddlepaddle_gpu"并重新打包wheel包:`python setup.py bdist_wheel`。 - * 上传方法: - ``` - cd build/python - pip install twine - twine upload dist/[package to upload] - ``` - * 编译这个版本的Docker发行镜像,发布到dockerhub。如果失败,修复Docker编译镜像问题,Patch号加一,返回第二步 -1. 第三步完成后,将`release/版本号`分支合入master分支,并删除`release/版本号`分支。将master分支的合入commit打上tag,tag为`版本号`。同时再将`master`分支合入`develop`分支。最后删除`release/版本号`分支。 -1. 协同完成Release Note的书写 - - -需要注意的是: - -* `release/版本号`分支一旦建立,一般不允许再从`develop`分支合入`release/版本号`。这样保证`release/版本号`分支功能的封闭,方便测试人员测试PaddlePaddle的行为。 -* 在`release/版本号`分支存在的时候,如果有bugfix的行为,需要将bugfix的分支同时merge到`master`, `develop`和`release/版本号`这三个分支。 - -## 发布wheel包到pypi - -使用[PaddlePaddle CI](https://paddleci.ngrok.io/project.html?projectId=Manylinux1&tab=projectOverview) -完成自动化二进制编译,参考下图,选择需要发布的版本(通常包含一个CPU版本和一个GPU版本),点击"run"右侧的"..."按钮,可以 -弹出下面的选择框,在第二个tab (Changes)里选择需要发布的分支,这里选择0.11.0,然后点击"Run Build"按钮。等待编译完成后 -可以在此页面的"Artifacts"下拉框中找到生成的3个二进制文件,分别对应CAPI,`cp27m`和`cp27mu`的版本。然后按照上述的方法 -使用`twine`工具上传即可。 - - - -* 注:CI环境使用 https://github.com/PaddlePaddle/buildtools 这里的DockerImage作为编译环境以支持更多的Linux - 发型版,如果需要手动编译,也可以使用这些镜像。这些镜像也可以从 https://hub.docker.com/r/paddlepaddle/paddle_manylinux_devel/tags/ 下载得到。 -* pypi不支持覆盖上传,所以一个版本号的wheel包发布之后,不可以更改。下一个wheel包需要更新版本号才可以上传。 - -## 发布Docker镜像 - -上述PaddlePaddle CI编译wheel完成后会自动将Docker镜像push到DockerHub,所以,发布Docker镜像只需要对自动push的镜像打上 -版本号对应的tag即可: - -1. 进入 https://hub.docker.com/r/paddlepaddle/paddle/tags/ 查看latest tag的更新时间是否在上述编译wheel包完成后是否最新。 -1. 执行 `docker pull paddlepaddle/paddle:[latest tag]`,latest tag可以是latest或latest-gpu等。 -1. 执行 `docker tag paddlepaddle/paddle:[latest tag] paddlepaddle/paddle:[version]` -1. 执行 `docker push paddlepaddle/paddle:[version]` - -## PaddlePaddle 分支规范 - -PaddlePaddle开发过程使用[git-flow](http://nvie.com/posts/a-successful-git-branching-model/)分支规范,并适应github的特性做了一些区别。 - -* PaddlePaddle的主版本库遵循[git-flow](http://nvie.com/posts/a-successful-git-branching-model/)分支规范。其中: - * `master`分支为稳定(stable branch)版本分支。每一个`master`分支的版本都是经过单元测试和回归测试的版本。 - * `develop`分支为开发(develop branch)版本分支。每一个`develop`分支的版本都经过单元测试,但并没有经过回归测试。 - * `release/版本号`分支为每一次Release时建立的临时分支。在这个阶段的代码正在经历回归测试。 - -* 其他用户的fork版本库并不需要严格遵守[git-flow](http://nvie.com/posts/a-successful-git-branching-model/)分支规范,但所有fork的版本库的所有分支都相当于特性分支。 - * 建议,开发者fork的版本库使用`develop`分支同步主版本库的`develop`分支 - * 建议,开发者fork的版本库中,再基于`develop`版本fork出自己的功能分支。 - * 当功能分支开发完毕后,向PaddlePaddle的主版本库提交`Pull Reuqest`,进而进行代码评审。 - * 在评审过程中,开发者修改自己的代码,可以继续在自己的功能分支提交代码。 - -* BugFix分支也是在开发者自己的fork版本库维护,与功能分支不同的是,BugFix分支需要分别给主版本库的`master`、`develop`与可能有的`release/版本号`分支,同时提起`Pull Request`。 - -## PaddlePaddle回归测试列表 - -本列表说明PaddlePaddle发版之前需要测试的功能点。 - -### PaddlePaddle Book中所有章节 - -PaddlePaddle每次发版本首先要保证PaddlePaddle Book中所有章节功能的正确性。功能的正确性包括验证PaddlePaddle目前的`paddle_trainer`训练和纯使用`Python`训练模型正确性。 - -| | 新手入门章节 | 识别数字 | 图像分类 | 词向量 | 情感分析 | 语意角色标注 | 机器翻译 | 个性化推荐 | -| --- | --- | --- | --- | --- | --- | --- | --- | --- | -| API.V2 + Docker + GPU | | | | | | | | | -| API.V2 + Docker + CPU | | | | | | | | | -| `paddle_trainer` + Docker + GPU | | | | | | | | | -| `paddle_trainer` + Docker + CPU | | | | | | | | | -| API.V2 + Ubuntu + GPU | | | | | | | | | -| API.V2 + Ubuntu + CPU | | | | | | | | | -| `paddle_trainer` + Ubuntu + GPU | | | | | | | | | -| `paddle_trainer` + Ubuntu + CPU | | | | | | | | | diff --git a/develop/doc/_sources/design/scope.md.txt b/develop/doc/_sources/design/scope.md.txt deleted file mode 100644 index 4da76eebb74..00000000000 --- a/develop/doc/_sources/design/scope.md.txt +++ /dev/null @@ -1,124 +0,0 @@ -# Design of Scope in Paddle - -## Overview - -Scope is an important concept in programming languages, which defines a program region that a set of bindings between names and entities applies. In a specific scope, a valid name is uniquely associated with an entity, such as a variable. And in another scope, this name may refer to other entity or nothing at all. It clearly restricts the visibility and validity of names in a program. Hence **Scope** is introduced to PaddlePaddle to manage variables in context. But different from the original abstract concept, Scope now becomes an object with two important attributes: - -- Scope is an association of a name to variable. -- Variables in a parent scope can be retrieved from local scope. - -A detailed explanation of these two attributes goes as following. - - -## Scope is an association of a name to variable. - -Scope is an association of a name to variable. All variables belong to `Scope`. You need to specify a scope to run a Net, i.e., `net.Run(&scope)`. One net can run in different scopes and update different variable in the scope. - - -1. Scope only contains a map of a name to variable. - - All parameters, data, states in a Net should be variables and stored inside a scope. Each op should get inputs and outputs to do computation from a scope, such as data buffer, state (momentum) etc. - -1. Variable can only be created by Scope and a variable can only be got from Scope. User cannot create or get a variable outside a scope. This is a constraints of our framework, and will keep our framework simple and clear. - -1. Scope only contains methods that are used to Create and Get Variables. Scope do not contain Operators and have no information to run them. - `Net` is designed to drive the computation and Scope only contains a map of variables. There is no computation logic inside a `Scope`. Scope just handles the lifetime management of variables. - - `Create` is used to create a Variable by its name and add the mapping relation. - - `Get` is used to find a Variable by name. - -1. Every variable only belongs to one certain Scope. - - Variable can not belong to many scopes. If you want to use variables from parent scope, you can use `parent scope`. - -1. Scope should destruct all Variables inside it when itself is destructed. User can never store `Variable` pointer somewhere else. - - Because Variable can only be got from Scope. When destroying Scope, we also need to destroy all the Variables in it. If user store `Variable` pointer to private data member or some global variable, the pointer will be an invalid pointer when associated `Scope` is destroyed. - -```cpp -class Scope { - public: - Variable* Var(const std::string& name); - const Variable* FindVar(const std::string& name) const; - - private: - std::unordered_map> vars_; -}; -``` - - -## Parent scope and local scope - -Just like [scope](https://en.wikipedia.org/wiki/Scope_(computer_science)) in programming languages, `Scope` in the neural network can also be a local scope. There are two attributes about local scope. - -1. We can create local variables in a local scope. When that local scope is destroyed, all local variables should also be destroyed. -2. Variables in a parent scope can be retrieved from local scopes of that parent scope, i.e., when user get a variable from a scope, it will try to search this variable in current scope. If there is no such variable in the local scope, `scope` will keep searching from its parent, until the variable is found or there is no parent. - -```cpp -class Scope { - public: - Scope(const std::shared_ptr& scope): parent_(scope) {} - - Variable* FindVar(const std::string& name) const { - auto it = vars_.find(name); - if (it != vars_.end()) { - return it->second.get(); - } else if (parent_ != nullptr) { - return parent_->FindVar(name); - } else { - return nullptr; - } - } - - private: - std::shared_ptr parent_ {nullptr}; -}; -``` - -In `Scope` class, there is a private data member called `parent_`. `parent_` is a smart pointer to its parent scope. When user `Get` a variable by its `name`, the `name` will be searched inside the current scope. If the variable cannot be found locally and parent scope is not a `nullptr`, the variable will be searched inside that parent scope. `parent_` pointer's default value is `nullptr`. It means that the scope is a global scope when `parent_` is nullptr. - -A local scope is very useful when we implement Recurrent Neural Network. Each timestep of an RNN should be a `Net`. Each `Net` of timestep (`StepNet` for short) should use an independent local scope. Just like variables in a while loop is inside a local scope in programming languages. By using a single `StepNet` and changing local scope, we can implement an RNN easily. - -# Interface Design - -```cpp -class Variable { - private: - Variable() = default; - friend class Scope; -}; - -class Scope { - private: - Scope(const std::shared_ptr& parent = nullptr); - - public: - static std::shared_ptr Create(const std::shared_ptr& parent = nullptr); - - // return nullptr if not found. - Variable* FindVar(const std::string& name) const; - - // return if already contains same name variable. - Variable* Var(const std::string& name); - - private: - std::shared_ptr parent_; - std::unordered_map> vars_; -}; -``` -## Only scope can create a variable - -To ensure `only scope can create a variable`, we should mark `Variable`'s constructor as a private member function, and Scope is a friend class of Variable. And then only `Var` can construct `Variable`. - -## When scope destroyed, all variables inside this scope should be destroyed together - -The scope hold unique pointers for all variables. User can `FindVar` from scope, but he should not hold this pointer as a member variable. Because when scope is destroyed, all variables inside this scope will be destroyed together. - -## Sharing a parent scope - -Local scope contains a `parent_` pointer. It is a linked-list for scopes. Using a `shared_ptr` because when a local scope is using, its parents cannot be destroyed. - -Also, as the parent scope is a `shared_ptr`, we can only `Create()` a scope shared pointer. We cannot construct a scope variable, because it cannot be passed to other scope as `parent` pointer. - -## Orthogonal interface - -`FindVar` will return `nullptr` when `name` is not found. It can be used as `Contains` method. `Var` will return an `Error` when there is a name conflict locally. Combine `FindVar` and `Var`, we can implement `Var` easily. diff --git a/develop/doc/_sources/design/selected_rows.md.txt b/develop/doc/_sources/design/selected_rows.md.txt deleted file mode 100644 index 1a98839a957..00000000000 --- a/develop/doc/_sources/design/selected_rows.md.txt +++ /dev/null @@ -1,74 +0,0 @@ -# Design Doc: Selected Rows - -`SelectedRows` is a type of sparse tensor data type, which is designed to support `embedding` operators. The gradient of embedding table is a sparse tensor. Only a few rows are non-zero values in this tensor. It is straight-forward to represent a sparse tensor by the following sparse tensor data structure: - -```cpp -class SelectedRows { - private: - vector rows_; - Tensor value_; - int height_; -}; -``` - -The field `height_` is the first dimension of `SelectedRows`. The `rows` are the indices of the non-zero rows of `SelectedRows`. The `value_` field is an N-dim tensor of shape `[rows.size() /* NUM_ROWS */, ...]`, which supplies values for each row. The dimension of `SelectedRows` satisfies `[height_] + value_.shape[1:]`. - -Suppose that a SelectedRows-typed variable `x` has many rows, but only two of them have values -- row 73 is `[1, 2]` and row 84 is `[3, 4]`, the `SelectedRows` representation would be: - -``` -x = SelectedRow { - rows = [73, 84], - value = [[1, 2], [3,4]] -} -``` - - -## SelectedRows in Protobuf - -`SelectedRows` is a type of `Variable`. `VarDesc` in protobuf should describe the `SelectedRows` information. Only the tensor dimension of a `SelectedRows` will be described in compile-time because the `rows_` and `value_` are dependent on the training data. -So we use `TensorDesc` to unify `data_type` and `dims`. A LodTensorDesc contains a `TensorDesc` and `lod_level`. The description of `SelectedRows` is a Tensor description. - -```proto -message TensorDesc { - required DataType data_type = 1; - repeated int64 dims = 2; // [UNK, 640, 480] is saved as [-1, 640, 480] -} - -message LodTensorDesc { - required TensorDesc tensor = 1; - optional int lod_level = 2; -} - -message VarDesc { - required string name = 1; - enum VarType { - LOD_TENSOR = 0; - SELECTED_ROWS = 1; - } - required VarType type = 2; - optional LodTensorDesc lod_desc = 3; - optional TensorDesc selected_rows_desc = 4; - optional bool persistable = 5 [ default = false ]; -} -``` - -## InferShape for Selected Rows - -Just like `LoD` information, `InferShape` method will infer the output tensor type as well. The operator should decide whether its output is a `SelectedRows` or `Dense` tensor. - -For example, the gradient operator of `TableLookup` will always generate `SelectedRows`. Its `InferShape` method should be like following - -```cpp -void TableLookupGrad::InferShape(context) { - ... - context.SetDataType("Embedding.Grad", kSelectedRows); -} -``` - - -## Sparse Operators - -There are several operators that need to be written to support `SelectedRows`. These are: - -1. Operators which generate `SelectedRows` gradient. e.g. Gradient of `TableLookupOp`. -2. Optimize operators which support `SelectedRows` gradient. e.g. `SGD` or `AdaGrad` for `SelectedRows`. However, there should be only one `SGD` operator. `OpWithKernel::Run` should select a suitable kernel for both `dense` tensor or `SelectedRows`. diff --git a/develop/doc/_sources/design/simple_op_design.md.txt b/develop/doc/_sources/design/simple_op_design.md.txt deleted file mode 100644 index c7aeed7f9b4..00000000000 --- a/develop/doc/_sources/design/simple_op_design.md.txt +++ /dev/null @@ -1,202 +0,0 @@ -## Interaction between C++ and Python - -Users employ API in Python to describe their own network, however, the network construction actually happens in C++. so Protobuf is introduced to send the message between Python and C++. - -The Interaction between Python and C++ can be simplified as two steps: - -1. C++ tells Python how many Ops there are, and what parameter do users need to offer to initialize a new Op. Python then builds API for each Op at compile time. - -2. Users invoke APIs built by Python and provide necessary parameters. These parameters will be sent to C++ for finishing the Op construction task. - -### Message from C++ to Python - -We define a Protobuf message class `OpProto` to hold message needed in the first step. What should an `OpProto` contain? This question is equivalent to “What message do we need to offer, to build a Python API which is legal and user oriented and can use to describe a whole Op.” - -Following message are necessary: - -1. Op's name, and its simple comment. -2. Input and output variable number; each variable's name, type, and comment. -3. Op's attributes; each attribute includes name, type, comment, **default value** and **value range**. - -So `OpProto` can be defined as follows: - -```proto -enum AttrType { - INT = 1; - FLOAT = 2; - STRING = 3; - INTS = 4; - FLOATS = 5; - STRINGS = 6; -}; - -message AttrValue { - AttrType type = 1; - optional int iv = 2; - optional float fv = 3; - optional string sv = 4; - repeated int ivs = 5; - repeated float fvs = 6; - repeated string svs = 7; -}; - -message AttrProto { - required string name = 1; - required string comment = 2; - required AttrType type = 3; -}; - -message VarProto { - required string name = 1; - required string comment = 2; - required bool is_tensor = 3; -}; - -message OpProto { - repeated VarProto inputs = 1; - repeated VarProto outputs = 2; - repeated AttrProto attrs = 3; - required string type = 4; - required string comment = 5; -}; -``` - -To generate Python code automatically: - -```python -def create_python_ops_creatation_functions(): - op_protos = paddle.framework.OpRegistry.get_all_op_proto() - for type_name in op_protos: - op_proto = op_protos[type_name] - def __impl__(**kwargs): # User must use key word args in Paddle API - inputs = [kwargs.get(ipt.name, "") for ipt in op_proto.inputs] - outputs = [kwargs.get(opt.name, "") for opt in op_proto.outputs] - attrs = [cast_to_op_attr(attr, kwargs.get(attr.name, None)) for attr in op_proto.attrs] - opdesc = (input, outputs, type_name, attrs) - return paddle.framework.OpRegistry.CreateOp(opdesc) - __impl__.__doc__ = create_doc_string(op_proto) - globals()[type_name] = __impl__ - -create_python_ops_creatation_functions() -``` - -### Message from Python to C++ - -To hold message needed in the above second step, we define Protobuf message class `OpDesc`. It is used to hold user-specified parameters in Op describing. - -```proto -message OpDesc { - required string type = 1; - repeated string inputs = 2; - repeated string outputs = 3; - map attrs = 4; -}; -``` - -## OpProto Register - -Every Op has its own `OpProto`. For using convenience, we need to register them and record all their messages. For each `Op` class, we define a corresponding `OpMaker` class, in whose constructor we implement the `OpProto`'s building process. `OpMaker`'s constructor will be invoked by another function `OpRegistry::RegisterOp()`. - -```cpp -class OpProtoMaker { -public: - OpProtoMaker(OpProto* proto): proto_(proto) {} -protected: - OpProto* proto_; - void AddInput(const std::string& name, const std::string& desc) {...} - void AddAttr(const std::string& name, const std::string& desc, TypeId type) {...} - void AddComment(const std::string& comment) { ... } -}; - -class OpRegistry { -public: - using OpCreator = std::function; - - template - static void RegisterOp(const std::string& name) { - gCreators_[name] = [](const OpDesc& desc) { - return new OpType(desc); - }; - OpProto& opProto = gProtos_[name]; - OpMaker()(&opProto); - } - - static map gCreators_; - static map gProtos_; -}; - -template -class OpRegister { - public: - OpRegister(std::string type) { - OpRegistry::RegisterOp(type); - } -}; - -#define REGISTER_OP(op_class, op_maker_class, type_name) \ - class op_class##Register { \ - private: \ - const static OpRegister<#op_class, #op_maker_class> reg; \ - }; \ - const Register op_class##Register::reg(#type_name); - -class CosineOp { -// ... -} - -struct CosineOpProtoMaker : public OpProtoMaker { - CosineOpProtoMaker(OpProto* proto) : OpProtoMaker(proto) { - AddInput("input", "input of cosine op"); - AddAttr("scale", "scale of cosine op", float).Default(1.0).GreaterThan(0.0); - AddType("cos"); - AddComment("This is cos op"); - } -} - -REGISTER_OP(CosineOp, CosineOpProtoMaker, cos); -``` - -In `REGISTER_OP(CosineOp, CosineOpProtoMaker, cos)`, we register not only `CosineOp` but also `CosineOpProto`. As fields of `CosineOpProto`, the default value and value range of `scale` are also registered here. - -## Python API - -Python APIs are divided into two types, high-level API and low-level API. - -### High-Level API - -High-level API is called by users directly, so it should keep its style consistent with existing V2 APIs. - -Here is a sample about how a define a fc layer: - -```python -hd = fc_layer(input=data, size=56, with_bias=True, activation="sigmoid"); -``` - -`hd` is the output of `fc_layer` and it's a `variable`. It can be further sent into other layers as input. - -The definition of `fc_layer()`: - -```python -def fc_layer(input, size, with_bias, activation): - attr_map = {"size":size} - check_attrs(attr_map) - w = make_variable('w') - if with_bias: - b = make_variable('b') - else: - b = None - fc_output = make_variable('fc_output'); - fc_op(input, w, b, fc_output, attr_map) - act_output = make_variable('sigmod_output'); - if activation == "sigmod": - sigmod_op(fc_output, act_output); - elif: - # ... - return act_output; -``` - -### Low Leval API - -In above sample, `fc_op` and `sigmod_op` are low-level API. They build `OpDesc` and invoke corresponding C++ code. - -*TODO* diff --git a/develop/doc/_sources/design/speech/deep_speech_2.md.txt b/develop/doc/_sources/design/speech/deep_speech_2.md.txt deleted file mode 100644 index cfdc4d6df04..00000000000 --- a/develop/doc/_sources/design/speech/deep_speech_2.md.txt +++ /dev/null @@ -1,168 +0,0 @@ -# DeepSpeech2 on PaddlePaddle: Design Doc - -We are planning to build Deep Speech 2 (DS2) \[[1](#references)\], a powerful Automatic Speech Recognition (ASR) engine, on PaddlePaddle. For the first-stage plan, we have the following short-term goals: - -- Release a basic distributed implementation of DS2 on PaddlePaddle. -- Contribute a chapter of Deep Speech to PaddlePaddle Book. - -Intensive system optimization and low-latency inference library (details in \[[1](#references)\]) are not yet covered in this first-stage plan. - -## Table of Contents - -- [Tasks](#tasks) -- [Task Dependency](#task-dependency) -- [Design Details](#design-details) - - [Overview](#overview) - - [Row Convolution](#row-convolution) - - [Beam Search With CTC and LM](#beam-search-with-ctc-and-lm) -- [Future Work](#future-work) -- [References](#references) - -## Tasks - -We roughly break down the project into 14 tasks: - -1. Develop an **audio data provider**: - - Json filelist generator. - - Audio file format transformer. - - Spectrogram feature extraction, power normalization etc. - - Batch data reader with SortaGrad. - - Data augmentation (optional). - - Prepare (one or more) public English data sets & baseline. -2. Create a **simplified DS2 model configuration**: - - With only fixed-length (by padding) audio sequences (otherwise need *Task 3*). - - With only bidirectional-GRU (otherwise need *Task 4*). - - With only greedy decoder (otherwise need *Task 5, 6*). -3. Develop to support **variable-shaped** dense-vector (image) batches of input data. - - Update `DenseScanner` in `dataprovider_converter.py`, etc. -4. Develop a new **lookahead-row-convolution layer** (See \[[1](#references)\] for details): - - Lookahead convolution windows. - - Within-row convolution, without kernels shared across rows. -5. Build KenLM **language model** (5-gram) for beam search decoder: - - Use KenLM toolkit. - - Prepare the corpus & train the model. - - Create infererence interfaces (for Task 6). -6. Develop a **beam search decoder** with CTC + LM + WORDCOUNT: - - Beam search with CTC. - - Beam search with external custom scorer (e.g. LM). - - Try to design a more general beam search interface. -7. Develop a **Word Error Rate evaluator**: - - update `ctc_error_evaluator`(CER) to support WER. -8. Prepare internal dataset for Mandarin (optional): - - Dataset, baseline, evaluation details. - - Particular data preprocessing for Mandarin. - - Might need cooperating with the Speech Department. -9. Create **standard DS2 model configuration**: - - With variable-length audio sequences (need *Task 3*). - - With unidirectional-GRU + row-convolution (need *Task 4*). - - With CTC-LM beam search decoder (need *Task 5, 6*). -10. Make it run perfectly on **clusters**. -11. Experiments and **benchmarking** (for accuracy, not efficiency): - - With public English dataset. - - With internal (Baidu) Mandarin dataset (optional). -12. Time **profiling** and optimization. -13. Prepare **docs**. -14. Prepare PaddlePaddle **Book** chapter with a simplified version. - -## Task Dependency - -Tasks parallelizable within phases: - -Roadmap | Description | Parallelizable Tasks ------------ | :------------------------------------ | :-------------------- -Phase I | Simplified model & components | *Task 1* ~ *Task 8* -Phase II | Standard model & benchmarking & profiling | *Task 9* ~ *Task 12* -Phase III | Documentations | *Task13* ~ *Task14* - -Issue for each task will be created later. Contributions, discussions and comments are all highly appreciated and welcomed! - -## Design Details - -### Overview - -Traditional **ASR** (Automatic Speech Recognition) pipelines require great human efforts devoted to elaborately tuning multiple hand-engineered components (e.g. audio feature design, accoustic model, pronuncation model and language model etc.). **Deep Speech 2** (**DS2**) \[[1](#references)\], however, trains such ASR models in an end-to-end manner, replacing most intermediate modules with only a single deep network architecture. With scaling up both the data and model sizes, DS2 achieves a very significant performance boost. - -Please read Deep Speech 2 \[[1](#references),[2](#references)\] paper for more background knowledge. - -The classical DS2 network contains 15 layers (from bottom to top): - -- **Two** data layers (audio spectrogram, transcription text) -- **Three** 2D convolution layers -- **Seven** uni-directional simple-RNN layers -- **One** lookahead row convolution layers -- **One** fully-connected layers -- **One** CTC-loss layer - -
-
-Figure 1. Archetecture of Deep Speech 2 Network. -
- -We don't have to persist on this 2-3-7-1-1-1 depth \[[2](#references)\]. Similar networks with different depths might also work well. As in \[[1](#references)\], authors use a different depth (e.g. 2-2-3-1-1-1) for final experiments. - -Key ingredients about the layers: - -- **Data Layers**: - - Frame sequences data of audio **spectrogram** (with FFT). - - Token sequences data of **transcription** text (labels). - - These two type of sequences do not have the same lengthes, thus a CTC-loss layer is required. -- **2D Convolution Layers**: - - Not only temporal convolution, but also **frequency convolution**. Like a 2D image convolution, but with a variable dimension (i.e. temporal dimension). - - With striding for only the first convlution layer. - - No pooling for all convolution layers. -- **Uni-directional RNNs** - - Uni-directional + row convolution: for low-latency inference. - - Bi-direcitional + without row convolution: if we don't care about the inference latency. -- **Row convolution**: - - For looking only a few steps ahead into the feature, instead of looking into a whole sequence in bi-directional RNNs. - - Not nessesary if with bi-direcitional RNNs. - - "**Row**" means convolutions are done within each frequency dimension (row), and no convolution kernels shared across. -- **Batch Normalization Layers**: - - Added to all above layers (except for data and loss layer). - - Sequence-wise normalization for RNNs: BatchNorm only performed on input-state projection and not state-state projection, for efficiency consideration. - - -Required Components | PaddlePaddle Support | Need to Develop -:------------------------------------- | :-------------------------------------- | :----------------------- -Data Layer I (Spectrogram) | Not supported yet. | TBD (Task 3) -Data Layer II (Transcription) | `paddle.data_type.integer_value_sequence` | - -2D Convolution Layer | `paddle.layer.image_conv_layer` | - -DataType Converter (vec2seq) | `paddle.layer.block_expand` | - -Bi-/Uni-directional RNNs | `paddle.layer.recurrent_group` | - -Row Convolution Layer | Not supported yet. | TBD (Task 4) -CTC-loss Layer | `paddle.layer.warp_ctc` | - -Batch Normalization Layer | `paddle.layer.batch_norm` | - -CTC-Beam search | Not supported yet. | TBD (Task 6) - -### Row Convolution - -TODO by Assignees - -### Beam Search with CTC and LM - -
-
-Figure 2. Algorithm for CTC Beam Search Decoder. -
- -- The **Beam Search Decoder** for DS2 CTC-trained network follows the similar approach in \[[3](#references)\] as shown in Figure 2, with two important modifications for the ambiguous parts: - - 1) in the iterative computation of probabilities, the assignment operation is changed to accumulation for one prefix may comes from different paths; - - 2) the if condition ```if l^+ not in A_prev then``` after probabilities' computation is deprecated for it is hard to understand and seems unnecessary. -- An **external scorer** would be passed into the decoder to evaluate a candidate prefix during decoding whenever a white space appended in English decoding and any character appended in Mandarin decoding. -- Such external scorer consists of language model, word count or any other custom scorers. -- The **language model** is built from Task 5, with parameters should be carefully tuned to achieve minimum WER/CER (c.f. Task 7) -- This decoder needs to perform with **high efficiency** for the convenience of parameters tuning and speech recognition in reality. - - -## Future Work - -- Efficiency Improvement -- Accuracy Improvement -- Low-latency Inference Library -- Large-scale benchmarking - -## References - -1. Dario Amodei, etc., [Deep Speech 2 : End-to-End Speech Recognition in English and Mandarin](http://proceedings.mlr.press/v48/amodei16.pdf). ICML 2016. -2. Dario Amodei, etc., [Deep Speech 2 : End-to-End Speech Recognition in English and Mandarin](https://arxiv.org/abs/1512.02595). arXiv:1512.02595. -3. Awni Y. Hannun, etc. [First-Pass Large Vocabulary Continuous Speech Recognition using Bi-Directional Recurrent DNNs](https://arxiv.org/abs/1408.2873). arXiv:1408.2873 diff --git a/develop/doc/_sources/design/support_new_device.md.txt b/develop/doc/_sources/design/support_new_device.md.txt deleted file mode 100644 index 8983df90046..00000000000 --- a/develop/doc/_sources/design/support_new_device.md.txt +++ /dev/null @@ -1,240 +0,0 @@ -# Design Doc: Supporting new Device/Library - -## Background - -Deep learning has a high demand for computing resources. New high-performance devices and computing libraries are appearing very frequently. Deep learning frameworks have to integrate these high-performance devices and computing libraries in a flexible and efficient manner. - -On one hand, hardware and computing libraries usually do not have a one-to-one correspondence. For example, Intel CPUs support Eigen and MKL computing libraries while Nvidia GPUs support Eigen and cuDNN computing libraries. We have to implement operator specific kernels for each computing library. - -On the other hand, users usually do not want to care about the low-level hardware and computing libraries when writing a neural network configuration. In Fluid, `Layer` is exposed in `Python`, and `Operator` is exposed in `C++`. Both `Layer` and `Operator` are hardware independent. - -So, how to support a new Device/Library in Fluid becomes a challenge. - - -## Basic: Integrate A New Device/Library - -For a general overview of fluid, please refer to the [overview doc](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/read_source.md). - -There are mainly three parts that we have to consider while integrating a new device/library: - -- Place and DeviceContext: indicate the device id and manage hardware resources - -- Memory and Tensor: malloc/free data on certain device - -- Math Functor and OpKernel: implement computing unit on certain devices/libraries - -### Place and DeviceContext - -Please note that device and computing library are not one-to-one corresponding. A device can have a lot of computing libraries and a computing library can also support several devices. - -#### Place -Fluid uses class [Place](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/place.h#L55) to represent the device memory where data is located. If we add another device, we have to add the corresponding `DevicePlace`. - -``` - | CPUPlace -Place --| CUDAPlace - | FPGAPlace -``` - -And `Place` is defined as follows: - -``` -typedef boost::variant Place; -``` - -#### DeviceContext - -Fluid uses class [DeviceContext](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/device_context.h#L30) to manage the resources in different libraries, such as CUDA stream in `CDUADeviceContext`. There are also inheritance relationships between different kinds of `DeviceContext`. - - -``` - /-> CPUDeviceContext -DeviceContext ----> CUDADeviceContext - \-> FPGADeviceContext -``` - -An example of Nvidia GPU is as follows: - -- DeviceContext - - -``` -class DeviceContext { - virtual Place GetPlace() const = 0; -}; -``` - - -- CUDADeviceContext - - -``` -class CUDADeviceContext : public DeviceContext { - Place GetPlace() const override { return place_; } -private: - CUDAPlace place_; - cudaStream_t stream_; - cublasHandle_t cublas_handle_; - std::unique_ptr eigen_device_; // binds with stream_ -}; -``` - -### Memory and Tensor - - -#### memory module - -Fluid provides the following [memory interfaces](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/memory/memory.h#L36): - -``` -template -void* Alloc(Place place, size_t size); - -template -void Free(Place place, void* ptr); - -template -size_t Used(Place place); -``` - -To implement these interfaces, we have to implement MemoryAllocator for different Devices. - - -#### Tensor - -[Tensor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/tensor.h#L36) holds data with some shape in a specific Place. - -```cpp -class Tensor { - public: - /*! Return a pointer to mutable memory block. */ - template - inline T* data(); - - /** - * @brief Return a pointer to mutable memory block. - * @note If not exist, then allocation. - */ - template - inline T* mutable_data(platform::Place place); - - /** - * @brief Return a pointer to mutable memory block. - * - * @param[in] dims The dimensions of the memory block. - * @param[in] place The place of the memory block. - * - * @note If not exist, then allocation. - */ - template - inline T* mutable_data(DDim dims, platform::Place place); - - /*! Resize the dimensions of the memory block. */ - inline Tensor& Resize(const DDim& dims); - - /*! Return the dimensions of the memory block. */ - inline const DDim& dims() const; - - private: - /*! holds the memory block if allocated. */ - std::shared_ptr holder_; - - /*! points to dimensions of memory block. */ - DDim dim_; -}; -``` - -`Placeholder` is used to delay memory allocation; that is, we can first define a tensor, using `Resize` to configurate its shape, and then call `mutuable_data` to allocate the actual memory. - -```cpp -paddle::framework::Tensor t; -paddle::platform::CPUPlace place; -// set size first -t.Resize({2, 3}); -// allocate memory on CPU later -t.mutable_data(place); -``` - - - -### Math Functor and OpKernel - -Fluid implements computing units based on different DeviceContexts. Some computing units are shared between operators. This common part will be put in operators/math directory as basic Functors. - -Let's take [MaxOutFunctor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/math/maxouting.h#L27) as an example: - -The interface is defined in the header file. - -``` -template -class MaxOutFunctor { - public: - void operator()(const DeviceContext& context, const framework::Tensor& input, - framework::Tensor* output, int groups); -}; -``` - -CPU implementation is in .cc file - -``` -template -class MaxOutFunctor { - public: - void operator()(const platform::CPUDeviceContext& context, - const framework::Tensor& input, framework::Tensor* output, - int groups) { - ... - } -}; -``` - -CUDA implementation is in .cu file - -``` -template -class MaxOutFunctor { - public: - void operator()(const platform::CUDADeviceContext& context, - const framework::Tensor& input, framework::Tensor* output, - int groups) { - ... - } -}; -``` - - -We first obtain the computing handle from a concrete DeviceContext and then compute on tensors. - -The implementation of `OpKernel` is similar to math functors, the extra thing we need to do is to register the OpKernel in a global map. - -Fluid provides different register interfaces in op_registry.h - - -Let's take [Crop](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/crop_op.cc#L134) operator as an example: - -In .cc file: - -``` -REGISTER_OP_CPU_KERNEL(crop, ops::CropKernel); -REGISTER_OP_CPU_KERNEL( - crop_grad, ops::CropGradKernel); -``` - -In .cu file: - -``` -REGISTER_OP_CUDA_KERNEL(crop, ops::CropKernel); -REGISTER_OP_CUDA_KERNEL( - crop_grad, ops::CropGradKernel); -``` - - -## Advanced topics: How to switch between different Device/Library - -Generally, we will implement OpKernel for all Device/Library of an Operator. We can easily train a Convolutional Neural Network in GPU. However, some OpKernel is not suitable on a specific Device. For example, crf operator can only run on CPU, whereas most other operators can run on GPU. To achieve high performance in such circumstance, we have to switch between different Device/Library. - - -For more details, please refer to following docs: - -- operator kernel type [doc](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/operator_kernel_type.md) -- switch kernel [doc](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/switch_kernel.md) diff --git a/develop/doc/_sources/design/switch.md.txt b/develop/doc/_sources/design/switch.md.txt deleted file mode 100644 index 827d0601c62..00000000000 --- a/develop/doc/_sources/design/switch.md.txt +++ /dev/null @@ -1,31 +0,0 @@ -### Design Doc: Switch - -### Background - -Many programming languages provide `switch` as a generalization of `if-elif-else`. We want to add it to Fluid. - -The following example shows the usage of `fluid.switch`. - -```python -a = fluid.Var(10) -b = fluid.Var(0) - -with switch() as switch: - with switch.case(fluid.less_equal(a, 10)): - fluid.print("Case 1") - with switch.case(fluid.larger(a, 0)): - fluid.print("Case 2") - with switch.default(): - fluid.print("Case 3") -``` - -### The Semantics - -1. A `switch` control-flow checks cases one-by-one. -1. The condition of each case is a boolean value, which is a scalar, and differs from the `fluid.if_else` control-flow, which condition could be a vector of boolean values. -1. It runs the first matched case, or the default case if there is one. -1. Once it matches a case, it runs the corresponding branch and only that branch. It's like there is a C's `break` keyword at the end of each case. - -The above program should print and print only "Case 1". - -The implementation of the backward pass of the `switch` control-flow is easier than the backward of the `if_else`, because `switch` runs at most one branch, whereas `if-else` could run more than one branches. diff --git a/develop/doc/_sources/design/tensor_array.md.txt b/develop/doc/_sources/design/tensor_array.md.txt deleted file mode 100644 index 37e4f7b90f9..00000000000 --- a/develop/doc/_sources/design/tensor_array.md.txt +++ /dev/null @@ -1,271 +0,0 @@ -# Design for TensorArray -This design doc presents the necessity of a new C++ class `TensorArray`. -In addition to the very simple C++ implementation - -```c++ -class TensorArray { - public: - explicit TensorArray(const LoDTensor&); - explicit TensorArray(size_t size); - - private: - vector values_; -}; -``` - -We also need to expose it to PaddlePaddle's Python API, -because users would want to use it with our very flexible operators `WhileLoop`. -An example for a RNN based on dynamic operators is - -```python -input = pd.data(...) -num_steps = Var(12) - -TensorArray states(size=num_steps) -TensorArray step_inputs(unstack_from=input) -TensorArray step_outputs(size=num_steps) - -W = Tensor(...) -U = Tensor(...) -default_state = some_op() - -step = Var(1) - -wloop = paddle.create_whileloop(loop_vars=[step]) -with wloop.frame(): - wloop.break_if(pd.equal(step, num_steps) - pre_state = states.read(step-1, default_state) - step_input = step_inputs.read(step) - state = pd.sigmoid(pd.matmul(U, pre_state) + pd.matmul(W, step_input)) - states.write(step, state) - step_outputs.write(step, state) # output state - step.update(state+1) - -output = step_outputs.stack() -``` - -## Background -Steps are one of the core concepts of RNN. In each time step of RNN, there should be several input segments, states, and output segments; all these components act like arrays, for example, call `states[step_id]` will get the state in `step_id`th time step. - -An RNN can be implemented with the following pseudocode - -```c++ -Array states; -Array input_segments; -Array output_segments; -Parameter W, U; - -step = 1 -seq_len = 12 -while_loop { - if (step == seq_len) break; - states[step] = sigmoid(W * states[step-1] + U * input_segments[step]); - output_segments[step] = states[step] // take state as output - step++; -} -``` -According to the [RNN roadmap](https://github.com/PaddlePaddle/Paddle/issues/4561), there are several different RNNs that PaddlePaddle will eventually support. - -Currently, the basic RNN implementation supported by PaddlePaddle is the `recurrent_op` which takes tensors as input and splits them into `input_segments`. - - -Since a tensor cannot store variable-length sequences directly, PaddlePaddle implements the tensor with level of details (`LoDTensor` for short). -Segmenting the `LoDTensor` is much more complicated than splitting a tensor, that makes it necessary to refactor the `recurrent_op` with `LoDTensor` segmenting support. - -As the next step in RNN support, `dynamic_recurrent_op` should be introduced to handle inputs with variable-length sequences. - -The implementation is similar to `recurrent_op`. -The key difference is the way **the original input `LoDTensors` and outupts are split to get the `input_segments` and the `output_segments`.** - - -Though it can't be built over `recurrent_op` or `dynamic_recurrent_op` directly, -the logic behind splitting a tensor or a LoD tensor into `input_segments` remains the same. - -## Why `TensorArray` -The logic behind splitting the inputs to segments, states and outputs is similar and can be shared in a seperate module. - -The array of `states`, `input_segments` and `output_segments` would be exposed to users when writing a dynamic RNN model similar to the above pseudo codes. - -So there should be an array-like container, which can store the segments of a tensor or LoD tensor. - -**This container can store an array of tensors and provides several methods to split a tensor or a LoD tensor** . -This is where the notion of `TensorArray` comes from. - -## Introduce TensorArray to uniform all the three RNNs -TensorArray as a new concept is borrowed from TensorFlow, -it is meant to be used with dynamic iteration primitives such as `while_loop` and `map_fn`. - -This concept can be used to support our new design of dynamic operations, and help to refactor some existing variant-sentence-related layers, -such as `recurrent_op`, `RecurrentGradientMachine`. - -In [our design for dynamic RNN](https://github.com/PaddlePaddle/Paddle/pull/4401), -`TensorArray` is used to segment inputs and store states in all time steps. -By providing some methods similar to a C++ array, -the definition of some state-based dynamic models such as RNN can be more natural and highly flexible. - -## Dynamic-operations on TensorArray - -`TensorArray` will be used directly when defining dynamic models, so some operators listed below should be implemented - -```python -# several helper operators for TensorArray -def tensor_array_stack(ta, tensor): - ''' - get a tensor array `ta`, return a packed `tensor`. - ''' - pass - -def tensor_array_unstack(tensor, ta): - ''' - get a `tensor`, unstack it and get a tensor array `ta`. - ''' - pass - -def tensor_array_write(ta, index, tensor, data_shared): - ''' - get a `tensor` and a scalar tensor `index`, write `tensor` into index-th - value of the tensor array `ta`. - `data_shared` is an attribute that specifies whether to copy or reference the tensors. - ''' - pass - -def tensor_array_read(ta, index, tensor): - ''' - get a tensor array `ta`, a scalar tensor `index`, read the index-th value of - `ta` and return as the `tensor`. - ''' - pass - -def tensor_array_size(ta, tensor): - ''' - get a tensor array `ta`, return the size of `ta` and return as the scalar `tensor`. - ''' - pass -``` - -It is trivial for users to use so many low-level operators, so some helper methods should be proposed in python wrapper to make `TensorArray` easier to use, -for example - -```python -class TensorArray: - def __init__(self, name): - self.name = name - self.desc = TensorArrayDesc() - - def stack(self, name=None): - ''' - Pack the values in a `TensorArray` into a tensor with rank one higher - than each tensor in `values`. - `stack` can be used to split tensor into time steps for RNN or whileloop. - - @name: str - the name of the variable to output. - ''' - tensor = Var(name) - tensor_array_stack(self.name, tensor) - return tensor - - def unstack(self, input): - ''' - Unpacks the given dimension of a rank-`R` tensor into rank-`(R-1)` tensors. - `unstack` can be used to concatenate all the time steps for RNN or whileloop. - - @input: str - the name of input tensor - ''' - tensor_array_unstack(tensor, self.name) - - def write(self, index, value, data_shared=True): - ''' - Write value into index of the TensorArray. - If `data_shared` is set to True, than the index-th value in TensorArray will - be shared with the tensor passed in. - - @index: str - name of a scalar tensor - @value: str - name of a tensor - @data_shared: bool - ''' - tensor_array_write(self.name, index, value, data_shared) - - def read(self, index, output): - ''' - Read the value at location `index` in the `TensorArray`. - - @index: str - name of a scalar tensor - @output: - name of a output variable - ''' - tensor_array_read(self.name, index, output) - - - def size(self, output): - ''' - Return the number of values. - - @output: str - name of a scalar tensor - ''' - tensor_array_size(self.name, output) -``` - -## LoDTensor-related Supports -The `RecurrentGradientMachine` in Paddle serves as a flexible RNN layer; it takes varience-length sequences as input, and output sequences too. - -Since each step of RNN can only take a tensor-represented batch of data as input, -some preprocess should be taken on the inputs such as sorting the sentences by their length in descending order and cut each word and pack to new batches. - -Such cut-like operations can be embedded into `TensorArray` as general methods called `unpack` and `pack`, -these two operations are similar to `stack` and `unstack` except that they operate on variable-length sequences formated as a LoD tensor rather than a tensor. - -Some definitions are like - -```python -def unpack(level): - ''' - Split LodTensor in some `level` and generate batches, if set `sort_by_length`, - will sort by length. - - Returns: - - a new `TensorArray`, whose values are LodTensors and represents batches - of data. - - an int32 Tensor, which stores the map from the new batch's indices to - original LoDTensor - ''' - pass - -def pack(level, indices_map): - ''' - Recover the original LoD-arranged LoDTensor with the values in a `TensorArray` - and `level` and `indices_map`. - ''' - pass -``` - -With these two methods, a varience-length sentence supported RNN can be implemented like - -```c++ -// input is the varient-length data -LodTensor sentence_input(xxx); -TensorArray ta; -Tensor indice_map; -Tensor boot_state = xxx; // to initialize rnn's first state -TensorArray::unpack(input, 1/*level*/, true/*sort_by_length*/, &ta, &indice_map); -TessorArray step_outputs; -TensorArray states; - -for (int step = 0; step = ta.size(); step++) { - auto state = states.read(step); - // rnnstep is a function which acts like a step of RNN - auto step_input = ta.read(step); - auto step_output = rnnstep(step_input, state); - step_outputs.write(step_output, true/*data_shared*/); -} - -// rnn_output is the final output of an rnn -LoDTensor rnn_output = ta.pack(ta, indice_map); -``` -the code above shows that by embedding the LoDTensor-related preprocess operations into `TensorArray`, -the implementation of a RNN that supports varient-length sentences is far more concise than `RecurrentGradientMachine` because the latter mixes all the codes together, hard to read and extend. diff --git a/develop/doc/_sources/design/var_desc.md.txt b/develop/doc/_sources/design/var_desc.md.txt deleted file mode 100644 index 6a45af19954..00000000000 --- a/develop/doc/_sources/design/var_desc.md.txt +++ /dev/null @@ -1,81 +0,0 @@ -## Background -PaddlePaddle divides the description of neural network computation into two stages: compile time and runtime. At compile time, the neural network computation is described as a `ProgramDesc` whereas at runtime an `Executor` interprets the `ProgramDesc` to compute the operations. - -PaddlePaddle uses proto message to describe compile time program because : - -1. The computation program description must be serializable and saved in a file. -1. During distributed training, the serialized program will be sent to multiple workers. It should also be possible to break the program into different components, each of which can be executed on a different worker. - -The computation `Program` consists of nested `Blocks`. Each `Block` will consist of data(i.e. `Variable`) and `Operations`. The concept to represent them is in the table below. - -| |compile time|runtime| -|---|---|---| -|Data|VarDesc(proto)|Variable(cpp)| -|Operation|OpDesc(proto)|Operator(cpp)| - - -## Definition of VarType - -A VarDesc should have a name, type and whether or not it is persistable. The are different kinds of variable types supported in PaddlePaddle, apart from the POD_Types like: `LOD_TENSOR`, `SELECTED_ROWS`, `FEED_MINIBATCH`, `FETCH_LIST`, `STEP_SCOPES`, `LOD_RANK_TABLE`, `LOD_TENSOR_ARRAY`, `PLACE_LIST`, `READER` and `CHANNEL`. These are declared inside `VarType`. A `VarDesc` then looks as the following: - -```proto -message VarDesc { - required string name = 1; - required VarType type = 2; - optional bool persistable = 3 [ default = false ]; -} -``` - -## Definition of TensorDesc - -```proto -message TensorDesc { - // Should only be PODType. Is enforced in C++ - required Type data_type = 1; - repeated int64 dims = 2; // [UNK, 640, 480] is saved as [-1, 640, 480] -} -``` - -The `Type` here comes from the enum defined inside of `VarType` : - -```proto -enum Type { - // Pod Types - BOOL = 0; - INT16 = 1; - INT32 = 2; - INT64 = 3; - FP16 = 4; - FP32 = 5; - FP64 = 6; - - // Other types that may need additional descriptions - LOD_TENSOR = 7; - SELECTED_ROWS = 8; - FEED_MINIBATCH = 9; - FETCH_LIST = 10; - STEP_SCOPES = 11; - LOD_RANK_TABLE = 12; - LOD_TENSOR_ARRAY = 13; - PLACE_LIST = 14; - READER = 15; - CHANNEL = 16; -} -``` - -A TensorDesc describes `SelectedRows` and `LoDTensor`. For details of `SelectedRows`, please reference [`SelectedRows`](./selected_rows.md). - -## Definition of LodTensorDesc - -```proto -message LoDTensorDesc { - required TensorDesc tensor = 1; - optional int32 lod_level = 2 [ default = 0 ]; -} -``` - -A LoDTensorDesc contains a tensor and a lod_level. - -## Definition of Variable in Python - -For Variable in Python, please reference [`Python API`](./python_api.md). diff --git a/develop/doc/_sources/dev/index_en.rst.txt b/develop/doc/_sources/dev/index_en.rst.txt index 5fdc30a2d68..549f5fa9aac 100644 --- a/develop/doc/_sources/dev/index_en.rst.txt +++ b/develop/doc/_sources/dev/index_en.rst.txt @@ -6,3 +6,4 @@ Development contribute_to_paddle_en.md write_docs_en.rst + new_layer_en.rst diff --git a/develop/doc/_sources/dev/new_op_en.md.txt b/develop/doc/_sources/dev/new_op_en.md.txt deleted file mode 100644 index da8b1bdd108..00000000000 --- a/develop/doc/_sources/dev/new_op_en.md.txt +++ /dev/null @@ -1,336 +0,0 @@ -# How to write a new operator - - - [Background](#background) - - [Implementing C++ Types](#implementing-c-types) - - [Defining ProtoMaker](#defining-protomaker) - - [Defining Operator](#defining-operator) - - [Defining OpKernel](#defining-opkernel) - - [Registering Operator and OpKernel](#registering-operator-and-opkernel) - - [Compilation](#compilation) - - [Python Binding](#python-binding) - - [Unit Tests](#unit-tests) - - [Testing Forward Operators](#testing-forward-operators) - - [Testing Backward Operators](#testing-backward-operators) - - [Compiling and Running](#compiling-and-running) - - [Remarks](#remarks) -## Background - -Here are the base types needed. For details, please refer to the design docs. - -- `class OpProtoAndCheckerMaker`: Describes an Operator's input, output, attributes and description, mainly used to interface with Python API. -- `framework::OperatorBase`: Operator (Op)base class. -- `framework::OpKernel`: Base class for Op computation kernel. -- `framework::OperatorWithKernel`: Inherited from OperatorBase, describing an operator with computation kernels. - - -Operators can be categorized into two groups: operator with kernel(s) and operator without kernel(s). An operator with kernel(s) inherits from `OperatorWithKernel` while the one without kernel(s) inherits from `OperatorBase`. This tutorial focuses on implementing operators with kernels. In short, an operator includes the following information: - - - Information | Where is it defined --------------- | :---------------------- -OpProtoMake definition | `.cc`files, Backward Op does not need an OpProtoMake interface. -Op definition | `.cc` files -Kernel implementation | The kernel methods shared between CPU and CUDA are defined in `.h` files. CPU-specific kernels live in `.cc` files, while CUDA-specific kernels are implemented in `.cu`files. -Registering the Op | Ops are registered in `.cc` files; For Kernel registration, `.cc` files contain the CPU implementation, while `.cu` files contain the CUDA implementation. - - -New Operator implementations are added to the list [paddle/operators](https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/operators), with file names in the format `*_op.h` (if applicable), `*_op.cc`, `*_op.cu` (if applicable).** The system will use the naming scheme to automatically build operators and their corresponding Python extensions.** - - -Let's take matrix multiplication operator, [MulOp](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/mul_op.cc), as an example to introduce the writing of an Operator with Kernel. - - -## Implementing C++ Types - - -### Defining ProtoMaker - -Matrix Multiplication can be written as $Out = X * Y$, meaning that the operation consists of two inputs and pne output. - -First, define `ProtoMaker` to describe the Operator's input, output, and additional comments: - -```cpp -class MulOpMaker : public framework::OpProtoAndCheckerMaker { - public: - MulOpMaker(OpProto *proto, OpAttrChecker *op_checker) - : OpProtoAndCheckerMaker(proto, op_checker) { - AddInput("X", "(Tensor), 2D tensor of size (M x K)"); - AddInput("Y", "(Tensor), 2D tensor of size (K x N)"); - AddOutput("Out", "(Tensor), 2D tensor of size (M x N)"); - AddComment(R"DOC( -Two Element Mul Operator. -The equation is: Out = X * Y -)DOC"); - } -}; -``` - -[`MulOpMaker`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/mul_op.cc#L43)is inherited from`framework::OpProtoAndCheckerMaker`, consisting of 2 variables in the constructor: - - - `framework::OpProto` stores Operator input and variable attribute, used for generating Python API interfaces. - - `framework::OpAttrChecker` is used to validate variable attributes. - -The constructor utilizes `AddInput`, `AddOutput`, and `AddComment`, so that the corresponding information will be added to `OpProto`. - -The code above adds two inputs `X` and `Y` to `MulOp`, an output `Out`, and their corresponding descriptions, in accordance to Paddle's [naming convention](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/name_convention.md). - - -An additional example [`ScaleOp`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/scale_op.cc#L37) is implemented as follows: - -```cpp -template -class ScaleOpMaker : public framework::OpProtoAndCheckerMaker { - public: - ScaleOpMaker(OpProto *proto, OpAttrChecker *op_checker) - : OpProtoAndCheckerMaker(proto, op_checker) { - AddInput("X", "The input tensor of scale operator.").NotInGradient(); - AddOutput("Out", "The output tensor of scale operator.").NotInGradient(); - AddComment(R"DOC(Scale operator -The equation is: Out = scale*X -)DOC"); - AddAttr("scale", "scale of scale operator.").SetDefault(1.0); - } -}; -``` - -There are two changes in this example: - -- `AddInput("X","...").NotInGradient()` expresses that input `X` is not involved in `ScaleOp`'s corresponding computation. If an input to an operator is not participating in back-propagation, please explicitly set `.NotInGradient()`. - -- `AddAttr("scale", "...").SetDefault(1.0);` adds `scale`constant as an attribute, and sets the default value to 1.0. - - -### Defining Operator - -The following code defines the interface for MulOp: - -```cpp -class MulOp : public framework::OperatorWithKernel { - public: - using framework::OperatorWithKernel::OperatorWithKernel; - - protected: - void InferShape(const framework::InferShapeContext &ctx) const override { - auto dim0 = ctx.Input("X")->dims(); - auto dim1 = ctx.Input("Y")->dims(); - PADDLE_ENFORCE_EQ(dim0.size(), 2, - "input X(%s) should be a tensor with 2 dims, a matrix", - ctx.op_.Input("X")); - PADDLE_ENFORCE_EQ(dim1.size(), 2, - "input Y(%s) should be a tensor with 2 dims, a matrix", - ctx.op_.Input("Y")); - PADDLE_ENFORCE_EQ( - dim0[1], dim1[0], - "First matrix's width must be equal with second matrix's height."); - ctx.Output("Out")->Resize({dim0[0], dim1[1]}); - } -}; -``` - -[`MulOp`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/mul_op.cc#L22) is inherited from `OperatorWithKernel`. Its `public` member - -```cpp -using framework::OperatorWithKernel::OperatorWithKernel; -``` - -expresses an operator constructor using base class `OperatorWithKernel`, alternatively written as - -```cpp -MulOp(const std::string &type, const framework::VariableNameMap &inputs, - const framework::VariableNameMap &outputs, - const framework::AttributeMap &attrs) - : OperatorWithKernel(type, inputs, outputs, attrs) {} -``` - -`InferShape` interface needs to be re-written.`InferShape` is a constant method and cannot modify Op's member variables, its constant member `const framework::InferShapeContext &ctx` can be used to extract input, output, and attributes. It functions to - - - 1). validate and error out early: it checks input data dimensions and types. - - 2). configures the tensor shape in the output. - -Usually `OpProtoMaker` and `Op`'s type definitions are written in `.cc` files, which also include the registration methods introduced later. - -### Defining OpKernel - -`MulKernel` inherits `framework::OpKernel`, which includes the following templates: - -- `typename DeviceContext` denotes device context type. When different devices, namely the CPUDeviceContext and the CUDADeviceContext, share the same kernel, this template needs to be added. If they don't share kernels, this must not be added. An example of a non-sharing kernel is [`OnehotCrossEntropyOpKernel`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/cross_entropy_op.h#L43). - -- `typename T` denotes data type, such as `float` or `double`. - -`MulKernel` types need to rewrite the interface for `Compute`. - -- `Compute` takes one input parameter: `const framework::ExecutionContext& context`. -- Compared with `InferShapeContext`, `ExecutionContext` includes device types, and can similarly extract input, output, and attribute variables. -- `Compute` implements the computation logics of an `OpKernel`. - -`MulKernel`'s implementation of `Compute` is as follows: - - ```cpp - template - class MulKernel : public framework::OpKernel { - public: - void Compute(const framework::ExecutionContext& context) const override { - auto* X = context.Input("X"); - auto* Y = context.Input("Y"); - auto* Z = context.Output("Out"); - Z->mutable_data(context.GetPlace()); - auto& device_context = context.template device_context(); - math::matmul(*X, false, *Y, false, 1, Z, 0, device_context); - } - }; - ``` - -Note that **different devices (CPU, CUDA)share one Op definition; whether or not they share the same `OpKernel` depends on whether `Compute` calls functions can support both devices.** - -`MulOp`'s CPU and CUDA share the same `Kernel`. A non-sharing `OpKernel` example can be seen in [`OnehotCrossEntropyOpKernel`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/cross_entropy_op.h#L43). - -To ease the writing of `OpKernel` compute, and for reusing code cross-device, [`Eigen-unsupported Tensor`](https://bitbucket.org/eigen/eigen/src/default/unsupported/Eigen/CXX11/src/Tensor/README.md?fileviewer=file-view-default) module is used to implement `Compute` interface. To learn about how the Eigen library is used in PaddlePaddle, please see [usage document](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/dev/use_eigen_cn.md). - - -This concludes the forward implementation of an operator. Next its operation and kernel need to be registered in a `.cc` file. - -The definition of its corresponding backward operator, if applicable, is similar to that of an forward operator. **Note that a backward operator does not include a `ProtoMaker`**. - -### Registering Operator and OpKernel - -- In `.cc` files, register forward and backward operator classes and the CPU kernel. - - ```cpp - namespace ops = paddle::operators; - REGISTER_OP(mul, ops::MulOp, ops::MulOpMaker, mul_grad, ops::MulOpGrad); - - REGISTER_OP_CPU_KERNEL(mul, ops::MulKernel); - REGISTER_OP_CPU_KERNEL(mul_grad, - ops::MulGradKernel); - ``` - - In that code block, - - - `REGISTER_OP` registers the `ops::MulOp` class, type named `mul`, its type `ProtoMaker` is `ops::MulOpMaker`, registering `ops::MulOpGrad` as `mul_grad`. - - `REGISTER_OP_WITHOUT_GRADIENT` registers an operator without gradient. - - - `REGISTER_OP_CPU_KERNEL` registers `ops::MulKernel` class and specialized template types `paddle::platform::CPUPlace` and `float`, which also registers `ops::MulGradKernel`. - - -- Registering CUDA Kernel in `.cu` files - - Note that if CUDA Kernel is implemented using the `Eigen unsupported` module, then on top of `.cu`, a macro definition `#define EIGEN_USE_GPU` is needed, such as - - ```cpp - // if use Eigen unsupported module before include head files - #define EIGEN_USE_GPU - - namespace ops = paddle::operators; - REGISTER_OP_CUDA_KERNEL(mul, ops::MulKernel); - REGISTER_OP_CUDA_KERNEL(mul_grad, - ops::MulGradKernel); - ``` - -### Compilation - -Run the following commands to compile. - -``` -# maybe you need to rerun cmake -make mul_op -``` - -## Python Binding - -The system will automatically bind to Python and link it to a generated library. - -## Unit Tests - -Unit tests for an operator include - -1. comparing a forward operator's implementations on different devices, - -2. comparing a backward operator's implementation on different devices, and - -3. a scaling test for the backward operator. - -Here, we introduce the [unit tests for `MulOp`](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/v2/framework/tests/test_mul_op.py). - -### Testing Forward Operators - -A forward operator unit test inherits `unittest.TestCase` and defines metaclass `__metaclass__ = OpTestMeta`. More concrete tests are performed in `OpTestMeta`. Testing a forward operator requires the following: - -1. Defining input, output and relevant attributes in `setUp` method. - -2. Generating random input data. - -3. Implementing the same computation logic in a Python script. - -4. Call check gradient function to check the backward operator. - - ```python - import unittest - import numpy as np - from op_test import OpTest - - - class TestMulOp(OpTest): - def setUp(self): - self.op_type = "mul" - self.inputs = { - 'X': np.random.random((32, 84)).astype("float32"), - 'Y': np.random.random((84, 100)).astype("float32") - } - self.outputs = {'Out': np.dot(self.inputs['X'], self.inputs['Y'])} - - def test_check_output(self): - self.check_output() - - def test_check_grad_normal(self): - self.check_grad(['X', 'Y'], 'Out', max_relative_error=0.5) - - def test_check_grad_ingore_x(self): - self.check_grad( - ['Y'], 'Out', max_relative_error=0.5, no_grad_set=set("X")) - - def test_check_grad_ingore_y(self): - self.check_grad( - ['X'], 'Out', max_relative_error=0.5, no_grad_set=set('Y')) - ``` -Get its output, and compare it with the forward operator's own output. - -The code above first loads required packages. In addition, we have - -- `self.op_type = "mul" ` defines the type that is identical to what the operator's registered type. -- `self.inputs` defines input, with type `numpy.array` and initializes it. -- `self.outputs` defines output and completes the same operator computation in the Python script, and returns its result from the Python script. - -### Testing Backward Operators - -Some key points in checking gradient above include: - -- `test_normal` calls `check_grad` to validate scaling tests' correctness and stability through numeric methods. - - The first variable `["X", "Y"]` appoints `X` and `Y` to be scale tested. - - The second variable `"Out"` points to the network's final output target `Out`. - - The third variable `max_relative_error` points to the maximum relative tolerance error during scaling tests. -- `test_check_grad_ingore_x` and `test_check_grad_ingore_y`branches test the cases where there is only one scaling input. - -### Compiling and Running - - -Any new unit testing file of the format `test_*.py` added to the director `python/paddle/v2/framework/tests` is automatically added to the project to compile. - -Note that **unlike the compile test for Ops, running unit tests requires compiling the entire project** and requires compiling with flag `WITH_TESTING` on i.e. `cmake paddle_dir -DWITH_TESTING=ON`. - -After successfully compiling the project, run the following command to run unit tests: - -```bash -make test ARGS="-R test_mul_op -V" -``` - -Or, - -```bash -ctest -R test_mul_op -``` - -## Remarks - -- Every `*_op.h` (if applicable), `*_op.cc`, and `*_op.cu` (if applicable) must be created for a unique Op. Compiling will fail if multiple operators are included per file. -- The type with which an operator is registered needs to be identical to the Op's name. Registering `REGISTER_OP(B, ...)` in `A_op.cc` will cause unit testing failures. -- If the operator does not implement a CUDA kernel, please refrain from creating an empty `*_op.cu` file, or else unit tests will fail. -- If multiple operators rely on some shared methods, a file NOT named `*_op.*` can be created to store them, such as `gather.h`. diff --git a/develop/doc/_sources/dev/new_op_kernel_en.md.txt b/develop/doc/_sources/dev/new_op_kernel_en.md.txt deleted file mode 100644 index 123df0a7ee4..00000000000 --- a/develop/doc/_sources/dev/new_op_kernel_en.md.txt +++ /dev/null @@ -1,121 +0,0 @@ -## Add Kernels for a New Device - -### Background - -PaddlePaddle Fluid have hundreds of operators. Each operator could have one or more kernels. A kernel is an implementation of the operator for a certain device, which could be a hardware device, e.g., the CUDA GPU, or a library that utilizes a device, e.g., Intel MKL that makes full use of the Xeon CPU. - -[This document](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/dev/new_op_en.md) explains how to add an operator, and its kernels. The kernels of an operator are indexed by a C++ type [`OpKernelType`](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/operator_kernel_type.md). An operator chooses the right kernel at runtime. This choosing mechanism is described [here](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/switch_kernel.md). - -### Write Kernels for A New Device - -#### Add A New Device - - For some historical reaons, we misuse the word *library* for *device*. For example, we call the deivce type by *library type*. An example is the header file [`library_type.h`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/library_type.h#L24). We will correct this ASAP. - -To register a new device, we need to add an enum value to `LibraryType`: - -``` -enum class LibraryType { - kPlain = 0, - kMKLDNN = 1, - kCUDNN = 2, -}; -``` - - -#### Add A New [Place](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/place.h#L53) - -If you have a new kind of Device, firstly you need to add a new kind of [`Place`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/place.h#L53). For example `CUDAPlace`: - -```cpp -struct CUDAPlace { - CUDAPlace() : CUDAPlace(0) {} - explicit CUDAPlace(int d) : device(d) {} - - inline int GetDeviceId() const { return device; } - // needed for variant equality comparison - inline bool operator==(const CUDAPlace &o) const { - return device == o.device; - } - inline bool operator!=(const CUDAPlace &o) const { return !(*this == o); } - - int device; -}; - -typedef boost::variant Place; -``` - -#### Add [device context]((https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/device_context.h#L37)) -After a new kind of Device is added, you should add a corresponding [DeviceContext](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/device_context.h#L37) for it. - -```cpp -class DeviceContext { - public: - virtual ~DeviceContext() {} - virtual Place GetPlace() const = 0; - - virtual void Wait() const {} -}; -``` - -#### Implement new [OpKernel](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/operator.h#L351) for your Device. - -A detailed documentation can be found in [`new_op_and_kernel`](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/dev/new_op_en.md) - -```cpp -class OpKernelBase { - public: - /** - * ExecutionContext is the only parameter of Kernel Run function. - * Run will get input/output variables, state such as momentum and - * device resource such as CUDA stream, cublas handle, etc. from - * ExecutionContext. User should construct it before run the Operator. - */ - - virtual void Compute(const ExecutionContext& context) const = 0; - - virtual ~OpKernelBase() = default; -}; - -template -class OpKernel : public OpKernelBase { - public: - using ELEMENT_TYPE = T; -}; -``` - - -#### Register the OpKernel to framework - -After writing the components described above, we should register the kernel to the framework. - -We use `REGISTER_OP_KERNEL` to do the registration. - -```cpp -REGISTER_OP_KERNEL( - op_type, - library_type, - place_type, - kernel0, kernel1, ...) -``` - -kernel0, kernel1 are kernels that have the same `op_type`, `library_type`, `place_type` but different `data_types`. - -take [`conv2d`]((https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/conv_cudnn_op.cu.cc#L318)) as an example: - - ```cpp - REGISTER_OP_KERNEL(conv2d, CPU, paddle::platform::CPUPlace, - paddle::operators::GemmConvKernel, - paddle::operators::GemmConvKernel); - - REGISTER_OP_KERNEL(conv2d, CUDNN, ::paddle::platform::CUDAPlace, - paddle::operators::CUDNNConvOpKernel, - paddle::operators::CUDNNConvOpKernel); - ``` - -In the code above: - - - `conv2d` is the type/name of the operator - - `CUDNN/CPU` is `library` - - `paddle::platform::CUDAPlace/CPUPlace` is `place` - - template parameter `float/double` on `CUDNNConvOpKernel` is `data_type`. diff --git a/develop/doc/_sources/dev/use_eigen_en.md.txt b/develop/doc/_sources/dev/use_eigen_en.md.txt deleted file mode 100644 index e169106e12f..00000000000 --- a/develop/doc/_sources/dev/use_eigen_en.md.txt +++ /dev/null @@ -1,146 +0,0 @@ -## How to use Eigen in Paddle - -Essentially, a neural network is a compute graph. T data needed for the computation is stored in `Tensor`s and its computation procedure is described by `Operator`s. An `Operator` calls the `Compute` interface in its corresponding `OpKernel` and operates on the `Tensor`. - - -### Eigen Tensor Module - -The Eigen Tensor module supports powerful element-wise computation. In addition, a piece of code written using it can be run on both the CPU and the GPU. - -Note that Eigen Tensor is still being actively developed, so its tests are not completely covered and its documentation may be sparse. - -For details on Eigen Tensor module, please see [doc 1](https://github.com/RLovelett/eigen/blob/master/unsupported/Eigen/CXX11/src/Tensor/README.md) and [doc 2](https://bitbucket.org/eigen/eigen/src/default/unsupported/Eigen/CXX11/src/Tensor/README.md). - - -### paddle::framework::Tensor - -Paddle Tensor's is defined in the framework directory with the following interface: - -```cpp -class Tensor { - public: - /*! Return a pointer to mutable memory block. */ - template - inline T* data(); - - /** - * @brief Return a pointer to mutable memory block. - * @note If not exist, then allocation. - */ - template - inline T* mutable_data(platform::Place place); - - /** - * @brief Return a pointer to mutable memory block. - * - * @param[in] dims The dimensions of the memory block. - * @param[in] place The place of the memory block. - * - * @note If not exist, then allocation. - */ - template - inline T* mutable_data(DDim dims, platform::Place place); - - /*! Resize the dimensions of the memory block. */ - inline Tensor& Resize(const DDim& dims); - - /*! Return the dimensions of the memory block. */ - inline const DDim& dims() const; - - private: - /*! holds the memory block if allocated. */ - std::shared_ptr holder_; - - /*! points to dimensions of memory block. */ - DDim dim_; -}; -``` - -`Placeholder` is used to delay memory allocation; that is, we can first define a tensor, using `Resize` to configure its shape, and then call `mutuable_data` to allocate the actual memory. - -```cpp -paddle::framework::Tensor t; -paddle::platform::CPUPlace place; -// set size first -t.Resize({2, 3}); -// allocate memory on CPU later -t.mutable_data(place); -``` - -### paddle::framework::Tensor Usage -`AddOp` demonstrates Tensor's usage. - -- InferShape - -When computing a neural network's compute graph, first call every `Operator`'s `InferShape` method, and use `Resize` to configure the size of the output tensor. - -```cpp -void InferShape(const framework::InferShapeContext &ctx) const override { - PADDLE_ENFORCE_EQ(ctx.Input("X")->dims(), - ctx.Input("Y")->dims(), - "Two input of Add Op's dimension must be same."); - ctx.Output("Out")->Resize(ctx.Input("X")->dims()); -} -``` - - -- Run - -```cpp -void Compute(const framework::ExecutionContext& context) const override { - auto* input0 = context.Input("X"); - auto* input1 = context.Input("Y"); - auto* output = context.Output("Out"); - - output->mutable_data(context.GetPlace()); - - auto x = EigenVector::Flatten(*input0); - auto y = EigenVector::Flatten(*input1); - auto z = EigenVector::Flatten(*output); - - auto place = context.GetEigenDevice(); - - z.device(place) = x + y; -} -``` - - -### paddle::framework::Tensor到EigenTensor的转换 - -As shown above, in actual computation, we need to transform the input and output `Tensor`s into formats Eigen supports. We show some functions in [eigen.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/eigen.h) to implement the transformation from `paddle::framework::Tensor`to `EigenTensor/EigenMatrix/EigenVector/EigenScalar`. - -Using EigenTensor as an example: - -```cpp -Tensor t; -float* p = t.mutable_data(make_ddim({1, 2, 3}), platform::CPUPlace()); -for (int i = 0; i < 1 * 2 * 3; i++) { - p[i] = static_cast(i); -} - -EigenTensor::Type et = EigenTensor::From(t); -``` - -`From` is an interfacing method provided by the EigenTensor template, which implements the transformation from a `paddle::framework::Tensor` object to an EigenTensor. Since `rank` is a template parameter, it needs to be explicitly specified at the time of the transformation. - -In Eigen, tensors with different ranks are different types, with `Vector` bring a rank-1 instance. Note that `EigenVector::From` uses a transformation from an 1-dimensional Paddle tensor to a 1-dimensional Eigen tensor while `EigenVector::Flatten` reshapes a paddle tensor and flattens it into a 1-dimensional Eigen tensor. Both resulting tensors are still typed EigenVector. - -For more transformations, see the [unit tests](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/eigen_test.cc) in the `eigen_test.cc` file. - - - -### Implementing Computation - -While computing, the device interface is needed from the EigenTensors on the left hand side of the assignments. Note that the computation between EigenTensors only changes the data originally inthe Tensor and does not change all the shape information associated with the Tensor. - -```cpp -auto x = EigenVector::Flatten(*input0); -auto y = EigenVector::Flatten(*input1); -auto z = EigenVector::Flatten(*output); -auto place = context.GetEigenDevice(); -z.device(place) = x + y; -``` - -In this code segment, input0/input1/output can be Tensors of arbitrary dimension. We are calling Flatten from EigenVector, transforming a tensor of any dimension into a 1-dimensional EigenVector. After completing computation, input0/input1/output will retain the same shape information, and they can be resized using the `Resize` interface. - -Because the Eigen Tensor module is under-documented, please refer to `OpKernel`'s computation code in TensorFlow's [kernel module documentation](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/core/kernels). diff --git a/develop/doc/_sources/howto/cluster/fluid_cluster_train_en.md.txt b/develop/doc/_sources/howto/cluster/fluid_cluster_train_en.md.txt deleted file mode 100644 index b4465e8269c..00000000000 --- a/develop/doc/_sources/howto/cluster/fluid_cluster_train_en.md.txt +++ /dev/null @@ -1,153 +0,0 @@ -# Fluid Distributed Training - -## Introduction - -In this article, we'll explain how to configure and run distributed training jobs with PaddlePaddle Fluid in a bare metal cluster. - -## Preparations - -### Getting the cluster ready - -Prepare the compute nodes in the cluster. Nodes in this cluster can be of any specification that runs PaddlePaddle, and with a unique IP address assigned to it. Make sure they can communicate to each other. - -### Have PaddlePaddle installed - -PaddlePaddle must be installed on all nodes. If you have GPU cards on your nodes, be sure to properly install drivers and CUDA libraries. - -PaddlePaddle build and installation guide can be found [here](http://www.paddlepaddle.org/docs/develop/documentation/en/getstarted/build_and_install/index_en.html). - -In addition to above, the `cmake` command should be run with the option `WITH_DISTRIBUTE` set to on. An example bare minimum `cmake` command would look as follows: - -``` bash -cmake .. -DWITH_DOC=OFF -DWITH_GPU=OFF -DWITH_DISTRIBUTE=ON -DWITH_SWIG_PY=ON -DWITH_PYTHON=ON -``` - -### Update the training script - -#### Non-cluster training script - -Let's take [Deep Learning 101](http://www.paddlepaddle.org/docs/develop/book/01.fit_a_line/index.html)'s first chapter: "fit a line" as an example. - -The non-cluster version of this demo with fluid API is as follows: - -``` python -import paddle.v2 as paddle -import paddle.fluid as fluid - -x = fluid.layers.data(name='x', shape=[13], dtype='float32') -y_predict = fluid.layers.fc(input=x, size=1, act=None) -y = fluid.layers.data(name='y', shape=[1], dtype='float32') - -cost = fluid.layers.square_error_cost(input=y_predict, label=y) -avg_cost = fluid.layers.mean(x=cost) - -sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.001) -sgd_optimizer.minimize(avg_cost) - -BATCH_SIZE = 20 - -train_reader = paddle.batch( - paddle.reader.shuffle( - paddle.dataset.uci_housing.train(), buf_size=500), - batch_size=BATCH_SIZE) - -place = fluid.CPUPlace() -feeder = fluid.DataFeeder(place=place, feed_list=[x, y]) -exe = fluid.Executor(place) - -exe.run(fluid.default_startup_program()) - -PASS_NUM = 100 -for pass_id in range(PASS_NUM): - fluid.io.save_persistables(exe, "./fit_a_line.model/") - fluid.io.load_persistables(exe, "./fit_a_line.model/") - for data in train_reader(): - avg_loss_value, = exe.run(fluid.default_main_program(), - feed=feeder.feed(data), - fetch_list=[avg_cost]) - - if avg_loss_value[0] < 10.0: - exit(0) # if avg cost less than 10.0, we think our code is good. -exit(1) -``` - -We created a simple fully-connected neural network training program and handed it to the fluid executor to run for 100 passes. - -Now let's try to convert it to a distributed version to run on a cluster. - -#### Introducing parameter server - -As we can see from the non-cluster version of training script, there is only one role in the script: the trainer, that performs the computing as well as holds the parameters. In cluster training, since multi-trainers are working on the same task, they need one centralized place to hold and distribute parameters. This centralized place is called the Parameter Server in PaddlePaddle. - -![parameter server architecture](src/trainer.png) - -Parameter Server in fluid not only holds the parameters but is also assigned with a part of the program. Trainers communicate with parameter servers via send/receive OPs. For more technical details, please refer to [this document](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/dist_refactor/distributed_architecture.md). - -Now we need to create programs for both: trainers and parameter servers, the question is how? - -#### Slice the program - -Fluid provides a tool called "Distributed Transpiler" that automatically converts the non-cluster program into cluster program. - -The idea behind this tool is to find the optimize OPs and gradient parameters, slice the program into 2 pieces and connect them with send/receive OP. - -Optimize OPs and gradient parameters can be found from the return values of optimizer's minimize function. - -To put them together: - -``` python -... #define the program, cost, and create sgd optimizer - -optimize_ops, params_grads = sgd_optimizer.minimize(avg_cost) #get optimize OPs and gradient parameters - -t = fluid.DistributeTranspiler() # create the transpiler instance -# slice the program into 2 pieces with optimizer_ops and gradient parameters list, as well as pserver_endpoints, which is a comma separated list of [IP:PORT] and number of trainers -t.transpile(optimize_ops, params_grads, pservers=pserver_endpoints, trainers=2) - -... #create executor - -# in pserver, run this -#current_endpoint here means current pserver IP:PORT you wish to run on -pserver_prog = t.get_pserver_program(current_endpoint) -pserver_startup = t.get_startup_program(current_endpoint, pserver_prog) -exe.run(pserver_startup) -exe.run(pserver_prog) - -# in trainer, run this -... # define data reader -exe.run(fluid.default_startup_program()) -for pass_id in range(100): - for data in train_reader(): - exe.run(t.get_trainer_program()) - - -``` - -### E2E demo - -Please find the complete demo from [here](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/tests/book_distribute/notest_dist_fit_a_line.py). -First `cd` into the folder that contains the `python` files. In this case: - -```bash -cd /paddle/python/paddle/fluid/tests/book_distribute -``` - -In parameter server node run the following in the command line: - -``` bash -PSERVERS=192.168.1.2:6174 SERVER_ENDPOINT=192.168.1.2:6174 TRAINING_ROLE=PSERVER python notest_dist_fit_a_line.py -``` - -*please note we assume that your parameter server runs at 192.168.1.2:6174* - -Wait until the prompt `Server listening on 192.168.1.2:6174` - -Then in 2 of your trainer nodes run this: - -``` bash -PSERVERS=192.168.1.2:6174 SERVER_ENDPOINT=192.168.1.2:6174 TRAINING_ROLE=TRAINER python notest_dist_fit_a_line.py -``` - -*the reason you need to run this command twice in 2 nodes is because: in the script we set the trainer count to be 2. You can change this setting on line 50* - -Now you have 2 trainers and 1 parameter server up and running. diff --git a/develop/doc/_sources/howto/index_en.rst.txt b/develop/doc/_sources/howto/index_en.rst.txt index ae8b86f75b5..2079be766f2 100644 --- a/develop/doc/_sources/howto/index_en.rst.txt +++ b/develop/doc/_sources/howto/index_en.rst.txt @@ -6,5 +6,6 @@ HOW TO cmd_parameter/index_en.rst cluster/index_en.rst + capi/index_en.rst rnn/index_en.rst optimization/gpu_profiling_en.rst diff --git a/develop/doc/_sources/howto/optimization/cpu_profiling_en.md.txt b/develop/doc/_sources/howto/optimization/cpu_profiling_en.md.txt deleted file mode 100644 index 01e5fddf615..00000000000 --- a/develop/doc/_sources/howto/optimization/cpu_profiling_en.md.txt +++ /dev/null @@ -1,196 +0,0 @@ -This tutorial introduces techniques we use to profile and tune the -CPU performance of PaddlePaddle. We will use Python packages -`cProfile` and `yep`, and Google's `perftools`. - -Profiling is the process that reveals performance bottlenecks, -which could be very different from what's in the developers' mind. -Performance tuning is done to fix these bottlenecks. Performance optimization -repeats the steps of profiling and tuning alternatively. - -PaddlePaddle users program AI applications by calling the Python API, which calls -into `libpaddle.so.` written in C++. In this tutorial, we focus on -the profiling and tuning of - -1. the Python code and -1. the mixture of Python and C++ code. - -## Profiling the Python Code - -### Generate the Performance Profiling File - -We can use Python standard -package, [`cProfile`](https://docs.python.org/2/library/profile.html), -to generate Python profiling file. For example: - -```bash -python -m cProfile -o profile.out main.py -``` - -where `main.py` is the program we are going to profile, `-o` specifies -the output file. Without `-o`, `cProfile` would outputs to standard -output. - -### Look into the Profiling File - -`cProfile` generates `profile.out` after `main.py` completes. We can -use [`cprofilev`](https://github.com/ymichael/cprofilev) to look into -the details: - -```bash -cprofilev -a 0.0.0.0 -p 3214 -f profile.out main.py -``` - -where `-a` specifies the HTTP IP, `-p` specifies the port, `-f` -specifies the profiling file, and `main.py` is the source file. - -Open the Web browser and points to the local IP and the specifies -port, we will see the output like the following: - -``` - ncalls tottime percall cumtime percall filename:lineno(function) - 1 0.284 0.284 29.514 29.514 main.py:1() - 4696 0.128 0.000 15.748 0.003 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/executor.py:20(run) - 4696 12.040 0.003 12.040 0.003 {built-in method run} - 1 0.144 0.144 6.534 6.534 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/v2/__init__.py:14() -``` - -where each line corresponds to Python function, and the meaning of -each column is as follows: - -| column | meaning | -| --- | --- | -| ncalls | the number of calls into a function | -| tottime | the total execution time of the function, not including the execution time of other functions called by the function | -| percall | tottime divided by ncalls | -| cumtime | the total execution time of the function, including the execution time of other functions being called | -| percall | cumtime divided by ncalls | -| filename:lineno(function) | where the function is defined | - -### Identify Performance Bottlenecks - -Usually, `tottime` and the related `percall` time is what we want to -focus on. We can sort above profiling file by tottime: - -```text - 4696 12.040 0.003 12.040 0.003 {built-in method run} - 300005 0.874 0.000 1.681 0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/v2/dataset/mnist.py:38(reader) - 107991 0.676 0.000 1.519 0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:219(__init__) - 4697 0.626 0.000 2.291 0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:428(sync_with_cpp) - 1 0.618 0.618 0.618 0.618 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/__init__.py:1() -``` - -We can see that the most time-consuming function is the `built-in -method run`, which is a C++ function in `libpaddle.so`. We will -explain how to profile C++ code in the next section. At this -moment, let's look into the third function `sync_with_cpp`, which is a -Python function. We can click it to understand more about it: - -``` -Called By: - - Ordered by: internal time - List reduced from 4497 to 2 due to restriction <'sync_with_cpp'> - -Function was called by... - ncalls tottime cumtime -/home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:428(sync_with_cpp) <- 4697 0.626 2.291 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:562(sync_with_cpp) -/home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:562(sync_with_cpp) <- 4696 0.019 2.316 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:487(clone) - 1 0.000 0.001 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:534(append_backward) - - -Called: - - Ordered by: internal time - List reduced from 4497 to 2 due to restriction <'sync_with_cpp'> -``` - -The lists of the callers of `sync_with_cpp` might help us understand -how to improve the function definition. - -## Profiling Python and C++ Code - -### Generate the Profiling File - -To profile a mixture of Python and C++ code, we can use a Python -package, `yep`, that can work with Google's `perftools`, which is a -commonly-used profiler for C/C++ code. - -In Ubuntu systems, we can install `yep` and `perftools` by running the -following commands: - -```bash -apt update -apt install libgoogle-perftools-dev -pip install yep -``` - -Then we can run the following command - -```bash -python -m yep -v main.py -``` - -to generate the profiling file. The default filename is -`main.py.prof`. - -Please be aware of the `-v` command line option, which prints the -analysis results after generating the profiling file. By examining the - the print result, we'd know that if we stripped debug -information from `libpaddle.so` at build time. The following hints -help make sure that the analysis results are readable: - -1. Use GCC command line option `-g` when building `libpaddle.so` so to - include the debug information. The standard building system of - PaddlePaddle is CMake, so you might want to set - `CMAKE_BUILD_TYPE=RelWithDebInfo`. - -1. Use GCC command line option `-O2` or `-O3` to generate optimized - binary code. It doesn't make sense to profile `libpaddle.so` - without optimization, because it would anyway run slowly. - -1. Profiling the single-threaded binary file before the - multi-threading version, because the latter often generates tangled - profiling analysis result. You might want to set environment - variable `OMP_NUM_THREADS=1` to prevents OpenMP from automatically - starting multiple threads. - -### Examining the Profiling File - -The tool we used to examine the profiling file generated by -`perftools` is [`pprof`](https://github.com/google/pprof), which -provides a Web-based GUI like `cprofilev`. - -We can rely on the standard Go toolchain to retrieve the source code -of `pprof` and build it: - -```bash -go get github.com/google/pprof -``` - -Then we can use it to profile `main.py.prof` generated in the previous -section: - -```bash -pprof -http=0.0.0.0:3213 `which python` ./main.py.prof -``` - -Where `-http` specifies the IP and port of the HTTP service. -Directing our Web browser to the service, we would see something like -the following: - -![result](./pprof_1.png) - -### Identifying the Performance Bottlenecks - -Similar to how we work with `cprofilev`, we'd focus on `tottime` and -`cumtime`. - -![kernel_perf](./pprof_2.png) - -We can see that the execution time of multiplication and the computing -of the gradient of multiplication takes 2% to 4% of the total running -time, and `MomentumOp` takes about 17%. Obviously, we'd want to -optimize `MomentumOp`. - -`pprof` would mark performance critical parts of the program in -red. It's a good idea to follow the hints. diff --git a/develop/doc/_sources/howto/optimization/gpu_profiling_en.rst.txt b/develop/doc/_sources/howto/optimization/gpu_profiling_en.rst.txt index ed208ceaf7a..50adb7da249 100644 --- a/develop/doc/_sources/howto/optimization/gpu_profiling_en.rst.txt +++ b/develop/doc/_sources/howto/optimization/gpu_profiling_en.rst.txt @@ -54,7 +54,7 @@ In this tutorial, we will focus on nvprof and nvvp. :code:`test_GpuProfiler` from :code:`paddle/math/tests` directory will be used to evaluate above profilers. -.. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp +.. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp :language: c++ :lines: 137-151 :linenos: @@ -80,7 +80,7 @@ As a simple example, consider the following: 1. Add :code:`REGISTER_TIMER_INFO` and :code:`printAllStatus` functions (see the emphasize-lines). - .. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp + .. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp :language: c++ :lines: 137-151 :emphasize-lines: 8-12,14 @@ -127,7 +127,7 @@ To use this command line profiler **nvprof**, you can simply issue the following 1. Add :code:`REGISTER_GPU_PROFILER` function (see the emphasize-lines). - .. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp + .. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp :language: c++ :lines: 137-151 :emphasize-lines: 6-7 diff --git a/develop/doc/_sources/howto/read_source.md.txt b/develop/doc/_sources/howto/read_source.md.txt deleted file mode 100644 index edf46aff8c6..00000000000 --- a/develop/doc/_sources/howto/read_source.md.txt +++ /dev/null @@ -1,67 +0,0 @@ -# PaddlePaddle Fluid Source Code Overview - -Examples: https://github.com/PaddlePaddle/Paddle/tree/develop/python/paddle/fluid/tests/book - -Core: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/framework - -Operator: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/operators - -Memory: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/memory - -Platform: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/platform - -# Compile Time - -The following **defines** the NN. The definition goes into this [protocol buffer](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto). - -```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_cost = fluid.layers.mean(x=cost) - -sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.001) -sgd_optimizer.minimize(avg_cost) -``` - -- Variables: `x`, `y`, `y_predict`, `cost` and `avg_cost`. [Python](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/framework.py#) -- Layers: `fluid.layers.data`, `fluid.layers.fc` and `fluid.layers.mean` are layers. [Python](https://github.com/PaddlePaddle/Paddle/tree/develop/python/paddle/fluid/layers) - - Every Layer has one or more operators and variables/parameters - - All the operators are defined at [`paddle/operators/`](https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/operators). Other worth-looking files: - - Base class: [`paddle/framework/operator.h`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/operator.h) - - Operator Registration: [`paddle/framework/op_registry.h`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/op_registry.h) - - Operator Lookup: [`paddle/framework/op_info.h`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/op_info.h) -- Optimizer: `fluid.optimizer.SGD`. It does the following - - Add backward operators. [[Python](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/backward.py)] - - Add optimizer operators. [[Python](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/optimizer.py)] - -# Run Time - -The following **evaluates** the NN. Instantiates all the variables, operators. - -```python -place = fluid.CPUPlace() -feeder = fluid.DataFeeder(place=place, feed_list=[x, y]) -exe = fluid.Executor(place) - -# Allocate memory. Initialize Parameter. -exe.run(fluid.default_startup_program()) - -# Allocate memory. Do computation. -exe.run(fluid.default_main_program(), - feed=feeder.feed(data), - fetch_list=[avg_cost]) -``` - -- Place: `place`. one of CPU, GPU or FPGA. [C++](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/place.h) - - The device handle are at [paddle/platform/device_context.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/device_context.h) -- Executor: `fluid.Executor(place)`. [[Python](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/executor.py), [C++](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/executor.cc)] - - Feeds the data: `feed=feeder.feed(data)` - - Evaluates all the operators - - Fetches the result: `fetch_list=[avg_cost]` -- Other worth looking files: - - Scope: [paddle/framework/scope.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/scope.h). Where all the variables live - - Variable: [paddle/framework/variable.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/variable.h). Where all the data (most likely tensors) live - - Tensor: [paddle/framework/tensor.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/tensor.h). Where we allocate memory through [`paddle/memory/`](https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/memory) diff --git a/develop/doc/_sources/mobile/cross_compiling_for_android_en.md.txt b/develop/doc/_sources/mobile/cross_compiling_for_android_en.md.txt deleted file mode 100644 index 6af16fc114a..00000000000 --- a/develop/doc/_sources/mobile/cross_compiling_for_android_en.md.txt +++ /dev/null @@ -1,189 +0,0 @@ -# Build PaddlePaddle for Android - -There are two approaches to build PaddlePaddle for Android: - -- [Cross-Compiling Using Docker](#cross-compiling-using-docker) -- [Cross-Compiling on Linux](#cross-compiling-on-linux) - -## Cross-Compiling Using Docker - -Docker-based cross-compiling is the recommended approach because Docker runs on all major operating systems, including Linux, Mac OS X, and Windows. - -### Build the Docker Image - -The following steps pack all the tools that we need to build PaddlePaddle into a Docker image. - -```bash -$ git clone https://github.com/PaddlePaddle/Paddle.git -$ cd Paddle -$ docker build -t paddle:dev-android . -f Dockerfile.android -``` - -Users can directly use the published Docker image. - -```bash -$ docker pull paddlepaddle/paddle:latest-dev-android -``` - -For users in China, we provide a faster mirror. - -```bash -$ docker pull docker.paddlepaddlehub.com/paddle:latest-dev-android -``` - -### Build the Inference Library - -We can run the Docker image we just created to build the inference library of PaddlePaddle for Android using the command below: - -```bash -$ docker run -it --rm -v $PWD:/paddle -e "ANDROID_ABI=armeabi-v7a" -e "ANDROID_API=21" paddle:dev-android -``` - -The Docker image accepts two arguments `ANDROID_ABI` and `ANDROID_API`: - - -- - - - - - - - - - - - - - - - - - - - - - - -
ArgumentOptional ValuesDefault
ANDROID_ABIarmeabi-v7a, arm64-v8aarmeabi-v7a
ANDROID_API>= 1621
- -The ARM-64 architecture (`arm64-v8a`) requires at least level 21 of Android API. - -The default entry-point of the Docker image, [`paddle/scripts/docker/build_android.sh`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/scripts/docker/build_android.sh) generates the [Android cross-compiling standalone toolchain](https://developer.android.com/ndk/guides/standalone_toolchain.html) based on the argument: `ANDROID_ABI` or `ANDROID_API`. For information about other configuration arguments, please continue reading. - -The above command generates and outputs the inference library in `$PWD/install_android` and puts third-party libraries in `$PWD/install_android/third_party`. - -## Cross-Compiling on Linux - -The Linux-base approach to cross-compile is to run steps in `Dockerfile.android` manually on a Linux x64 computer. - -### Setup the Environment - -To build for Android's, we need [Android NDK]( -https://developer.android.com/ndk/downloads/index.html): - -```bash -wget -q https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip -unzip -q android-ndk-r14b-linux-x86_64.zip -``` - -Android NDK includes everything we need to build the [*standalone toolchain*](https://developer.android.com/ndk/guides/standalone_toolchain.html), which in then used to build PaddlePaddle for Android. (We plan to remove the intermediate stage of building the standalone toolchain in the near future.) - -- To build the standalone toolchain for `armeabi-v7a` and Android API level 21: - -```bash -your/path/to/android-ndk-r14b-linux-x86_64/build/tools/make-standalone-toolchain.sh \ - --arch=arm --platform=android-21 --install-dir=your/path/to/arm_standalone_toolchain -``` - - The generated standalone toolchain will be in `your/path/to/arm_standalone_toolchain`. - -- To build the standalone toolchain for `arm64-v8a` and Android API level 21: - -```bash -your/path/to/android-ndk-r14b-linux-x86_64/build/tools/make-standalone-toolchain.sh \ - --arch=arm64 --platform=android-21 --install-dir=your/path/to/arm64_standalone_toolchain -``` - - The generated standalone toolchain will be in `your/path/to/arm64_standalone_toolchain`. - -### Cross-Compiling Arguments - -CMake supports [choosing the toolchain](https://cmake.org/cmake/help/v3.0/manual/cmake-toolchains.7.html#cross-compiling). PaddlePaddle provides [`android.cmake`](https://github.com/PaddlePaddle/Paddle/blob/develop/cmake/cross_compiling/android.cmake), which configures the Android cross-compiling toolchain for CMake. `android.cmake` is not required for CMake >= 3.7, which support Android cross-compiling. PaddlePaddle detects the CMake version, for those newer than 3.7, it uses [the official version](https://cmake.org/cmake/help/v3.7/manual/cmake-toolchains.7.html#cross-compiling). - -Some other CMake arguments you need to know: - -- `CMAKE_SYSTEM_NAME` must be `Android`. This tells PaddlePaddle's CMake system to cross-compile third-party dependencies. This also changes some other CMake arguments like `WITH_GPU=OFF`, `WITH_AVX=OFF`, `WITH_PYTHON=OFF`, `WITH_RDMA=OFF`, `WITH_MKL=OFF` and `WITH_GOLANG=OFF`. -- `WITH_C_API` must be `ON`, to build the C-based inference library for Android. -- `WITH_SWIG_PY` must be `OFF` because the Android platform doesn't support SWIG-based API. - -Some Android-specific arguments: - -- `ANDROID_STANDALONE_TOOLCHAIN`: the absolute path of the Android standalone toolchain, or the path relative to the CMake build directory. PaddlePaddle's CMake extensions would derive the cross-compiler, sysroot and Android API level from this argument. -- `ANDROID_TOOLCHAIN`: could be `gcc` or `clang`. The default value is `clang`. - - For CMake >= 3.7, it should anyway be `clang`. For older versions, it could be `gcc`. - - Android's official `clang` requires `glibc` >= 2.15. -- `ANDROID_ABI`: could be `armeabi-v7a` or `arm64-v8a`. The default value is `armeabi-v7a`. -- `ANDROID_NATIVE_API_LEVEL`: could be derived from the value of `ANDROID_STANDALONE_TOOLCHAIN`. -- `ANROID_ARM_MODE`: - - could be `ON` or `OFF`, and defaults to `ON`, when `ANDROID_ABI=armeabi-v7a`; - - no need to specify when `ANDROID_ABI=arm64-v8a`. -- `ANDROID_ARM_NEON`: indicates if to use NEON instructions. - - could be `ON` or `OFF`, and defaults to `ON`, when `ANDROID_ABI=armeabi-v7a`; - - no need to specify when `ANDROID_ABI=arm64-v8a`. - -Other useful arguments: - -- `USE_EIGEN_FOR_BLAS`: indicates if using Eigen. Could be `ON` or `OFF`, defaults to `OFF`. -- `HOST_C/CXX_COMPILER`: specifies the host compiler, which is used to build the host-specific protoc and target-specific OpenBLAS. It defaults to the value of the environment variable `CC/C++`, or `cc/c++`. - -Some frequent configurations for your reference: - -```bash -cmake -DCMAKE_SYSTEM_NAME=Android \ - -DANDROID_STANDALONE_TOOLCHAIN=your/path/to/arm_standalone_toolchain \ - -DANDROID_ABI=armeabi-v7a \ - -DANDROID_ARM_NEON=ON \ - -DANDROID_ARM_MODE=ON \ - -DUSE_EIGEN_FOR_BLAS=ON \ - -DCMAKE_INSTALL_PREFIX=your/path/to/install \ - -DWITH_C_API=ON \ - -DWITH_SWIG_PY=OFF \ - .. -``` - -``` -cmake -DCMAKE_SYSTEM_NAME=Android \ - -DANDROID_STANDALONE_TOOLCHAIN=your/path/to/arm64_standalone_toolchain \ - -DANDROID_ABI=arm64-v8a \ - -DUSE_EIGEN_FOR_BLAS=OFF \ - -DCMAKE_INSTALL_PREFIX=your/path/to/install \ - -DWITH_C_API=ON \ - -DWITH_SWIG_PY=OFF \ - .. -``` - - -There are some other arguments you might want to configure. - -- `CMAKE_BUILD_TYPE=MinSizeRel` minimizes the size of library. -- `CMAKE_BUILD_TYPE-Release` optimizes the runtime performance. - -Our own tip for performance optimization to use clang and Eigen or OpenBLAS: - -- `CMAKE_BUILD_TYPE=Release` -- `ANDROID_TOOLCHAIN=clang` -- `USE_EIGEN_BLAS=ON` for `armeabi-v7a`, or `USE_EIGEN_FOR_BLAS=OFF` for `arm64-v8a`. - -### Build and Install - -After running `cmake`, we can run `make; make install` to build and install. - -Before building, you might want to remove the `third_party` and `build` directories including pre-built libraries for other architectures. - -After building,in the directory `CMAKE_INSTALL_PREFIX`, you will find three sub-directories: - -- `include`: the header file of the inference library, -- `lib`: the inference library built for various Android ABIs, -- `third_party`: dependent third-party libraries built for Android. diff --git a/develop/doc/_sources/mobile/cross_compiling_for_ios_en.md.txt b/develop/doc/_sources/mobile/cross_compiling_for_ios_en.md.txt deleted file mode 100644 index 19bfe86c511..00000000000 --- a/develop/doc/_sources/mobile/cross_compiling_for_ios_en.md.txt +++ /dev/null @@ -1,120 +0,0 @@ -# Build PaddlePaddle for iOS - -This tutorial will walk you through cross compiling the PaddlePaddle library for iOS from the source in MacOS. - -## Preparation - -Apple provides Xcode for cross-compiling and IDE for iOS development. Download from App store or [here](https://developer.apple.com/cn/xcode/). To verify your installation, run command as follows - -```bash -$ xcodebuild -version -Xcode 9.0 -Build version 9A235 -``` - -## Cross-compiling configurations - -PaddlePaddle provides cross-compiling toolchain configuration documentation [cmake/cross_compiling/ios.cmake](https://github.com/PaddlePaddle/Paddle/blob/develop/cmake/cross_compiling/ios.cmake), which has some default settings for frequently used compilers. - -There are some mandatory environment variables need to be set before cross compiling PaddlePaddle for iOS: - -- `CMAKE_SYSTEM_NAME`, CMake compiling target platform name, has to be `iOS`. PaddlePaddle CMake will compile all the third party dependencies and enforce some parameters (`WITH_C_API=ON`, `WITH_GPU=OFF`, `WITH_AVX=OFF`, `WITH_PYTHON=OFF`,`WITH_RDMA=OFF`) when this variable is set with value `iOS`. - -- `WITH_C_API`, Whether to compile inference C-API library, has to be `ON`, since C-API is the only supported interface for inferencing in iOS. -- `WITH_SWIG_PY`, has to be `OFF`. It's not supported to inference or train via swig in iOS. - -Optional environment variables for iOS are: - -- `IOS_PLATFORM`, either `OS` (default) or `SIMULATOR`. - - `OS`, build targets ARM-based physical devices like iPhone or iPad. - - `SIMULATOR`, build targets x86 architecture simulators. -- `IOS_ARCH`, target architecture. By default, all architecture types will be compiled. If you need to specify the architecture to compile for, please find valid values for different `IOS_PLATFORM` settings from the table below: - - - - - - - - - - - - - - - - - - - - - - -
IOS_PLATFORMIOS_ARCH
OSarmv7, armv7s, arm64
SIMULATORi386, x86_64
- -- `IOS_DEPLOYMENT_TARGET`, minimum iOS version to deployment, `7.0` by default. -- `IOS_ENABLE_BITCODE`, whether to enable [Bitcode](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/AppThinning/AppThinning.html#//apple_ref/doc/uid/TP40012582-CH35-SW3), values can be `ON/OFF`, `ON` by default. -- `IOS_USE_VECLIB_FOR_BLAS`, whether to use [vecLib](https://developer.apple.com/documentation/accelerate/veclib) framework for BLAS computing. values can be `ON/OFF`, `OFF` by default. -- `IOS_DEVELOPMENT_ROOT`, the path to `Developer` directory, can be explicitly set with your `/path/to/platform/Developer`. If left blank, PaddlePaddle will automatically pick the Xcode corresponding `platform`'s `Developer` directory based on your `IOS_PLATFORM` value. -- `IOS_SDK_ROOT`, the path to `SDK` root, can be explicitly set with your `/path/to/platform/Developer/SDKs/SDK`. if left black, PaddlePaddle will pick the latest SDK in the directory of `IOS_DEVELOPMENT_ROOT`. - -other settings: - -- `USE_EIGEN_FOR_BLAS`, whether to use Eigen for matrix computing. effective when `IOS_USE_VECLIB_FOR_BLAS=OFF`. Values can be `ON/OFF`, `OFF` by default. -- `HOST_C/CXX_COMPILER`, host C/C++ compiler. Uses value from environment variable `CC/CXX` by default or `cc/c++` if `CC/CXX` doesn't exist. - -some typical cmake configurations: - -```bash -cmake -DCMAKE_SYSTEM_NAME=iOS \ - -DIOS_PLATFORM=OS \ - -DIOS_ARCH="armv7;arm64" \ - -DIOS_ENABLE_BITCODE=ON \ - -DIOS_USE_VECLIB_FOR_BLAS=ON \ - -DCMAKE_INSTALL_PREFIX=your/path/to/install \ - -DWITH_C_API=ON \ - -DWITH_TESTING=OFF \ - -DWITH_SWIG_PY=OFF \ - .. -``` - -```bash -cmake -DCMAKE_SYSTEM_NAME=iOS \ - -DIOS_PLATFORM=SIMULATOR \ - -DIOS_ARCH="x86_64" \ - -DIOS_USE_VECLIB_FOR_BLAS=ON \ - -DCMAKE_INSTALL_PREFIX=your/path/to/install \ - -DWITH_C_API=ON \ - -DWITH_TESTING=OFF \ - -DWITH_SWIG_PY=OFF \ - .. -``` - -You can set other compiling parameters for your own need. I.E. if you are trying to minimize the library size, set `CMAKE_BUILD_TYPE` with `MinSizeRel`; or if the performance is your concern, set `CMAKE_BUILD_TYPE` with `Release`. You can even manipulate the PaddlePaddle compiling procedure by manually set `CMAKE_C/CXX_FLAGS` values. - -**TIPS for a better performance**: - -- set `CMAKE_BUILD_TYPE` with `Release` -- set `IOS_USE_VECLIB_FOR_BLAS` with `ON` - -## Build and install - -After CMake, run following commands, PaddlePaddle will download the compile 3rd party dependencies, compile and install PaddlePaddle inference library. - -``` -$ make -$ make install -``` - -Please Note: if you compiled PaddlePaddle in the source directory for other platforms, do remove `third_party` and `build` directory within the source with `rm -rf` to ensure that all the 3rd party libraries dependencies and PaddlePaddle is newly compiled with current CMake configuration. - -`your/path/to/install` directory will have following directories after `make install`: - -- `include`, contains all the C-API header files. -- `lib`, contains PaddlePaddle C-API static library. -- `third_party` contains all the 3rd party libraries. - -Please note: if PaddlePaddle library need to support both physical devices and simulators, you will need to compile correspondingly, then merge fat library with `lipo`. - -Now you will have PaddlePaddle library compiled and installed, the fat library can be used in deep learning related iOS APPs. Please refer to C-API documentation for usage guides. diff --git a/develop/doc/_sources/mobile/cross_compiling_for_raspberry_en.md.txt b/develop/doc/_sources/mobile/cross_compiling_for_raspberry_en.md.txt deleted file mode 100644 index 3c1a5950ff9..00000000000 --- a/develop/doc/_sources/mobile/cross_compiling_for_raspberry_en.md.txt +++ /dev/null @@ -1,62 +0,0 @@ -# Build PaddlePaddle for Raspberry Pi - -You may use any of the following two approaches to build the inference library of PaddlePaddle for Raspberry Pi: - -1. Build using SSH: Log in to a Raspberry Pi using SSH and build the library. The required development tools and third-party dependencies are listed in here: [`/Dockerfile`](https://github.com/PaddlePaddle/Paddle/blob/develop/Dockerfile). - -1. Cross-compile: We talk about how to cross-compile PaddlePaddle for Raspberry Pi on a Linux/x64 machine, in more detail in this article. - -## The Cross-Compiling Toolchain - -Step 1. Clone the Github repo by running the following command. - -```bash -git clone https://github.com/raspberrypi/tools.git -``` - -Step 2. Use the pre-built cross-compiler found in `./tools/tree/master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64`. To run it on a Linux computer, glibc version >= 2.14 is needed. - -## CMake Arguments - -CMake supports [cross-compiling](https://cmake.org/cmake/help/v3.0/manual/cmake-toolchains.7.html#cross-compiling). All CMake configuration arguments required for the cross-compilation for Raspberry Pi can be found in [`cmake/cross_compiling/raspberry_pi.cmake`](https://github.com/PaddlePaddle/Paddle/blob/develop/cmake/cross_compiling/raspberry_pi.cmake). - -Some important arguments that need to be set: - -- `CMAKE_SYSTEM_NAME`: The target platform. Must be `RPi`. - -- `RPI_TOOLCHAIN`: The absolute path of the cross-compiling toolchain. - -- `RPI_ARM_NEON`: Use ARM NEON Intrinsics. This is a required argument and set default to `ON`. - -- `HOST_C/CXX_COMPILER`: The C/C++ compiler for the host. It is used to build building tools running on the host, for example, protoc. - -A commonly-used CMake configuration is as follows: - -``` -cmake -DCMAKE_SYSTEM_NAME=RPi \ - -DRPI_TOOLCHAIN=your/path/to/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64 \ - -DRPI_ARM_NEON=ON \ - -DCMAKE_INSTALL_PREFIX=your/path/to/install \ - -DWITH_GPU=OFF \ - -DWITH_C_API=ON \ - -DWITH_PYTHON=OFF \ - -DWITH_SWIG_PY=OFF \ - .. -``` - -To build the inference library, please set the argument WITH\_C\_API to ON: `WITH_C_API=ON`. - -You can add more arguments. For example, to minimize the size of the generated inference library, you may use `CMAKE_BUILD_TYPE=MinSizeRel`. For performance optimization, you may use `CMAKE_BUILD_TYPE=Release`. - -## Build and Install - -The following commands build the inference library of PaddlePaddle for Raspberry Pi and third-party dependencies. - -```bash -make -make install -``` - - The intermediate files will be stored in `build`. Third-party libraries will be located in `build/third_party`. If you have already built it for other platforms like Android or iOS, you may want to clear these directories by running the command: `rm -rf build`. - -The infernece library will be in `your/path/to/install/lib`, with related header files in `your/path/to/install/include`. diff --git a/develop/doc/_sources/survey/cluster_bootstrapping_tools.md.txt b/develop/doc/_sources/survey/cluster_bootstrapping_tools.md.txt deleted file mode 100644 index 1cd9962700b..00000000000 --- a/develop/doc/_sources/survey/cluster_bootstrapping_tools.md.txt +++ /dev/null @@ -1,71 +0,0 @@ -# Cluster bootstrapping tool survey -## Abstract -In order to bring up a cluster from bare metal machine to a fully functional kubernetes cluster for Paddlepaddle to run, we need to utilize some tools. Here we are going to compare [Sextant](https://github.com/k8sp/sextant) and [Tectonic installer](https://github.com/coreos/tectonic-installer) - -## Basic assumptions -Here are some basic assumptions before we move on to details -1. You are an administrator of a bare metal machine cluster, which means: - * you have full control to each of the machines. - * you have full control to the network which machines are connected to. -2. Machines can be booted from network with PEX or iPXE -3. You understand the [general procedure to bring up a cluster](#appendix-general-procedure-to-bring-up-a-cluster) - -if your cluster is able to mark above items with checkmarks, then keep reading. - -## Comparing Sextant and Tectonic installer -### Sextant -Sextant is an end2end solution to bring up a bare metal cluster to a fully functional k8s cluster, it integrates DHCP, name service, PEX, cloud-config-service, docker registry services altogether. - -#### Pros -1. End2End: basically all admin need to do is to config the cluster.yaml and power on the cluster. -2. Offline cluster configuration: Sextant has 2 phases during working with it, config time and deploy time. when admin is configuring, it requires admin's machine has internet connectivity, which will download some images, etc. But in deploy time, it's completely OK to go offline since all dependencies are ready during config time. -3. docker registry integrated. -4. GPU machine took care of. - -### Cons -1. k8s API server is not deployed with high availability in considering by default. -2. No grouping support. -3. No API interface, a one-off service. - - -### Tectonic installer -First of all, Tectonic is not free, it requires coreos.com account as a step of installation, and free user can only create less than 10 nodes. - -Tectonic is a suite of software which wraps around k8s and providing more utility regarding dev ops, ie, -Tectonic installer as it's named, it installs Tectonic to a bare metal cluster which means it's not totally an equivalent of Sextant. At the "booting a cluster" part, it mostly utilizes [Matchbox](https://github.com/coreos/matchbox), which is a general cluster bootstrapper. - -Matchbox's Approach is similar to Sexstant. - -### Pros -1. supports grouping machines. -2. supports running provisioning service in rtk. (not a big deal though). -3. supports http/gRPC API interface. -4. supports multi-template. - -### Cons -1. Not an e2e solution to bring up a cluster, need a lot of extra work and other software. -2. [Not fully supporting](https://github.com/coreos/matchbox/issues/550) centOS deployment yet. - -## Conclusion -Sextant is a better solution overall for paddle cloud deploying to a bare metal cluster. It would be great if Sextant can also 1) deploy k8s api server with high availability by default; 2) not designed as a one-off service. - - - -## Appendix: General procedure to bring up a cluster -It's physically impossible for a cluster admin to manually install OS and applications into cluster nodes one by one, here is what an admin would do in cloud industry: -1. setup a bootstrap machine with static IP in the cluster, which has following services: - * DHCP: assigns ip address for rest of the nodes. - * name service: to map node name to a IP - * PXE related services: the booting related info will be delivered to newly booted machines as their IP is assigned via DHCP service, PXE service will provide further booting and installing info and image with TFTP and http protocol. - * cluster config service: this is for providing cluster node with OS config via http - * optional docker registry: a built-in docker registry makes the whole cluster independent from connecting internet, and speeds up software distribution. -2. New node powers on, it will - * broadcast the request for an IP address - * DHCP server assigns the IP address, and deliver the PXE booting related info to the node. - * cluster node will request config files with booting info delivered with DHCP via the TFTP service, and in most of the cases, the config file will point to a http service for the booting image. - * Since PXE is configured with initrd, it will utilize the cloud config service and do further installations like coreOS or K8s installations. - * then restart the node. - -For further understanding, following 2 links from Matchbox are some good readings: -* [Machine lifecycle](https://github.com/coreos/matchbox/blob/master/Documentation/machine-lifecycle.md) -* [PXE booting](https://github.com/coreos/matchbox/blob/master/Documentation/network-booting.md) diff --git a/develop/doc/build_and_install/build_from_source_en.html b/develop/doc/build_and_install/build_from_source_en.html index 0b204e71fa5..b5205b56252 100644 --- a/develop/doc/build_and_install/build_from_source_en.html +++ b/develop/doc/build_and_install/build_from_source_en.html @@ -124,6 +124,12 @@ var _hmt = _hmt || []; +
  • C-API Prediction Library +
  • RNN Models
    • RNN Configuration
    • Recurrent Group Tutorial
    • @@ -137,6 +143,7 @@ var _hmt = _hmt || [];
    • Development
    • FAQ
        diff --git a/develop/doc/build_and_install/docker_install_en.html b/develop/doc/build_and_install/docker_install_en.html index 9b671607407..bdb1c639082 100644 --- a/develop/doc/build_and_install/docker_install_en.html +++ b/develop/doc/build_and_install/docker_install_en.html @@ -124,6 +124,12 @@ var _hmt = _hmt || [];
    • +
    • C-API Prediction Library +
    • RNN Models
      • RNN Configuration
      • Recurrent Group Tutorial
      • @@ -137,6 +143,7 @@ var _hmt = _hmt || [];
      • Development
      • FAQ
          diff --git a/develop/doc/build_and_install/index_en.html b/develop/doc/build_and_install/index_en.html index 100f9219623..cb8a791304f 100644 --- a/develop/doc/build_and_install/index_en.html +++ b/develop/doc/build_and_install/index_en.html @@ -123,6 +123,12 @@ var _hmt = _hmt || [];
      • +
      • C-API Prediction Library +
      • RNN Models
        • RNN Configuration
        • Recurrent Group Tutorial
        • @@ -136,6 +142,7 @@ var _hmt = _hmt || [];
        • Development
        • FAQ
            diff --git a/develop/doc/build_and_install/pip_install_en.html b/develop/doc/build_and_install/pip_install_en.html index d46ee40b08e..d2c6ea45ee0 100644 --- a/develop/doc/build_and_install/pip_install_en.html +++ b/develop/doc/build_and_install/pip_install_en.html @@ -124,6 +124,12 @@ var _hmt = _hmt || [];
        • +
        • C-API Prediction Library +
        • RNN Models
          • RNN Configuration
          • Recurrent Group Tutorial
          • @@ -137,6 +143,7 @@ var _hmt = _hmt || [];
          • Development
          • FAQ
              diff --git a/develop/doc/design/api.html b/develop/doc/design/api.html deleted file mode 100644 index ce7ec999cae..00000000000 --- a/develop/doc/design/api.html +++ /dev/null @@ -1,487 +0,0 @@ - - - - - - - - - - - - - PaddlePaddle Design Doc — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              PaddlePaddle Design Doc

              -
              -

              Ingredients

              -

              As our design principle is starting from the essence: how could we -allow users to express and solve their problems as neural networks. -Some essential concepts that our API have to provide include:

              -
                -
              1. A topology is an expression of layers.
              2. -
              3. A layer could be any kind of computation, including cost.
              4. -
              5. Some layers have parameters, some don’t. Most costs don’t have -parameters.
              6. -
              7. In some topologies, layers share parameters. For -example, -the network for training a ranking model.
              8. -
              9. At programming time, users specify topologies and possible sharing -of parameters. PaddlePaddle can figure out and create parameters -required (and possibly shared) by one or more topologies.
              10. -
              -
              -
              -

              Starting from Examples

              -

              As a summarization -of -our disucssion, -let us present two examples here:

              -
              -

              Example 1. Sharing Parameters between Layers

              -

              We use -the -3-branch ranking model -in this example. For your convenience, I copy-a-paste the model’s -topology as follows:

              -
              A -> f -\
              -Q -> f --> cost
              -B -> f -/
              -
              -
              -

              The following program trains the topology including the cost, and then -use the sub-network in the trained topology in inference:

              -
              def f(in):
              -    e = paddle.layer.embedding(in, parameter_name="embedding")
              -    o = paddle.layer.softmax(e, parameter_name="semantic")
              -    return o
              -
              -# Create 3 topologies (subnets), they share parameters because all
              -# correspoinding layers have the same parameter names.
              -fA = f(paddle.layer.data(input_name="A"))
              -fB = f(paddle.layer.data(input_name="B"))
              -fQ = f(paddle.layer.data(input_name="Q"))
              -
              -topology = paddle.layer.less_than(
              -               paddle.layer.cross_entropy(fA, fQ),
              -               paddle.layer.corss_entropy(fB, fQ))
              -
              -# Derive parameters required in topology and create them in model.
              -parameters = paddle.parameters.create(topology)
              -
              -# Estimate parameters used in topology from data.
              -paddle.train(topology, parameters, reader=read_ranking_model_data)
              -
              -# Inference using fA (or fB or fC, as they share their parameters).
              -[testA, testB, testQ] = read_ranking_model_data()
              -print "The sematic-vector of testA: ", paddle.infer(fA, parameters, testA)
              -
              -
              -
              -
              -

              Example 2. Sharing Parameters between “Models”

              -

              We use GAN in -this example. In the following example program, d0 and d1 -correspond to the two networks in the following figure:

              -

              -
              def G(in):
              -    # over-simplified example as G has only one layers:
              -    return paddle.layer.fc(in, parameter_name="G")
              -
              -def D(in);
              -    # again, over-simplified:
              -    return paddle.layer.fc(in, parameter_name="D")
              -
              -# Construct the first topology, which contains both D and G.
              -# By learning this topology, we update parameters of G.
              -d0 = paddle.layer.should_be_false(D(G(paddle.layer.data())))
              -
              -# Construct a second topology d1, which contains only D. By
              -# training this topology, we update parameters of D.  Note
              -# that d1 share parameters with d0.
              -d1 = paddle.layer.should_be_true(D(paddle.layer.data()))
              -
              -# Create parameters from a list of multiple topologies (models) for
              -# the chance to share parameters between these topologies.
              -parameters = paddle.parameters.create([d0, d1])
              -
              -# Iterative training of GAN.
              -for ...:
              -    train(d0, parameters, reader=read_from_rng, immutable_parameters={"D"})
              -    train(d1, parameters, reader=read_from_realistic_images)
              -
              -# Use d1 for inference:
              -print "D thinks a batch of images are realistic ", infer(d1, parameters, read_mnist_images)
              -
              -
              -
              -
              -

              Summarization

              -

              Above two programs reveal some important design concerns:

              -
                -
              1. Users describe a topology as an expression of layers. Every layer -has a parameter name. If the users don’t specify it explicitly, it’s automatically generated as a unique name. By -specifying the parameter name, users can specify the sharing of -parameters between layers and even between topologies.
              2. -
              3. paddle.parameters.create figures out parameters required by one -or more topologies from parameter names of layers. It creates these -parameters and returns a ParameterSet object, which is in essence -a map from parameter names to parameters.
              4. -
              5. At training and inference time, paddle.train and paddle.infer -requires both a topology and the parameter set that holds the parameters of that topology. There are some reasons:
                  -
                1. This prevents users from forgetting to call -paddle.parameters.create.
                2. -
                3. paddle.train needs to know which parameter set to update.
                4. -
                5. Users could load another (pre-trained) parameter set and use it -with a topology in train.infer.
                6. -
                -
              6. -
              7. By specifying the immutable_parameters parameter of -paddle.train, we can forbid the update of these parameters.
              8. -
              -
              -
              -
              -

              Reader

              -

              Not all programming frameworks allow users to define I/O functions. -An example is Google MapReduce, which can only read from text, -SSTable, and RecordIO files. Hadoop MapReduce allows users to define -readers and writers by deriving from base classes Reader and -Writer. The former is less flexible but also less error-prone. We -decide to provide the flexibility to users to define their readers.

              -

              There are some open questions here:

              -
                -
              1. Should a reader return a Python dictionary?
              2. -
              3. How to map multiple outputs from a reader to multiple data layers?
              4. -
              5. How to easily compose some existing readers to read more data and -feed a topology with more data layers?
              6. -
              -
              -
              -

              Training

              -

              The recommended way to training a model is to call paddle.train, -which simply calls paddle.trainer.Default, a global variable of -type paddle.trainer.SGD. Equivalently, we can do

              -
              opt = paddle.trainer.SGD(..., paddle.updater.Adam(...))
              -opt.train(topology, parameters, reader=read, ...)
              -
              -
              -
              -

              Updater

              -

              Please be aware that a trainer can accept an updater as its data -member, where an updater is a class derived from -paddle.trainer.Updater. This is to make it easier to customize -trainers, as discussed -here.

              -
              -
              -

              Event Handler

              -

              paddle.train and paddle.trainer.XXX.train take an optional -parameter event_handler, which should be either None or a function -that handle some events:

              -
                -
              1. BeginTraining
              2. -
              3. EndTraining
              4. -
              5. BeginIteration
              6. -
              7. EndIteration
              8. -
              9. BeginPass
              10. -
              11. EndPass
              12. -
              -

              where EndPass is sent if and only if the reader yields -end_pass=True.

              -

              An example as follows:

              -
              def event_handler(event):
              -    if ininstance(event, paddle.event.EndIteration):
              -        print paddle.test(...)
              -
              -paddle.train(topology, parameters, reader, event_handler)
              -
              -
              -

              If we are writing a PaddlePaddle program in and for iPython/Jypyter, -we can use metaplotlib in the event handler to plot a curve of -cost/error versus iterations, as shown -here.

              -
              -
              -

              Distributed Training

              -

              If users want to do distributed training on a cluster, s/he should -call paddle.dist_train and provides access tokens to the cluster as -a parameter.

              -

              For example, if the user has a TLS certificate that allows him to -access a Kubernetes cluster, s/he should be able to call

              -
              paddle.dist_train(model,
              -                  trainer=paddle.trainer.SGD(...,
              -                                             paddle.updater.Adam(...)),
              -                  reader=read,
              -                  k8s_user="yi",
              -                  k8s_token="kube_cluster_tls.pem",
              -                  k8s_job="hello",
              -                  num_parameter_servers=15)
              -
              -
              -

              The pseudo code of paddle.dist_train is as follows:

              -
              def dist_train(topology, parameters, trainer, reader, ...):
              -    if os.getenv("KUBERNETES_SERVICE_HOST") == None:
              -        image_name = k8s_user + '/' + k8s_job
              -        docker_build(image_name)
              -        docker_push()
              -        kube_ctrl_start_job(image_name, k8s_user, k8s_token)
              -    else:
              -        rank = kube_list_containers_in_job_and_return_current_containers_rank()
              -        if rank == 0:
              -            master()
              -        elif rank < 15:
              -            parameter_server()
              -        else:
              -            trainer.train(model, reader=read)
              -
              -
              -

              Please be aware that if a process is running on the Kubernetes -cluster, it will have some environment variables pre-defined.

              -

              If dist_train doesn’t see these environment variables, it knows -that it’s running on users’ personal computer, and it should work as a -launcher. Otherwise, it knows that it’s running on the cluster and -need to figure out its role as either the master, or a trainer, or a -parameter server.

              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/auto_gradient_check.html b/develop/doc/design/auto_gradient_check.html deleted file mode 100644 index ed0cc19b019..00000000000 --- a/develop/doc/design/auto_gradient_check.html +++ /dev/null @@ -1,423 +0,0 @@ - - - - - - - - - - - - - Auto Gradient Check Design — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Auto Gradient Check Design

              -
              -
              -

              Background:

              -
                -
              • Generally, it is easy to check whether the forward computation of an Operator is correct or not. However, backpropagation is a notoriously difficult algorithm to debug and get right because of the following challenges:
                  -
                1. The formula for backpropagation formula should be correct according to the forward computation.
                2. -
                3. The Implementation of the above shoule be correct in CPP.
                4. -
                5. It is difficult to prepare an unbiased test data.
                6. -
                -
              • -
              • Auto gradient checking gets a numerical gradient using forward Operator and uses it as a reference for the backward Operator’s result. It has several advantages:
                  -
                1. Numerical gradient checker only needs the forward operator.
                2. -
                3. The user only needs to prepare the input data for forward Operator and not worry about the backward Operator.
                4. -
                -
              • -
              -
              -
              -

              Mathematical Theory

              -

              The following documents from Stanford have a detailed explanation of how to compute the numerical gradient and why it is useful.

              - -
              -
              -

              Numerical Gradient Implementation

              -
              -

              Python Interface

              -
              def get_numerical_gradient(op,
              -                         input_values,
              -                         output_name,
              -                         input_to_check,
              -                         delta=0.005,
              -                         local_scope=None):
              -    """
              -    Get Numerical Gradient for the input of an operator.
              -
              -    :param op: C++ operator instance, could be an network.
              -    :param input_values: The input variables. Should be an dictionary, whose key is
              -    variable name, and value is a numpy array.
              -    :param output_name: The final output variable name.
              -    :param input_to_check: The input variable with respect to which the gradient has to be computed.
              -    :param delta: The perturbation value for numerical gradient method. The
              -    smaller the delta, the more accurate the result. But if the delta is too
              -    small, it will suffer from the numerical stability problem.
              -    :param local_scope: The local scope used for get_numeric_gradient.
              -    :return: The gradient array in numpy format.
              -    """
              -
              -
              -
              -
              -

              Explanation:

              -
                -
              • Why do we need an output_name
                  -
                • An Operator may have multiple Outputs, one can compute an independent gradient from each Output. So the caller should specify the name of the output variable.
                • -
                -
              • -
              • Why do we need input_to_check
                  -
                • One operator can have multiple inputs. Gradient Op can calculate the gradient of these inputs at the same time. But Numerical Gradient needs to calculate them one by one. So get_numeric_gradient is designed to calculate the gradient for one input. If you need to compute multiple inputs, you can call get_numeric_gradient multiple times each with a different input.
                • -
                -
              • -
              -
              -
              -

              Core Algorithm Implementation

              -
                  # we only compute the gradient of one element a time.
              -    # we use a for loop to compute the gradient of each element.
              -    for i in xrange(tensor_size):
              -        # get one input element using the index i.
              -        original = tensor_to_check.get_float_element(i)
              -
              -        # add delta to it, run the forward op and then
              -        # get the new value of the result tensor.
              -        x_pos = original + delta
              -        tensor_to_check.set_float_element(i, x_pos)
              -        y_pos = get_output()
              -
              -        # Subtract delta from this element, run the op again
              -        # and get the new value of the result tensor.
              -        x_neg = original - delta
              -        tensor_to_check.set_float_element(i, x_neg)
              -        y_neg = get_output()
              -
              -        # restore old value
              -        tensor_to_check.set_float_element(i, original)
              -
              -        # compute the gradient of this element and store
              -        # it into a numpy array.
              -        gradient_flat[i] = (y_pos - y_neg) / delta / 2
              -
              -    # reshape the gradient result to the shape of the source tensor.
              -    return gradient_flat.reshape(tensor_to_check.get_dims())
              -
              -
              -
              -
              -
              -

              Auto Gradient Check Framework

              -

              Each Operator Kernel has three kinds of Gradient:

              -
                -
              1. Numerical gradient
              2. -
              3. CPU kernel gradient
              4. -
              5. GPU kernel gradient (if supported by the device)
              6. -
              -

              The numerical gradient only relies on the forward Operator, so we use the numerical gradient as the reference value. The gradient checking is performed in the following three steps:

              -
                -
              1. Calculate the numerical gradient
              2. -
              3. Calculate CPU kernel gradient with the backward Operator and compare it with the numerical gradient.
              4. -
              5. Calculate GPU kernel gradient with the backward Operator and compare it with the numeric gradient. (if supported)
              6. -
              -
              -

              Python Interface

              -
                  def check_grad(self,
              -                   forward_op,
              -                   input_vars,
              -                   inputs_to_check,
              -                   output_name,
              -                   no_grad_set=None,
              -                   only_cpu=False,
              -                   max_relative_error=0.005):
              -        """
              -        :param forward_op: used to create backward_op
              -        :param input_vars: numpy value of input variable. The following
              -          computation will use these variables.
              -        :param inputs_to_check: the input variable with respect to which the
              -          gradient will be computed.
              -        :param output_name: The final output variable name.
              -        :param max_relative_error: The relative tolerance parameter.
              -        :param no_grad_set: used to create backward ops
              -        :param only_cpu: only compute and check gradient on cpu kernel.
              -        :return:
              -        """
              -
              -
              -
              -
              -

              How to check if two numpy arrays are close enough?

              -

              if abs_numerical_grad is nearly zero, then use absolute error for numerical_grad.

              -
              numerical_grad = ...
              -operator_grad = numpy.array(scope.find_var(grad_var_name(name)).get_tensor())
              -
              -abs_numerical_grad = numpy.abs(numerical_grad)
              -# if abs_numerical_grad is nearly zero, then use abs error for
              -# numeric_grad, instead of relative error.
              -abs_numerical_grad[abs_numerical_grad < 1e-3] = 1
              -
              -diff_mat = numpy.abs(abs_numerical_grad - operator_grad) / abs_numerical_grad
              -max_diff = numpy.max(diff_mat)
              -
              -
              -
              -

              Notes:

              -

              The Input data for auto gradient checker should be reasonable to avoid numerical stability problem.

              -
              - -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/backward.html b/develop/doc/design/backward.html deleted file mode 100644 index 94debbec115..00000000000 --- a/develop/doc/design/backward.html +++ /dev/null @@ -1,394 +0,0 @@ - - - - - - - - - - - - - Backward Building — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Backward Building

              -
              -

              Motivation

              -

              In Neural Network, most models are solved by the backpropagation algorithm(known as BP) at present. Technically, BP calculates the gradient of the loss function, then propagates it back through the networks following the chain rule. However, when configuring the model structure, users do not need to define the backward part. So a mechanism is required by the framework which can complete the model’s backward part automatically according to the given forward part.

              -

              When implementing a specific op, the developer is also asked to implement its backward version, called grad_op. A grad_op takes gradients of its corresponding op‘s outputs, and calculate gradients of the op‘s inputs. During the building of a model’s backward part, the framework creates each forward op‘s grad_op, and then string them together in reverse order of forwarding part. In this way, gradients spread from the end to the beginning of the model, in another word, from the loss to parameters.

              -
              -
              -

              Challenges

              -

              The motivation of backward building is apparent. However, implementation it correctly is not so easy. In the Fluid design, a deep learning model is described by Program, Block, Op and Variable. The Block itself can be nested. It means that the ops and variables are scattered across different blocks rather than all be gathered in a single graph. Our backward building algorithm shall visit blocks in recursive order and be able to insert grad_ops and new created variables into the right place.

              -
              -
              -

              Usage

              -

              Although the whole algorithm is comprised of many functions, only one is exposed as API:

              -
              def append_backward(loss, parameter_list=None, no_grad_set=None):
              -    """
              -    Append backward part to main_program
              -
              -    Args:
              -        loss(Variable): The variable generated by the cost function.
              -        parameter_list(list): Parameters that need to be updated by optimizers.
              -            If None, it means all parameters need to be updated.
              -
              -        no_grad_set(set): Variables that have no gradients in Block 0. 
              -            If None, the set will be generated inside the function and 
              -            contains all variables with `step_gradient=True` from all blocks.
              -        
              -    Return:
              -        (list[Variable]): list of (parameters, gradients) pair.
              -    """
              -
              -
              -

              By invoking this API, the framework appends backward part of the program where the loss is. It takes three arguments. loss means the final loss value. It must be a scalar and is usually the output of the loss layer. It is also where the gradient generated and backpropagation starts. parameter_list marks all parameters needs updating. If it’s None, all parameter will be updated by optimizers. no_grad_set marks variables without gradient. if all outputs of some grad_op are in no_grad_set, the grad_op will not be run.

              -

              This API will be invoked automatically before optimizer building. -As a result, in most cases, users do not need to invoke the API by themselves to append backward part.

              -
              -
              -

              Implementation

              -

              The implementation of backward building algorithm is in backward.py file. The whole algorithm can be divided into two independent parts: creating grad_ops and creating new variables.

              -
              -

              Creating grad_ops

              -

              The creating of grad_ops is implemented by:

              -
              def _append_backward_ops_(target,
              -                          block,
              -                          target_block,
              -                          no_grad_dict,
              -                          grad_to_var):
              -    """
              -    Create all grad ops, and insert them into given block
              -
              -    Args:
              -        target(Variable): the target variable of forward pass
              -        block(Block): the block where forward ops are
              -        target_block(Block): the block which is going to hold new generated grad ops
              -        no_grad_dict(dict): 
              -            key(int)  block index
              -            val(set) a set of varibale names. These varibales have no gradient
              -        grad_to_var(dict)(output argument):
              -            key(str): grad variable name
              -            val(str): corresponding forward variable name
              -    """
              -
              -
              -

              Given a block, the function will traverses all ops in this block in reverse order, gets corresponding grad_op from the C++ core via core.get_grad_op_desc(), then append it to target_block.

              -

              However, some specific op(e.g. while_op, if_else_op) can hold its own sub-block. For these sub-blocks contains ops as well, the grad_op creating should be recursive.

              -

              During the reverse traversal, we check each op whether it has an attribute named sub_block. If so, it means there is a sub-block and we need to deal with it first. After creating a new block whose father is the one in op‘s attribute, we invoke _append_backward_ops_() recursively, assigning the new block to parameter target_block and the one in op‘s attribute to block. The pseudo-code shows this process:

              -
              ******* pseudo-code ********
              -for op in reversed(block.ops):
              -    if op has an attribute named 'sub_block':
              -        Get the sub-block(`s_block`) from op's attribute.
              -        Create a new block(`grad_s_block`), whose father is `s_block`.
              -        Invoke _append_backward_ops_(), with `block=s_block` and `target_block=grad_s_block`
              -    
              -    Invoke `core.get_grad_op_desc()` to get op's grad_op.
              -    Insert name correspondings between variables and their gradients of the grad_op to grad_to_var
              -    Assign grad_s_block to grad_op as it's 'sub_block' attribute.
              -    Append grad_op to current target_block.
              -
              -
              -

              The first invoking of _append_backward_ops_() is initiated by append_backward(), in which parameters block and target_block are all assigned with root block(the block with index 0).

              -
              -
              -

              Corner Cases of grad_op Creating

              -

              In the previous section, we show the regular process of grad_op creating. However, in some corner cases, the conventional algorithm is not enough to get the correct result and appending handling is required. These additional processes run after the algorithm mentioned above and do some special adjusts on its output grad_ops.

              -
              -

              Shared Variables

              -

              If a variable is read by more than one op in the forward pass, its gradient is likely to be written by more than one grad_ops in the next backward pass. To make the gradient result being the sum of all grad_ops’ outputs instead of the last running one, we assign each output with a temporary variable and then add a sum_op to add them up.

              -

              For the debug convenience, if the final gradient name is w@GRAD, it’s corresponding temporary variables will be named as w@GRAD@RENAME@0, w@GRAD@RENAME@1...

              -

              See function _addup_repetitive_outputs_ in backward.py for implementation details.

              -
              -
              -

              No Gradient Variables

              -

              In our framework, variables can be marked as no_gradient, it means that the gradient of this variable is unnecessary and can be considered as zero in model training. Apparently, when all the outputs of some grad_op are marked as no_gradient, the grad_op itself can be skipped in backward pass.

              -

              Another situation is all the gradient inputs of some grad_op are marked as no_gradient, which means all of them can be considered as zeros. For grad_ops are in essence the propagation of gradients, all the outputs are definitely zeros when all gradient inputs are zeros. Therefore the grad_op can also be skipped.

              -

              It should be noted that all these zero gradients still need to be creating and initialized by something, otherwise following grad_ops who take these gradients as inputs take the risk of using uninitialized memory. In our code, we employ fill_zeros_like_op to initialize them as all zeros.

              -

              This features are implemented in function _remove_no_grad_branch_. It checks new created grad_ops one-by-one, removes who can be skipped and inserts fill_zeros_like_op when its necessary. We can get the no_grad_set from the _append_backward_ops_ argument no_grad_dict or generate it on the fly by scanning all variables’ no_gradient attribute(True or False).

              -
              -
              -
              -

              Creating Backward Variables

              -

              Up to now, we have completed all creating and adjusting jobs of grad_ops. However, backward variables have not been created. Now they are only represented by grad_op‘s input and output arguments. The backward variable creating job will be done by:

              -
              def _append_backward_vars_(block, 
              -                           start_op_idx, 
              -                           grad_to_var, 
              -                           grad_info_map):
              -    """
              -    Create new variables required by backward pass.
              -
              -    Args:
              -        block(Block): the block where new variables will be created
              -        start_op_idx(int): Only variables required by ops in block.ops[start_op_idx : ] will be created
              -        grad_to_var(dict):
              -            key(str): grad variable name
              -            val(str): corresponding forward variable name
              -            In most cases, this dict is generated by _append_backward_ops_()
              -        grad_info_map(dict)(output argument):
              -            key(str): forward variable name
              -            val(tuple): a tuple of (str, int), str is the corresponding grad name, int is the block index
              -    """
              -
              -
              -

              Given a block, this function traverses all the grad_ops in it(The argument start_op_idx indicates where the grad_op sequence starts.) and creates all the uncreated outputs. The pseudo-code shows this process:

              -
              for op in block.ops[start_op_idx : ]:
              -
              -    if op has an attribute named 'sub_block':
              -        Get the sub-block(`s_block`) from op's attribute.
              -        Invoke _append_backward_vars_(), with `block=s_block`
              -        
              -    for var_name in op.all_output_names():
              -        if block.has_var_recursive(var_name) or var_name is the name of empty variable:
              -            continue
              -        create a new variable named 'var_name' in block
              -        if grad_to_var.has_key(var_name):
              -            set grad_info_map[grad_to_var[var_name]] as a tuple of (var_name. block)
              -            
              -    do op's var type inference
              -    do op's shape inference
              -
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/block.html b/develop/doc/design/block.html deleted file mode 100644 index cb3f25c7ba4..00000000000 --- a/develop/doc/design/block.html +++ /dev/null @@ -1,559 +0,0 @@ - - - - - - - - - - - - - Design Doc: Block and Scope — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Block and Scope

              -
              -

              The Representation of Computation

              -

              Both deep learning systems and programming languages help users describe computation procedures. These systems use various representations of computation:

              -
                -
              • Caffe, Torch, and Paddle: sequences of layers.
              • -
              • TensorFlow, Caffe2, Mxnet: graph of operators.
              • -
              • PaddlePaddle: nested blocks, like C++ and Java programs.
              • -
              -
              -
              -

              Block in Programming Languages and Deep Learning

              -

              In programming languages, a block is a pair of curly braces that includes local variables definitions and a sequence of instructions or operators.

              -

              Blocks work with control flow structures like if, else, and for, which have equivalents in deep learning:

              -

              | programming languages | PaddlePaddle | -|———————–|———————–| -| for, while loop | RNN, WhileOp | -| if, if-else, switch | IfElseOp, SwitchOp | -| sequential execution | a sequence of layers |

              -

              A key difference is that a C++ program describes a one pass computation, whereas a deep learning program describes both the forward and backward passes.

              -
              -
              -

              Stack Frames and the Scope Hierarchy

              -

              The existence of the backward pass makes the execution of a block of PaddlePaddle different from traditional programs:

              -

              | programming languages | PaddlePaddle | -|———————–|———————————| -| stack | scope hierarchy | -| stack frame | scope | -| push at entering block| push at entering block | -| pop at leaving block | destroy when minibatch completes|

              -
                -
              1. In traditional programs:
                  -
                • When the execution enters the left curly brace of a block, the runtime pushes a frame into the stack, where it realizes local variables.
                • -
                • After the execution leaves the right curly brace, the runtime pops the frame.
                • -
                • The maximum number of frames in the stack is the maximum depth of nested blocks.
                • -
                -
              2. -
              3. In PaddlePaddle
                  -
                • When the execution enters a block, PaddlePaddle adds a new scope, where it realizes variables.
                • -
                • PaddlePaddle doesn’t pop a scope after the execution of the block because variables therein are used by the backward pass. So it has a stack forest known as a scope hierarchy.
                • -
                • The height of the highest tree is the maximum depth of nested blocks.
                • -
                • After the processing of a minibatch, PaddlePaddle destroys the scope hierarchy.
                • -
                -
              4. -
              -
              -
              -

              Use Blocks in C++ and PaddlePaddle Programs

              -

              Let us consolidate the discussion by presenting some examples.

              -
              -

              Blocks with if-else and IfElseOp

              -

              The following C++ programs shows how blocks are used with the if-else structure:

              -
              namespace pd = paddle;
              -
              -int x = 10;
              -int y = 1;
              -int z = 10;
              -bool cond = false;
              -int o1, o2;
              -if (cond) {
              -  int z = x + y;
              -  o1 = z;
              -  o2 = pd::layer::softmax(z);
              -} else {
              -  int d = pd::layer::fc(z);
              -  o1 = d;
              -  o2 = d+1;
              -}
              -
              -
              -

              An equivalent PaddlePaddle program from the design doc of the IfElseOp operator is as follows:

              -
              import paddle as pd
              -
              -x = minibatch([10, 20, 30]) # shape=[None, 1]
              -y = var(1) # shape=[1], value=1
              -z = minibatch([10, 20, 30]) # shape=[None, 1]
              -cond = larger_than(x, 15) # [false, true, true]
              -
              -ie = pd.ifelse()
              -with ie.true_block():
              -    d = pd.layer.add_scalar(x, y)
              -    ie.output(d, pd.layer.softmax(d))
              -with ie.false_block():
              -    d = pd.layer.fc(z)
              -    ie.output(d, d+1)
              -o1, o2 = ie(cond)
              -
              -
              -

              In both examples, the left branch computes x+y and softmax(x+y), the right branch computes fc(x) and x+1 .

              -

              The difference is that variables in the C++ program contain scalar values, whereas those in the PaddlePaddle programs are mini-batches of instances.

              -
              -
              -

              Blocks with for and RNNOp

              -

              The following RNN model in PaddlePaddle from the RNN design doc :

              -
              x = sequence([10, 20, 30]) # shape=[None, 1]
              -m = var(0) # shape=[1]
              -W = var(0.314, param=true) # shape=[1]
              -U = var(0.375, param=true) # shape=[1]
              -
              -rnn = pd.rnn()
              -with rnn.step():
              -  h = rnn.memory(init = m)
              -  h_prev = rnn.previous_memory(h)
              -  a = layer.fc(W, x)
              -  b = layer.fc(U, h_prev)  
              -  s = pd.add(a, b)
              -  act = pd.sigmoid(s)
              -  rnn.update_memory(h, act)
              -  rnn.output(a, b)
              -o1, o2 = rnn()
              -
              -
              -

              has its equivalent C++ program as follows

              -
              int* x = {10, 20, 30};
              -int* m = {0};
              -int* W = {0.314};
              -int* U = {0.375};
              -
              -int mem[sizeof(x) / sizeof(x[0]) + 1];
              -int o1[sizeof(x) / sizeof(x[0]) + 1];
              -int o2[sizeof(x) / sizeof(x[0]) + 1];
              -for (int i = 1; i <= sizeof(x)/sizeof(x[0]); ++i) {
              -  int x = x[i-1];
              -  if (i == 1) mem[0] = m;
              -  int a = W * x;
              -  int b = Y * mem[i-1];
              -  int s = fc_out + hidden_out;
              -  int act = sigmoid(sum);
              -  mem[i] = act;
              -  o1[i] = act;
              -  o2[i] = hidden_out;
              -}
              -
              -
              -
              -
              -
              -

              Compilation and Execution

              -

              Like TensorFlow, a PaddlePaddle program is written in Python. The first part describes a neural network as a protobuf message, and the rest executes the message for training or inference.

              -

              The generation of this protobuf message is similar to how a compiler generates a binary executable file. The execution of the message is similar to how the OS executes the binary file.

              -
              -
              -

              The “Binary Executable File Format”

              -

              The definition of the protobuf message is as follows:

              -
              message BlockDesc {
              -  repeated VarDesc vars = 1;
              -  repeated OpDesc ops = 2;
              -}
              -
              -
              -

              The step net in above RNN example would look like

              -
              BlockDesc {
              -  vars = {
              -    VarDesc {...} // x
              -    VarDesc {...} // h
              -    VarDesc {...} // fc_out
              -    VarDesc {...} // hidden_out
              -    VarDesc {...} // sum
              -    VarDesc {...} // act
              -  }
              -  ops = {
              -    OpDesc {...} // matmul
              -    OpDesc {...} // add_two
              -    OpDesc {...} // sigmoid
              -  }
              -};
              -
              -
              -

              Also, the RNN operator in above example is serialized into a protobuf message of type OpDesc and would look like:

              -
              OpDesc {
              -  inputs = {0} // the index of x in vars of BlockDesc above
              -  outputs = {5, 3} // indices of act and hidden_out in vars of BlockDesc above
              -  attrs {
              -    "states" : {1} // the index of h
              -    "step_net" : <above step net>
              -  }
              -};
              -
              -
              -

              This OpDesc value is in the ops field of the BlockDesc value representing the global block.

              -
              -
              -

              The Compilation of Blocks

              -

              During the generation of the Protobuf message, the Block should store VarDesc (the Protobuf message which describes Variable) and OpDesc (the Protobuf message which describes Operator).

              -

              VarDesc in a block should have its name scope to avoid local variables affecting parent block’s name scope. -Child block’s name scopes should inherit the parent’s so that OpDesc in child block can reference a VarDesc that is stored in the parent block. For example:

              -
              a = pd.Variable(shape=[20, 20])
              -b = pd.fc(a, params=["fc.w", "fc.b"])
              -
              -rnn = pd.create_rnn()
              -with rnn.stepnet():
              -    x = a.as_step_input()
              -    # reuse fc's parameter
              -    fc_without_b = pd.get_variable("fc.w")
              -    rnn.output(fc_without_b)
              -
              -out = rnn()
              -
              -
              -

              The method pd.get_variable can help retrieve a Variable by the name. The Variable may be stored in a parent block, but might be retrieved in a child block, so block should have a variable scope that supports inheritance.

              -

              In compiler design, the symbol table is a data structure created and maintained by compilers to store information about the occurrence of various entities such as variable names, function names, classes, etc.

              -

              To store the definition of variables and operators, we define a C++ class SymbolTable, like the one used in compilers.

              -

              SymbolTable can do the following:

              -
                -
              • store the definitions (some names and attributes) of variables and operators,
              • -
              • verify if a variable was declared,
              • -
              • make it possible to implement type checking (offer Protobuf message pointers to InferShape handlers).
              • -
              -
              // Information in SymbolTable is enough to trace the dependency graph. So maybe
              -// the Eval() interface takes a SymbolTable is enough.
              -class SymbolTable {
              - public:
              -  SymbolTable(SymbolTable* parent) : parent_(parent) {}
              -
              -  OpDesc* NewOp(const string& name="");
              -
              -  // TODO determine whether name is generated by python or C++.
              -  // Currently assume that a unique name will be generated by C++ if the
              -  // argument name is left default.
              -  VarDesc* Var(const string& name="");
              -
              -  // find a VarDesc by name, if recursive is true, find parent's SymbolTable
              -  // recursively.
              -  // this interface is introduced to support InferShape, find protobuf messages
              -  // of variables and operators, pass pointers into InferShape.
              -  //
              -  // NOTE maybe some C++ classes such as VarDescBuilder and OpDescBuilder should
              -  // be proposed and embedded into pybind to enable python operation on C++ pointers.
              -  VarDesc* FindVar(const string& name, bool recursive=true);
              -
              -  OpDesc* FindOp(const string& name);
              -
              -  BlockDesc Compile() const;
              -
              - private:
              -  SymbolTable* parent_;
              -
              -  map<string, OpDesc> ops_;
              -  map<string, VarDesc> vars_;
              -};
              -
              -
              -

              After all the description of variables and operators is added into SymbolTable, -the block has enough information to run.

              -

              The Block class takes a BlockDesc as input, and provides Run and InferShape functions.

              -
              namespace {
              -
              -class Block : OperatorBase {
              -public:
              -  Block(const BlockDesc& desc) desc_(desc) {}
              -
              -  void InferShape(const framework::Scope& scope) const override {
              -    if (!symbols_ready_) {
              -      CreateVariables(scope);
              -      CreateOperators();
              -    }
              -    // should run InferShape first.
              -    for (auto& op : runtime_table_.ops()) {
              -      op->InferShape(scope);
              -    }
              -  }
              -
              -  void Run(const framework::Scope& scope,
              -           const platform::Place& place) const override {
              -    PADDLE_ENFORCE(symbols_ready_, "operators and variables should be created first.");
              -    for (auto& op : runtime_table_.ops()) {
              -      op->Run(scope, place);
              -    }
              -  }
              -
              -  void CreateVariables(const framework::Scope& scope);
              -  void CreateOperators();
              -
              -  // some other necessary interfaces of NetOp are listed below
              -  // ...
              -
              -private:
              -  BlockDesc desc_;
              -  bool symbols_ready_{false};
              -};
              -
              -
              -
              -
              -

              The Execution of Blocks

              -

              Block inherits from OperatorBase, which has a Run method. -Block’s Run method will run its operators sequentially.

              -

              There is another important interface called Eval, which takes some arguments called targets and generates a minimal graph which treats targets as the end points and creates a new Block. After Run, Eval will get the latest value and return the targets.

              -

              The definition of Eval is as follows:

              -
              // clean a block description by targets using the corresponding dependency graph.
              -// return a new BlockDesc with minimal number of operators.
              -// NOTE: The return type is not a Block but the block's description so that this can be distributed
              -// to a cluster.
              -BlockDesc Prune(const BlockDesc& desc, vector<string> targets);
              -
              -void Block::Eval(const vector<string>& targets,
              -                 const framework::Scope& scope,
              -                 const platform::DeviceContext& dev_ctx) {
              -  BlockDesc min_desc = Prune(desc_, targets);
              -  Block min_block(min_desc);
              -  min_block.Run(scope, dev_ctx);
              -}
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/build_system/README.html b/develop/doc/design/build_system/README.html deleted file mode 100644 index 2b46da65563..00000000000 --- a/develop/doc/design/build_system/README.html +++ /dev/null @@ -1,401 +0,0 @@ - - - - - - - - - - - - - Required CMake Function — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -

              A few months ago when we were trying to replace CMake with Bazel, @emailweixu suggested that we rewrite those handy Bazel functions using CMake. Now it seems that it’s the right time to get this done, as we are facing problems from the porting of Majel and the development of new the parameter server using Go and C++.

              -

              Here are some initial thoughts. Your comments are welcome!

              -
              -

              Required CMake Function

              -

              I think we need only the following few CMake functions to make a project description mean and clean:

              -

              | C++ | CUDA C++ | Go | -|—|—|—| -| cc_library | nv_library | go_library | -| cc_binary | nv_binary | go_binary | -| cc_test | nv_test | go_test |

              -
                -
              • The _library functions generate .a files from source code.
              • -
              • The _binary functions generate executable binary files.
              • -
              • The _test functions generate executable unit test files. They work like _binary but links -lgtest and -lgtest_main.
              • -
              -

              The difference between nv_ functions and cc_ functions is that the former use nvcc instead of the system-default C++ compiler.

              -

              Both nv_ and cc_ functions enables C++11 (-std=c++11).

              -

              Also,

              -
                -
              • to describe external dependencies, we need external_library.
              • -
              • to build shared libraries, we need shared_library.
              • -
              -
              -
              -

              An Example Project

              -

              Suppose that we have aforementioned functions defined in our /cmake directory. The following example CMakeLists.txt describes a project including the following source files:

              -
                -
              • tensor.h
              • -
              • tensor.cc
              • -
              • tensor_test.cc
              • -
              • ops.h
              • -
              • ops.cu
              • -
              • ops_test.cu
              • -
              • api.go
              • -
              • api_test.go
              • -
              -

              Suppose that ops.cu depends on CUDNN.

              -
              # cc_binary parses tensor.cc and figures out that target also depend
              -# on tensor.h.
              -cc_binary(tensor
              -  SRCS
              -  tensor.cc)
              -
              -# The dependency to target tensor implies that if any of
              -# tensor{.h,.cc,_test.cc} is changed, tensor_test need to be re-built.
              -cc_test(tensor_test
              -  SRCS
              -  tensor_test.cc
              -  DEPS
              -  tensor)
              -
              -# I don't have a clear idea what parameters external_library need to
              -# have.  @gangliao as a CMake expert would have better ideas.
              -external_library(cudnn
              -  ....)
              -
              -# Suppose that ops.cu depends on external target CUDNN.  Also, ops.cu
              -# include global functions that take Tensor as their parameters, so
              -# ops depend on tensor.  This implies that if any of tensor.{h.cc},
              -# ops.{h,cu} is changed, ops need to be re-built.
              -nv_library(ops
              -  SRCS
              -  ops.cu
              -  DEPS
              -  tensor
              -  cudnn)  # cudnn is defined later.
              -
              -nv_test(ops_test
              -  SRCS
              -  ops_test.cu
              -  DEPS
              -  ops)
              -
              -# Because api.go defines a GO wrapper to ops and tensor, it depends on
              -# both.  This implies that if any of tensor.{h,cc}, ops.{h,cu}, or
              -# api.go is changed, api need to be re-built.
              -go_library(api
              -  SRCS
              -  api.go
              -  DEPS
              -  tensor # Because ops depend on tensor, this line is optional.
              -  ops)
              -
              -go_test(api_test
              -  SRCS
              -  api_test.go
              -  DEPS
              -  api)
              -
              -
              -# This builds libapi.so.  shared_library might use CMake target
              -# api_shared so to distinguish it from above target api.
              -shared_library(api
              -  DEPS
              -  api)
              -
              -
              -
              -
              -

              Implementation

              -

              As above example CMakeLists.txt executes, each function invocation adds “nodes” to a dependency graph. It also use this graph to generate CMake commands including add_executable, add_dependencies, target_link_libraries, and add_test.

              -
              -
              -

              Using Package Manager For Go

              -

              Building Go binaries and libraries need to satisfy their dependencies, generally -we can do go get ./... to download and compile all external dependencies. The -problems are:

              -
                -
              1. go get will always get the latest code from the default branch of the -remote repo, so changes of dependents might break the build. This is very -different with what we already have in cmake/external which download a -specific version or commit id of the dependency.
              2. -
              3. Some locations can not access external dependencies through the internet, as mentioned -in https://github.com/PaddlePaddle/Paddle/issues/2605. Using package management -tools can package the dependencies as a “vendor” package, which can be mirrored -at many cloud file hosting, so users what to compile paddle by themselves can -download this “vendor” package from a mirror site.
              4. -
              -
              -

              Choose A Suitable Tool

              -

              As mentioned by @wangkuiyi, Here -list dozens of Go package managers. We choose the tool using following principles:

              -
                -
              • Most “active” projects with more stars, more pull requests or commits
              • -
              • Widely used project
              • -
              -

              After comparing all these projects, we shall choose between the most popular -tools: Godep and Glide.

              -

              Here’s a brief comparison between Godep and Glide -: https://github.com/Masterminds/glide/wiki/Go-Package-Manager-Comparison. There are -also many complaints about using Godep. There’s also a new “official” pakcage -management tool has been started at: https://github.com/golang/dep to resolve -such problems, but it’s currently at Alpha stage. So the best choice now is -glide obviously.

              -
              -
              -

              Manage Go Packages

              -
                -
              • Dependencies: go/glide.yaml will store the dependencies and their versions which -is directly imported by paddle. go/glide.lock will store all dependencies recursively -with their commit id. Builds will “lock” to these packages if we don’t glide up -them
              • -
              • Vendor package: go/vendor directory will generated when running cmake command. cmake -will download the code corresponding to go/glide.lock. If we put a vendor folder -under go/, cmake will just check the commit id to the packages under the folder, -if commit id matches, there will be no download at all.
              • -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/cluster_train/README.html b/develop/doc/design/cluster_train/README.html deleted file mode 100644 index 00a0bc6f73b..00000000000 --- a/develop/doc/design/cluster_train/README.html +++ /dev/null @@ -1,430 +0,0 @@ - - - - - - - - - - - - - Design Doc: Distributed Training — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Distributed Training

              -
              -

              Objective

              -

              In this slides, we explained that we’d like PaddlePaddle running on general-purpose clusters like those managed by Kubernetes, so to address demands for AI from both Internet and non-Internet industries.

              -

              This poses technical challenges to PaddlePaddle:

              -
                -
              1. Support fault-recovery.
              2. -
              3. Support both offline and online training.
              4. -
              5. Serverless computing of distributed training.
              6. -
              -
              -
              -

              Training Job

              -

              A training job will be created once user asks Paddle cloud to train a model. The training job is made up of different processes that collaboratively consume data and produce a trained model. There are three kinds of processes:

              -
                -
              1. the master server process, which dispatches tasks to
              2. -
              3. one or more trainer processes, which run distributed training and synchronize gradients/models via
              4. -
              5. one or more parameter server processes, where each holds a shard of the global model, and receive the uploaded gradients from every trainer process, so they can run the optimize functions to update their parameters.
              6. -
              -

              Their relation is illustrated in the following graph:

              -

              -

              By coordinating these processes, PaddlePaddle supports use both Synchronize Stochastic Gradient Descent (sync SGD) and Asynchronous Stochastic Gradient Descent (async SGD) to train user-defined neural network topologies.

              -

              When training with sync SGD, parameter servers wait for all trainers to finish gradients update and then send the updated parameters to trainers, training can not proceed until the trainer received the updated parameters. This creates a synchronization point between trainers. When training with async SGD, each trainer upload gradient and download new parameters individually, without the synchronization with other trainers. Using asyc SGD will be faster in terms of time per pass, but have more noise in gradient since trainers are likely to have a stale model.

              -
              -

              Master Server Process

              -

              The master server process will:

              -
                -
              • Partition a dataset into tasks and dispatch tasks to trainers.
              • -
              • Keep track of training progress on the dataset with task queue. A training job will iterate on the dataset for a full pass until it goes into next pass.
              • -
              -
              -

              Task

              -

              A task is a data shard to be trained. The total number of tasks will be much bigger than the total number of trainers. The number of data instances inside a task will be much bigger than the mini-batch size.

              -
              -
              -

              Task Queue

              -

              The master server has three task queues to track training progress. As illustrated in the graph below, Job A and Job B both have one master server. Each master server process has three task queues.

              -

              -
                -
              • The todo queue holds tasks to be dispatched. When a job starts, the master server fills in the todo queue with all tasks.
              • -
              • The pending queue holds tasks that are currently training by trainers.
              • -
              • the done queue holds tasks that are already trained.
              • -
              -

              The life cycle of a single task is illustrated below:

              -

              -
                -
              1. When a new pass of training starts, all tasks will be placed in the todo queue.
              2. -
              3. Upon trainer requests for new task, the master server will dispatch a task from todo queue to it, put the task in the pending queue and wait for completion.
              4. -
              5. The trainer will work on its task and tell the master server once the task is completed and ask for new task. The master server will dispatch a new task to that trainer.
              6. -
              7. If a task fails for any reason in trainer, or takes longer than a specific period of time, the master server will move the task back to the todo queue. The timeout count for that task will increase by one. If the timeout count is above a threshold, the task is likely to cause a trainer to crash, then it will be discarded.
              8. -
              9. The master server will move completed task to the done queue. When the todo queue is empty, the master server will start a new pass by moving all tasks in the done queue to todo queue and reset the timeout counter of all tasks to zero.
              10. -
              -
              -
              -
              -

              Trainer Process

              -

              The trainer process will:

              -
                -
              • Request tasks from the master.
              • -
              • Work on the tasks
              • -
              • Upload gradient to parameter servers, and update local model by downloading new parameters from parameter servers.
              • -
              -
              -
              -

              Parameter Server Process

              -

              Parameter server processes hold the parameters collaboratively. The parameters are partitioned on different parameter servers.

              -

              The parameter server will:

              -
                -
              • Receive gradient from the trainers, update its parameters, and give the trainers the latest parameters.
              • -
              • Periodically save its parameters to distributed file system by overriding the previous save.
              • -
              -
              -
              -

              Optimization Algorithms

              -

              The communication pattern between the trainers and the parameter servers depends on the category of optimization algorithm:

              -
                -
              • Synchronous Stochastic Gradient Descent (sync-SGD)

                -

                Parameter server will wait for all trainer finish n-th mini-batch calculation and send their gradients before broadcasting new parameters to every trainer. Every trainer will wait for the new parameters before starting n+1-th mini-batch.

                -
              • -
              • Asynchronous Stochastic Gradient Descent (async-SGD)

                -

                There will no synchronization between different trainers, and parameter server updates its parameter as soon as it receives new gradient:

                -
                  -
                • Each trainer uploads its accumulated gradient every n mini-batches.
                • -
                • Every m mini-batches, the trainer downloads new parameters from parameter server.
                • -
                • n and m do not have to be equal.
                • -
                -
              • -
              -
              -
              -
              -

              Fault Tolerant

              -

              The training job will pause if the master server processes is dead, or any of the parameter server process is dead. They will be started by Kubernetes and recover in few minutes. Please refer to fault recovery.

              -

              The training job will continue to make progress if there is at least one training process running. The strategy depends on the type of optimization algorithm:

              -
                -
              • sync-SGD

                -

                TODO

                -
              • -
              • async-SGD

                -

                Since async-SGD does not require synchronization between mini-batches, the system will by definition make process if at least one trainer is running.

                -
              • -
              -
              -
              -

              Fault Recovery

              -

              PaddlePaddle uses etcd to keep track of the states of processes. Because etcd is a distributed reliable key-value store, the restarted process can recover its states from etcd. The model parameters are periodically saved into distributed file system, so a restarted parameter server can recover its parameters from the saved file.

              -

              Now we will introduce how each process recovers from a failure, the graph below shows how etcd is used:

              -

              -
              -

              Master Server Process

              -

              When the master is started by the Kubernetes, it executes the following steps at startup:

              -
                -
              1. Grabs a unique master lock in etcd, which prevents concurrent master instantiations.
              2. -
              3. Recovers the task queues from etcd if they already exist, otherwise, the master will create them.
              4. -
              5. Write its ip address to /master/addr so that trainers can discover it.
              6. -
              7. Listens to trainers’ request of task, dispatch one upon request, and updates task queue using an etcd transaction to ensure lock is held during the update.
              8. -
              -

              When the master server process is dead for any reason, Kubernetes will restart it. It will be online again with all states recovered from etcd in few minutes.

              -
              -
              -

              Trainer Process

              -

              When the trainer is started by the Kubernetes, it executes the following steps at startup:

              -
                -
              1. Watches the available parameter server prefix keys /ps/ on etcd and waits until the count of parameter servers reaches the desired count /ps_desired.
              2. -
              3. Finds and watches /master/addr to get master’s address.
              4. -
              5. Requests for tasks from the master to start training.
              6. -
              -

              When a trainer fails, Kuberentes would try to restart it. The recovered trainer would fetch tasks from master and go on training.

              -
              -
              -

              Parameter Server Process

              -

              When the parameter server is started by Kubernetes, it executes the following steps at startup:

              -
                -
              1. Read desired total number of parameter servers from etcd /ps_desired

                -
              2. -
              3. Search through etcd keys /ps/<index> (/ps/0, /ps/1, ...) to find the first non-existant key whose index is smaller than the total number of parameter servers. Set the key using a transaction to avoid concurrent writes. The parameter server’s index is inferred from the key name.

                -

                The desired number of parameter servers is 3:

                -

                -

                The third parameter server joined:

                -

                -
              4. -
              5. The parameter server can load parameters if there are already saved parameters in the save path (inferred from its index).

                -
              6. -
              7. Now the parameter server is ready for the trainers’ requests.

                -
              8. -
              -

              If the parameter server’s etcd lease expires, the parameter server will kill itself.

              -
              -
              -
              -

              Parameter Server Checkpointing

              -

              See here

              -
              -
              -

              Store and dispatching trainning data

              -

              See here

              -
              -
              -

              Dynamic Scaling

              -
              -

              Trainer Scaling

              -

              TODO

              -
              -
              -

              Parameter Server Scaling

              -

              Not planned for v1.

              -
              -
              -
              -

              Training Dataset Format

              -

              TODO

              -
              -
              -

              User Interface

              -

              TODO

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/cluster_train/checkpointing.html b/develop/doc/design/cluster_train/checkpointing.html deleted file mode 100644 index 78bf1a684e6..00000000000 --- a/develop/doc/design/cluster_train/checkpointing.html +++ /dev/null @@ -1,305 +0,0 @@ - - - - - - - - - - - - - 模型参数检查点(Checkpointing) — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              模型参数检查点(Checkpointing)

              -

              模型数据检查点的实现,可以有效的避免parameter server的单点或多点同时故障。模型参数检查点通过定期向磁盘上保存一份存储在parameter server内存中的模型数据的完整镜像,来保证训练过程可以从中间状态重新启动。在一个不可中断并缺少备份的训练任务中,可以通过阶段性的保存每个parameter server的数据快照(snapshot)到 分布式存储服务 达到容灾的目的,比如每隔10分钟最新的快照,并删除更早的快照。在出现单点故障时,只需要恢复这台节点,或者将这台节点迁移到另一个节点并启动即可恢复训练任务。

              -

              -
              -

              快照保存的设计如下:

              -

              说明:

              -
                -
              • parameter server在集群中启动后,自动挂载分布式存储目录,并把快照保存到这个目录下。
              • -
              • 注:每个parameter server的检查点各自独立保存,暂时不考虑多个parameter server同步的保存一个特定时间点的全局检查点,因为这样做也没法保证消除随机性。
              • -
              -

              检查点保存程序流程:

              -
                -
              1. 如果满足条件”每隔10分钟”时,parameter server会获取parameters内存的read_lock,启动一个新的线程开始保存检查点。如果已经正在执行保存检查点的线程,则忽略。由于对parameters的更新需要获取parameters内存的write_lock,所以在写入快照的过程中,parameter server会暂停参数更新并等待。
              2. -
              3. parameter server生成一个UUID,向指定的目录中一个新的文件(文件名为此UUID)写入快照数据。在快照写入完成后,计算这个文件的MD5 sum。然后在etcd的/checkpoints/[pserver_id]中写入json内容:{"uuid": [UUID], "md5", "MD5 sum", "timestamp": xxxx}
              4. -
              5. 删除磁盘目录中不是当前uuid的快照文件。
              6. -
              7. 释放对paramters内存的锁定,停止保存检查点的线程。
              8. -
              -

              这里需要用户额外注意,在您的实际环境中,训练任务的运行可能会占满trainer和parameter server之间的网络带宽,如果parameter server此时还需要通过网络访问分布式存储以保存快照,可能会造成网络拥塞,而出现阶段性的运行停滞。

              -
              -
              -

              从快照恢复

              -

              在parameter server第一次启动或任意时间parameter server故障后被Kubernetes重新启动,则需要回滚到上一个检查点:

              -
                -
              1. 从etcd中读取节点:/checkpoints/[pserver_id]获取最新的检查点的文件uuid
              2. -
              3. 从磁盘文件中加载uuid文件名的检查点快照文件,并加载其中的参数
              4. -
              5. 如果上面两步出现错误,则使用启动参数定义的初始化方法初始化参数
              6. -
              7. 开始提供服务
              8. -
              -
              -
              -
              -

              TODO List

              -
              -

              推测执行/加速执行(TODO)

              -

              在异构集群中,如果存在某些trainer执行速度过慢会影响整体集群的速度(如图中Trainer 1),此时master将负责启动一个新的Trainer(Accelerate Trainer 2),使用同样的训练数据block。哪个trainer先完成block的训练,则把另一个慢速的kill掉。

              -
              -
              -

              动态扩容/缩容

              -

              目前只考虑动态扩容trainer数量,可以减小系统复杂性。

              -
              -
              -
              -

              术语

              -
                -
              • model: 指深度学习训练之后得到的所有参数,使用这个神经网络可以完成对新数据的预测
              • -
              • parameters: 神经网络中的参数,包括权重w和偏置b。一个神经网络的模型由大量的参数组成
              • -
              • shard: 分片,通常指将一个整体拆分成多份的其中的一份。
              • -
              • model shard: 将一个神经网络参数拆分成多份,每个shard分别存储在其中一台parameter server之上
              • -
              • parameter block: 多个parameter block构成一个model shard
              • -
              • 单点故障: 任意时刻只可能同时有一台服务器故障。由于集群中同时存在两台机器故障的概率极低((平均故障率*平均故障修复时间)^2)只对特殊在线系统考虑两台以上同时故障的容灾。
              • -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/cluster_train/data_dispatch.html b/develop/doc/design/cluster_train/data_dispatch.html deleted file mode 100644 index 506a37824ff..00000000000 --- a/develop/doc/design/cluster_train/data_dispatch.html +++ /dev/null @@ -1,406 +0,0 @@ - - - - - - - - - - - - - 训练数据的存储和分发 — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              训练数据的存储和分发

              -
              -

              概念解释

              -
              -
              -

              流程介绍

              -

              生产环境中的训练数据集通常体积很大,并被存储在诸如Hadoop HDFS,Ceph,AWS S3之类的分布式存储之上。这些分布式存储服务通常会把数据切割成多个分片分布式的存储在多个节点之上。这样就可以在云端执行多种数据类计算任务,包括:

              -
                -
              • 数据预处理任务
              • -
              • Paddle训练任务
              • -
              • 在线模型预测服务
              • -
              -
              - -

              在上图中显示了在一个实际生产环境中的应用(人脸识别)的数据流图。生产环境的日志数据会通过实时流的方式(Kafka)和离线数据的方式(HDFS)存储,并在集群中运行多个分布式数据处理任务,比如流式数据处理(online data process),离线批处理(offline data process)完成数据的预处理,提供给paddle作为训练数据。用户也可以上传labeled data到分布式存储补充训练数据。在paddle之上运行的深度学习训练输出的模型会提供给在线人脸识别的应用使用。

              -
              -
              -

              训练数据存储

              -

              我们选择CephFS作为存储系统。

              -
                -
              • 无论是从PFSClient的角度,还是从Pod中运行任务的角度,统一用/pfs/$DATACENTER/home/$USER来访问用户自己的数据。
              • -
              • /pfs/$DATACENTER/common下存放公共数据集合
                  -
                • 做只读挂载
                • -
                -
              • -
              -
              - -
              -
              -

              文件预处理

              -

              在开始训练之前, 数据集需要预先被转换成PaddlePaddle分布式训练使用的存储格RecordIO。我们提供两个转换方式:

              -
                -
              1. 用户在本地转换好再上传
              2. -
              3. 用户上传数据后,在机群上运行转换程序
              4. -
              -

              转换生成的文件名会是以下格式:

              -
              name_prefix-aaaaa-of-bbbbb
              -
              -
              -

              “aaaaa”和”bbbbb”都是五位的数字,每一个文件是数据集的一个shard,”aaaaa”代表shard的index,”bbbbb”代表这个shard的最大index。

              -

              比如ImageNet这个数据集可能被分成1000个shard,它们的文件名是:

              -
              imagenet-00000-of-00999
              -imagenet-00001-of-00999
              -...
              -imagenet-00999-of-00999
              -
              -
              -
              -

              转换库

              -

              无论是在本地或是云端转换,我们都提供Python的转换库,接口是:

              -
              def convert(output_path, reader, num_shards, name_prefix)
              -
              -
              -
                -
              • output_path: directory in which output files will be saved.
              • -
              • reader: a data reader, from which the convert program will read data instances.
              • -
              • num_shards: the number of shards that the dataset will be partitioned into.
              • -
              • name_prefix: the name prefix of generated files.
              • -
              -

              reader每次输出一个data instance,这个instance可以是单个值,或者用tuple表示的多个值:

              -
              yield 1 # 单个值
              -yield numpy.random.uniform(-1, 1, size=28*28) # 单个值
              -yield numpy.random.uniform(-1, 1, size=28*28), 0 # 多个值
              -
              -
              -

              每个值的类型可以是整形、浮点型数据、字符串,或者由它们组成的list,以及numpy.ndarray。如果是其它类型,会被Pickle序列化成字符串。

              -
              -
              -
              -

              示例程序

              -
              -

              使用转换库

              -

              以下reader_creator生成的reader每次输出一个data instance,每个data instance包涵两个值:numpy.ndarray类型的值和整型的值:

              -
              def reader_creator():
              -    def reader():
              -        for i in range(1000):
              -            yield numpy.random.uniform(-1, 1, size=28*28), 0 # 多个值
              -    return reader
              -
              -
              -

              reader_creator生成的reader传入convert函数即可完成转换:

              -
              convert("./", reader_creator(), 100, random_images)
              -
              -
              -

              以上命令会在当前目录下生成100个文件:

              -
              random_images-00000-of-00099
              -random_images-00001-of-00099
              -...
              -random_images-00099-of-00099
              -
              -
              -
              -
              -

              进行训练

              -

              PaddlePaddle提供专用的data reader creator,生成给定RecordIO文件对应的data reader。无论在本地还是在云端,reader的使用方式都是一致的

              -
              # ...
              -reader = paddle.reader.creator.RecordIO("/pfs/datacenter_name/home/user_name/random_images-*-of-*")
              -batch_reader = paddle.batch(paddle.dataset.mnist.train(), 128)
              -trainer.train(batch_reader, ...)
              -
              -
              -

              以上代码的reader输出的data instance与生成数据集时,reader输出的data instance是一模一样的。

              -
              -
              -
              -

              上传训练文件

              -

              使用下面命令,可以把本地的数据上传到存储集群中。

              -
              paddle pfs cp filename /pfs/$DATACENTER/home/$USER/folder/
              -
              -
              -

              比如,把之前示例中转换完毕的random_images数据集上传到云端的/home/可以用以下指令:

              -
              paddle pfs cp random_images-*-of-* /pfs/$DATACENTER/home/$USER/folder/
              -
              -
              -

              需要$DATACENTER的配置写到配置文件中,例如

              -
              # config file
              -[datacenter_1]
              -username=user
              -usercert=user.pem
              -userkey=user-key.pem
              -endpoint=datacenter1.paddlepaddle.org
              -
              -[datacenter_2]
              -username=user
              -usercert=user.pem
              -userkey=user-key.pem
              -endpoint=datacenter2.paddlepaddle.org
              -
              -
              -
              -
              -
              -

              TODO

              -
              -

              文件访问的权限

              -

              控制用户权限

              -
                -
              • 用户可以把自己的数据分享给别人
              • -
              -
              -
              -

              文件访问方式

              -

              不用mount的方式来访问数据,而是直接用API的接口远程访问

              -

              例如:

              -
              f = open('/pfs/datacenter_name/home/user_name/test1.dat')
              -
              -
              -
              -
              -

              支持用户自定义的数据预处理job

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/cluster_train/large_model_dist_train.html b/develop/doc/design/cluster_train/large_model_dist_train.html deleted file mode 100644 index 9d46d073ee2..00000000000 --- a/develop/doc/design/cluster_train/large_model_dist_train.html +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - - - - - - - Alalysis of large model distributed training in Paddle — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Alalysis of large model distributed training in Paddle

              -

              NOTE: This is only some note for how we implemeted this scheme in V1, not a new design.

              -
              -

              What is it

              -

              We often encounter cases that the embedding layer parameters(sparse) are so large that we can not store it in the trainer’s memory when training. So we need to put them to several servers, and fetch them row by row instead of fetch all of the parameters.

              -
              -
              -

              How to use

              -

              Specify command-line argument like --loadsave_parameters_in_pserver=true --ports_num_for_sparse=1 --use_old_updater=1 when starting the paddle trainer. And also add something like --ports_num_for_sparse=1 --pserver_num_threads=5 when starting pserver processes.

              -

              Accrodingly, configure your embedding layers like:

              -
              SPARSE_REMOTE=True
              -
              -w1 = data_layer(name="w1", size=dict_size)
              -emb1 = embedding_layer(input=w1, size=32, param_attr=ParameterAttribute(sparse_update=SPARSE_REMOTE))
              -w2 = data_layer(name="w2", size=dict_size)
              -emb2 = embedding_layer(input=w2, size=32, param_attr=ParameterAttribute(sparse_update=SPARSE_REMOTE))
              -...
              -
              -
              -
              -
              -

              Implementation details

              -
              enum MatType {
              -  MAT_NORMAL,
              -  MAT_NORMAL_SHARED,
              -  MAT_VALUE_SHARED,
              -  MAT_SPARSE_ROW_IDS,
              -  MAT_SPARSE_ROW_AUTO_GROW,
              -  MAT_CACHE_ROW,
              -  MAT_SPARSE_ROW,
              -  MAT_SPARSE_ROW_PREFETCH,
              -  MAT_SPARSE_ROW_PREFETCH_FULL_SIZE,
              -};
              -
              -
              -

              MAT_SPARSE_ROW_PREFETCH is what we use when configured to fetch only row of matrix when training.

              -

              In trainer_internal.cpp:L93 trainOneBatch:

              -
                if (config_->getOptConfig().use_sparse_remote_updater()) {
              -    REGISTER_TIMER("prefetch");
              -    gradientMachine_->prefetch(inArgs);
              -    parameterUpdater_->getParametersRemote();
              -  }
              -
              -
              -

              When doing actual network forward and backward, at the beginning of each batch, the trainer will try to download one row of data from pserver.

              -

              In trainer/RemoteParameterUpdater.cpp: parameterUpdater_->getParametersRemote();:

              -
              if (fullSize) {
              -    ...
              -} else {
              -getParams = [&] {
              -    parameterClient_->getParameterSparse(
              -        /* recvParameterType= */ PARAMETER_VALUE, sendBackParameterType);
              -};
              -applyL1 = [](Parameter& para, real decayRate) {
              -    para.getMat(PARAMETER_VALUE)->applyL1(/*lr=*/1.0f, decayRate);
              -};
              -}
              -
              -
              -

              Calling parameterClient_->getParameterSparse will do remote call to pserver’s getParameterSparse:

              -
              void ParameterServer2::getParameterSparse(const SendParameterRequest& request,
              -                                          std::vector<Buffer>& inputBuffers,
              -                                          SendParameterResponse* response,
              -                                          std::vector<Buffer>* outputBuffers) {
              -  (void)inputBuffers;
              -  auto& buffer = *readWriteBuffer_;
              -  size_t numReals = 0;
              -  for (const auto& block : request.blocks()) {
              -    numReals += getParameterConfig(block).dims(1);
              -  }
              -  buffer.resize(numReals);
              -
              -  VLOG(3) << "pserver: getParameterSparse, numReals=" << numReals;
              -
              -  ReadLockGuard guard(parameterMutex_);
              -  size_t offset = 0;
              -  for (const auto& block : request.blocks()) {
              -    size_t width = getParameterConfig(block).dims(1);
              -    Buffer buf = {buffer.data() + offset, width};
              -    int type = request.send_back_parameter_type();
              -    sendBackParameterSparse(block, type, response, &buf, width, outputBuffers);
              -    offset += width;
              -  }
              -}
              -
              -
              -

              getParameterConfig(block).dims(1) returns the width of the current “parameter block”(a shard of parameter object), -then getParameterSparse remote call returns only one row of data to the client.

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/cluster_train/master_server.html b/develop/doc/design/cluster_train/master_server.html deleted file mode 100644 index bdf41d457bb..00000000000 --- a/develop/doc/design/cluster_train/master_server.html +++ /dev/null @@ -1,341 +0,0 @@ - - - - - - - - - - - - - Design Doc: Master Server — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Master Server

              -

              For an overview of master server’s role, please refer to distributed training design doc. In this design doc we will discuss the master server in more details. The master will be implemented in Go.

              -
              -

              Dataset

              -

              -

              A dataset is a list of files in RecordIO format. A RecordIO file consists of chunks, whereas each chunk consists some records.

              -
              -
              -

              Task Queue

              -

              As mentioned in distributed training design doc, a task is a data shard that the master server assigns to the trainer process to train on. A task consists of one or multiple chunks from one or multiple files. The master server maintains task queues to track the training progress.

              -
              -

              Task Queue Creation

              -
                -
              1. Each trainer will make an RPC call (using Go’s rpc package) to the master server, telling it the RecordIO files representing the dataset specified by the user. Since every trainer will tell the master server the same dataset, only the first RPC call will be honored.

                -

                The RPC interface is:

                -
                func (m *RPCServer) ReportDataset(Paths []string, dummy *int) error {
                -}
                -
                -
                -
              2. -
              3. The master server will scan through each RecordIO file to generate the chunk index and know how many chunks does each file have. A chunk can be referenced by the file path and the index of the chunk within the file. The chunk index is in memory data structure that enables fast access to each chunk, and the index of the chunk with the file is an integer start from 0, representing the n-th chunk within the file.

                -

                The definition of the chunk is:

                -
                type Chunk struct {
                -    Idx   int // index of the chunk within the file
                -    Path  string
                -    Index recordio.Index // chunk index
                -}
                -
                -
                -
              4. -
              5. Chunks are grouped into tasks, and tasks are filled into the todo queue. The pending queue and the done queue are initialized with no element.

                -

                The definition of the task is:

                -
                type Task struct {
                -    Index  int
                -    Chunks []Chunk
                -}
                -
                -
                -

                The elements in the tasks queues is of type TaskEntry, containing a timeout counter (described in task retry logic), and a task:

                -
                type TaskEntry struct {
                -    NumTimeout int
                -    Task       Task
                -}
                -
                -
                -

                The definition of task queues is:

                -
                type TaskQueues struct {
                -    Todo    []TaskEntry
                -    Pending map[int]TaskEntry // map from task index to task entry
                -    Done    []TaskEntry
                -}
                -
                -
                -
              6. -
              -
              -
              -

              Task Queue Persistence

              -

              The task queues need to be persisted on etcd for fault recovery. Since the task queues only change once a task is completed or timed out, which is not very frequent, we can afford to synchronize with etcd every time the task queues change.

              -

              We will serialize the task queues data structure with gob encoding, compress with gzip, and save into etcd synchronously under key /task_queues.

              -
              -
              -

              Task Dispatch

              -

              The trainer will make an RPC call to master to get a new task when:

              -
                -
              • the trainer first started, or
              • -
              • the trainer finishes a task.
              • -
              -

              The RPC interface is:

              -
              func (m *RPCServer) GetTask(finished *Task, result *Task) error {
              -}
              -
              -
              -

              Argument finished will be nil when the trainer is just started.

              -

              During the RPC call the master will do the following:

              -
                -
              • Make a copy of the task queues, and update the copy reflecting the finished tasks and the new pending tasks.
              • -
              • Synchronize the copy of task queues with etcd using a transaction conditioned on holding the master lock.
              • -
              • Replace the task queues with the copy and report to the trainer with the new tasks if succeeded, or discard the copy and report the error to the trainer if failed.
              • -
              -
              -
              -

              Task Retry Logic

              -

              When a task is dispatched to the trainer, the master will schedule a function for execution after the timeout duration (based on the moving average of task completion time). If the task entry in still in the pending queue, its timeout counter will increase by one, and the task will be moved to todo queue. If the timeout counter is above the threshold, the master will log the error and discard the task.

              -

              Please note that since a timed out task could be completed after it has been dispatched for retry, so it is possible for a task to be processed multiple times. We do not try to prevent it from happening since it’s fine to train on the same task multiple times due to the stochastic nature of the stochastic gradient decent algorithm.

              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/cluster_train/pserver_client.html b/develop/doc/design/cluster_train/pserver_client.html deleted file mode 100644 index 4cd70aed90f..00000000000 --- a/develop/doc/design/cluster_train/pserver_client.html +++ /dev/null @@ -1,418 +0,0 @@ - - - - - - - - - - - - - Design Doc: The Client Library of Parameter Server — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: The Client Library of Parameter Server

              -

              For an overview of trainer’s role, please refer to distributed training design doc. In this design doc, we will discuss the parameter server’s client library, which will manage communication with parameter servers. The library will be implemented in Go and made available as a static or dynamic library with a C header file.

              -
              -

              Parameter Partition

              -

              Each parameter will be partitioned into parameter blocks to make the parameters evenly distributed on parameter servers. The partition is done automatically by the client library. The sparse parameter require a little different treatment:

              -
              -

              Sparse Parameter

              -

              The sparse parameter is a parameter that is updated sparsely. The name is somewhat misleading, it does not have a sparse representation, it has the same representation as a dense vector.

              -

              Because a sparse parameter is updated sparsely, the trainer will have to partition the sparse parameter. Because the parameter server will merge all sparse parameter shard into the same file when saving the parameter. It needs special naming convention:

              -

              If a sparse parameter is partitioned into n shards, they should be named as:

              -
              name:sparse-0
              -name:sparse-1
              -...
              -name:sparse-n-1
              -
              -
              -

              The library is unaware of the partition, and treat each parameter independently. Only when saving parameters, the parameter servers will merge the sparse parameters according to the naming convention.

              -
              -
              -
              -

              Model Optimization Using Gradients

              -

              There are two ways to perform model optimization using gradients:

              -
                -
              • On Client

                -

                The client does multiple steps of forward and backward update. In each step, the gradients are calculated and a new model is generated. After some steps, the client will calculate the difference between the newest model and the old model at step 0. The difference will be updated to parameter servers. Parameter servers will just update parameters using the difference without any optimization using gradients (such as Adam and L1 regularization).

                -
              • -
              • On Parameter Server

                -

                The client will send accumulated gradients to parameter servers, the parameter server will do the optimization using gradients.

                -
              • -
              -
              -
              -

              L1 and L2 Regularization

              -

              PaddlePaddle allows L1 or L2 regularizations to be specified per parameter, so when the trainer initializes the parameter it needs include a parameter configuration when L1 or L2 regularization is necessary.

              -
              -
              -

              Parameter Initialization

              -

              The parameters on parameter servers need to be initialized. To provide maximum flexibility, the trainer will initialize the parameters. Only one trainer will do the initialization, the other trainers will wait for the completion of initialization and get the parameters from the parameter servers.

              -
              -

              Trainer Selection

              -

              To select the trainer for initialization, every trainer will try to get a distributed lock, whoever owns the lock will do the initialization. As illustrated below:

              -

              -
              -
              -

              Trainer Selection Process

              -

              The trainer select process is encapsulated in the C API function:

              -
              int paddle_begin_init_params(paddle_pserver_client* client, const char* config_proto);
              -
              -
              -

              The selected trainer’s call to paddle_begin_init_params will return with 1, and the other trainers’ call to paddle_begin_init_params will return 0. paddle_get_params will be blocked until initialization is completed. As illustrated below:

              -

              -
              -
              -
              -

              C Interface

              -
              typedef enum {
              -  PADDLE_ELEMENT_TYPE_INT32   = 0,
              -  PADDLE_ELEMENT_TYPE_UINT32  = 1,
              -  PADDLE_ELEMENT_TYPE_INT64   = 2,
              -  PADDLE_ELEMENT_TYPE_UINT64  = 3,
              -  PADDLE_ELEMENT_TYPE_FLOAT32 = 4,
              -  PADDLE_ELEMENT_TYPE_FLOAT64 = 5,
              -} paddle_element_type;
              -
              -typedef struct {
              -  char*               name;
              -  paddle_element_type element_type;
              -  unsigned char*      content;
              -  int                 content_len;
              -} paddle_parameter, paddle_gradient;
              -
              -typedef int paddle_pserver_client;
              -
              -/**
              - * @brief creates a pserver client that talks to etcd for coordination.
              - */
              -paddle_pserver_client paddle_new_etcd_pserver_client(char* etcd_addr);
              -
              -/**
              - * @brief creates a pserver client given pserver addresses.
              - *
              - * @param pserver_addrs comma-separated pserver addresses.
              - * @param selected if current pserver client is selected to initialize all parameter servers.
              - */
              -paddle_pserver_client paddle_new_pserver_client(char* pserver_addrs, int selected);
              -void paddle_pserver_client_release(paddle_pserver_client c);
              -
              -/**
              - * @brief paddle_begin_init_params begins to initialize parameters on
              - * parameter servers.
              - *
              - * paddle_begin_init_params will be called from multiple trainers,
              - * only one trainer will be selected to initialize the parameters on
              - * parameter servers. Other trainers need to get the initialized
              - * parameters from parameter servers using @paddle_get_params.
              - *
              - * @return 1 if the trainer is selected to initialize parameter
              - * servers, otherwise 0.
              - */
              -int paddle_begin_init_params(paddle_pserver_client client);
              -
              -/**
              - * @brief paddle_init_param initializes the parameter on parameter
              - * servers.
              - *
              - * @param param the parameter to initialize.
              - * @param param_config_proto the configuration for the parameter.
              - * @param config_len the length of param_config_proto
              - * @return 0 if successful, otherwise -1. On failure, the trainer
              - * needs to restart the entire initialization process (starting from
              - * @paddle_begin_init_param). Or simply exit the program and wait for
              - * the cluster management system to restart the trainer.
              - */
              -int paddle_init_param(paddle_pserver_client client, paddle_parameter param, const unsigned char* param_config_proto, int config_len);
              -
              -/**
              - * @brief paddle_finish_init_params tells parameter servers client has
              - * sent all parameters to parameter servers as initialization.
              - *
              - * @return 0 if successful, otherwise -1. On failure, the trainer
              - * needs to restart the entire initialization process (starting from
              - * @paddle_begin_init_param). Or simply exit the program and wait for
              - * the cluster management system to restart the trainer.
              - */
              -int paddle_finish_init_params(paddle_pserver_client client);
              -
              -/**
              - * @brief paddle_send_grads sends gradients to parameter servers for
              - * updating parameters.
              - *
              - * @param grads the array of gradients to send.
              - * @param len the length of the gradient array.
              - * @param learning_rate the learning rate for the gradients.
              - * @return 0 if successful, otherwise -1.
              - */
              -int paddle_send_grads(paddle_pserver_client client, const paddle_gradient* grads, int len);
              -
              -/**
              - * @brief paddle_get_params gets parameters from parameter servers.
              - *
              - * paddle_get_params will block until parameters are initialized on
              - * the parameter servers.
              - *
              - * @param dst the destination array of parameter pointers to save to.
              - * The parameter pointer must be pre-popullated with required parameter name,
              - * and the content of parameter must be pre-allocated of the size of required
              - * parameter on pserver.
              - * @param len the length of the names array and the paddle_parameter
              - * array.
              - * @return 0 if successful, otherwise -1.
              - */
              -int paddle_get_params(paddle_pserver_client client, paddle_parameter** dst, int len);
              -
              -/**
              - * @brief paddle_save_model indicates parameters to save the parameter
              - * to the given path
              - *
              - * @param path the path to save parameters.
              - * @return 0 if successful, otherwise -1.
              - */
              -int paddle_save_model(paddle_pserver_client client, const char* path);
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/cluster_train/remote_parameter_updater.html b/develop/doc/design/cluster_train/remote_parameter_updater.html deleted file mode 100644 index b993733790a..00000000000 --- a/develop/doc/design/cluster_train/remote_parameter_updater.html +++ /dev/null @@ -1,273 +0,0 @@ - - - - - - - - - - - - - Design Doc: Remote Parameter Updater for Cluster Train — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Remote Parameter Updater for Cluster Train

              -

              For an overview of distribute training, please refer to distributed training design doc. In this design doc, we will discuss the parameter updater that will use parameter server cclient The Client Library of Parameter Server Design Doc to manage and update parameters.

              -
              -

              Parameter Updater

              -

              Parameter Updater is used by trainer to manage and update parameter, there are mainly two kind of parameter updater: local and remote, since this design is for cluster train, we will only discuss remote parameter updater here.

              -
              -

              Remote Parameter Updater

              -

              Remote Parameter Updater manage parameters through remote parameter server with the client that communicate with pserver(The Client Library of Parameter Server Design Doc)

              -

              In PaddlePaddle Python V2 API, trainer is implemented in python, and the trainer will hold a instance of parameter updater and call it’s functions directly. In this design, we will also expose the api of RemoteParameterUpdater to python with swig.

              -
              -

              Sparse Remote Parameter Updater

              -

              Since we will only implement dense parameter management new, the mechanism for sparse parameter will be discussed in next stage.

              -
              -
              -
              -

              Interface Design

              -

              TBD

              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/cluster_train/save_model.html b/develop/doc/design/cluster_train/save_model.html deleted file mode 100644 index 92e58966fe7..00000000000 --- a/develop/doc/design/cluster_train/save_model.html +++ /dev/null @@ -1,360 +0,0 @@ - - - - - - - - - - - - - Design Doc: Save Model — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Save Model

              -
              -

              Overview

              -

              The model is the output of the training process. There are two -ways from which user can obtain a model:

              -
                -
              • Save model triggered by user code: user code asks PaddlePaddle to -save a model.
              • -
              • Convert model from the checkpoint: model being converted from -pservers’ periodic checkpoint. In this way, the user can cancel a -job at any time, and still have a relatively fresh model (we -checkpoint around every 5 minutes).
              • -
              -
              -

              Trainer Saving Model vs. Pservers Saving Model

              -

              Both trainers and pservers have access to the model. So the model can -be saved from a trainer or pservers. We need to decide where the model -is saved from.

              -
              -

              Dense Update vs. Sparse Update

              -

              There are two types of model update methods: dense update and sparse -update (when the model parameter is configured to be sparse).

              -
                -
              • Dense update

                -

                Every trainer has it’s own full copy of the model. Every model -update will update the entire model.

                -
              • -
              • Sparse update

                -

                The training input is sparse, and the trainer does not have the -entire model. It will only download the sub-model necessary related -to the input. When updating the model, only the sub-model related to -the training input is updated.

                -
              • -
              -
              -
              -

              Pservers Saving Model

              -

              The benefit of letting pservers save model is they have the entire -model all the time. However, since pservers are on different nodes, it -requires a merging process to merge model shards into the same -model. Thus requires the pservers to write models to a distributed -filesystem, making the checkpoint shards visible to the merge program.

              -
              -
              -

              Trainer Saving Model

              -

              The benefit of letting one trainer to save the model is it does not -require a distributed filesystem. And it’s reusing the same save model -logic when training locally - except when doing sparse update, the -trainer needs to download the entire model during the saving process.

              -
              -
              -

              Conclusion

              -

              Given trainer saving model does not require a distributed filesystem, -and is an intuitive extension to trainer saving model when training -locally, we decide to let the trainer save the model when doing -distributed training.

              -
              -
              -
              -

              Convert Model from Checkpoint

              -

              TODO

              -
              -
              -
              -

              Timeline

              -

              We first implement trainer save the model. Converting the latest -snapshot to a model will be a TODO for future.

              -
              -
              -

              Trainer Save Model

              -
              -

              Trainer Election

              -

              One trainer will be elected as the one to save the model. When using -etcd, trainer ID is a randomly generated UUID, the trainer will -contact the master server requesting to save the model, and find out -if itself is elected. When the master server is not used, unique -trainer IDs will be given by the administrator, the trainer whose ID -is “0” is elected to save the model.

              -
              -
              -

              Model Save Path

              -

              Each trainer will be given the directory to save the model. The -elected trainer will save the model to -given-directory/trainerID. Since the trainer ID is unique, this -would prevent concurrent save to the same file when multiple trainers -are elected to save the model when split-brain problem happens.

              -
              -
              -

              What Happens When Model Is Saving

              -

              It takes some time to save model, we need to define what will happen -when save model is taking place.

              -

              When doing dense update, the trainer uses the local model. Pservers -does not need to pause model update.

              -

              When doing sparse update. The trainer needs to download the entire -model while saving. To get the most accurate model, the model update -needs to be paused before the download starts and resumed after the -download finishes. Otherwise, the trainer gets a model that is -“polluted”: some part of the model is old, some part of the model is -new.

              -

              It’s unclear that the “polluted” model will be inferior due to the -stochastic nature of deep learning, and pausing the model update will -add more complexity to the system. Since supporting sparse update is a -TODO item. We defer the evaluation of pause the model update or not -during saving model to the future.

              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/cluster_train/submit-job.html b/develop/doc/design/cluster_train/submit-job.html deleted file mode 100644 index 1a85ff027df..00000000000 --- a/develop/doc/design/cluster_train/submit-job.html +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - - - - - - - Submit a Distributed Training Job — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Submit a Distributed Training Job

              -

              The user can submit a distributed training job with Python code, rather than with a command-line interface.

              -
              -

              Runtime Environment On Kubernetes

              -

              For a distributed training job, there is two Docker image called runtime Docker image and base Docker image. The runtime Docker image is the Docker image that gets scheduled by Kubernetes to run during training. The base Docker image is for building the runtime Docker image.

              -
              -

              Base Docker Image

              -

              Usually, the base Docker image is PaddlePaddle product Docker image including paddle binary files and python package. And of course, users can specify any image name hosted on any docker registry which users have the access right.

              -
              -
              -

              Runtime Docker Image

              -

              The trainer package which user upload and some Python dependencies are packaged into a runtime Docker image based on base Docker image.

              -
                -
              • Handle Python Dependencies

                -

                You need to provide requirements.txt file in your trainer-package folder. Example:

                -
                pillow
                -protobuf==3.1.0
                -
                -
                -

                More details about requirements, an example project looks like:

                -
                  paddle_example
                -    |-quick_start
                -      |-trainer.py
                -      |-dataset.py
                -      |-requirements.txt
                -
                -
                -
              • -
              -
              -
              -
              -

              Submit Distributed Training Job With Python Code

              -

              -
                -
              • paddle.job.dist_train() will call the Job Server API /v1/packages to upload the trainer package and save them on CephFS, and then call /v1/trainer/job to submit the PaddlePaddle distributed job.
              • -
              • /v1/trainer/job will start a building job for preparing the runtime Docker image. When the building job is finished, Job Server will submit the PaddlePaddle distributed job to Kubernetes.
              • -
              • NOTE: For the first version, we will not prepare the runtime Docker image, instead, the package is uploaded to Paddle Cloud, and Paddle Cloud will mount the package in a temporary folder into the base Docker image. We will not support custom Python dependencies in the first version as well.
              • -
              -

              You can call paddle.job.dist_train and provide distributed training configuration as the parameters:

              -
              paddle.job.dist_train(
              -  trainer=dist_trainer(),
              -  paddle_job=PaddleJob(
              -    job_name = "paddle-cloud",
              -    entry_point = "python %s"%__file__,
              -    trainer_package = "/example/word2vec",
              -    image = "yancey1989/paddle-job",
              -    trainers = 10,
              -    pservers = 3,
              -    trainer_cpu = 1,
              -    trainer_gpu = 1,
              -    trainer_mem = "10G",
              -    pserver_cpu = 1,
              -    pserver_mem = "2G"
              -  ))
              -
              -
              -

              The parameter trainer of paddle.job.dist_train is a function and you can implement it as follows:

              -
              def dist_trainer():
              -  def trainer_creator():
              -    trainer = paddle.v2.trainer.SGD(...)
              -    trainer.train(...)
              -  return trainer_creator
              -
              -
              -

              The pseudo code of paddle.job.dist_train is as follows:

              -
              def dist_train(trainer, paddle_job):
              -  # if the code is running on cloud, set PADDLE_ON_CLOUD=YES
              -  if os.getenv("RUNNING_ON_CLOUD", "NO") == "NO":
              -    #submit the paddle job
              -    paddle_job.submit()
              -  else:
              -    #start the training
              -    trainer()
              -
              -
              -
              -

              PaddleJob Parameters

              -

              parameter | type | explanation -— | — | — -job_name | str | the unique name for the training job -entry_point | str | entry point for startup trainer process -trainer_package | str | trainer package file path which user have the access right -image|str|the base image for building the runtime image -pservers|int| Parameter Server process count -trainers|int| Trainer process count -pserver_cpu|int| CPU count for each Parameter Server process -pserver_mem|str| memory allocated for each Parameter Server process, a plain integer using one of these suffixes: E, P, T, G, M, K -trainer_cpu|int| CPU count for each Trainer process -trainer_mem|str| memory allocated for each Trainer process, a plain integer using one of these suffixes: E, P, T, G, M, K -trainer_gpu|int| GPU count for each Trainer process, if you only want CPU, do not set this parameter

              -
              -
              -

              Deploy Parameter Server, Trainer and Master Process

              -
                -
              • Deploy PaddlePaddle Parameter Server processes, it’s a Kubernetes ReplicaSet.
              • -
              • Deploy PaddlePaddle Trainer processes, it’s a Kubernetes Job.
              • -
              • Deploy PaddlePaddle Master processes, it’s a Kubernetes ReplicaSet.
              • -
              -
              -
              -
              -

              Job Server

              -
                -
              • RESTful API

                -

                Job server provides RESTful HTTP API for receiving the trainer package and displaying -PaddlePaddle job related informations.

                -
                  -
                • POST /v1/package receive the trainer package and save them on CephFS
                • -
                • POST /v1/trainer/job submit a trainer job
                • -
                • GET /v1/jobs/ list all jobs
                • -
                • GET /v1/jobs/<job-name> the status of a job
                • -
                • DELETE /v1/jobs/<job-name> delete a job
                • -
                • GET /v1/version job server version
                • -
                -
              • -
              • Build Runtime Docker Image on Kubernetes

                -

                paddle.job.dist_train will upload the trainer package to Job Server, save them on the distributed filesystem, and then start up a job for building the runtime Docker image that gets scheduled by Kubernetes to run during training.

                -

                There are some benefits for building runtime Docker image on JobServer:

                -
                  -
                • On Paddle Cloud, users will run the trainer code in a Jupyter Notebook which is a Kubernetes Pod, if we want to execute docker build in the Pod, we should mount the host’s docker.sock to the Pod, user’s code will connect the host’s Docker Engine directly, it’s not safe.
                • -
                • Users only need to upload the training package files, does not need to install docker engine, docker registry as dependencies.
                • -
                • If we want to change another image type, such as RKT, users do not need to care about it.
                • -
                -
              • -
              • Deploy Parameter Server, Trainer and Master Processes

                -

                POST /v1/trainer/job receives the distributed training parameters, and deploy the job as follows:

                -
                  -
                • Deploy PaddlePaddle Parameter Server processes, it’s a Kubernetes ReplicaSet.
                • -
                • Deploy PaddlePaddle Trainer processes, it’s a Kubernetes Job.
                • -
                • Deploy PaddlePaddle Master processes, it’s a Kubernetes ReplicaSet.
                • -
                -
              • -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/concurrent_programming.html b/develop/doc/design/concurrent_programming.html deleted file mode 100644 index f17ac541ae7..00000000000 --- a/develop/doc/design/concurrent_programming.html +++ /dev/null @@ -1,413 +0,0 @@ - - - - - - - - - - - - - Design Doc: Concurrent Programming with Fluid — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Concurrent Programming with Fluid

              -

              With PaddlePaddle Fluid, users describe a program other than a model. The program is a ProgramDesc protobuf message. TensorFlow/MxNet/Caffe2 applications generate protobuf messages too, but their protobuf messages represent the model, a graph of operators, but not the program that trains/uses the model.

              -

              Many know that when we program TensorFlow, we can specify the device on which each operator runs. This allows us to create a concurrent/parallel AI application. An interesting questions is how does a ProgramDesc represents a concurrent program?

              -

              The answer relies on the fact that a ProgramDesc is similar to an abstract syntax tree (AST) that describes a program. So users just program a concurrent program that they do with any concurrent programming language, e.g., Go.

              -
              -

              An Analogy

              -

              The following table compares concepts in Fluid and Go

              -

              | Go | Fluid | -|—-|——-| -|user-defined functions | layers | -| control-flow and built-in functions | intrinsics/operators | -| goroutines, channels | class ThreadPool | -| runtime | class Executor |

              -
              -
              -

              An Example Concurrent Program

              -

              To review all above concepts in an example, let us take a simple program and writes its distributed version.

              -

              Suppose that we want to parallelize a naive Fluid program (written in Go and calling Fluid’s Go binding) that multiplies two tensors.

              -
              import "fluid"
              -
              -func paddlepaddle() {
              -  X = fluid.read(...)
              -  W = fluid.Tensor(...)
              -  Y = fluid.mult(X, W)
              -}
              -
              -
              -

              Please be aware that the Fluid’s Go binding provides the default main function, which calls the paddlepaddle function, which, in this case, is defined in above program and creates the following ProgramDesc message.

              -
              message ProgramDesc {
              -  block[0] = Block {
              -    vars = [X, W, Y],
              -    ops = [
              -      read(output = X)
              -      assign(input = ..., output = W)
              -      mult(input = {X, W}, output = Y)
              -    ],
              -  }
              -}
              -
              -
              -

              Then, the default main function calls fluid.run(), which creates an instance of the class Executor and calls Executor.Run(block[0]), where block[0] is the first and only block defined in above ProgramDesc message.

              -

              The default main function is defined as follows:

              -
              func main() {
              -  paddlepaddle()
              -  fluid.run()
              -}
              -
              -
              -
              -
              -

              The Concurrent Version

              -

              By parallelizing the above program, we could support very big tensor X by splitting into small pieces {x_1, x_2, ...} and sent each piece to worker process/node for parallel multiplication.

              -

              In this case, we can write a transpiler that takes a ProgramDesc message that represents the above example program and outputs two ProgramDesc messages, one for running on the master process/node, and the other one for worker processes/nodes.

              -
              -

              The Master Program

              -

              The master program could look like the following:

              -
              message ProgramDesc {
              -  block[0] = Block {
              -    vars = [X, L, Y],
              -    ops = [
              -      read(output = X)
              -      kube_get_workers_addrs(output = L)
              -      Y = tensor_array(len(L))
              -      parallel_for(input = X, output = Y, 
              -                   attrs = {L, block_id(1)}) # referring to block 1
              -    ]
              -  }
              -  
              -  block[1] = Block {
              -    parent = 0,
              -    vars = [x, y, index],
              -    ops = [
              -      slice(input = [X, index], output = x) # index is initialized by parallel_for
              -      send(input = x, attrs = L[index])
              -      recv(outputs = y, attrs = L[index])
              -      assign(input = y, output = Y[index])
              -    ]
              -  }
              -}
              -
              -
              -

              The equivalent Fluid program (calling the Go binding) is:

              -
              func main() {  //// block 0
              -  X = fluid.read(...)
              -  L = fluid.k8s.get_worker_addrs()
              -  Y = fluid.tensor_array(len(L))
              -  fluid.parallel_for(X, L, 
              -                     func(index int) {  //// block 1
              -                       x = X[index]
              -                       fluid.send(L[index], x)
              -                       y = fluid.recv(L[index])
              -                       Y[index] = y
              -                     })
              -}
              -
              -
              -

              An explanation of the above program:

              -
                -
              • fluid.k8s is a package that provides access to Kubernetes API.
              • -
              • fluid.k8s.get_worker_addrs returns the list of IP and ports of all pods of the current job except for the current one (the master pod).
              • -
              • fluid.tensor_array creates a tensor array. fluid.parallel_for creates a ParallelFor intrinsic, which, when executed,
                  -
                1. creates len(L) scopes, each for the concurrent running of the sub-block (block 1 in this case), and initializes a variable named “index” in the scope to an integer value in the range [0, len(L)-1], and
                2. -
                3. creates len(L) threads by calling into the ThreadPool singleton, each thread
                    -
                  1. creates an Executor instance, and
                  2. -
                  3. calls Executor.Run(block), where block is block 1 as explained above.
                  4. -
                  -
                4. -
                -
              • -
              -
                -
              1. Please be aware that block 1 is a sub-block of block 0, so ops in block 1 could refer to variables defined in block 0.
              2. -
              -
              -
              -

              The Worker Program

              -

              The worker program looks like

              -
              func main() {
              -  W = Tensor(...)
              -  x = fluid.listen_and_do(
              -        fluid.k8s.self_addr(),
              -        func(input Tensor) {
              -          output = fluid.mult(input, W)
              -        })
              -}
              -
              -
              -

              where

              -
                -
              • fluid.listen_and_do creates a ListenAndDo intrinsic, which, when executed,
                  -
                1. listens on the current pod’s IP address, as returned by fliud.k8s.self_addr(),
                2. -
                3. once a connection is established,
                    -
                  1. creates a scope of two parameters, “input” and “output”,
                  2. -
                  3. reads a Fluid variable and saves it into “input”,
                  4. -
                  5. creates an Executor instance and calls Executor.Run(block), where the block is generated by running the lambda specified as the second parameter of fluid.listen_and_do.
                  6. -
                  -
                4. -
                -
              • -
              -
              -
              -
              -

              Summarization

              -

              From the above example, we see that:

              -
                -
              1. Fluid enables the imperative programming paradigm by:
                  -
                1. letting users describe a program, but not a model (a sequence of layers, or a graph of operators), and
                2. -
                3. call the fluid.run function that runs the program implicitly.
                4. -
                -
              2. -
              3. The program is described as a ProgramDesc protobuf message.
              4. -
              5. Function Executor.Run takes a block, instead of a ProgramDesc, as its parameter.
              6. -
              7. fluid.run calls Executor.Run to run the first block in the ProgramDesc message.
              8. -
              9. Executor.Run‘s implementation is extremely simple – it doesn’t plan the execution nor create threads; instead, it runs on the current thread and execute intrinsics/operators’ Run method sequentially as they appear in the Block.ops array.
              10. -
              11. Intrinsics/operators’ Run method might create threads. For example, the ListenAndDo operator creates a thread to handle each incoming request.
              12. -
              13. Threads are not necessarily OS thread; instead, they could be green threads managed by ThreadPool. Multiple green threads might run on the same OS thread. An example green threads is Go’s goroutines.
              14. -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/cpp_data_feeding.html b/develop/doc/design/cpp_data_feeding.html deleted file mode 100644 index cdc3b0ecf46..00000000000 --- a/develop/doc/design/cpp_data_feeding.html +++ /dev/null @@ -1,322 +0,0 @@ - - - - - - - - - - - - - C++ Data Feeding — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              C++ Data Feeding

              -

              In training with Paddle V2 API, data feeding wholly dependents on Python code. To get rid of the Python environment and achieve the goal of “wrapping the whole training by a while loop op” in Paddle Fluid, a C++ data feeding mechanism is required.

              -

              In this document we show the fundamental design of C++ data feeding process, which includes the data reading, shuffling and batching.

              -
              -

              Reader

              -

              A new concept named ‘Reader’ is introduced. Reader is a series of inherited classes which can be hold by our Variable and they are used to read or process file data.

              -
              -

              ReaderBase

              -

              ReaderBase is the abstract base class of all readers. It defines the all readers’ interfaces.

              -
              class ReaderBase {
              - public:
              -  explicit ReaderBase(const std::vector<DDim>& shapes) : shapes_(shapes) {
              -    PADDLE_ENFORCE(!shapes_.empty());
              -  }
              -  // Read the next batch of data. (A 'batch' can be only one instance)
              -  virtual void ReadNext(std::vector<LoDTensor>* out) = 0;
              -  // Show whether the next bacth exists.
              -  virtual bool HasNext() const = 0;
              -  
              -  // Reinitialize the reader and read the file from the begin.
              -  virtual void ReInit() = 0;
              -  
              -  // Get a certain read in data's shape.
              -  DDim shape(size_t idx) const;
              -  // Get shapes of all read in data.
              -  std::vector<DDim> shapes() const { return shapes_; }
              -  // Set shapes of read in data.
              -  void set_shapes(const std::vector<DDim>& shapes) { shapes_ = shapes; }
              -
              -  virtual ~ReaderBase() {}
              -
              - protected:
              -  std::vector<DDim> shapes_;
              -};
              -
              -
              -
              -
              -

              FileReader and DecoratedReader

              -

              These two classes are derived from the ReaderBase and will further be derived by respective specific readers. That is to say, in our design, there are two kinds of readers: file readers and decorated readers. A file reader reads from a file of some specific format, and yield only one instance of data at a time. e.g. RecordIO reader, jpg reader, .... A decorated reader takes another reader(both file reader and decorated reader are OK) as its ‘underlying reader’. It gets data from its underlying reader, does some process on them(shuffling, or batching), then yields processed data. The output data of a decorated reader can be a single instance or a batch. ShuffleReader and BatchReader are both decorated readers.

              -

              All the readers share exactly the same interfaces defined in ReaderBase. So they can be decorated for more than one time: We can shuffle a reader’s outputs and then batch the shuffle outputs. The interface consistency also allows related ops use readers without knowing what they are exactly.

              -
              -
              -

              ReaderHolder

              -

              Different readers belong to different class types. It leads to a problem: How can we drop them into Variables and fetch them out by a unified method? For example, if a Variable holds a BatchReader, we can not get it by the following code:

              -
              var->Get<ReaderBase>("batch_reader");
              -
              -
              -

              we have to write:

              -
              var->Get<BatchReader>("batch_reader");
              -
              -
              -

              This requires each time getting a reader from a variable we must know the reader’s type exactly. It is nearly impossible.

              -

              To solve this problem, we introduce ReaderHolder as a wrapper. It acts as an empty decorator of ReaderBase, which erases reader’s type. With ReaderHolder we are able to fetch all types of readers by var->Get<ReaderHolder>("...") and regard the obtained object as a reader.

              -
              -
              - -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/csp.html b/develop/doc/design/csp.html deleted file mode 100644 index 38bc562da48..00000000000 --- a/develop/doc/design/csp.html +++ /dev/null @@ -1,451 +0,0 @@ - - - - - - - - - - - - - Design Doc: CSP in PaddlePaddle Fluid — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: CSP in PaddlePaddle Fluid

              -
              -

              Motivation

              -

              Concurrent programming is important for deep learning. Few example applications are:

              -
                -
              1. The main thread keeps reading the next mini-batch while another thread uses the GPU for computing.
              2. -
              3. The main thread performs the computation while another thread uploads the local gradients from each trainer to the parameter server.
              4. -
              -

              Most DL systems, including TensorFlow, Caffe2, and MxNet, can asynchronously execute operators in a graph. However, Fluid doesn’t have the concept of a graph at all, as the design goal of Fluid is that of a programming language.

              -
              -
              -

              Concurrent Programming Models

              -

              There were many concurrent programming models, implemented in various forms:

              -

              | concurrent programming model | implementation | -|—–|—–| -| mutex | types and functions in standard libraries | -| semaphore | types and functions in standard libraries | -| communicating sequential processes (CSP) | Go programming language | -| actor model | Erlang programming language | -| message passing | MPI | -| bulk synchronous parallel (BSP) | Pregel distributed programming framework |

              -

              Since Fluid was designed to be a programming language, we would like to implement CSP in Fluid.

              -
              -

              CSP v.s. Actor Model

              -

              A well-known implementation of Actor Model is the Erlang programming language. In Actor Model, processes could send messages to another process and receive messages from another process given the process IDs. We can find the three ingredients, process with ID, send, and recv, in MPI too. Indeed, we can rewrite Erlang programs in Python + MPI with possibly fewer lines of code. Our concern with Actor Model is that it doesn’t seem reasonable to implement process management in a programming language’s runtime library; instead, it should be the operating systems’ responsibility to manage processes and libraries like MPI for send/recv.

              -
              -
              -
              -

              CSP in Fluid

              -

              Fluid has two fundamental control-flows: if-else and while. If we are to implement CSP, we need the following:

              -
                -
              1. a new data type: channel and operators send and recv,
              2. -
              3. goroutine or thread, and
              4. -
              5. a new control-flow: select.
              6. -
              -

              We also need Python wrappers for the above components.

              -

              The type channel is conceptually the blocking queue. In Go, its implemented is a blocking circular queue, which supports send and recv.

              -

              The select operation has been in OS kernels long before Go language. All Unix kernels implement system calls poll and select. They monitor multiple file descriptors to see if I/O is possible on any of them. This takes O(N) time. Since Linux 2.6, a new system call, epoll, can do the same in O(1) time. In BSD systems, there is a similar system call kqueue. Go’s Linux implementation uses epoll.

              -

              It might be a good idea to implement Fluid’s select using epoll too. In this design doc, we start from the O(N) way so that we could focus on Python binding and the syntax.

              -
              -

              Type Channel

              -

              Fluid supports many data types:

              -
                -
              1. Tensor,
              2. -
              3. Row-sparse Tensor
              4. -
              5. LoD Tensor,
              6. -
              7. Tensor array, etc
              8. -
              -

              Each data type is registered in the framework.proto as an enum value. To add a new type channel, we need to add a new type enum.

              -

              To expose a C++ type to Python, we need to edit the pybind.cc file. Here is an example how we expose C++ class LoDTensor.

              -
              -
              -
              -

              Syntax Design

              -
              -

              Create Channel

              -

              In Go, we create a channel by specifying the element type and buffer size:

              -
              ch  := make(chan int)       // a channel without buffer
              -ch1 := make(chan int, 100)  // a channel that can buffer 100 ints.
              -
              -
              -

              In Fluid, we should be able to do the same:

              -
              ch  = fluid.make_channel(dtype=INT)
              -ch1 = fluid.make_channel(dtype=INT, 100)
              -
              -
              -

              In addition to that, we want channels that can hold more complex element types, e.g., Tensors of float16:

              -
              ch = fluid.make_channel(dtype=Tensor, etype=float16)
              -
              -
              -

              or Tensors of Tensors of float16 etc.

              -

              The point here is that we need a consistent way to compose types, like in C++ we can have Tensor<Tensor<...<float16>...> >.

              -
              -
              -

              Send and Recv

              -

              Go’s CSP implementation depends on data type channel. There are two types of channels:

              -
                -
              1. The unblocked channel, or buffered channel, is a blocking queue with a non-zero sized buffer. The sending to buffered channel blocks if the buffer is full, and the receive operation blocks if the buffer is empty.
              2. -
              3. blocked channel, or unbuffered channel, is a blocking queue with no buffer. Both sending and receiving block with unbuffered channels.
              4. -
              -

              There are four types of actions with a channel:

              -
                -
              1. Create a channel

                -
                ch := make(chan int) // this is an unbuffered channel
                -ch := make(chan int, 100) // this is a buffered channel of 100 ints.
                -
                -
                -
              2. -
              3. Send

                -
                ch <- 111
                -
                -
                -
              4. -
              5. Recv

                -
                y, ok <- ch
                -
                -
                -
              6. -
              7. Close

                -
                close(ch)
                -
                -
                -

                Please be aware that a closed channel is not a nil channel, which is var ch chan int.

                -
              8. -
              -

              There are some axioms with channels:

              -
                -
              1. A send to a nil channel blocks forever
              2. -
              3. A receive from a nil channel blocks forever
              4. -
              5. A send to a closed channel panics
              6. -
              7. A receive from a closed channel returns the residual values and then zeros.
              8. -
              -

              In Fluid, we have buffered channels and unbuffered channels

              -

              The following program illustrates the Python syntax for accessing Fluid buffers.

              -
              import fluid
              -
              -buffer_size = 10
              -ch = fluid.make_channel(dtype=INT, buffer_size)
              -
              -# Now write three elements to the channel
              -with fluid.while(steps=buffer_size):
              -  fluid.send(ch, step)
              -
              -fluid.close_channel(ch)
              -
              -with fluid.while(steps=buffer_size):
              -  fluid.print(fluid.recv(ch))
              -
              -
              -

              The following example shows that to avoid the always-blocking behavior of unbuffered channels, we need to use Fluid’s goroutines.

              -
              import fluid
              -
              -ch = fluid.make_channel(dtype=INT)
              -
              -with fluid.go():
              -  fluid.send(ch)
              -
              -y = fluid.recv(ch)
              -
              -fluid.close_channel(ch)
              -
              -
              -
              -
              -

              Select

              -

              In Go, the select statement lets a goroutine wait on multiple communication operations. A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.

              -
              ch1  := make(chan int)       
              -ch2  := make(chan int, 100)
              -
              -x := 0
              -
              -for {
              -    select {
              -    case ch1 <- x:
              -      x := x + 1
              -    case y <- ch2:
              -      fmt.Println("Received on channel")
              -    default:
              -      fmt.Println("Default")
              -    }
              -  }
              -
              -
              -

              In Fluid, we should be able to do the same:

              -
              ch1  = fluid.make_chan(dtype=INT)
              -ch2 = fluid.make_chan(dtype=INT, 100)
              -
              -sel = fluid.select()
              -
              -with sel.case(ch1, 'w', X):
              -    fluid.layers.increment(X)
              -
              -with sel.case(ch2, 'r', Y):
              -    fluid.print("Received on Channel")
              -
              -with sel.default():
              -    fluid.print("Default")
              -
              -
              -
              -

              In the above code snippet, X and Y are variables. Now let us look at each of these statements one by one.

              -
                -
              • sel.case(ch1, 'w', X) : This specifies that we are writing to ch1 and we want to write the integer in variable X to the channel. The character w is used here to make the syntax familiar to write syntax in Python I/O.
              • -
              • sel.case(ch2, 'r', Y) : This specifies that we would like to read the result from ch2 into variable Y. The character r is used here to make the syntax familiar to read syntax in Python I/O.
              • -
              • sel.default() : This is equivalent to the default in Go select. If none of the channels are ready for read or write, then the fluid code in the default block will be executed.
              • -
              -
              -
              -
              -

              Example Programs

              -
              -

              1. RPC between Trainers and Parameter Servers

              -
              -
              -

              2. Concurrent Minibatch Loading

              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/dist_refactor/distributed_architecture.html b/develop/doc/design/dist_refactor/distributed_architecture.html deleted file mode 100644 index 0e2b9e754d3..00000000000 --- a/develop/doc/design/dist_refactor/distributed_architecture.html +++ /dev/null @@ -1,424 +0,0 @@ - - - - - - - - - - - - - Design Doc: Distributed Training Architecture — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Distributed Training Architecture

              -
              -

              Abstract

              -

              PaddlePaddle version 0.10.0 uses the “trainer-parameter server” architecture. We run multiple instances of trainers (where each trainer runs the same model) and parameter servers for distributed training. This architecture serves well, but has few limitations:

              -
                -
              1. There is a need to write special code that handles tasks which should only be run on a single trainer. E.g., initializing the model, saving the model etc.
              2. -
              3. Model parallelism is hard: It would need all the if-else branches conditioned on the trainer ID to partition the model onto the trainers, and eventually manually writing out the inter-model-shard communication code to communicate between different trainers.
              4. -
              5. The user can not directly specify the parameter update rule: This would need to modify the parameter server code and compile a new binary. This makes things more complicated for researchers: A lot of extra effort is required to make this work. Besides, the training job submission program may not allow running arbitrary binaries.
              6. -
              -

              This design doc discusses PaddlePaddle’s new distributed training architecture that addresses the above mentioned limitations.

              -
              -
              -

              Analysis

              -

              The assumption is that the user writes the trainer program in either Python or C++.

              -
              -

              Limitation 1

              -

              There are two basic functionalities in the trainer program:

              -
                -
              1. The training logic such as loading / saving the model and printing out the logs.
              2. -
              3. The neural network definition such as the definition of the data layer, the fully connected layer, the cost function and the -optimizer.
              4. -
              -

              When we train using PaddlePaddle v0.10.0 in a distributed fashion, multiple instances of the same Python code are run on different nodes, hence both: the -training logic as well as the neural network computation logic, is replicated.

              -

              The tasks that only need to be run once belong to the training logic. Hence if we only replicate the neural network computation part, and do not -replicate the training logic, the limitation mentioned above can be avoided.

              -
              -
              -

              Limitation 2

              -

              Model parallelism means that a single model is partitioned into different components and each node runs one of the component separately. This comes at the extra cost of managing the -inter-model-shard communication between nodes.

              -

              PaddlePaddle should ideally be able to modify the neural network computation and figure out the support for model parallelism automatically. However, the -computation is only specified in Python code which sits outside of PaddlePaddle, hence PaddlePaddle can not support the feature in this setup.

              -

              Similar to how a compiler uses an intermediate representation (IR) so that the programmer does not need to manually optimize their code for most of the cases, we can have an intermediate representation in PaddlePaddle as well. The compiler optimizes the IR as follows:

              -

              -

              PaddlePaddle can support model parallelism by converting the IR so that the user no longer needs to manually perform the computation and operations in the Python component:

              -

              -

              The IR for PaddlePaddle after refactoring is called a Block, it specifies the computation dependency graph and the variables used in the computation.

              -
              -
              -

              Limitation 3

              -

              The user can not directly specify the parameter update rule for the parameter server in the Python module, since the parameter server does not use the same computation definition as the trainer. Instead, the update rule is baked inside the parameter server. The user can not specify the update rule explicitly.

              -

              This could be fixed by making the parameter server also run an IR, which can be different to the trainer side -For a detailed explanation, refer to this document - -Design Doc: Parameter Server

              -
              -
              -
              -

              Distributed Training Architecture

              -

              The revamped distributed training architecture can address the above discussed limitations. Below is the illustration of how it does so:

              -

              -

              The major components are: Python API, Distribute Transpiler and Remote Executor.

              -
              -

              Python API

              -

              Python API is the Python library that user’s Python code invokes, to read the data, build the neural network topology, and start training, etc.

              -
              images = fluid.layers.data(name='pixel', shape=[1, 28, 28], dtype='float32')
              -label = fluid.layers.data(name='label', shape=[1], dtype='int64')
              -...
              -predict = fluid.layers.fc(input=conv_pool_2, size=10, act="softmax")
              -cost = fluid.layers.cross_entropy(input=predict, label=label)
              -avg_cost = fluid.layers.mean(x=cost)
              -optimizer = fluid.optimizer.Adam(learning_rate=0.01)
              -optimizer.minimize(avg_cost)
              -
              -train_reader = paddle.batch(
              -    paddle.reader.shuffle(
              -        paddle.dataset.mnist.train(), buf_size=500),
              -    batch_size=BATCH_SIZE)
              -
              -place = fluid.CPUPlace()
              -exe = fluid.Executor(place)
              -
              -for pass_id in range(10):
              -    for data in train_reader():
              -        loss, acc = exe.run(trainer_prog,
              -                            feed=feeder.feed(data),
              -                            fetch_list=[avg_cost])
              -
              -
              -

              The code above is a typical local training program, the “Training Program” is built using helper functions such as -fluid.layer.fc. The training is done by calling Executor.run -iteratively.

              -

              For more details, the implementation of IR is Program, and ProgramDesc is the protobuf type.

              -

              Executor simply runs the ProgramDesc. For local training you generally use -Executor to run the program locally. For any kind of distributed training, you can use -RemoteExecutor to specify desired distributed training method with some optional arguments.

              -
              -
              -

              Distributed Transpiler

              -

              The Distributed Transpiler automatically converts the IR (in protobuf format) to partitioned IRs. Then -the Remote Executor dispatches the new IRs to Remote Executors across the cluster. -Below are the steps that are followed :

              -
                -
              1. User only need to change Executor to RemoteExecutor to change local program to distributed program.
              2. -
              3. RemoteExecutor calls Distributed Transpiler to “transpile” user’s program to several IRs representing a -distributed training program:
                  -
                1. Parse configurations from RemoteExecutor.
                2. -
                3. Determine the type of distributed program, can be DataParallelism, ModelParallelism or Streaming.
                4. -
                5. Partition the ProgramDesc according to type and add send / recv OP pair on the boundaries. Take -DataParallelism type for example, it removes the optimization operators and add a send OP to the -“trainer” role, then add the optimization operators to the parameter server role within the recv OP.
                6. -
                -
              4. -
              5. Dispatch the partitioned graph to different RemoteExecutor in the cluster.
              6. -
              7. RemoteExecutor on each node run the received ProgramDesc utill the end.
              8. -
              -
              -
              -

              RemoteExecutor

              -

              As shown in the graph, RemoteExecutor.run sends the IR to the cluster for Execution. -You can also use parameter fetch_list to interactively fetch variable back to local for -log printing.

              -

              The Python RemoteExecutor is derived from Executor class.

              -
              exe = RemoteExecutor(
              -    feed=feeder.feed(data),
              -    fetch_list=[avg_cost],
              -    job_desc=JobDesc(
              -      jobname,
              -      num_trainer,
              -      num_pserver,
              -      cpu_per_trainer,
              -      gpu_per_trainer,
              -      mem_per_trainer,
              -      cpu_per_pserver,
              -      mem_per_pserver
              -    ))
              -for data in train_reader():
              -    loss, acc = exe.run(trainer_prog,
              -                        feed=feeder.feed(data),
              -                        fetch_list=[avg_cost])
              -
              -
              -

              JobDesc object describe the distributed job resource specification to run on -Cluster environment.

              -

              -

              RemoteExecutor.run sends the ProgramDesc and -TrainingJob -to a server in the cluster which executes RemoteExecutor.listen. This server is responsible -to start the final Kubernetes Jobs to run the different role of ProgramDesc from ConfigMap.

              -
              -
              -

              Placement Algorithm

              -

              Our first implementation will only support “trainer-parameter server” placement: the parameters, initializers, and optimizers are all placed on the PaddlePaddle runtimes with the parameter server role. Everything else will be placed on the PaddlePaddle runtimes with the trainer role. This has the same functionality as the “trainer-parameter server” architecture of PaddlePaddle v0.10.0, but is more generic and flexible.

              -

              In the future, a more general placement algorithm should be implemented, which makes placements according to the input IR, and a model of device computation time and device communication time. Model parallelism requires the generic placement algorithm.

              -
              -
              -

              Local Training Architecture

              -

              The local training architecture will be the same as the distributed training architecture, the difference is that everything runs locally, and there is just one PaddlePaddle runtime:

              -

              -
              -
              -

              Training Data

              -

              In PaddlePaddle v0.10.0, training data is typically read -with data reader from Python. This approach is -no longer efficient when training distributedly since the Python -process no longer runs on the same node with the trainer processes, -the Python reader will need to read from the distributed filesystem -(assuming it has the access) and send to the trainers, doubling the -network traffic.

              -

              When doing distributed training, the user can still use Python data -reader: the training data are sent with Executor.run. However, should -be used for debugging purpose only. The users are encouraged to use -the read data OPs.

              -
              -
              - -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/dist_refactor/multi_cpu.html b/develop/doc/design/dist_refactor/multi_cpu.html deleted file mode 100644 index 63c35fc79f0..00000000000 --- a/develop/doc/design/dist_refactor/multi_cpu.html +++ /dev/null @@ -1,306 +0,0 @@ - - - - - - - - - - - - - Design Doc: Execute the Program with Multi CPU — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Execute the Program with Multi CPU

              -
              -

              Abstract

              -

              This Design Doc propose an approach to make the user-defined Op graph -running with multi-CPU, we will use an auto transpiler to convert the user-defined -Op graph to a multi-CPU Op graph, and run ParallelDo Op to run the graph.

              -
              -
              -

              Transpiler

              -

              -

              After converted:

              -

              -
              -
              -

              Implement

              -
                -
              • Multi-CPU Transpiler will convert the graph to a multi-CPU graph -which would be executed with multi-threads.

                -
              • -
              • BlockingCounter will Init/Decrement an atomic counter, and Blocking Wait -for the atomic counter become 0:

                -
                BlockingCounter bc(thread_count);
                -for (int i = 0; i < thread_count; ++i) {
                -  thread_pool->Start([&bc] {bc.DecrementCount(); })
                -}
                -bc.Wait();
                -
                -
                -
              • -
              • ParallelDo Operator

                -
                  -
                • Initialize a thread pool which is a Singleton.
                • -
                • Use a block id as the input, and create run the specify Block on independent scope -with multi-threads.
                • -
                • Initialize a BlockingCounter instance and wait until all threads are done.
                • -
                -
              • -
              • Split Operator will split the Input Tensor into a TensorArray.

                -
              • -
              • Merge merge all the gradients which calculated in different threads -with mean/sum/max/min... method, and then run the Optimizer Op to optimize W.

                -
              • -
              -
              -
              -

              TODO

              -
                -
              • Improve the optimizer stage with multi-threads, since we could -assign the parameters to the different threads and execute -optimizer with multi-threads.
              • -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/dist_refactor/parameter_server.html b/develop/doc/design/dist_refactor/parameter_server.html deleted file mode 100644 index 3b09173d80d..00000000000 --- a/develop/doc/design/dist_refactor/parameter_server.html +++ /dev/null @@ -1,354 +0,0 @@ - - - - - - - - - - - - - Design Doc: Parameter Server — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Parameter Server

              -
              -

              Abstract

              -

              We propose an approach to implement the parameter server. In this -approach, there is no fundamental difference between the trainer and -the parameter server: they both run subgraphs, but subgraphs of -different purposes.

              -
              -
              -

              Background

              -

              The previous implementations of the parameter server do not run a -fluid sub-program. Parameter initialization, optimizer computation, network -communication and checkpointing are implemented twice on both the -trainer as well as the parameter server.

              -

              It would be great if we can write code once and use them on both: the -trainer and the parameter server, since this reduces code duplication and -improves extensibility. Given that after the current refactoring, we are -representing everything as a computation graph on the -trainer. Representing everything as a computation graph on the parameter -server becomes a natural extension.

              -
              -
              -

              Design

              -
              -

              Distributed Transpiler

              -

              The Distributed Transpiler converts the user-defined fluid program -into sub-programs to be scheduled on different nodes with the following -steps:

              -
                -
              1. OP placement: the OPs will be placed on different nodes according -to a heuristic that minimizes the estimated total computation -time. Currently we will use a simple heuristic that puts parameter -variable on parameter server workers and everything else on trainer -workers.
              2. -
              3. Add communication OPs to enable the communication between nodes.
              4. -
              -

              We will need these OPs: Send, Recv, Enqueue, Dequeue.

              -

              Below is an example of converting the user defined graph to the -subgraphs for the trainer and the parameter server:

              -

              -

              After converting:

              -

              -
                -
              1. The parameter variable W and its optimizer program are placed on the parameter server.
              2. -
              3. Operators are added to the program.
                  -
                • Send sends data to the connected Recv operator. The -scheduler on the receive node will only schedule Recv operator -to run when the Send operator has ran (the Send OP will mark -the Recv OP runnable automatically).
                • -
                • Enqueue enqueues the input variable, it can block until space -become available in the queue.
                • -
                • Dequeue outputs configurable numbers of tensors from the -queue. It will block until the queue has the required number of -tensors.
                • -
                -
              4. -
              -
              -
              -

              Benefits

              -
                -
              • Model parallelism becomes easier to implement: it is an extension to -the trainer - parameter server approach. We can have several “Transpilers” -to achieve different goals.
              • -
              • User-defined optimizer is easier to add - user can now express it as -a sub-program.
              • -
              • No more duplication logic inside the trainer and the parameter -server mentioned in the background section.
              • -
              -
              -
              -

              Challenges

              -
                -
              • It is important to balance the parameter shards on multiple -parameter servers. If a single parameter is very big (for example: some -word-embedding, fully connected, softmax layer), we need to -automatically partition the single parameter onto different -parameter servers when possible (only element-wise optimizer depends -on the parameter variable).
              • -
              • In the “Async SGD” figure, the “W” variable on the parameter server -could be read and written concurrently. See -here for more -details about concurrent program in Fluid.
              • -
              -
              -
              -

              Discussion

              -
                -
              • Can the Enqueue OP be implemented under our current tensor design -(put the input tensor into the queue tensor)?
              • -
              • Dequeue OP will have variable numbers of output (depending on the -min_count attribute), does our current design support it? (similar -question for the Add OP)
              • -
              -
              - -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/error_clip.html b/develop/doc/design/error_clip.html deleted file mode 100644 index 382711db636..00000000000 --- a/develop/doc/design/error_clip.html +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - Error Clip — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Error Clip

              -
              -

              Overview

              -

              Error clip is widely used in model training to prevent gradient exploding. It takes some specific rules to adjust variables’ gradients and prevent them from being too large. With it, values of a gradient will be checked before they are taken by the next grad_op and be shrunk if necessary.

              -
              -
              -

              Usage

              -

              Users are allowed to assign different error clip methods or attributes to different Variables. Users can specify it as a parameter of Variable‘s constructor:

              -
              var = framework.Variable(..., error_clip=myErrorClip, ...)
              -
              -
              -

              The default value of error_clip is None, which means no error clip is employed. When it’s not None, it should take an object of BaseErrorClipAttr‘s derived class. So far, BaseErrorClipAttr has only one derived class: ErrorClipByValue, whose constructor is:

              -
              ErrorClipByValue(max, min=None)
              -
              -
              -

              max and min represent the maximal and minimal clip threshold respectively. In backward pass, all values of var‘s gradient greater than max or less than min will be clipped to max and min respectively. When the min is None, the minimal threshold will be assigned with -max automatically.

              -

              So we can enable the error clip with threshold [-5.0, 5.0] for variable var by:

              -
              var = framework.Variable(..., error_clip=ErrorClipByValue(max=5.0), ...)
              -
              -
              -
              -
              -

              Implementation

              -

              The BaseErrorClipAttr and its derived class ErrorClipByValue are defined in clip.py.

              -
              class BaseErrorClipAttr(object):
              -    def append_clip_op(self, block, grad_name):
              -        raise NotImplementedError()
              -
              -
              -class ErrorClipByValue(BaseErrorClipAttr):
              -    def __init__(self, max, min=None):
              -        max = float(max)
              -        if min is None:
              -            min = -max
              -        else:
              -            min = float(min)
              -        self.max = max
              -        self.min = min
              -
              -    def append_clip_op(self, block, grad_name):
              -        clip_op_desc = block.desc.append_op()
              -        clip_op_desc.set_type("clip")
              -        clip_op_desc.set_input("X", [grad_name])
              -        clip_op_desc.set_output("Out", [grad_name])
              -        clip_op_desc.set_attr("min", self.min)
              -        clip_op_desc.set_attr("max", self.max)
              -
              -
              -

              The BaseErrorClipAttr have one main member functions: append_clip_op(self, block, grad_name).

              -

              This function is used to create a clip_op and append it to the end of given block. For different error clip algorithm require different clip_op, the function is defined as virtual in the base class. All derived classes must implement their own versions of this function.

              -

              These clip_ops should be inserted after grad_ops whose output gradients need to be clipped. It is equivalent to appending some clip_ops to the end of the target block every time a new grad_op is added.

              -
              for op_desc in grad_op_descs:
              -        new_op_desc = target_block.desc.append_op()
              -        new_op_desc.copy_from(op_desc)
              -        callback(block=target_block, context=grad_to_var)
              -
              -
              -

              Here we employ a callback function to complete this kind of jobs. In _append_backward_ops_ function, each time after a grad_op is added to the target_block, a callback function is invoked. The logic of clip_op appending can be implemented inside the callback function.

              -

              The callback function for clip_op appending is defined in clip.py:

              -
              def error_clip_callback(block, context):
              -    # the context is a grad_to_var map
              -    grad_to_var = context
              -    op_desc = block.desc.op(block.desc.op_size() - 1)
              -    for grad_n in filter(lambda n: grad_to_var.has_key(n),
              -                         op_desc.output_arg_names()):
              -        fwd_var = block.var_recursive(grad_to_var[grad_n])
              -        error_clip = getattr(fwd_var, "error_clip", None)
              -        if not (error_clip is None or isinstance(error_clip,
              -                                                 BaseErrorClipAttr)):
              -            raise TypeError(
              -                "Variable's error_clip should be an instance of BaseErrorClipAttr or None."
              -            )
              -        if error_clip is not None:
              -            error_clip.append_clip_op(block, grad_n)
              -
              -
              -

              This function takes a block and a context(which is actually a grad_to_var map) as inputs. It checks each output of the last OpDesc in the block. Notice that the last OpDesc of the block must be a grad_op and its outputs must be some forward variables’ gradients. If an output gradient’s corresponding forward variable has an attribute of error_clip, error_clip_callback will call the error_clip‘s append_clip_op function to append the required clip_op into the block.

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/evaluator.html b/develop/doc/design/evaluator.html deleted file mode 100644 index 11935402b87..00000000000 --- a/develop/doc/design/evaluator.html +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - - - - Evaluator Design — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Evaluator Design

              -
              -

              Problem Statement

              -

              During training or inference, we provide an evaluation function to measure the model performance, for example, accuracy, precision, etc. In the operator based framework design, the data passes through the network pipeline batch by batch. As a result, inside the operator, we only calculate the metrics for one minibatch. Thus, we need to provide a mechanism to calculate the metrics for each N pass/batch the user wants.

              -
              -
              -

              Evaluator Design

              -

              Currently, every operation is expressed in the graph. We divide the evaluator process into three steps.

              -
                -
              1. Initialize the metric state and add it into the block.
              2. -
              3. Calculate the concerned metrics for every mini-batch. The single evaluator operator is only responsible for calculating the necessary statistics for one mini-batch. For example, the accuracy operator only calculates the accuracy for a minibatch data if run once.
              4. -
              -
                -
              1. Merge the mini-batch statistics to form the evaluation result for multiple mini-batches. When it comes to distributed training/Multi-GPU training, aggregate the value from different devices.
              2. -
              -
              -
              -

              Implementation

              -

              This design is shown in the Python API. -Each metric operator needs to caculate the metric statistic and return the batch-aware states. Python side is responsible for accumulating the states for each pass.

              -
              class Evaluator(object):
              -    """
              -    Evaluator Base class.
              -    """
              -    def __init__(self, name, **kwargs):
              -       """
              -       Different evaluator may has different metric states. E.g, Accuracy need two variables, total and right sample counts.
              -       Auc need four variables, `true_positives`,
              -         `true_negatives`, `false_positives` and `false_negatives`. So every evaluator should create its needed variables and append to main_program
              -
              -       The initialization of Evaluator should be responsible for:
              -       create metric states and append to the main_program
              -       """ 
              -       pass
              -
              -    def _update_ops(self, input, label, **kwargs)
              -       """
              -       Add mini-batch evaluator caculate operators to the main_program.
              -       Add increment operator to accumulate the metric states.
              -       """
              -    
              -
              -    def reset(self, executor, reset_program=None):
              -      """
              -      Reset metric states at the begin of each pass/user specified batch number.
              -      Execute the reset_program to reset the states.
              -      """
              -      
              -
              -    def eval(self, executor, eval_program=None):
              -      """
              -      Merge the mini-batch statistics to form the evaluation result for multiple mini-batches.
              -      Execute the eval_program and return the result.
              -      """
              -      return eval_result
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/executor.html b/develop/doc/design/executor.html deleted file mode 100644 index 92243f88022..00000000000 --- a/develop/doc/design/executor.html +++ /dev/null @@ -1,284 +0,0 @@ - - - - - - - - - - - - - Executor Design Doc — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Executor Design Doc

              -
              -

              Motivation

              -

              In fluid, we encourage the user to use deep learning programming paradigms to describe the training process. When the user-written Python program is executed, it will first create a protobuf message -ProgramDesc that describes the process and is conceptually like an abstract syntax tree.

              -

              The executor runs the ProgramDesc like an interpreter. ProgramDesc contains the intrinsics (operators in this case) and variables which will be used, executor explicitly executes the stored precompiled code.

              -
              -
              -

              Overview

              -

              An executor takes a ProgramDesc, a block_id and a Scope. The ProgramDesc is a list of blocks and each block contains the protobuf definition of all the parameters and operators in the block. The block_id specifies the entrance block. And the Scope is the container of all the variable instances, which is persistent throughout different runs.

              -
              -
              -

              Executor

              -

              The Executor explicitly executes all the intrinsics (operators here) in the block_idth block of a ProgramDesc. Essentially, it instantiates Variables and Operators, then runs all the operators in sequence one-by-one. -It is very similar to how a push stack frame works when entering a block, following which it cleans up all the temporary variables when a mini-batch is finished. It does not however, have the stack frame pop process.

              -
              -

              The interface

              -
                Executor(places);
              -
              -
              -

              A executor does not own any computing resources, a user can only construct an executor using the specified places.

              -
              -
              -

              Running an Executor

              -
                void Run(ProgramDesc, Scope, block_id, create_local_scope);
              -
              -
              -

              An Executor only provides a unified way to execute ProgramDesc. ProgramDesc is the target that will be executed, the Scope specifies the variable container, the block_id indicates the entrance block and create_local_scope is a boolean that states whether it will destroy the temporary variables after the execution is finished.

              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/file_manager/README.html b/develop/doc/design/file_manager/README.html deleted file mode 100644 index 8160b3c67db..00000000000 --- a/develop/doc/design/file_manager/README.html +++ /dev/null @@ -1,365 +0,0 @@ - - - - - - - - - - - - - FileManager设计文档 — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              FileManager设计文档

              -
              -

              目标

              -

              在本文档中,我们设计说明了名为FileManager系统,方便用户上传自己的训练数据以进行分布式训练

              -

              主要功能包括:

              -
                -
              • 提供常用的命令行管理命令管理文件和目录
              • -
              • 支持大文件的断点上传、下载
              • -
              -
              -
              -

              名词解释

              -
                -
              • PFS:是Paddlepaddle cloud File System的缩写,是对用户文件存储空间的抽象,与之相对的是local filesystem。目前我们用CephFS来搭建。
              • -
              • CephFS:一个POSIX兼容的文件系统。
              • -
              • Chunk:逻辑划上文件分块的单位。
              • -
              -
              -
              -

              模块

              -
              -

              架构图

              -

              -
              -
              -

              PFSClient

              -
                -
              • 功能: 详细设计link
                  -
                • 提供用户管理文件的命令
                • -
                • 需要可以跨平台执行
                • -
                -
              • -
              • 双向验证PFSClient需要和Ingress之间做双向验证tls,所以用户需要首先在cloud.paddlepaddle.org上注册一下,申请用户空间,并且把系统生成的CA(certificate authority)、Key、CRT(CA signed certificate)下载到本地,然后才能使用PFSClient。
              • -
              -
              -
              -

              Ingress

              -
                -
              • 功能:提供七层协议的反向代理、基于粘性会话的负载均衡功能。
              • -
              • 透传用户身份的办法Ingress需要把PFSClient的身份信息传给PFSServer,配置的方法参考link
              • -
              -
              -
              -

              PFSServer

              -

              PFSServer提供RESTful API接口,接收处理PFSClient端的文件管理请求,并且把结果返回PFSClient端。

              -

              RESTful API

              -
                -
              • /api/v1/files
                  -
                • GET /api/v1/files: Get metadata of files or directories.
                • -
                • POST /api/v1/files: Create files or directories.
                • -
                • PATCH /api/v1/files: Update files or directories.
                • -
                • DELETE /api/v1/files: Delete files or directories.
                • -
                -
              • -
              • /api/v1/file/chunks
                  -
                • GET /api/v1/storage/file/chunks: Get chunks’s metadata of a file.
                • -
                -
              • -
              • /api/v1/storage/files
                  -
                • GET /api/v1/storage/files: Download files or directories.
                • -
                • POST /api/v1/storage/files: Upload files or directories.
                • -
                -
              • -
              • /api/v1/storage/file/chunks
                  -
                • GET /api/v1/storage/file/chunks: Download chunks’s data.
                • -
                • POST /api/v1/storage/file/chunks: Upload chunks’s data.
                • -
                -
              • -
              -
              -
              -
              -

              文件传输优化

              -
              -

              分块文件传输

              -

              用户文件可能是比较大的,上传到Cloud或者下载到本地的时间可能比较长,而且在传输的过程中也可能出现网络不稳定的情况。为了应对以上的问题,我们提出了Chunk的概念,一个Chunk由所在的文件偏移、数据、数据长度及校验值组成。文件的上传和下载都是通过对Chunk的操作来实现的。由于Chunk比较小(默认256K),完成一个传输动作完成的时间也比较短,不容易出错。PFSClient需要在传输完毕最后一个Chunk的时候检查destination文件的MD5值是否和source文件一致。

              -

              一个典型的Chunk如下所示:

              -
              type Chunk struct {
              -    fileOffset int64
              -    checksum uint32
              -    len     uint32
              -    data    []byte
              -}
              -
              -
              -
              -
              -

              生成sparse文件

              -

              当destination文件不存在或者大小和source文件不一致时,可以用Fallocate生成sparse文件,然后就可以并发写入多个Chunk。

              -
              -
              -

              覆盖不一致的部分

              -

              文件传输的的关键在于需要PFSClient端对比source和destination的文件Chunks的checksum是否保持一致,不一致的由PFSClient下载或者传输Chunk完成。这样已经传输成功的部分就不用重新传输了。

              -
              -
              -
              -

              用户使用流程

              -

              参考link

              -
              -
              -

              框架生成

              -

              swagger生成PFSClient和PFSServer的框架部分,以便我们可以把更多的精力放到逻辑本身上。

              -
              - -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/file_manager/pfs/pfsclient.html b/develop/doc/design/file_manager/pfs/pfsclient.html deleted file mode 100644 index 8e2d7f67417..00000000000 --- a/develop/doc/design/file_manager/pfs/pfsclient.html +++ /dev/null @@ -1,391 +0,0 @@ - - - - - - - - - - - - - PFSClient — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              PFSClient

              -
              -

              Description

              -

              The pfs command is a Command Line Interface to manage your files on PaddlePaddle Cloud

              -
              -
              -

              Synopsis

              -
              paddle [options] pfs <subcommand> [parameters]
              -
              -
              -
              -
              -

              Options

              -
              --profile (string)
              -    Use a specific profile from your credential file.
              -
              ---help (string)
              -    Display more information about command
              -
              ---version
              -    Output version information and exit
              -
              ---debug
              -    Show detailed debugging log 
              -    
              ---only-show-errors (boolean) 
              -    Only errors and warnings are displayed. All other output is suppressed.
              -
              -
              -
              -
              -

              Path Arguments

              -

              When using a command, we need to specify path arguments. There are two path argument type: localpath and pfspath.

              -

              A pfspath begin with /pfs, eg: /pfs/$DATACENTER/home/$USER/folder.

              -

              Here is how to config datacenters.

              -
              -
              -

              order of Path Arguments

              -

              Commonly, if there are two path arguments, the first is the source, and the second is the destination.

              -
              -
              -

              Subcommonds

              -
                -
              • rm - remove files or directories
              • -
              -
              Synopsis:
              -    rm [-r] [-v] <PFSPath> ...
              -
              -Options:
              -    -r 
              -        Remove directories and their contents recursively 
              -    -v      
              -        Cause rm to be verbose, showing files after they are removed.
              -    
              -Examples:
              -    paddle pfs rm /pfs/$DATACENTER/home/$USER/file
              -    paddle pfs rm -r /pfs/$DATACENTER/home/$USER/folder
              -
              -
              -
                -
              • mv - move (rename) files
              • -
              -
              Synopsis:
              -    mv [-f | -n] [-v] <LocalPath> <PFSPath>
              -    mv [-f | -n] [-v] <LocalPath> ... <PFSPath>
              -    mv [-f | -n] [-v] <PFSPath> <LocalPath> 
              -    mv [-f | -n] [-v] <PFSPath> ... <LocalPath> 
              -    mv [-f | -n] [-v] <PFSPath> <PFSPath> 
              -    mv [-f | -n] [-v] <PFSPath> ... <PFSPath> 
              -    
              -Options:
              -    -f      
              -        Do not prompt for confirmation before overwriting the destination path.  (The -f option overrides previous -n options.)
              -    -n      
              -        Do not overwrite an existing file.  (The -n option overrides previous -f options.)
              -    -v      
              -        Cause mv to be verbose, showing files after they are moved.
              -        
              -Examples:
              -    paddle pfs mv ./text1.txt /pfs/$DATACENTER/home/$USER/text1.txt
              -
              -
              -
                -
              • cp - copy files or directories
              • -
              -
              Synopsis:
              -    cp [-r] [-f | -n] [-v] [--preserve--links] <LocalPath> <PFSPath>
              -    cp [-r] [-f | -n] [-v] [--preserve--links] <LocalPath> ... <PFSPath>
              -    cp [-r] [-f | -n] [-v] [--preserve--links] <PFSPath> <LocalPath> 
              -    cp [-r] [-f | -n] [-v] [--preserve--links] <PFSPath> ... <LocalPath>
              -    cp [-r] [-f | -n] [-v] [--preserve--links] <PFSPath> <PFSPath> 
              -    cp [-r] [-f | -n] [-v] [--preserve--links] <PFSPath> ... <PFSPath>
              -
              -Options:
              -    -r
              -        Copy directories recursively
              -    -f      
              -        Do not prompt for confirmation before overwriting the destination path.  (The -f option overrides previous -n options.)
              -    -n      
              -        Do not overwrite an existing file.  (The -n option overrides previous -f options.)
              -    -v      
              -        Cause cp to be verbose, showing files after they are copied.
              -    --preserve--links
              -       Reserve links when copy links
              -       
              -Examples:
              -    paddle pfs cp ./file /pfs/$DATACENTER/home/$USER/file
              -    paddle pfs cp /pfs/$DATACENTER/home/$USER/file ./file
              -
              -
              -
                -
              • ls- list files
              • -
              -
              Synopsis:
              -    ls [-r] <PFSPath> ...
              -    
              -Options:
              -    -R
              -        List directory(ies) recursively
              -
              -Examples:
              -    paddle pfs ls  /pfs/$DATACENTER/home/$USER/file
              -    paddle pfs ls  /pfs/$DATACENTER/home/$USER/folder
              -
              -
              -
                -
              • mkdir - mkdir directory(ies) -Create intermediate directory(ies) as required.
              • -
              -
              Synopsis:
              -    mkdir <PFSPath> ...
              -
              -Examples:
              -    paddle pfs mkdir  /pfs/$DATACENTER/home/$USER/folder
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/float16.html b/develop/doc/design/float16.html deleted file mode 100644 index 355a5a79d45..00000000000 --- a/develop/doc/design/float16.html +++ /dev/null @@ -1,370 +0,0 @@ - - - - - - - - - - - - - Design Doc: float16 — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: float16

              -
              -

              Why float16

              -

              Half precision (float16) is a binary floating-point format that occupies 16 bits in memory. float16 is half the size of traditional 32-bit single precision format (float) and has lower precision and smaller range.

              -

              When high precision computation is not required, using float16 data type could potentially

              -
                -
              • reduce storage space, memory bandwidth, and power usages;
              • -
              • increase the chance of data fitting into a smaller cache of lower latency;
              • -
              • provide arithmetic speed up if supported by hardware.
              • -
              -
              -
              -

              Survey of current float16 support

              -

              A brief survey of float16 support on different compilers, hardwares, and libraries can be found below. Interested readers can refer to link1 and link2 for more info.

              -

              The goal of float16 is to serve as a key for the executor to find and run the correct version of compute method specialized for float16 in operator kernel. It should be compatible with various natively supported float16 implementations including __half for cuda, float16_t for ARM, and Eigen::half for Eigen to make writing customized float16 kernels easier.

              -
              -

              Compiler

              -
                -
              • nvcc supports __half data type after CUDA 7.5.
              • -
              • __fp16 or float16_t is supported as storage type for gcc >= 6.1 and clang >= 3.4.
              • -
              • __fp16 or float16_t is supported as arithmetic type for gcc >= 7.1 and clang >= 3.9.
              • -
              -
              -
              -

              Hardware

              -
                -
              • __half is supported on GPU with compute capability >= 5.3.
              • -
              • __fp16 is supported as storage type for ARMv7-A, ARMv8-A, and above.
              • -
              • __fp16 is supported as arithmetic type after ARMv8.2-A (currently, the only microarchitecture implementing ARMv8.2-A is ARM Cortex-A75, which is announced in May 2017. There seems to be no application processors currently available on market that adopts this architecture. It is reported that Qualcomm Snapdragon 845 uses Cortex-A75 design and will be available in mobile devices in early 2018).
              • -
              -
              -
              -

              Libraries

              -
                -
              • Eigen >= 3.3 supports float16 calculation on both GPU and CPU using the Eigen::half class. It is mostly useful for Nvidia GPUs because of the overloaded arithmetic operators using cuda intrinsics. It falls back to using software emulation on CPU for calculation and there is no special treatment to ARM processors.
              • -
              • ARM compute library >= 17.02.01 supports NEON FP16 kernels (requires ARMv8.2-A CPU).
              • -
              -
              -
              -

              CUDA version issue

              -

              There are currently three versions of CUDA that supports __half data type, namely, CUDA 7.5, 8.0, and 9.0. -CUDA 7.5 and 8.0 define __half as a simple struct that has a uint16_t data (see cuda_fp16.h) as follows:

              -
              typedef struct __align__(2) {
              -   unsigned short x;
              -} __half;
              -
              -typedef __half half;
              -
              -
              -

              This struct does not define any overloaded arithmetic operators. So you have to directly use __hadd instead of + to correctly add two half types:

              -
              __global__ void Add() {
              -  half a, b, c;
              -  c = __hadd(a, b); // correct
              -  c = a + b; // compiler error: no operator "+" matches these operands
              -}
              -
              -
              -

              CUDA 9.0 provides a major update to the half data type. The related code can be found in the updated cuda_fp16.h and the newly added cuda_fp16.hpp.

              -

              Essentially, CUDA 9.0 renames the original __half type in 7.5 and 8.0 as __half_raw, and defines a new __half class type that has constructors, conversion operators, and also provides overloaded arithmetic operators such as follows:

              -
              typedef struct __CUDA_ALIGN__(2) {
              -    unsigned short x;
              -} __half_raw;
              -
              -
              -struct __CUDA_ALIGN__(2) __half {
              -protected:
              -    unsigned short __x;
              -public:
              -    // constructors and conversion operators from/to 
              -    // __half_raw and other built-in data types
              -}
              -
              -typedef __half half;
              -
              -__device__ __forceinline__ 
              -__half operator+(const __half &lh, const __half &rh) { 
              -    return __hadd(lh, rh); 
              -}
              -
              -// Other overloaded operators
              -
              -
              -

              This new design makes c = a + b work correctly for CUDA half data type.

              -
              -
              -
              -

              Implementation

              -

              The float16 class holds a 16-bit uint16_t data internally.

              -
              struct float16 {
              -  uint16_t x;
              -};
              -
              -
              -

              float16 supports the following features:

              -
                -
              • constructors / assignment operators that take input from primitive data types including bool, integers of various length, float, and double.
              • -
              • constructors / assignment operators that take input from __half on cuda, float16_t on ARM, and Eigen::half on Eigen.
              • -
              • conversion operators to primitive data types and half precision data types on cuda, ARM and Eigen.
              • -
              • overloaded arithmetic operators for cuda, arm, and non-arm cpu, respectively. These operators will take advantage of the cuda and ARM intrinsics on the corresponding hardware.
              • -
              -

              To support the above features, two fundamental conversion functions are provided:

              -
              float16 float_to_half_rn(float f);  // convert to half precision in round-to-nearest-even mode
              -float half_to_float(float16 h);
              -
              -
              -

              which provides one-to-one conversion between float32 and float16. These twos functions will do different conversion routines based on the current hardware. CUDA/ARM instrinsics will be used when the corresonding hardware is available. If the hardware or compiler level does not support float32 to float16 conversion, software emulation will be performed to do the conversion.

              -
              -
              -

              To do

              -

              After float16 class is available, some of the future items are below:

              -
                -
              • Update pybind/tensor_py.h to bind c++ float16 with numpy float16.
              • -
              • Modify GetKernelType() method in framework/operator.h to make it compatible with float16.
              • -
              • Create a type-casting operator that can convert the data type in tensor between float16 and other types.
              • -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/fluid.html b/develop/doc/design/fluid.html deleted file mode 100644 index 9084d6b4f98..00000000000 --- a/develop/doc/design/fluid.html +++ /dev/null @@ -1,350 +0,0 @@ - - - - - - - - - - - - - Design Doc: PaddlePaddle Fluid — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: PaddlePaddle Fluid

              -
              -

              Why Fluid

              -

              When Baidu developed PaddlePaddle in 2013, the only well-known open source deep learning system at the time was Caffe. However, when PaddlePaddle was open-sourced in 2016, many other choices were available. There was a challenge – what is the need for open sourcing yet another deep learning framework?

              -

              Fluid is the answer. Fluid is similar to PyTorch and TensorFlow Eager Execution, which describes the “process” of training or inference using the concept of a model. In fact in PyTorch, TensorFlow Eager Execution and Fluid, there is no concept of a model at all. The details are covered in the sections below. Fluid is currently more extreme in the above mentioned idea than PyTorch and Eager Execution, and we are trying to push Fluid towards the directions of a compiler and a new programming language for deep learning.

              -
              -
              -

              The Evolution of Deep Learning Systems

              -

              Deep learning infrastructure is one of the fastest evolving technologies. Within four years, there have already been three generations of technologies invented.

              -

              | Existed since | model as sequence of layers | model as graph of operators | No model | -|–|–|–|–| -| 2013 | Caffe, Theano, Torch, PaddlePaddle | | | -| 2015 | | TensorFlow, MxNet, Caffe2, ONNX, n-graph | | -| 2016 | | | PyTorch, TensorFlow Eager Execution, PaddlePaddle Fluid |

              -

              From the above table, we see that the deep learning technology is evolving towards getting rid of the concept of a model. To understand the reasons behind this direction, a comparison of the programming paradigms or the ways to program deep learning applications using these systems, would be helpful. The following section goes over these.

              -
              -
              -

              Deep Learning Programming Paradigms

              -

              With the systems listed as the first or second generation, e.g., Caffe or TensorFlow, an AI application training program looks like the following:

              -
              x = layer.data("image")
              -l = layer.data("label")
              -f = layer.fc(x, W)
              -s = layer.softmax(f)
              -c = layer.mse(l, s)
              -
              -for i in xrange(1000): # train for 1000 iterations
              -    m = read_minibatch()
              -    forward({input=x, data=m}, minimize=c)
              -    backward(...)
              -
              -print W # print the trained model parameters.
              -
              -
              -

              The above program includes two parts:

              -
                -
              1. The first part describes the model, and
              2. -
              3. The second part describes the training process (or inference process) for the model.
              4. -
              -

              This paradigm has a well-known problem that limits the productivity of programmers. If the programmer made a mistake in configuring the model, the error messages wouldn’t show up until the second part is executed and forward and backward propagations are performed. This makes it difficult for the programmer to debug and locate a mistake that is located blocks away from the actual error prompt.

              -

              This problem of being hard to debug and re-iterate fast on a program is the primary reason that programmers, in general, prefer PyTorch over the older systems. Using PyTorch, we would write the above program as following:

              -
              W = tensor(...)
              -
              -for i in xrange(1000): # train for 1000 iterations
              -    m = read_minibatch()
              -    x = m["image"]
              -    l = m["label"]
              -    f = layer.fc(x, W)
              -    s = layer.softmax(f)
              -    c = layer.mse(l, s)
              -    backward()
              -
              -print W # print the trained model parameters.
              -
              -
              -

              We can see that the main difference is the moving the model configuration part (the first step) into the training loop. This change would allow the mistakes in model configuration to be reported where they actually appear in the programming block. This change also represents the model better, or its forward pass, by keeping the configuration process in the training loop.

              -
              -
              -

              Describe Arbitrary Models for the Future

              -

              Describing the process instead of the model also brings Fluid, the flexibility to define different non-standard models that haven’t been invented yet.

              -

              As we write out the program for the process, we can write an RNN as a loop, instead of an RNN as a layer or as an operator. A PyTorch example would look like the following:

              -
              for i in xrange(1000):
              -    m = read_minibatch()
              -    x = m["sentence"]
              -    for t in xrange x.len():
              -        h[t] = the_step(x[t])
              -
              -
              -

              With Fluid, the training loop and the RNN in the above program are not really Python loops, but just a “loop structure” provided by Fluid and implemented in C++ as the following:

              -
              train_loop = layers.While(cond)
              -with train_loop.block():
              -  m = read_minibatch()
              -  x = m["sentence"]
              -  rnn = layers.While(...)
              -  with rnn.block():
              -    h[t] = the_step(input[t])
              -
              -
              -

              An actual Fluid example is described here.

              -

              From the example, the Fluid programs look very similar to their PyTorch equivalent programs, except that Fluid’s loop structure, wrapped with Python’s with statement, could run much faster than just a Python loop.

              -

              We have more examples of the if-then-else structure of Fluid.

              -
              -
              -

              Turing Completeness

              -

              In computability theory, a system of data-manipulation rules, such as a programming language, is said to be Turing complete if it can be used to simulate any Turing machine. For a programming language, if it provides if-then-else and loop, it is Turing complete. From the above examples, Fluid seems to be Turing complete; however, it is noteworthy to notice that there is a slight difference between the if-then-else of Fluid and that of a programming language. The difference being that the former runs both of its branches and splits the input mini-batch into two – one for the True condition and another for the False condition. This hasn’t been researched in depth if this is equivalent to the if-then-else in programming languages that makes them Turing-complete. Based on a conversation with Yuang Yu, it seems to be the case but this needs to be looked into in-depth.

              -
              -
              -

              The Execution of a Fluid Program

              -

              There are two ways to execute a Fluid program. When a program is executed, it creates a protobuf message ProgramDesc that describes the process and is conceptually like an abstract syntax tree.

              -

              There is a C++ class Executor, which runs a ProgramDesc, similar to how an interpreter runs a Python program.

              -

              Fluid is moving towards the direction of a compiler, which is explain in fluid.

              -
              -
              -

              Backward Compatibility of Fluid

              -

              Given all the advantages from the removal of the concept of a model, hardware manufacturers might still prefer the existence of the concept of a model, so it would be easier for them to support multiple frameworks all at once and could run a trained model during inference. For example, Nervana, a startup company acquired by Intel, has been working on an XPU that reads the models in the format known as n-graph. Similarly, Movidius is producing a mobile deep learning chip that reads and runs graphs of operators. The well-known ONNX is also a file format of graphs of operators.

              -

              For Fluid, we can write a converter that extracts the parts in the ProgramDesc protobuf message, converts them into a graph of operators, and exports the graph into the ONNX or n-graph format.

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/fluid_compiler.html b/develop/doc/design/fluid_compiler.html deleted file mode 100644 index 443508b649d..00000000000 --- a/develop/doc/design/fluid_compiler.html +++ /dev/null @@ -1,352 +0,0 @@ - - - - - - - - - - - - - PaddlePaddle Fluid: Towards a Compiled Programming Language — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              -
                -
              • Docs »
              • - -
              • PaddlePaddle Fluid: Towards a Compiled Programming Language
              • -
              • - - - View page source - - -
              • -
              -
              -
              -
              -
              - -
              -

              PaddlePaddle Fluid: Towards a Compiled Programming Language

              -

              As described in fluid.md, when a Fluid application program -runs, it generates a ProgramDesc protobuf message as an intermediate -representation of itself. The C++ class Executor can run this -protobuf message as an interpreter. This article describes the Fluid -compiler.

              -

              -
              -

              ProgramDesc

              -

              Before we go deeper into the idea of compiled language, let us take a -look at a simple example Fluid application.

              -
              import "fluid"
              -
              -func paddlepaddle() {
              -  X = fluid.read(...)
              -  W = fluid.Tensor(...)
              -  Y = fluid.mult(X, W)
              -}
              -
              -
              -

              This program consists of a block of three operators – -read, assign, and mult. Its ProgramDesc message looks like -the following

              -
              message ProgramDesc {
              -  block[0] = Block {
              -    vars = [X, W, Y],
              -    ops = [
              -      read(output = X)
              -      assign(input = ..., output = W)
              -      mult(input = {X, W}, output = Y)
              -    ],
              -  }
              -}
              -
              -
              -
              -
              -

              Transpilers

              -

              We can write a transpiler program that takes a ProgramDesc, e.g., -the above one, and outputs another ProgramDesc. Let us take some -examples:

              -
                -
              1. Memory optimization transpiler: We can write a transpiler that -inserts some FreeMemoryOps in the above example ProgramDesc so -to free memory early, before the end of an iteration, so to keep a -small memory footprint.
              2. -
              3. Distributed training transpiler: We can write a transpiler that -converts aProgramDesc into its distributed version of two -ProgramDescs – one for running by the trainer processes and the -other for the parameter server.
              4. -
              -

              In the rest of this article, we talk about a special kind of -transpiler, Native code generator, which takes a ProgramDesc and -generates a .cu (or .cc) file, which could be built by C++ -compilers (gcc, nvcc, icc) into binaries.

              -
              -
              -

              Native Code Generator

              -

              For the above example, the native code generator transpiler, say, the -CUDA code generator, should generate a main function:

              -
              void main() {
              -  auto X = fluid_cuda_read(...);
              -  auto W = fluid_cuda_create_tensor(...);
              -  auto Y = fluid_cuda_mult(X, W);
              -}
              -
              -
              -

              and the definitions of functions fluid_cuda_read, -fluid_cuda_create_tensor, and fluid_cuda_mult. Please be aware -that each function could just define a C++ instance of an operator and -run it. For example

              -
              paddle::Tensor fluid_cuda_read(...) {
              -  paddle::Tensor t;
              -  paddle::operator::Read r(&t, ...);
              -  r.Run();
              -  return t;
              -}
              -
              -
              -

              For computational operators that have multiple kernels, each for a -specific hardware platform, for example, the mult operator, the -generated code should call its CUDA kernel:

              -
              paddle::Tensor fluid_cuda_mult(const paddle::Tensor& a, 
              -                               const paddle::Tensor& b) {
              -  paddle::Tensor t;
              -  paddle::operator::Mult m(a, b, ...);
              -  Mult.Run(cuda_context);
              -}
              -
              -
              -

              where cuda_context could be a global variable of type -paddle::CUDADeviceContext.

              -
              -
              -

              Multi-Block Code Generation

              -

              Most Fluid application programs may have more than one blocks. To -execute them, we need to trace scopes.

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/functions_operators_layers.html b/develop/doc/design/functions_operators_layers.html deleted file mode 100644 index fff2ecae7bd..00000000000 --- a/develop/doc/design/functions_operators_layers.html +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - - - - - - - - Design Doc: Functions, Operators, and Layers — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Functions, Operators, and Layers

              -

              In a DL system, we can compose one or more fine grained operators into a coarse grained one. For example, the FC layer can be composed of a multiplication operator and an add operator.

              -

              Historically, some fine grained operations are known as operators, and some coarse level ones are known as layers. But we need a well-defined separation.

              -

              In general, operators are those very fine grained operations, e.g., mul and add. In the implementation, we can write them as C++ functions:

              -
              template <typename T> T add(T x, T y) { return x + y; }
              -template <typename T> T mul(T x, T y) { return x * y; }
              -
              -
              -

              Then we can wrap them into operators which are C++ classes and can be created from Python bindings by name. A C macro can do this. For example, the following macro invocation

              -
              #define MAKE_FUNCTION_OPERATOR(mul);
              -
              -
              -

              generates

              -
              template <typename T> class mulOp : public OperatorBase {...};
              -REGISTER_OP(mulOp<float32>, "mul");
              -
              -
              -

              so that in Python we can create operator mul by:

              -
              X1 = Var()
              -X2 = Var()
              -Y = Var()
              -paddle.cpp.create_operator("mul", input=[X1, X2], output=Y)
              -
              -
              -

              Also, at the same time, we can compose a coarse level C++ operator class by composing functions mul and add:

              -
              template <typename T>
              -class FCOp : public OperatorBase {
              - public:
              -  void Run(...) {
              -    add(mul(Input<T>("X"), Input<T>("W")), Input<T>("b");
              -  }
              -};
              -REGISTER_OP(FCOp, "fc");
              -
              -
              -

              We need to support such composition in Python as well. To do so, we need a higher level Python wrapping of operator creation than paddle.cpp.create_operator. This higher level operator API should be compatible with the layer API.

              -

              Let’s explain using an example. Suppose that we are going to compose the FC using mul and add in Python, we’d like to have Python functions mul and add defined in module operator:

              -
              def operator.mul(X1, X2):
              -    O = Var()
              -    paddle.cpp.create_operator("mul", input={X1, Y1}, output=O)
              -    return O
              -
              -def operator.add(X1, X2):
              -    O = Var()
              -    paddle.cpp.create_operator("add", input={X1, X2}, output=O)
              -    return O
              -
              -
              -

              Above code snippets are automatically generated. Given them, users can define

              -
              def layer.fc(X):
              -    W = Var()
              -    b = Var()
              -    return operator.add(operator.mul(X, W), b)
              -
              -
              -

              If we don’t have operator.mul and operator.add, the definiton of layer.fc would be complicated:

              -
              def layer.fc(X):
              -    W = Var()
              -    b = Var()
              -    O1 = Var()
              -    paddle.cpp.create_operator("mul", input=[X, W], output=O1)
              -    O2 = Var()
              -    paddle.cpp.create_operator("add", input=[O1, b], output=O2)
              -    return O2
              -
              -
              -

              We’d like to have Python bindings to operators in package paddle.operator, and Python compositions of operators in package paddle.layer. So we have the following concepts in above illustrative example:

              -

              | C++ functions/functors | mul | add | | | -|————————|————–|————–|————-|———-| -| C++ operator class | mulOp | addOp | FCOp | | -| Python binding | operator.mul | operator.add | operator.fc | | -| Python function | | | | layer.fc |

              -

              This is how we differentiate layer and operators in PaddlePaddle:

              -
                -
              • those defined in C++ and have a lightweighted Python wrapper in module operators are operators; whereas
              • -
              • those who don’t have C++ implementations but a Python implementation that compose C++ operators are known as layers.
              • -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/gan_api.html b/develop/doc/design/gan_api.html deleted file mode 100644 index 462f930e90d..00000000000 --- a/develop/doc/design/gan_api.html +++ /dev/null @@ -1,518 +0,0 @@ - - - - - - - - - - - - - Design for GAN — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design for GAN

              -

              GAN (General Adversarial Net [https://arxiv.org/abs/1406.2661]) is an important model for unsupervised learning and widely used in many areas.

              -

              It applies several important concepts in machine learning system design, including building and running subgraphs, dependency tracing, different optimizers in one executor and so forth.

              -

              In our GAN design, we wrap it as a user-friendly easily customized python API to design different models. We take the conditional DC-GAN (Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks [https://arxiv.org/abs/1511.06434]) as an example due to its good performance on image generation.

              -

              -
              -Figure 1. The overall running logic of GAN. The black solid arrows indicate the forward pass; the green dashed arrows indicate the backward pass of generator training; the red dashed arrows indicate the backward pass of the discriminator training. The BP pass of the green (red) arrow should only update the parameters in the green (red) boxes. The diamonds indicate the data providers. d\_loss and g\_loss marked in red and green are the two targets we would like to run. -

              The operators, layers and functions required/optional to build a GAN demo is summarized in https://github.com/PaddlePaddle/Paddle/issues/4563.

              -

              -
              -Figure 2. Photo borrowed from the original DC-GAN paper. -

              -

              The Conditional-GAN might be a class.

              -

              This design we adopt the popular open source design in https://github.com/carpedm20/DCGAN-tensorflow and https://github.com/rajathkmp/DCGAN. It contains following data structure:

              -
                -
              • DCGAN(object): which contains everything required to build a GAN model. It provides following member functions methods as API:
              • -
              • init(...): Initialize hyper-parameters (like conv dimension and so forth), and declare model parameters of discriminator and generator as well.
              • -
              • generator(z, y=None): Generate a fake image from input noise z. If the label y is provided, the conditional GAN model will be chosen. -Returns a generated image.
              • -
              • discriminator(image): -Given an image, decide if it is from a real source or a fake one. -Returns a 0/1 binary label.
              • -
              • build_model(self): -build the whole GAN model, define training loss for both generator and discrimator.
              • -
              -
              -
              -

              Discussion on Engine Functions required to build GAN

              -
                -
              • Trace the tensor and variable dependency in the engine executor. (Very critical, otherwise GAN can’be be trained correctly)
              • -
              • Different optimizers responsible for optimizing different loss.
              • -
              -

              To be more detailed, we introduce our design of DCGAN as following:

              -
              -

              Class member Function: Initializer

              -
                -
              • Set up hyper-parameters, including condtional dimension, noise dimension, batch size and so forth.
              • -
              • Declare and define all the model variables. All the discriminator parameters are included in the list self.theta_D and all the generator parameters are included in the list self.theta_G.
              • -
              -
              class DCGAN(object):
              -  def __init__(self, y_dim=None):
              -  
              -    # hyper parameters  
              -    self.y_dim = y_dim # conditional gan or not
              -    self.batch_size = 100
              -    self.z_dim = z_dim # input noise dimension
              -
              -    # define parameters of discriminators
              -    self.D_W0 = pd.Variable(shape=[3,3, 1, 128], data=pd.gaussian_normal_randomizer())
              -    self.D_b0 = pd.Variable(np.zeros(128)) # variable also support initialization using a  numpy data
              -    self.D_W1 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer())
              -    self.D_b1 = pd.Variable(np.zeros(128)) # variable also support initialization using a  numpy data
              -    self.D_W2 = pd.Varialble(np.random.rand(128, 1))
              -    self.D_b2 = pd.Variable(np.zeros(128))
              -    self.theta_D = [self.D_W0, self.D_b0, self.D_W1, self.D_b1, self.D_W2, self.D_b2]
              -
              -    # define parameters of generators
              -    self.G_W0 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer())
              -    self.G_b0 = pd.Variable(np.zeros(128)) # variable also support initialization using a  numpy data
              -    self.G_W1 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer())
              -    self.G_b1 = pd.Variable(np.zeros(128)) # variable also support initialization using a  numpy data
              -    self.G_W2 = pd.Varialble(np.random.rand(128, 1))
              -    self.G_b2 = pd.Variable(np.zeros(128))
              -    self.theta_G = [self.G_W0, self.G_b0, self.G_W1, self.G_b1, self.G_W2, self.G_b2]
              -
              -
              -
              -
              -

              Class member Function: Generator

              -
                -
              • Given a noisy input z, returns a fake image.
              • -
              • Concatenation, batch-norm, FC operations required;
              • -
              • Deconv layer required, which is missing now...
              • -
              -
              class DCGAN(object):
              -  def generator(self, z, y = None):
              -    # input z: the random noise
              -    # input y: input data label (optional)
              -    # output G_im: generated fake images
              -    
              -    if not self.y_dim:
              -      z = pd.layer.concat(1, [z, y])
              -      
              -    G_h0 = pd.layer.fc(z, self.G_w0, self.G_b0)
              -    G_h0_bn = pd.layer.batch_norm(G_h0)
              -    G_h0_relu = pd.layer.relu(G_h0_bn)
              -    
              -    G_h1 = pd.layer.deconv(G_h0_relu, self.G_w1, self.G_b1)
              -    G_h1_bn = pd.layer.batch_norm(G_h1)
              -    G_h1_relu = pd.layer.relu(G_h1_bn)
              -    
              -    G_h2 = pd.layer.deconv(G_h1_relu, self.G_W2, self.G_b2))
              -    G_im = pd.layer.tanh(G_im)
              -    return G_im
              -
              -
              -
              -
              -

              Class member function: Discriminator

              -
                -
              • Given a noisy input z, returns a fake image.
              • -
              • Concatenation, Convolution, batch-norm, FC, Leaky-ReLU operations required;
              • -
              -
              class DCGAN(object):
              -  def discriminator(self, image):
              -    # input image: either generated images or real ones
              -    # output D_h2: binary logit of the label
              -
              -    D_h0 = pd.layer.conv2d(image, w=self.D_w0, b=self.D_b0)
              -    D_h0_bn = pd.layer.batchnorm(h0)
              -    D_h0_relu = pd.layer.lrelu(h0_bn)
              -    
              -    D_h1 = pd.layer.conv2d(D_h0_relu, w=self.D_w1, b=self.D_b1)
              -    D_h1_bn = pd.layer.batchnorm(D_h1)
              -    D_h1_relu = pd.layer.lrelu(D_h1_bn)
              -    
              -    D_h2 = pd.layer.fc(D_h1_relu, w=self.D_w2, b=self.D_b2)
              -    return D_h2
              -
              -
              -
              -
              -

              Class member function: Build the model

              -
                -
              • Define data readers as placeholders to hold the data;
              • -
              • Build generator and discriminators;
              • -
              • Define two training losses for discriminator and generator, respectively. -If we have execution dependency engine to back-trace all tensors, the module building our GAN model will be like this:
              • -
              -
              class DCGAN(object):
              -  def build_model(self):
              -    if self.y_dim:
              -        self.y = pd.data(pd.float32, [self.batch_size, self.y_dim])
              -    self.images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size])
              -    self.faked_images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size])
              -    self.z = pd.data(tf.float32, [None, self.z_size])
              -    
              -    # step 1: generate images by generator, classify real/fake images with discriminator
              -    if self.y_dim: # if conditional GAN, includes label
              -        self.G = self.generator(self.z, self.y)
              -        self.D_t = self.discriminator(self.images)
              -        # generated fake images
              -        self.sampled = self.sampler(self.z, self.y)
              -        self.D_f = self.discriminator(self.G)
              -    else: # original version of GAN
              -        self.G = self.generator(self.z)
              -        self.D_t = self.discriminator(self.images)
              -        # generate fake images
              -        self.sampled = self.sampler(self.z)
              -        self.D_f = self.discriminator(self.images)
              -    
              -    # step 2: define the two losses
              -    self.d_loss_real = pd.reduce_mean(pd.cross_entropy(self.D_t, np.ones(self.batch_size))
              -    self.d_loss_fake = pd.reduce_mean(pd.cross_entropy(self.D_f, np.zeros(self.batch_size))
              -    self.d_loss = self.d_loss_real + self.d_loss_fake
              -    
              -    self.g_loss = pd.reduce_mean(pd.cross_entropy(self.D_f, np.ones(self.batch_szie))
              -
              -
              -

              If we do not have dependency engine but blocks, the module building our GAN model will be like this:

              -
              class DCGAN(object):
              -  def build_model(self, default_block):
              -    # input data in the default block
              -    if self.y_dim:
              -        self.y = pd.data(pd.float32, [self.batch_size, self.y_dim])
              -    self.images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size])
              -    # self.faked_images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size])
              -    self.z = pd.data(tf.float32, [None, self.z_size])
              -
              -    # step 1: generate images by generator, classify real/fake images with discriminator
              -    with pd.default_block().g_block():
              -      if self.y_dim: # if conditional GAN, includes label
              -        self.G = self.generator(self.z, self.y)
              -        self.D_g = self.discriminator(self.G, self.y)
              -      else: # original version of GAN
              -        self.G = self.generator(self.z)
              -        self.D_g = self.discriminator(self.G, self.y)
              -      self.g_loss = pd.reduce_mean(pd.cross_entropy(self.D_g, np.ones(self.batch_szie))
              -    
              -    with pd.default_block().d_block():
              -      if self.y_dim: # if conditional GAN, includes label
              -        self.D_t = self.discriminator(self.images, self.y)
              -        self.D_f = self.discriminator(self.G, self.y)
              -      else: # original version of GAN
              -        self.D_t = self.discriminator(self.images)
              -        self.D_f = self.discriminator(self.G)
              -
              -      # step 2: define the two losses
              -      self.d_loss_real = pd.reduce_mean(pd.cross_entropy(self.D_t, np.ones(self.batch_size))
              -      self.d_loss_fake = pd.reduce_mean(pd.cross_entropy(self.D_f, np.zeros(self.batch_size))
              -      self.d_loss = self.d_loss_real + self.d_loss_fake
              -
              -
              -

              Some small confusion and problems with this design:

              -
                -
              • D_g and D_f are actually the same thing, but has to be written twice; i.e., if we want to run two sub-graphs conceptually, the same codes have to be written twice if they are shared by the graph.
              • -
              • Requires ability to create a block anytime, rather than in if-else or rnn only;
              • -
              -
              -
              -
              -

              Main function for the demo:

              -

              Generally, the user of GAN just need to the following things:

              -
                -
              • Define an object as DCGAN class;
              • -
              • Build the DCGAN model;
              • -
              • Specify two optimizers for two different losses with respect to different parameters.
              • -
              -
              # pd for short, should be more concise.
              -from paddle.v2 as pd
              -import numpy as np
              -import logging
              -
              -if __name__ == "__main__":
              -    # dcgan class in the default graph/block
              -    # if we use dependency engine as tensorflow
              -    # the codes, will be slightly different like:
              -    # dcgan = DCGAN()
              -    # dcgan.build_model()
              -    with pd.block() as def_block:
              -      dcgan = DCGAN()
              -      dcgan.build_model(def_block)
              -
              -    # load mnist data
              -    data_X, data_y = self.load_mnist()
              -    
              -    # Two subgraphs required!!!
              -    with pd.block().d_block():
              -      d_optim = pd.train.Adam(lr = .001, beta= .1)
              -      d_step = d_optim.minimize(dcgan.d_loss, dcgan.theta_D)
              -    with pd.block.g_block():
              -      g_optim = pd.train.Adam(lr = .001, beta= .1)
              -      g_step = pd.minimize(dcgan.g_loss, dcgan.theta_G)
              -
              -    # executor
              -    sess = pd.executor()
              -    
              -    # training
              -    for epoch in xrange(10000):
              -      for batch_id in range(N / batch_size):
              -        idx = ...
              -        # sample a batch
              -        batch_im, batch_label = data_X[idx:idx+batch_size], data_y[idx:idx+batch_size]
              -        # sample z
              -        batch_z = np.random.uniform(-1., 1., [batch_size, z_dim])
              -
              -        if batch_id % 2 == 0:
              -          sess.run(d_step, 
              -                   feed_dict = {dcgan.images: batch_im,
              -                                dcgan.y: batch_label,
              -                                dcgan.z: batch_z})
              -        else:
              -          sess.run(g_step,
              -                   feed_dict = {dcgan.z: batch_z})
              -
              -
              -
              -
              -
              -

              More thinking about dependency engine v.s. block design:

              -
                -
              • What if we just want to run an intermediate result? Do we need to run the whole block/graph?
              • -
              • Should we call eval() to get the fake images in the first stage? And then train the discriminator in the second stage?
              • -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/graph.html b/develop/doc/design/graph.html deleted file mode 100644 index f77f80cba16..00000000000 --- a/develop/doc/design/graph.html +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - - - - Design Doc: Computations as a Graph — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Computations as a Graph

              -

              A primary goal of the refactorization of PaddlePaddle is a more flexible representation of deep learning computation, in particular, a graph of operators and variables, instead of sequences of layers as before.

              -

              This document explains that the construction of a graph as three steps:

              -
                -
              • construct the forward part
              • -
              • construct the backward part
              • -
              • construct the optimization part
              • -
              -
              -

              The Construction of a Graph

              -

              Let us take the problem of image classification as a simple example. The application program that trains the model looks like:

              -
              x = layer.data("images")
              -l = layer.data("label")
              -y = layer.fc(x)
              -cost = layer.mse(y, l)
              -optimize(cost)
              -train(cost, reader=mnist.train())
              -
              -
              -
              -

              Forward Part

              -

              The first four lines of above program build the forward part of the graph.

              -

              -

              In particular, the first line x = layer.data("images") creates variable x and a Feed operator that copies a column from the minibatch to x. y = layer.fc(x) creates not only the FC operator and output variable y, but also two parameters, W and b, and the initialization operators.

              -

              Initialization operators are kind of “run-once” operators – the Run method increments a class data member counter so to run at most once. By doing so, a parameter wouldn’t be initialized repeatedly, say, in every minibatch.

              -

              In this example, all operators are created as OpDesc protobuf messages, and all variables are VarDesc. These protobuf messages are saved in a BlockDesc protobuf message.

              -
              -
              -

              Backward Part

              -

              The fifth line optimize(cost) calls two functions, ConstructBackwardGraph and ConstructOptimizationGraph.

              -

              ConstructBackwardGraph traverses the forward graph in the BlockDesc protobuf message and builds the backward part.

              -

              -

              According to the chain rule of gradient computation, ConstructBackwardGraph would

              -
                -
              1. create a gradient operator G for each operator F,
              2. -
              3. make all inputs, outputs, and outputs’ gradient of F as inputs of G,
              4. -
              5. create gradients for all inputs of F, except for those who don’t have gradients, like x and l, and
              6. -
              7. make all these gradients as outputs of G.
              8. -
              -
              -
              -

              Optimization Part

              -

              For each parameter, like W and b created by layer.fc, marked as double circles in above graphs, ConstructOptimizationGraph creates an optimization operator to apply its gradient. Here results in the complete graph:

              -

              -
              -
              -
              -

              Block and Graph

              -

              The word block and graph are interchangable in the desgin of PaddlePaddle. A Block is a metaphore of the code and local variables in a pair of curly braces in programming languages, where operators are like statements or instructions. A graph of operators and variables is a representation of the block.

              -

              A Block keeps operators in an array BlockDesc::ops

              -
              message BlockDesc {
              -  repeated OpDesc ops = 1;
              -  repeated VarDesc vars = 2;
              -}
              -
              -
              -

              in the order that they appear in user programs, like the Python program at the beginning of this article. We can imagine that in ops, we have some forward operators, followed by some gradient operators, and then some optimization operators.

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/graph_survey.html b/develop/doc/design/graph_survey.html deleted file mode 100644 index 8f6722d0225..00000000000 --- a/develop/doc/design/graph_survey.html +++ /dev/null @@ -1,445 +0,0 @@ - - - - - - - - - - - - - Survey on Graph — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Survey on Graph

              -

              Neural network framework often provides symbolic API for users to write network topology conveniently. This doc manily focus on symbolic API in most popular neural network frameworks, and try to find out how to parse symbolic configuration to a portable file, such as protobuf or json.

              -
              -

              Mxnet

              -

              The core concept of symbolic API is Symbol. Mxnet implements Symbol class in C++, and export to Python using C-API. Please refer to the comments in Mxnet:

              -

              Symbol is help class used to represent the operator node in Graph. -Symbol acts as an interface for building graphs from different components like Variable, Functor and Group. Symbol is also exported to python front-end (while Graph is not) to enable quick test and deployment. Conceptually, symbol is the final operation of a graph and thus including all the information required (the graph) to evaluate its output value.

              -

              A simple network topology wrote by Symbol is as follows:

              -
              def get_symbol(num_classes=10, **kwargs):
              -    data = mx.symbol.Variable('data')
              -    data = mx.symbol.Flatten(data=data)
              -    fc1  = mx.symbol.FullyConnected(data = data, name='fc1', num_hidden=128)
              -    act1 = mx.symbol.Activation(data = fc1, name='relu1', act_type="relu")
              -    fc2  = mx.symbol.FullyConnected(data = act1, name = 'fc2', num_hidden = 64)
              -    act2 = mx.symbol.Activation(data = fc2, name='relu2', act_type="relu")
              -    fc3  = mx.symbol.FullyConnected(data = act2, name='fc3', num_hidden=num_classes)
              -    mlp  = mx.symbol.SoftmaxOutput(data = fc3, name = 'softmax')
              -    return mlp
              -
              -
              -

              Varible here is actually a Symbol. Every basic Symbol will correspond to one Node, and every Node has its own NodeAttr. There is a op field in NodeAttr class, when a Symbol represents Variable(often input data), the op field is null.

              -

              Symbol contains a data member, std::vector outputs, and NodeEntry cantains a poniter to Node. We can follow the Node pointer to get all the Graph.

              -

              And Symbol can be saved to a Json file.

              -

              Here is a detailed example:

              -
              >>> import mxnet as mx
              ->>> data = mx.symbol.Variable('data')
              ->>> print data.debug_str()
              -Variable:data
              -
              ->>> data = mx.symbol.Flatten(data=data)
              ->>> print data.debug_str()
              -Symbol Outputs:
              -    output[0]=flatten0(0)
              -Variable:data
              ---------------------
              -Op:Flatten, Name=flatten0
              -Inputs:
              -    arg[0]=data(0) version=0
              -
              ->>> fc1  = mx.symbol.FullyConnected(data = data, name='fc1', num_hidden=128)
              ->>> print fc1.debug_str()
              -Symbol Outputs:
              -    output[0]=fc1(0)
              -Variable:data
              ---------------------
              -Op:Flatten, Name=flatten0
              -Inputs:
              -    arg[0]=data(0) version=0
              -Variable:fc1_weight
              -Variable:fc1_bias
              ---------------------
              -Op:FullyConnected, Name=fc1
              -Inputs:
              -    arg[0]=flatten0(0)
              -    arg[1]=fc1_weight(0) version=0
              -    arg[2]=fc1_bias(0) version=0
              -Attrs:
              -    num_hidden=128
              -
              -
              -
              -
              -

              TensorFlow

              -

              The core concept of symbolic API is Tensor. Tensorflow defines Tensor in Python. Please refer to the comments in TensorFlow:

              -

              A Tensor is a symbolic handle to one of the outputs of an Operation. It does not hold the values of that operation’s output, but instead provides a means of computing those values in a TensorFlow Session.

              -

              A simple example is as follows:

              -
                # Build a dataflow graph.
              -  c = tf.constant([[1.0, 2.0], [3.0, 4.0]])
              -  d = tf.constant([[1.0, 1.0], [0.0, 1.0]])
              -  e = tf.matmul(c, d)
              -
              -  # Construct a `Session` to execute the graph.
              -  sess = tf.Session()
              -
              -  # Execute the graph and store the value that `e` represents in `result`.
              -  result = sess.run(e)
              -
              -
              -

              The main method of Tensor is as follows:

              -
              @property
              -def op(self):
              -  """The `Operation` that produces this tensor as an output."""
              -  return self._op
              -
              -@property
              -def dtype(self):
              -   """The `DType` of elements in this tensor."""
              -  return self._dtype
              -
              -@property
              -def graph(self):
              -  """The `Graph` that contains this tensor."""
              -  return self._op.graph
              -
              -@property
              -def name(self):
              -  """The string name of this tensor."""
              -  if not self._op.name:
              -    raise ValueError("Operation was not named: %s" % self._op)
              -  return "%s:%d" % (self._op.name, self._value_index)
              -
              -@property
              -def device(self):
              -  """The name of the device on which this tensor will be produced, or None."""
              -  return self._op.device
              -
              -
              -

              Tensor can be taken as target to run by session. Tensor contains all the information of Graph, and tracks data dependency.

              -

              Here is a detailed example:

              -
              >>> import tensorflow as tf
              ->>> c = tf.constant([[1.0, 2.0], [3.0, 4.0]])
              ->>> print c.graph
              -<tensorflow.python.framework.ops.Graph object at 0x10f256d50>
              ->>> d = tf.constant([[1.0, 1.0], [0.0, 1.0]])
              ->>> print d.graph
              -<tensorflow.python.framework.ops.Graph object at 0x10f256d50>
              ->>> e = tf.matmul(c, d)
              ->>> print e.graph
              -<tensorflow.python.framework.ops.Graph object at 0x10f256d50>
              -
              -
              -
              -
              -

              Dynet

              -

              The core concept of symbolic API is Expression, and Dynet defines Expression class in C++.

              -

              A simple example is as follows:

              -
              ComputationGraph cg;
              -Expression W = parameter(cg, pW);
              -
              -Expression in = input(cg, xs[i]);
              -Expression label = input(cg, ys[i]);
              -Expression pred = W * in;
              -Expression loss = square(pred - label);
              -
              -
              -

              The input data and parameter are also represented by Expression. Every basci Expression corresponds to a Node. And input data is also a Node.

              -

              Expression has a data member ComputationGraph, and ComputationGraph will be modified in users’ configuring process. Expression can be a running target, beacuse Expression contains all dependency.

              -

              Here is a detailed example:

              -

              write topology in C++

              -
              ComputationGraph cg;
              -Expression W = parameter(cg, pW);
              -cg.print_graphviz();
              -
              -Expression pred = W * xs[i];
              -cg.print_graphviz();
              -
              -Expression loss = square(pred - ys[i]);
              -cg.print_graphviz();
              -
              -
              -

              compile and print

              -
              # first print
              -digraph G {
              -  rankdir=LR;
              -  nodesep=.05;
              -  N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"];
              -}
              -# second print
              -digraph G {
              -  rankdir=LR;
              -  nodesep=.05;
              -  N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"];
              -  N1 [label="v1 = v0 * -0.98"];
              -  N0 -> N1;
              -}
              -# third print
              -digraph G {
              -  rankdir=LR;
              -  nodesep=.05;
              -  N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"];
              -  N1 [label="v1 = v0 * -0.98"];
              -  N0 -> N1;
              -  N2 [label="v2 = -1.88387 - v1"];
              -  N1 -> N2;
              -  N3 [label="v3 = -v2"];
              -  N2 -> N3;
              -  N4 [label="v4 = square(v3)"];
              -  N3 -> N4;
              -}
              -
              -
              -
              -
              -

              Conclusion

              -

              Actually, Symbol/Tensor/Expression in Mxnet/TensorFlow/Dynet are the same level concepts. We use a unified name Expression here, this level concept has following features:

              -
                -
              • Users wirte topoloy with symbolic API, and all return value is Expression, including input data and parameter.
              • -
              • Expression corresponds with a global Graph, and Expression can also be composed.
              • -
              • Expression tracks all dependency and can be taken as a run target
              • -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/if_else_op.html b/develop/doc/design/if_else_op.html deleted file mode 100644 index 0db369a4503..00000000000 --- a/develop/doc/design/if_else_op.html +++ /dev/null @@ -1,301 +0,0 @@ - - - - - - - - - - - - - The IfElse Operator — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              The IfElse Operator

              -

              PaddlePaddle’s IfElse operator differs from TensorFlow’s:

              -
                -
              • the TensorFlow version takes a scalar boolean value as the condition so that the whole mini-batch goes to either the true or the false branch, whereas
              • -
              • the PaddlePaddle version takes a vector of boolean value as the condition, and instances corresponding to true values go to the true branch, those corresponding to false values go to the false branch.
              • -
              -
              -

              Example

              -

              The following PaddlePaddle program shows the usage of the IfElse operator:

              -
              import paddle as pd
              -
              -x = minibatch([10, 20, 30]) # shape=[None, 1]
              -y = var(1) # shape=[1], value=1
              -z = minibatch([10, 20, 30]) # shape=[None, 1]
              -cond = larger_than(x, 15) # [false, true, true]
              -
              -ie = pd.ifelse()
              -with ie.true_block():
              -    d = pd.layer.add(x, y)
              -    ie.output(d, pd.layer.softmax(d))
              -with ie.false_block():
              -    d = pd.layer.fc(z)
              -    ie.output(d, d+1)
              -o1, o2 = ie(cond)
              -
              -
              -

              A challenge to implement the IfElse operator is to infer those variables to be split, or, say, to identify the variable of the mini-batch or those derived from the mini-batch.

              -

              An equivalent C++ program is as follows:

              -
              namespace pd = paddle;
              -
              -int x = 10;
              -int y = 1;
              -int z = 10;
              -bool cond = false;
              -int o1, o2;
              -if (cond) {
              -  int d = x + y;
              -  o1 = z;
              -  o2 = pd::layer::softmax(z);
              -} else {
              -  int d = pd::layer::fc(z);
              -  o1 = d;
              -  o2 = d+1;
              -}
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/infer_var_type.html b/develop/doc/design/infer_var_type.html deleted file mode 100644 index 7bc87b29f6b..00000000000 --- a/develop/doc/design/infer_var_type.html +++ /dev/null @@ -1,318 +0,0 @@ - - - - - - - - - - - - - Design Doc: InferVarType — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: InferVarType

              -
              -

              The Problem Posed

              -

              The variable in our design can hold variant types. Such as LoDTensor and SelectedRows. An operator should be able to inference the variable types of its output.

              -

              For example, a lookup table operator takes two LoDTensor; one is a float tensor as the embedding table, the other is an int tensor as word ID. The gradient operator of lookup table will generate a SelectedRows as its output. A sum operator can take both LoDTensor and SelectedRows as its inputs and will generate a LoDTensor if any of its inputs is LoDTensor, otherwise, the sum operator will generate SelectedRows as its output.

              -

              The variable type will be constant at runtime. Every variable’s type can either be set by the user (input data and parameter) or be inferred by the operator in compile time.

              -
              -
              -

              Proposed Solution

              -

              The InferVarType is a compile-time function which is registered to each operator. The inferface of that function is:

              -
              using InferVarTypeFN = std::function<
              -    void (const OpDescBind& /*op_desc*/, BlockDescBind* /*block*/)>;
              -
              -
              -

              It takes an operator description as its input and will write the output variable type and store them in block description.

              -

              The InferVarTypeFN will be registered in OpInfo, to replace infer_var_type_ field. The OpInfo should be

              -
              struct OpInfo {
              -  InferVarTypeFN infer_var_type_;
              -  ...
              -};
              -
              -
              -

              The default InferVarType will set output type as LoDTensor. It can be done by GetInferVarType().

              -
              void DefaultInferVarType(const OpDescBind& op_desc, BlockDescBind* block) {
              -  // set the output type of variable as `LoDTensor`.
              -  // ...
              -}
              -
              -struct OpInfo {
              -  InferVarTypeFN infer_var_type_;
              -  InferVarTypeFN GetInferVarType() const {
              -    if (infer_var_type_) {
              -      return infer_var_type_;
              -    } else {
              -      return DefaultInferVarType;
              -    }
              -  }
              -};
              -
              -
              -
              -
              -

              Register InferVarType

              -

              We provide a thin base class for registering an InferVarTypeFN. To use a base class will ease the implementation of registry since we can detect the registry entry is an InferVarTypeFN or not.

              -
              class VarTypeInferer {
              -public:
              -  virtual void operator()(const OpDescBind& op_desc, BlockDescBind* block) const = 0;
              -}
              -
              -
              -

              Operator developers can write the specialize VarTypeInferer as follow.

              -
              class SpecialVarTypeInferer : public VarTypeInferer {
              -public:
              -  virtual void operator()(const OpDescBind& op_desc, BlockDescBind* block) const {
              -    // .. own logic
              -  }
              -}
              -
              -
              -

              Then user can register the InferVarType just like GradOpDescMaker and OpInfoMaker.

              -
              REGISTER_OPERATOR(some_op, OpType, SpecialVarTypeInferer, ...);
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/kernel_hint_design.html b/develop/doc/design/kernel_hint_design.html deleted file mode 100644 index 1d2c38bb902..00000000000 --- a/develop/doc/design/kernel_hint_design.html +++ /dev/null @@ -1,306 +0,0 @@ - - - - - - - - - - - - - Problem — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Problem

              -

              In PaddlePaddle’s Design, one Operator may have multiple kernels. Users may have some personal preference to choose a certain type of kernel for an operator, such as force_cpu to choose a CPU kernel, use_cudnn to choose a CUDNN kernel, we need to provide a way for users to do this.

              -

              In the current design, we use KernelType to describe one kernel.

              -
              struct KernelType {
              -  Place place_;
              -  DataType data_type_;
              -  LayoutType layout_;
              -};
              -
              -
              -

              place_ data_type_ and layout_ can be got from the input tensors of the operator, GetActualKernelType(inputs) use inputs to infer the proper kernel key that fit the incoming data, but users can not directly configure it.

              -

              The design also provides a virtual method GetExpectedKernelType that user can overload and use to choose the KernelType they want to use.

              -

              So we should send the information user defined in proto to GetExpectedKernelType for choosing a kernel.

              -

              The problem is, how should we define and send the information for GetExpectedKernelType to use?

              -
              -
              -

              Solution

              -
              -

              Potential choice

              -
                -
              1. Do nothing, let the user add the information they want to operator‘s attribute and get them inside GetExpectedKernelType, this can work properly. But there is a little problem that users may define many kinds of hints for the same purpose, such as force_cpu, use_cpu, cpu_kernel to choose CPU kernel, and use_cudnn, force_cudnn, cudnn_kernel to choose CUDNN kernel.
              2. -
              3. Pre-define all the needed option and use a single attr key such as kernel_hint for the user, this is not so flexible if the user wants to define some more kind of hint.
              4. -
              -
              -
              -

              Final choice

              -

              To provide enough flexibility while avoiding confusion definition, we can define some global constants for these attribute names, such as force_cpu, use_cudnn, use_mkldnn for a user to choose.

              -

              In C++

              -
              const std::string kForceCPU = "force_cpu";
              -const std::string kUseCUDNN = "use_cudnn";
              -const std::string kUseMKLDNN = "use_mkldnn";
              -
              -KernelType GetExpectedKernelType() {
              -  if (Attr<bool>(kForceCPU)) {
              -    return KernelType(CPUPlace, ...)
              -  } else {
              -    ...
              -  }
              -}
              -
              -
              -

              In Python code

              -
              FORCE_CPU = core.kForceCPU()
              -
              -def xx_layer(..., force_cpu=false):
              -  layer_helper = LayerHelper(...)
              -  layer_helper.append_op(
              -    type="xx",
              -    attr={FORCE_CPU: force_cpu})
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/kernel_selection.html b/develop/doc/design/kernel_selection.html deleted file mode 100644 index 027db66a6b1..00000000000 --- a/develop/doc/design/kernel_selection.html +++ /dev/null @@ -1,337 +0,0 @@ - - - - - - - - - - - - - Background — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Background

              -

              Every operator has many kernels because there are multiple data types, places, data layout, library type that Fluid supports. We use the OpKernelType to describe kernel types that operators can hold.

              -

              The OpKernelType is as follows:

              -
              struct OpKernelType {
              -  Place place_;
              -  DataType data_type_;
              -  DataLayout data_layout_;
              -  LibraryType library_type_;
              -};
              -
              -
              -
                -
              • The place_ is a descriptor of the device, e.g., CPUPlace, CUDAPlace.
              • -
              • The data_type_ is the data type that this kernel performs on, e.g., FP32, INT64. Note that one kernel may have inputs with different data types. However, it will be a major data_type. For example, the cross_entropy takes int64 as it label, and double/float as its input logit and output cost. The major data_type of cross_entropy is float or double.
              • -
              • The data_layout_ is useful for some computational library. One example is that MKLDNN uses many kinds of layout, such as nChw8c. Each kind of layout will invoke the different kernel.
              • -
              • The library_type_ describes the computational library, e.g., MKLDNN, CUDNN.
              • -
              -
              -
              -

              Problem

              -

              We register a kernel for every operator and every kernel type ideally. However, it is impracticable for the following situations.

              -
                -
              1. Some operators, like CRF, are complicated and inefficient to be implemented on GPU. The CRF operator will only have a CPU kernel.
              2. -
              3. Some operators will take too many memory. It is better to force them into CPU. However, the rest of operators in this neural network will be performed on GPU, i.e., model parallel problem.
              4. -
              5. Some layout and place are particular. One example is that MKLDNN uses nChw8 and there is no other library uses nChw8c.
              6. -
              -

              Take one situation to give a detailed explanation, if we have two Operators: OP1 and OP2, OP1 has one output op1_to_op2, and op1_to_op2 is the input of OP2.

              -

              If OP1 and OP2 run on the same place(for example CPUPlace), then op1_2_op2 can be used directly by OP2.

              -
              OP1(CPUPlace)
              -     |
              - op1_2_op2
              -     |
              -OP2(CPUPlace)
              -
              -
              -

              If OP1 and OP2 run one different place, then OP2 cannot use op1_2_op2 directly.

              -

              Problems under these situations are similar. We can formalize this problem as follow.

              -

              We register kernels with types $KT = {kt_1, kt_2, kt_3, ...}$ for one operator. The inputs of this operator should be run on kernel type $kt_{?}$, which the $kt_{?} \notin KT$. How to cast the input of this operator from $kt_{?}$ to any of kernel type in $KT$.

              -
              -
              -

              Solution: data transform

              -

              It is clear that transforming inputs of an operator to adapt another kernel type is not related to the particular operator. So we should register these transformation methods as global methods.

              -

              We can infer kernel type for each input of an operator. We let this kernel type as actual kernel type for var, which means this kernel type is the kernel type that can process this input variable.

              -

              We can get a kernel type by 1) The configuration of operator description. (Users may want to force use MKL for conv operator). 2) The place of the current executor. (Executor is running on GPU). This kernel type is what we expect the operator will be performed on. We let this kernel type as expect kernel type.

              -

              We transform the input data from actual to expect if the actual kernel type is not as same as expect kernel type.

              -

              The algorithm is described as following

              -
              void OperatorWithKernel::Run(
              -        const Scope& scope,
              -        const platform::Place& place) const {
              -  ExecutionContext ctx(...);
              -  auto expected_kernel_key = this->GetExpectedKernelType(ctx);
              -
              -  Scope& new_scope = scope.NewScope();
              -
              -  for (auto& var_name : this->Inputs()) {
              -    auto* tensor_in = GetTensor(var_name);
              -    auto kernel_type_for_var = this->GetKernelTypeForVar(...);
              -    if (kernel_type_for_var.place_ != expected_kernel_key.place_) {
              -      auto* trans_var = new_scope.Var(var_name);
              -      auto* out = DataTransform(expected_kernel_key,
              -                                kernel_type_for_var,
              -                                *tensor_in);
              -      CopyVariableWithTensor(...);
              -    }
              -  }
              -
              -  auto kernel = kernels.find(expected_kernel_key);
              -  kernel->Compute(ExecutionContext(...));
              -}
              -
              -
              -

              then the actual process for the multi-device above will be:

              -
              OP1(CPUPlace)
              -     |
              -op1_2_op2(on CPU)
              -     |
              -[transform](from CPU to GPU)
              -     |
              -op1_2_op2(on GPU)
              -     |
              -OP2(CUDAPlace)
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/memory_optimization.html b/develop/doc/design/memory_optimization.html deleted file mode 100644 index 3262578c739..00000000000 --- a/develop/doc/design/memory_optimization.html +++ /dev/null @@ -1,446 +0,0 @@ - - - - - - - - - - - - - Memory Optimization — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Memory Optimization

              -
              -

              Problem

              -

              In a lecture from Andrew Ng, he attributes the recent sucess of AI due to a combination of these:

              -
                -
              • Availability of Big Data
              • -
              • Supercomputing power to process this Big Data over very large neural networks
              • -
              • Modern algorithms
              • -
              -

              Following graph shows the details:

              -

              -

              Larger model usually bring better performance. However, GPU memory is limited. For example, the memory size of a GTX TITAN X is only 12GB. To train complex and large models, we have to take care of memory usage. Besides, memory optimization is also necessary in both online/mobile inference.

              -
              -
              -

              Solution

              -
              -

              Basic Strategy

              -

              There are some basic strategies to improve memory usage, including in-place operations and memory sharing.

              -
              -

              In-place Operation

              -

              In a relu activation operator:

              -

              $y = \max(x, 0)$

              -

              If the variable x is not used in any other operator, we can make an in-place operation. In other words, the memory block of variable y and variable x will be the same. In-place operations will save 50% memory occupancy immediately.

              -
              -
              -

              Memory Sharing

              -

              Not all operators support in-place operations. Memory sharing is a more general strategy.

              -

              Following is an example:

              -
              a = op1(b, c);
              -d = op2(a)
              -e = op3(d, f)
              -
              -
              -

              In this case, variable a is no longer used, and op2 does not support in-place operation. After op2 finishes, we can put the memory of variable a to a memory pool. Then, variable e can share the memory of variable a from the pool.

              -
              -
              -
              -

              Live Variable Analysis

              -

              It’s not enough to only have some basic strategies. The pre-requisite of memory optimization is to know if a variable is still “live” after an operation.

              -

              In our design, the neural network topology is defined as a program. Luckily, live variable analysis is a classic problem in compilers which can be used in many stages, such as register allocation.

              -

              In compilers, the front end of the compiler translates programs into an intermediate language with an unbounded number of temporary variables. This program must run on a machine with a bounded number of registers. Two temporary variables a and b can fit into the same register, if a and b are never “in use” at the same time. Thus, many temporary variables can fit in few registers; if they don’t all fit, the excess tempory variables can be kept in memory.

              -

              Therefore, the compiler needs to analyze the intermediate-representation program to determine which temporary variables are in use at the same time. We say a variable is “live” if it holds a value that may be needed in the future, so this analysis is called liveness analysis.

              -

              We can leran these techniques from compilers. There are mainly two stages to make live variable analysis:

              -
                -
              • construct a control flow graph
              • -
              • solve the dataflow equations
              • -
              -
              -

              Control Flow Graph

              -

              To perform analysis on a program, it is often useful to make a control flow graph. A control flow graph (CFG) in computer science is a representation, using graph notation, of all paths that might be traversed through a program during its execution. Each statement in the program is a node in the flow graph; if statemment x can be followed by statement y, there is an egde from x to y.

              -

              Following is the flow graph for a simple loop.

              -

              -
              -
              -

              Dataflow Analysis

              -

              Liveness of variable “flows” around the edges of the control flow graph; determining the live range of each variable is an example of a dataflow problem. Dataflow analysis is a technique for gathering information about the possible set of values calculated at various points in a computer program.

              -

              A simple way to perform data-flow analysis of programs is to set up dataflow equations for each node of the control flow graph and solve them by repeatedly calculating the output from the input locally at each node until the whole system stabilizes.

              -
                -
              • Flow Graph Terminology
              • -
              -

              A flow graph node has out-edges that lead to sucessor nodes, and in-edges that come from predecessor nodes. The set pred[n] is all the predecessors of node n, and succ[n] is the set of sucessors. -In former control flow graph, the out-edges of node 5 are 5 –> 6 and 5 –> 2, and succ[5] = {2, 6}. The in-edges of 2 are 5 –> 2 and 1 –> 2, and pred[2] = {1, 5}.

              -
                -
              • Uses and Defs
              • -
              -

              An assignmemt to a variable or temporary defines that variable. An occurence of a variable on the right-hand side of an assginment(or in other expressions) uses the variable. We can define the def of a variable as the set of graph nodes that define it; or the def of a graph node as the set of variables that it defines; and the similarly for the use of a variable or graph node. In former control flow graph, def(3) = {c}, use(3) = {b, c}.

              -
                -
              • Liveness
              • -
              -

              A variable is live on an edge if there is a directed path from that edge to a use of the variable that does not go through any def. A variable is live-in at a node if it is live on any of the in-edges of that node; it is live-out at a node if it is live on any of the out-edges of the node.

              -

              The calcution of liveness can be solved by iteration until a fixed pointer is reached. Following is the recursive formula:

              -

              -
              -
              -
              -

              Memory optimization transpiler

              -

              At last, we take basic strategy and liveness analysis techniques learning from compilers to implement our memory optimization transpiler.

              -
              -

              add in-place attribute

              -

              In-place is a built-in attribute of an operator. Since we treat in-place and other operators differently, we have to add an in-place attribute for every operator.

              -
              -
              -

              contruct control flow graph

              -

              Following is the ProgramDesc protobuf of machine translation example.

              -
                -
              • Block0:
              • -
              -
              lookup_table
              -mul
              -...
              -while(sub-block idx 1)
              -...
              -array_to_lod_tensor
              -cross_entropy
              -...
              -while_grad(sub-block idx 2)
              -read_from_array
              -array_to_lod_tensor
              -...
              -
              -
              -
                -
              • Block1
              • -
              -
              read_from_array
              -read_from_array
              -...
              -write_to_array
              -increment
              -write_to_array
              -less_than
              -
              -
              -
                -
              • Block2
              • -
              -
              read_from_array
              -increment
              -...
              -write_to_array
              -write_to_array
              -
              -
              -

              We can transfer all the operators and variables in ProgramDesc to build a control flow graph.

              -
              class ControlFlowGraph(object):
              -    def __init__(self, Program):
              -        self._sucessors = defaultdict(set)
              -        self._presucessors = defaultdict(set)
              -        self._uses = defaultdict(set)
              -        self._defs = defaultdict(set)
              -        self._live_in = defaultdict(set)
              -        self._live_out = defaultdict(set)
              -        self._program = Program
              -    
              -    def build(self):
              -        pass
              -    
              -    def dataflow_analysis(self):
              -        pass
              -        
              -    def memory_optimization(self):
              -        pass
              -        
              -    def get_program(self):
              -        return self._program
              -
              -
              -
              -
              -

              Make dataflow analysis

              -

              We follow the guide from compilers and try to solve the dataflow equation to get liveness of every variable. If the live-in of an operator node is different from the live-out, then we can make memory sharing.

              -

              For example:

              -
              a = op1(b, c);
              -d = op2(a)
              -e = op3(d, f)
              -
              -
              -

              The dataflow analysis result is:

              -
              live_in(op1) = {b, c, f}
              -live_out(op1) = {a, f}
              -
              -live_in(op2) = {a, f}
              -live_out(op2) = {d, f}
              -
              -live_in(op3) = {d, f}
              -live_out(op3) = {}
              -
              -
              -

              After op1, we can process variable b and variable c; After op2, we can process variable a. After op3, we can process variable d and variable f.

              -
              -
              -

              memory sharing policy

              -

              A memory pool will be mantained in the stage of memory optimization. Each operator node will be scanned to determine memory optimization is done or not. If an operator satifies the requirement, following policy will be taken to handle input/output variables.

              -
              if op.support_inplace():
              -    i --> pool
              -    pool --> o
              -else:
              -    pool --> o
              -    i --> pool
              -
              -
              -
              -
              -
              - -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/mkl/mkl_packed.html b/develop/doc/design/mkl/mkl_packed.html deleted file mode 100644 index bf4d80cf6b8..00000000000 --- a/develop/doc/design/mkl/mkl_packed.html +++ /dev/null @@ -1,380 +0,0 @@ - - - - - - - - - - - - - Intel® MKL Packed on PaddlePaddle: Design Doc — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Intel® MKL Packed on PaddlePaddle: Design Doc

              - -
              -

              Overview

              -

              我们计划将 Intel® MKL 中引入的 GEMM Packed APIs[1] 集成到 PaddlePaddle 中,充分发挥英特尔平台的优势,有效提升PaddlePaddle在英特尔架构上的性能。 -现阶段的优化主要针对 Recurrent Neural Network(以下简称RNN)相关层(包括RecurrentLayer, GatedRecurrentLayerLstmLayer), 以及 PaddlePaddle V1 API。

              -
              -
              -

              Key Points

              -
              -

              Background

              -

              目前PaddlePaddle采用了 Intel® MKL库的cblas_?gemm函数,这个函数本身会在计算前将原数据转换为更适合英特尔平台的内部格式。

              -
                -
              1. 转换耗时 这一数据格式的转换操作(Packing),在问题本身的计算量比较小的时候,显得相对来说较为耗时。例如在DeepSpeech2 [2] 的Vanilla RNN部分中,矩阵大小是batch_size * 2048
              2. -
              3. 转换冗余 由于在现有的某些情况下(例如RNN),多次调用 cblas_?gemm 会使用相同的原数据,因此,每次调用时对原数据的重复Packing便成为了冗余。
              4. -
              -

              为了最大程度减少多次调用 cblas_?gemm 在Packing上的耗时,Intel® MKL 引入了以下四个API:

              -
              - -
              -

              通过使用这些API,我们可以先完成对原数据的Packing操作,再把已转换为Packed格式的数据传递给那些复用同一数据的gemm_compute函数,从而避免了Packing冗余。

              -
              -
              -

              Solution

              -

              在RNN的情况下,同一次前向、后向(forward/backward)过程中所有时间步(time step)共享同一个权重(weight)。当只做推断(inference)时,各次前向之间也都使用了相同的权重,没有必要在每次前向中每个时间步的计算时对权重进行重复的Packing操作。

              -

              我们通过使用新引入的GEMM Packed APIs,在层初始化的时候,先完成对权重的Packing操作,然后在前向,后向时复用已经转换过的权重,并在每次权重更新后,对新的权重进行转换用于下次迭代。

              -
                -
              • 优化前,对于序列长度(sequence length)为T的网络模型(model), N次迭代执行的转换次数为:
                  -
                • inferenceN * T
                • -
                • training2 * N * T
                • -
                -
              • -
              • 优化后,对于同样设置的网络模型,其转换次数减少至:
                  -
                • inference1
                • -
                • training2 * N
                • -
                -
              • -
              -
              -
              -
              -

              Actions

              -

              添加的相关文件和目录结构如下:

              -
              PaddlePaddle/Paddle
              -├── ...
              -└── paddle/
              -    ├── ...
              -    └── gserver/
              -        ├── ...
              -        ├── layers/
              -        │   ├── ...
              -        │   ├── MKLPackedRecurrentLayer.*
              -        |   ├── MKLPackedGatedRecurrentLayer.*
              -        |   ├── MKLPackedLstmLayer.*
              -        |   └── MKLPackedGemm.h
              -        └── tests/
              -            ├── ...
              -            └── test_MKLPacked.cpp
              -
              -
              -
              -

              CMake

              -

              在对应的CMakeLists.txt中根据WITH_MKL是否打开,来决定是否开启MKL Packed相关功能。

              -
              -
              -

              Layers

              -

              所有的MKLPacked*Layer都继承于PaddlePaddle的基类Layer, 并添加头文件 MKLPackedGemm.h,该文件对相关GEMM Packed APIs做了封装。

              -
              -
              -

              Unit Tests

              -

              我们会添加test_MKLPacked.cpp用于MKL Packed优化后layer的测试。 -对于每一个新加的RNN layer,我们会对比如下2个方面:

              -
                -
              1. 对比优化后layer自身,sequence mode(rnn_use_batch=false)与batch mode(rnn_use_batch=true)的结果。
              2. -
              3. 对比优化后layer与相对应的PaddlePaddle原有layer, 在batch mode下的结果。
              4. -
              -
              -
              -

              Python API

              -

              计划在paddle/utils.Flags中添加use_mkl_packed的flag,用于选择是否使用相关功能,并且当编译时WITH_MKL=ON的情况下,默认设置为true

              -

              同时,在python/paddle/trainer/config_parser.py中对应的layer处,添加use_mkl_packed这个选择,方便用户在Python端选择是否启用这个功能。

              -

              具体实现方式比如:

              -
              use_mkl_packed = bool(int(g_command_config_args.get("use_mkl_packed", 0)))
              -if use_mkl_packed:
              -    self.layer_type = mkl_packed_*
              -
              -
              -

              所有相关的layer_type会以*mkl_packed_*开头,这些会在MKLPacked*Layer注册layer的时候保证,以示区分。

              -
              -
              -

              Benchmarking

              -

              会添加相应的脚本用于测试和对比在使用MKL Packed recurrent layers 前后的网络性能。

              -
              -
              - -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/mkl/mkldnn.html b/develop/doc/design/mkl/mkldnn.html deleted file mode 100644 index 3344b42fbed..00000000000 --- a/develop/doc/design/mkl/mkldnn.html +++ /dev/null @@ -1,461 +0,0 @@ - - - - - - - - - - - - - Intel® MKL-DNN on PaddlePaddle: Design Doc — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Intel® MKL-DNN on PaddlePaddle: Design Doc

              -

              我们计划将英特尔深度神经网络数学库Intel MKL-DNN -(Intel Math Kernel Library for Deep Neural Networks)集成到PaddlePaddle, -充分展现英特尔平台的优势,有效提升PaddlePaddle在英特尔架构上的性能。

              -
              -
              -Figure 1. PaddlePaddle on IA -

              近期目标

              -
                -
              • 完成常用Layer的MKL-DNN实现。
              • -
              • 完成常见深度神经网络VGG,GoogLeNet 和 ResNet的MKL-DNN实现。
              • -
              -

              目前的优化,主要针对PaddlePaddle在重构之前的代码框架以及V1的API。 -具体的完成状态可以参见这里

              - -
              -

              Overview

              -

              我们会把MKL-DNN会作为第三方库集成进PaddlePaddle,与其他第三方库一样,会在编译PaddlePaddle的时候下载并编译MKL-DNN。

              -

              同时,为了进一步提升PaddlePaddle在基本数学运算的计算速度,我们也将MKLML即(MKL small library[1]) -作为另一个第三方库集成进PaddlePaddle,它只会包括生成好的动态库和头文件。

              -

              MKL,MKLML以及MKL-DNN三者关系如下表:

              -

              | Name | Open Source | License | Descriptions | -| :———- | :————— | :———- | :———— | -| MKL | No | Proprietary | Accelerate math processing routines | -| MKLML | No | Proprietary | Small package of MKL, especially for Machine Learning | -| MKL-DNN | Yes | Apache 2.0 | Accelerate primitives processing routines especially for Deep Neural Networks |

              -

              MKLML可以与MKL-DNN共同使用,以此达到最好的性能。

              -
              -
              -Figure 2. PaddlePaddle with MKL Engines -
              -
              -

              Actions

              -

              添加的相关文件和目录结构如下:

              -
              PaddlePaddle/Paddle
              -├── ...
              -├── cmake/
              -│   ├── external/
              -│   │   ├── ...
              -│   │   ├── mkldnn.cmake
              -│   │   └── mklml.cmake
              -└── paddle/
              -    ├── ...
              -    ├── math/
              -    │   ├── ...
              -    │   └── MKLDNNMatrix.*
              -    └── gserver/
              -        ├── ...
              -        ├── layers/
              -        │   ├── ...
              -        │   └── MKLDNN*Layer.*
              -        ├── activations/
              -        │   ├── ...
              -        │   └── MKLDNNActivations.*
              -        └── tests/
              -            ├── ...
              -            ├── MKLDNNTester.*
              -            └── test_MKLDNN.cpp
              -
              -
              -
              -

              CMake

              -

              CMakeLists.txt中提供一个与MKL有关的总开关:WITH_MKL,它负责决定编译时是否使用MKLML和MKL-DNN

              -
                -
              • WITH_MKLML 控制是否使用MKLML库。 -当打开WITH_MKL时,会自动使用MKLML库作为PaddlePaddle的CBLAS和LAPACK库,同时会开启Intel OpenMP用于提高MKLML的性能。 -编译时会把对应的头文件和库放在build/third_party/install/mklml/*目录下对应的地方。 -MKLML的库目前都是动态库,主要包括libiomp5.solibmklml_intel.so
              • -
              • WITH_MKLDNN 控制是否使用MKL-DNN。 -当开启WITH_MKL时,会自动根据硬件配置[2]选择是否编译MKL-DNN。 -编译时会把对应的头文件和库放在build/third_party/install/mkldnn/*目录下对应的地方。 -MKL-DNN的库目前只有动态库libmkldnn.so
              • -
              -
              -
              -

              Matrix

              -

              目前在PaddlePaddle中数据都是以NCHW的格式存储,但是在MKL-DNN中的排列方式不止这一种。 -所以我们定义了一个MKLDNNMatrix用于管理MKL-DNN数据的不同格式以及相互之间的转换。

              -
              -
              -Figure 3. MKLDNNMatrix -
              -
              -

              Layers

              -

              所有MKL-DNN的Layers都会继承于MKLDNNLayer,该类继承于PaddlePaddle的基类Layer。 -在MKLDNNLayer中会提供一些必要的接口和函数,并且会写好forwardbackward的基本逻辑, -子类只需要使用定义好的接口,实现具体的函数功能即可。

              -
              -
              -Figure 4. MKLDNNLayer -

              每个MKLDNNLayer都包含用于内部存储和外部存储的一系列MKLDNNMatrix:

              -
                -
              • 内部存储(internel memory):inVal_,inGrad_,outVal_outGrad_,分别代表输入数据,输入梯度,输出数据和输出梯度。
              • -
              • 外部存储(external memory):都是以ext开头,比如extInVal_extInGrad_,它们主要是用于, -当数据格式与PaddlePaddle默认的NCHW格式不匹配时,转换内存的工作。 -需要注意的是,PaddlePaddle的activation会直接使用output_.valueoutput_.grad, -所以extOutVal_extOutGrad_必须分别与output_.valueoutput_.grad共享内存, -如果不需要外部存储用于转换,那么对应的内部存储也会与它们共享内存。
              • -
              • 转换函数(resetXXX): 包括resetInValueresetInGradresetOutValueresetOutGrad, -表示对输入数据,输入梯度,输出数据和输出梯度的转换。 -这些函数会根据输入参数重新设置内部和外部存储,当然这两者也可以相等,即表示不需要转换。
              • -
              -

              注意:每个MKLDNNlayer的子类只需要使用内部存储就可以了,所有外部的转换工作都会在reset系列函数中都准备好。

              -
              -
              -

              Activations

              -

              在重构前的PaddlePaddle中,激活函数是独立于Layer的概念,并且输入输出都是共用一块内存, -所以添加了对应的MKLDNNActivation来实现,方式类似于MKLDNNLayer

              -
              -
              -

              Parameters

              -

              对于有参数的层,我们会保证MKLDNNLayer使用的参数与PaddlePaddle申请的buffer共用一块内存。 -如果存在数据排列格式不一样的情况时,我们会在网络训练之前把格式转换为MKL-DNN希望的格式, -在训练结束的时候再保存为PaddlePaddle的格式,但是整个训练过程中不需要任何转换。 -这样既使得最终保存的参数格式与PaddlePaddle一致,又可以避免不必要的转换。

              -
              -
              -

              Gradients

              -

              由于MKL-DNN的操作都是直接覆盖的形式,也就是说输出的结果不会在原来的数据上累加, -这样带来的好处就是不需要一直清空memory,节省了不必要的操作。 -但是注意的是,当网络出现分支且在backward的时候,需要累加不同Layer传过来的梯度。 -所以在MKLDNNlayer中实现了一个merge的方法,此时每个小分支的Input Gradient -会先临时保存在MKLDNNMatrix中,由分支处的Layer负责求和,并把结果放到当前层的output_.grad中。 -所以整体上,在实现每个子类的时候就不需要关心分支的事情了。

              -
              -
              -Figure 5. Merge Gradients -
              -
              -

              Unit Tests

              -

              我们会添加test_MKLDNN.cppMKLDNNTester.*用于MKL-DNN的测试。 -测试分为每个Layer(或Activation)的单元测试和简单网络的整体测试。 -每个测试会对比PaddlePaddle中CPU算出的结果与MKL-DNN的结果,小于某个比较小的阈值认为通过。

              -
              -
              -

              Python API

              -

              目前只考虑v1 API

              -

              计划在python/paddle/trainer/config_parser.py里面添加use_mkldnn这个选择,方便用户选择使用MKL-DNN的layers。

              -

              具体实现方式比如:

              -
              use_mkldnn = bool(int(g_command_config_args.get("use_mkldnn", 0)))
              -if use_mkldnn
              -    self.layer_type = mkldnn_*
              -
              -
              -

              所有MKL-DNN的layer_type会以*mkldnn_*开头,这些会在MKLDNN*Layer注册layer的时候保证,以示区分。

              -

              同时,会在paddle/utils.Flags中添加一个use_mkldnn的flag,用于选择是否使用MKL-DNN的相关功能。

              -
              -
              -

              Benchmarking

              -

              会添加相应的脚本在这里,用于测试和对比在使用MKL-DNN前后的CNN网络性能。 -测试的性能对比结果会在IntelOptimizedPaddle.md

              -
              -
              -

              Others

              -
                -
              1. 如果在使用MKL-DNN的情况下,会把CPU的Buffer对齐为4096,具体可以参考MKL-DNN中的memory
              2. -
              3. 深入PaddlePaddle,寻找有没有其他可以优化的可能,进一步优化。比如可能会用OpenMP改进SGD的更新性能。
              4. -
              -
              -
              -
              -

              Design Concerns

              -

              为了更好的符合PaddlePaddle的代码风格[3],同时又尽可能少的牺牲MKL-DNN的性能[4]。

              -

              我们总结出一些特别需要注意的点:

              -
                -
              1. 使用**deviceId_**。为了尽可能少的在父类Layer中添加变量或者函数, -我们决定使用已有的deviceId_变量来区分layer的属性,定义-2MKLDNNLayer特有的设备ID。
              2. -
              3. 重写父类Layer的init函数,修改deviceId_-2,代表这个layer是用于跑在MKL-DNN的环境下。
              4. -
              5. 创建MKLDNNBase,定义一些除了layer和memory相关的类和函数。 -包括MKL-DNN会用到MKLDNNStreamCPUEngine,和未来可能还会用到FPGAEngine等。
              6. -
              7. 如果MKL-DNN layer的后面接有cpu device,那么就会使output_.valueextOutVal_共享内存, -同时数据格式就是NCHW,这样下一个cpu device就能拿到正确的数据。 -在有普通的CPU layer时, extOutVal_extOutGrad_的格式始终是NCHW或者NC
              8. -
              -
              -
              -

              References

              -
                -
              1. MKL small libraryIntel MKL的一个子集。 -主要包括了深度学习相关的数学原语与操作,一般由MKL-DNN在发布新版本时一起更新。
              2. -
              3. MKL-DNN System Requirements。 -目前在PaddlePaddle中,仅会在支持AVX2指令集及以上的机器才使用MKL-DNN。
              4. -
              5. 原来的方案会引入nextLayer的信息。 -但是在PaddlePaddle中,无论是重构前的layer还是重构后的op,都不会想要知道next layer/op的信息。
              6. -
              7. MKL-DNN的高性能格式与PaddlePaddle原有的NCHW不同(PaddlePaddle中的cuDNN部分使用的也是NCHW,所以不存在这个问题)。 -所以需要引入一个转换方法,并且只需要在必要的时候转换这种格式,才能更好的发挥MKL-DNN的性能。
              8. -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/mkl/mkldnn_fluid.html b/develop/doc/design/mkl/mkldnn_fluid.html deleted file mode 100644 index 498613830b6..00000000000 --- a/develop/doc/design/mkl/mkldnn_fluid.html +++ /dev/null @@ -1,405 +0,0 @@ - - - - - - - - - - - - - Design Doc: Add MKLDNN Kernel in Fluid Operator — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Add MKLDNN Kernel in Fluid Operator

              -
              -

              Principles

              -

              First of all, we should follow some basical principles like:

              -
                -
              1. How to write a new operator. We are trying to add a new kind of kernel into operators, so basically we should follow this doc.
              2. -
              3. Supporting new Device/Library. Since MKLDNN is a new library to fluid, we should add MKLDNNDeviceContext and maybe mkldnn_helper.h, just like cudnn_helper.h.
              4. -
              5. Switch Kernel. Another important point is that we should ensure the data synchronization between different kernel types, which is this topic. So basically we should override GetExpectedKernelType and trans functions to support switching kernels.
              6. -
              7. The Keys of Operator Kernel Type. Kernel Type is a pivotal conception which can record the Place, Library, DataType and Layout.
              8. -
              -
              -
              -

              Sulution

              -

              In general, there are four parts we should follow to run a MKL-DNN primitive.

              -
                -
              • Create a primitive descriptor that describe this operator
              • -
              • Create a primitive itself by primitive descriptor and the engine
              • -
              • Create all memory buffers that primitive needed
              • -
              • Launch a stream to execute the primitive created -More details can refer to here.
              • -
              -

              It’s better to avoid reinitialization of primitives and memory handles in the first three stages in every iteration. So we plan to create a map to record all the primitive and memory, which should not take too much memories as discussed here.

              -

              It’s assumed that following three conditions should be satisfied.

              -
                -
              1. there is a unique key for each operator instance. May be the actual name of Output Tensor.
              2. -
              3. the Input Tensor inside Compute function is the one after converted.
              4. -
              5. we can get the phase(eg. is_test) inside Compute function, otherwise we need to expose this attribue to user.
              6. -
              -
              -

              Compute

              -

              The algorithm of Compute would be described as follow, let’s take conv like an example.

              -
                PADDLE_ENFORCE(platform::is_cpu_place(ctx.GetPlace()), "It must use CPUPlace.");
              -  PADDLE_ENFORCE(platform::is_mkldnn_library(ctx.GetLibrary()), "It must use MKLDNN Library.");
              -
              -  auto& dev_ctx = ctx.template device_context<platform::MKLDNNDeviceContext>();
              -
              -  // find primitive by unique key from mkldnn context
              -  // the op_key should be a unique name of this op instance
              -  auto& p = dev_ctx.findPrimitive(op_key + "_fwd");
              -
              -  // assuming the input tensor inside this compute function is the one after converted
              -  // this point should be guarantee by another mechanism
              -  auto& i = dev_ctx.findMemory(op_key + "_input");
              -  
              -  if (p == nullptr || i == nullptr || inputSizeChanged(p, i))  {
              -    auto fwd_primitive_desc = createPrimitiveDesc(ctx);
              -    auto* input = ctx.Input<Tensor>("Input");
              -    auto* filter = ctx.Input<Tensor>("Filter");
              -    auto* output = ctx.Output<Tensor>("Output");
              -    shared_ptr<mkldnn::memory> in(new mkldnn::memory(fwd_primitive_desc->src_primitive_desc(), input->data<T>()));
              -    shared_ptr<mkldnn::memory> wgt(new mkldnn::memory(fwd_primitive_desc->weights_primitive_desc(), filter->data<T>()));
              -    shared_ptr<mkldnn::memory> out(new mkldnn::memory(fwd_primitive_desc->dst_primitive_desc(), output->mutable_data<T>(ctx.GetPlace())));
              -    shared_ptr<mkldnn::conv_fwd> fwd_primitive(new mkldnn::conv_fwd(*fwd_primitive_desc, *in, *wgt, *out));
              -
              -    dev_ctx.addMemory(op_key+"_input", in);
              -    dev_ctx.addMemory(op_key+"_output", out);
              -    dev_ctx.addMemory(op_key+"_filer", wgt);
              -    dev_ctx.addPrimitive(op_key+"_fwd", fwd_primitive);
              -    dev_ctx.addPrimitiveDesc(op_key+"_fwd_PD", fwd_primitive_desc);
              -  }
              -
              -  p = dev_ctx.findPrimitive(op_key + "_fwd");
              -
              -  PADDLE_ENFORCE(p, "Should have forward Primitive");
              -  PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_input"), "Should have input memory");
              -  PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_output"), "Should have output memory");
              -  PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_filter"), "Should have filter memory");
              -  PADDLE_ENFORCE(dev_ctx.findPrimitiveDesc(op_unique_key+"_fwd_PD"), "Should have forward PrimitiveDesc");
              -  dev_ctx.submit(p);
              -  dev_ctx.execute();  // the convert primitive should have already contained.
              -
              -
              -

              The createPrimitiveDesc returns the primitive descripotor of this operator, would be like this:

              -
                auto* input = ctx.Input<Tensor>("Input");
              -  auto* filter = ctx.Input<Tensor>("Filter");
              -  auto* output = ctx.Output<Tensor>("Output");
              -  std::vector<int> strides = ctx.Attr<std::vector<int>>("strides");
              -  std::vector<int> paddings = ctx.Attr<std::vector<int>>("paddings");
              -  std::vector<int> dilations = ctx.Attr<std::vector<int>>("dilations");
              -  int groups = ctx.Attr<int>("groups");
              -  algorithm algo = static_cast<algorithm>(ctx.Attr<int>("convolution_algorithm_option"));
              -  prop_kind pk = ctx.Attr<bool>("is_test") ? prop_kind::forward_inference : prop_kind::forward_training;
              -    
              -  auto fwd_desc = mkldnn::conv_fwd::desc(/* all the setting above*/);
              -  shared_ptr<mkldnn::conv_fwd::primitive_desc> fwd_primitive_desc(new mkldnn::conv_fwd::primitive_desc(fwd_desc, ctx.getEngine()));
              -
              -  return fwd_primitive_desc;
              -  }
              -
              -
              -
              -
              -

              MKLDNNDeviceContext

              -

              MKLDNNDeviceContext, which is very straightforward, should contain some base information like: stream, engine and the map needed.

              -
              -
              -

              mkldnn_helper

              -

              Some functions would be put in paddle/platform/mkldnn_helper.h.

              -
                -
              • create MKLDNN memories
              • -
              • create MKLDNN primitives
              • -
              • error check function
              • -
              • etc
              • -
              -
              -
              -

              Kernel Switch

              -

              We should reorder the different Layout from other device or to other device. GetExpectedKernelType and trans functions can help us to implement it.

              -

              GetExpectedKernelType should get the context, and this operator can return the best KernelType. -trans would be like this:

              -
              void trans(inputs, ctx) override {
              -  if (NoNeedTrans()) {
              -    return;
              -  }
              -  // find reorder primitive by op_key from context
              -  auto& dev_ctx = ctx.template device_context<platform::MKLDNNDeviceContext>();
              -  auto& p = dev_ctx.findPrimitive(op_key + "_reorder_input");
              -  auto& i = dev_ctx.findMemory(op_key + "_src_input");
              -
              -  if (p == nullptr || i == nullptr || changeSized(i, input)) {
              -    auto prim = createPrimitiveDesc(ctx);
              -    auto src = createMemory(memoryDesc(input->dims(), actual_layout), input->data);
              -    auto newbuffer = paddle::memory::Alloc(ctx.GetPlace(), input->size_in_bytes());
              -    auto dst = createMemory(p->expected_desc(), newbuffer->data);
              -    auto reorder_primitive(new mkldnn::reorder(src, dst));
              -
              -    dev_ctx.addMemory(op_key+"_src_input", src);
              -    dev_ctx.addMemory(op_key+"_input", dst);
              -    dev_ctx.addPrimitive(op_key+"_reorder_input", reorder_primitive);
              -  }
              -
              -  p = dev_ctx.findPrimitive(op_key + "_reorder_input");
              -  PADDLE_ENFORCE(p, "Should have Reorder Primitive");
              -  dev_ctx.submit(p);
              -  if (! this->isMKLDNNKernel()) {
              -    // execute immediately only if this is not mkldnn kernel function.
              -    // otherwise, it can be executed with the operator primitive in Compute
              -    dev_ctx.stream();
              -  }
              -  // after submit, the input tensor in ExecutionContext should be changed as the converted one
              -  // there should be another mechanism to ensure this
              -}
              -
              -
              -
              -
              -

              Unit Test

              -

              All the functions should be tested corresponding. -TBD

              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/model_format.html b/develop/doc/design/model_format.html deleted file mode 100644 index 2e1fbe31105..00000000000 --- a/develop/doc/design/model_format.html +++ /dev/null @@ -1,285 +0,0 @@ - - - - - - - - - - - - - Design Doc: Model Format — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Model Format

              -
              -

              Motivation

              -

              A model is an output of the training process. One complete model consists of two parts, the topology and the parameters. In order to support industrial deployment, the model format must be self-complete and must not expose any training source code.

              -

              As a result, In PaddlePaddle, the topology is represented as a ProgramDesc, which describes the model structure. The parameters contain all the trainable weights in the model. We must support large size parameters and efficient serialization/deserialization of parameters.

              -
              -
              -

              Implementation

              -

              The topology is saved as a plain text in a detailed self-contain protobuf file.

              -

              The parameters are saved as a binary file. As we all know, the protobuf message has a limit of 64M size. We have done a benchmark experiment, which shows that protobuf is not fit for the task.

              -

              As a result, we design a particular format for tensor serialization. By default, an arbitrary tensor in Paddle is a LoDTensor, and has a description information proto of LoDTensorDesc. We save the DescProto as the byte string header. It contains all the necessary information, such as the dims, and the LoD information in LoDTensor. A tensor stores values in a continuous memory buffer. For speed we dump the raw memory to disk and save it as the byte string content. So, the binary format of one tensor is,

              -

              The table below shows a tensor’s byte view in detail. Note that all the signed values are written in the little-endian format.

              -

              |field name | type | description | -| — | — | — | -| version | uint32_t | Version of saved file. Always 0 now. | -| tensor desc length | uint32_t | TensorDesc(Protobuf message) length in bytes. | -| tensor desc | void* | TensorDesc protobuf binary message | -| tensor data | void* | Tensor’s data in binary format. The length of tensor_data is decided by TensorDesc.dims() and TensorDesc.data_type() | -| lod_level | uint64_t | Level of LoD | -| length of lod[0] | uint64_t | [Optional] length of lod[0] in bytes. | -| data of lod[0] | uint64_t* | [Optional] lod[0].data() | -| ... | ... | ... |

              -
              -
              -

              Summary

              -
                -
              • We introduce a model format.
              • -
              • The model represented by its forward-pass computation procedure is saved in a ProgramDesc protobuf message.
              • -
              • A bunch of specified format binary tensors describe the parameters.
              • -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/multi_language_interface/00.why_plain_c.html b/develop/doc/design/multi_language_interface/00.why_plain_c.html deleted file mode 100644 index 49bc6e27917..00000000000 --- a/develop/doc/design/multi_language_interface/00.why_plain_c.html +++ /dev/null @@ -1,391 +0,0 @@ - - - - - - - - - - - - - Paddle多语言接口实现 — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Paddle多语言接口实现

              -
              -

              背景

              -

              Paddle需要一个多语言接口,这个接口需要做到:

              -
                -
              • 有标准的,良好的文档
                  -
                • 例如Python可以使用Sphinx生成API文档,golang可以使用GoDoc生成文档。这都需要这个接口按照约定俗成的规则来注释完备。
                • -
                -
              • -
              • 不同语言的接口适应不同语言的特性
                  -
                • 例如Java与Python的错误处理是直接扔出来Exception,而对于golang错误处理应该使用返回值。
                • -
                -
              • -
              -
              -
              -

              基本要求

              -

              Paddle的多语言接口实现包括一下几个方面:

              -
                -
              • 我们使用动态库来分发Paddle。在这个动态库中不嵌入任何其他语言的解释器,也不使用其他动态库。
              • -
              • 这个动态库使用C99标准的头文件导出一些函数,不使用/导出C++符号。
              • -
              • 不导出Paddle内部的结构体、类,仅仅使用void*指针作为类型的句柄(handler)。
              • -
              • 不使用SWIG这种代码生成器,而是手写多语言绑定。
              • -
              -
              -
              -

              原因

              -
              -

              使用动态库来分发Paddle

              -
                -
              • Paddle的链接方式比较复杂
                  -
                • 如果用户要把Paddle的静态库(libpaddle.a)链接到自己的程序里,得使用 --whole-archive (for GCC) 或者 --force_load (for Clang) 参数,来确保把 libpaddle.a 里所有的符号都写入自己的程序的二进制文件里。这是因为 Paddle 的源码里使用了object factory design pattern
                • -
                -
              • -
              • 编译型语言,例如C/C++使用静态库和动态库难度差不多。但是解释性语言,例如Python或者Java,只能调用Paddle的动态库,否则得把Paddle静态库链接到解释器里。
                  -
                • 解释性语言实际运行的二进制是解释器本身,如果调用静态库只能将静态库与解释器链接。例如对于Java来说,便是将静态库加入JVM中。这对于通常的Java的开发者来说,是不常见的做法。
                • -
                -
              • -
              -
              -
              -

              动态库中不嵌入任何其他语言的解释器

              -
                -
              • 目前Paddle的进程模型是C++内部驱动Python解释器进行模型配置解析和数据读取
              • -
              • 我们最终的动态库中不嵌入Python或者其他任何语言的解释器。模型配置解析,数据读取均交由其他语言完成
              • -
              -

              现阶段Paddle有一个问题是,Paddle内嵌的Python解释器和外部使用的Python如果版本不同,会直接报错退出。

              -
              -
              -

              Paddle动态库中,不引用其他动态库

              -
                -
              • 即这个动态库是不依赖于其他任何文件的,可以在任何机器上执行的。
              • -
              -
              -
              -

              这个动态库使用C99标准的头文件导出一些函数,不使用/导出C++符号

              -
                -
              • 由于C++编译器没有名字修饰的规范,不同版本的编译器之间,对于同一段C++代码生成的符号可能不一致。而多语言接口需要直接读取生成的二进制(动态库),需要有稳定的导出符号。
              • -
              • C语言是有导出符号的标准的,并且在常见的平台上,都是ABI调用标准的。
              • -
              • 大多数语言都支持使用C语言API
              • -
              • 使用C99而不使用C89,是因为C99支持Fixed-width integer typesBoolean type
              • -
              • 使用C99而不使用C11的原因是,C11并没有Paddle特别需要的特性,且C99相对于C11使用更加广泛。
              • -
              -
              -
              -

              不导出Paddle内部的结构体、类,仅仅使用void*指针作为类型的句柄(handler)

              -
                -
              • Paddle内部的类为C++书写,直接导出到C的接口比较困难。
              • -
              • 在C-API中使用void*来表示Paddle内部类。再在每一个API中自己检查类型。
              • -
              -

              在C的头文件 paddle_matrix.h 中:

              -
              typedef void* paddle_matrix;
              -typedef int paddle_error;
              -
              -extern "C"
              -paddle_error paddle_matrix_get_shape(paddle_matrix matrix,
              -                                     uint64_t* width,
              -                                     uint64_t* height);
              -
              -
              -

              而在CPP里面实现这个C的接口,文件 paddle_matrix.cpp

              -
              #include "paddle/math/matrix.h"
              -extern "C"
              -paddle_error paddle_matrix_shape(paddle_matrix matrix,
              -                                 uint64_t *width,
              -                                 uint64_t *height) {
              -  auto m = (paddle::capi::CMatrix*)(matrix);
              -  *width = m->width();
              -  *height = m->height();
              -}
              -
              -
              -

              其中paddle/capi/CMatrix.hpp文件内容为:

              -
              namespace paddle {
              -namespace math {  
              -
              -class CMatrix {
              -  std::shared_ptr<paddle::Matrix> mat;
              -};
              -
              -}  // namespace math
              -}  // namespace paddle
              -
              -
              -
              -
              -

              不使用SWIG这种代码生成器,而是手写多语言绑定

              -
                -
              • SWIG是一个多语言接口的代码生成器。他的目标是使用C/C++写代码,SWIG直接读取C/C++的头文件,生成各种语言的绑定代码。
                  -
                • 对于多语言接口,SWIG需要写一个interface文件。这个文件具有独特的语法,学习成本高。且增加一个第三方语言,就需要对这个第三方语言增加一些定义。有的时候,interface文件的写法非常tricky。社区贡献代码学习成本高。
                • -
                • SWIG暴露的接口保留了C++的接口样式,很难保证多语言代码风格的一致性。(函数命名,错误处理)
                    -
                  • 因为SWIG在第三方语言中暴露的函数名,类名和C++中完全一致。C++的命名风格并不能适应其他第三方语言。如果使用SWIG我们需要将在interface文件里,将大量的SomeCppClass重命名成some_python_class,或者SomeGoTypes
                  • -
                  • 对于不同语言,错误处理的方式也不尽相同。例如对于Java或者Python,最常见的错误处理方式是Exception,而对于Golang,错误处理方式是返回值。而SWIG只能简单的暴露C++接口,无法做到对于各种语言错误处理方式的适配。
                  • -
                  -
                • -
                • 对于大多数语言,直接使用C语言的.h并不困难。例如Python的cffi或者Cython, golang的cgo
                • -
                • SWIG支持的语言或者解释器有局限。例如对于Python,使用SWIG只支持CPython解释器,而不支持PyPy解释器。
                • -
                -
              • -
              -
              -
              -
              -

              原因列表

              -

              | 结论 | 对比 | 原因 | -|—| — | — | -| 使用动态库 | 不使用静态库 | 解释型语言只能调用动态库,Paddle静态库链接复杂 | -| 不嵌入其他语言解释器 | 不嵌入Python解释器 | Paddle C++目前嵌入Python解释器,会导致不同版本Python在一个进程里的bug | -| 不引用其他动态库 | | Paddle一个动态库可以在任何Linux系统上运行 | -| 使用C99做接口 | 不使用C++做接口 | C有标准的ABI,C99是目前C最广泛的使用标准,且C99支持bool类型和定长整数(uint64_t等)类型 | -| 使用void*作为类句柄 | 不显示的写每个类具体包含什么| 实现简单,并且让接口脱离实现细节 | -| 手写多语言绑定 | 不使用SWIG | 使用SWIG需要多语言绑定的开发人员熟练掌握SWIG配置,社区参与困难。SWIG生成的代码不能保证多语言代码风格的一致性 |

              -
              -
              -

              实现

              -

              参考Inference implementation

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/multi_language_interface/01.inference_implementation.html b/develop/doc/design/multi_language_interface/01.inference_implementation.html deleted file mode 100644 index 968376c8a1f..00000000000 --- a/develop/doc/design/multi_language_interface/01.inference_implementation.html +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - - - - - - - - C-API 模型推断实现文档 — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              C-API 模型推断实现文档

              -

              本文档描述Paddle C-API的实现细节。Paddle C-API是多语言API的基础部分。Paddle需要暴露的API很多。先实现模型推断的API,通过模型推断API的实现作为一个样例,来进行讨论。至于为什么需要C-API,请参考Why Plain C

              - -
              -

              暴露接口原则

              -
                -
              1. 所有的接口均为C接口。即使用extern "C"
              2. -
              3. 除构造某种类型的函数(paddle_matrix_create等),其他函数均返回paddle_error。且调用时不能抛出异常或出现运行时错误。
              4. -
              5. 所有类型名为paddle_类型名,所有与类型相关的函数,函数名为paddle_类型名_函数名
              6. -
              7. 如果某一个Paddle Core概念(GradientMachine/Matrix)需要被暴露到其他语言,那么
                  -
                • 为了暴露的接口尽量简单。只暴露概念的接口,而不暴露概念的实现。即暴露GradientMachine或者Matrix但不暴露RecurrentGradientMachineCpuSparseMatrix
                • -
                • 暴露这个概念必要函数。必要是指,即完成某一个任务的最少函数。
                • -
                -
              8. -
              9. 不在capi接口层做过多封装。
                  -
                • 如果某一个Paddle概念必须要暴露,但是又过于琐碎。不在capi这一层进行封装,而是直接修改Paddle Core。让Paddle核心中,这一概念不再琐碎。
                • -
                -
              10. -
              -
              -
              -

              目录结构

              -
              Paddle
              -  `-- paddle
              -        `-- capi
              -              `-- examples  # The example project for C-API.
              -              `-- tests  # unittests for C-API
              -              `-- capi.h  # C-API header file.
              -              `-- capi_private.h  # The shared header file between implementation sources.
              -              `-- matrix.{h, cpp}
              -              `-- gradient_machine.{h, cpp}
              -              `-- ...
              -
              -
              -

              Paddle的C-API目录结构如上图表所示。这个目录中除了capi_private.h之外的所有头文件,均会被安装到include/paddle路径下。C-API生成的二进制文件会被安装到lib目录下。即,安装后的目录结构为

              -
              `-- include
              -      `-- paddle
              -             `-- capi.h
              -             `-- matrix.h
              -             `-- gradient_machine.h
              -             `-- ...
              -`-- lib
              -     `-- libpaddle_capi_shared.{so, dylib}  # In mac, dynamic libary's file name extention is `dylib`
              -     `-- libpaddle_capi_whole.a  # static library for all symbols of Paddle.
              -
              -
              -
              -
              -

              实现方式

              -

              下面分别介绍某一类文件的实现方式。

              -
              -

              capi.h

              -

              capi.h是用户使用C-API时所唯一需要引入的头文件。在capi.h中,引入了类型的头文件,matrix.h, gradient_machine.h。在引入其他类型的头文件时,使用相对路径的引用方式。即#include "matrix.h"

              -
              -
              -

              具体某种类型的头文件

              -

              具体某种类型的头文件,即例如matrix.hgradient_machine.h等。在这些头文件中,包含了某种类型的类型定义和暴露的全部函数。

              -

              这个头文件不假设其他文件的引用顺序,即使用户直接引用某种类型的头文件,也不应该报错(虽然不鼓励这样)。如果某一个类型需要引用另一个类型,例如gradient_machine需要引用matrix,则直接引入另一种类型的头文件,即#include "matrix.h"

              -
              -
              -

              capi_private.h

              -

              capi_prviate.h是各个实现中共享的头文件,他主要包含了实际暴露的类型结构。在用户使用C-API时,Paddle的类型全部退化成void *,即typedef paddle_matrix void*。但,对于每种C-API暴露的类型,均是在capi_private.h中实现的结构体。

              -
              struct CMatrix {
              -   int type = MatrixType;
              -   std::shared_ptr<paddle::Matrix> mat;
              -};
              -
              -
              -

              通常,这个结构体包含两个项目。

              -
                -
              • type是一个类型的标志。对于每种类型,type字段均不尽相同。这样,即使C-API接受的类型全是void *,我们也可以确定每一个参数的类型。

                -
                void some_c_api_function(void* some_instance) {
                -   int* type = (int *) some_instance;
                -   switch (*type) {
                -     case MatrixType:
                -       CMatrix* mat = (CMatrix *) some_instance;
                -       ...
                -     ...
                -   }
                -}
                -
                -
                -
              • -
              • 这个结构体中的另一个项目是,Paddle Core中这一类型接口的智能指针(shared_ptr)。

                -
                  -
                • 使用智能指针的原因是: 用户可以安全的释放某个C-API的实例,而不必在意Paddle Core是否还在使用这个实例。
                • -
                • 例如,用户通过C-API获得了神经网络的参数实例。当用户使用完这个参数后,直接删除这个参数即可。即便Paddle Core中的模型还在使用这个参数,这个参数也不会一并删除。
                • -
                -
              • -
              -
              -
              -

              具体某种类型的实现文件

              -

              具体某种类型的实现文件,即matrix.cpp, gradient_machine.cpp等文件。在这些文件中,使用C++ 11实现了C-API的接口,并且使用extern "C"导出这些接口。在实现过程中,对输入参数的安全性进行了必要的判断,并将C-API接口的参数转发给Paddle Core

              -
              -
              -

              libpaddle_capi_shared.{so, dylib}

              -

              libpaddle_capi_shared是C-API导出的动态库。这个动态库的连接参数与Paddle的其他二进制(例如paddle_trainer)类似。用户可以直接使用这个动态库来引入Paddle C-API。具体使用方法为-lpaddle_capi_shared

              -
              -
              -

              libpaddle_capi_whole.a

              -

              libpaddle_capi_whole是C-API导出的静态库。这个静态库包含了Paddle的全部符号。他是将libpaddle_gserver.a, libpaddle_math.a, libpaddle_capi.a等全部静态库中的目标文件全部打包后产生的文件。具体使用方法为--whole-archive -lpaddle_capi_whole --no-whole-archive

              -
              -
              -

              examples

              -

              在样例中,使用C99开发了模型预测的样例代码。具体请参考example/README.md

              -
              -
              -
              -

              编译选项

              -

              C-API的编译选项默认关闭,打开这个编译选项,需要在cmake的时候,设置

              -
              cmake ${YOUR_SOURCE_ROOT} -DWITH_C_API=ON -DWITH_PYTHON=OFF -DWITH_SWIG_PY=OFF
              -
              -
              -

              编译C-API的时候推荐Paddle不嵌入Python解释器,也不生成SWIG接口,具体原因参考Why Plain C

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/operator_kernel_type.html b/develop/doc/design/operator_kernel_type.html deleted file mode 100644 index d45a4297fd5..00000000000 --- a/develop/doc/design/operator_kernel_type.html +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - Design Doc: The Keys of Operator Kernel Type — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: The Keys of Operator Kernel Type

              -
              -

              Problem

              -

              An operator can have different kernel implementations, and each operator will have a map to store the related kernels. Fluid uses OpKernelType as a key to identify a unique kernel. Before an operator runs, a certain type of kernel must be chosen via a key of OpKernelType. Currently, OpKernelType is defined as follows:

              -
              struct OpKernelType {
              -  platform::Place place_;
              -  proto::DataType data_type_;
              -};
              -
              -
              -

              For more details, please refer to codes in github.

              -

              It contains two keys, Place and DataType. And these two keys will be hashed to a unique key to represent a certain type of kernel. However, these two keys do not provide enough information. We need a more complete representation of OpKernelType.

              -

              We often implement a kernel of an operator with some computing library on certain device(place). Please note that computing library and device do not have a one-to-one correspondence. A device can have a lot of computing libraries and a computing library can also support different devices.

              -

              For example, Eigen library supports Nvidia GPU/AMD GPU/CPU and MKLDNN library supports Intel CPU/Intel FPGA. Both Place and Library should be a key of OpKernelType.

              -

              Different DataTypes, such as fp64/fp32/int8, will obviously have different kernels. But different data layout of a Tensor will also lead to different implementations. Please refer to the batch norm operator kernels as an example. Data layout should also be taken into consideration.

              -
              -
              -

              Solution

              -

              There are four keys to determine a kernel type of an operator: Place/Library/DataType/Layout.

              -
              struct OpKernelType {
              -  platform::Place place_;
              -  platform::Library library_;
              -  proto::DataType data_type_;
              -  framework::Layout layout_;
              -};
              -
              -
              -

              The details are as follows:

              -
              -

              Place

              -

              Place is defined as:

              -
              typedef boost::variant<CUDAPlace, ROCmPlace, FPGAPlace, CPUPlace> Place;
              -
              -
              -

              Place represents the device memory where data is located.

              -
              -
              -

              Library

              -

              One operator kernel is usually implemented based on one library. Library is defined as a enum variable:

              -
              enum Library { Plain, MKLDNN, CUDNN };
              -
              -
              -

              We use Plain enumerator to represent default library. Since most operators in Fluid are implemented based on the Eigen library, we take Eigen library as the Plain enumerator. -A library usually has a corresponding DeviceContext which contains some handles needed for computation. Fluid now has two default DeviceContexts for CPU and CUDA, namely, CPUDeviceContext and CUDADeviceContext. CPUDeviceContext contains an Eigen library handle and CDUADeviceContext contains an Eigen library handle and a cuBLAS handle.

              -

              If we want to support new library, a new enumerator need to be added to Library and a corresponding new LibraryDeviceContext need to be created.

              -
              -
              -

              DataType

              -

              DataType is defined in framework.proto. Currently, int32/int64/fp32/fp64 are supported.

              -
              -
              -

              Layout

              -

              Actually, a Tensor is a view of a block of memory. Besides a pointer to the memory, we also have to get some other descriptions of this block of memory, such as shape(ddim), stride, and layout.

              -

              Different layout leads to different implementation of the operator kernel. There are mainly 4 principles we have to follow to support layout in our Fluid framework.

              -
                -
              • We take layout as a data member of Tensor. Layout is actually a enum variable. If Fluid is built with MKLDNN, then the memory format in MKLDNN will also be added into this enum variable.
              • -
              • Users have to set layout for input data. And some operators like fill_constant/random, also have to set layout for generating data. Of course, we can have some default layout, like NCHW.
              • -
              • The inference of Layout is at run-time, not at compile-time.
              • -
              • Every operator has to implement different kernels for different layouts. Let’s take MKLDNN as an example. If we want to implement an MKLDNN convolution operator, we have to implement all the kernels for different layouts, which are listed here. And we will have a special macro to register kernels for MKLDNN operators.
              • -
              -

              Layout is also defined as a enum variable:

              -
              enum Layout {
              -  kNCHW,
              -  kNHWC,
              -#ifdef PADDLE_WITH_MKLDNN
              -  knChw8c
              -  ...
              -#endif
              -};
              -
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/ops/rnn.html b/develop/doc/design/ops/rnn.html deleted file mode 100644 index a14d6e7c309..00000000000 --- a/develop/doc/design/ops/rnn.html +++ /dev/null @@ -1,386 +0,0 @@ - - - - - - - - - - - - - RNNOp design — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              RNNOp design

              -

              This document describes the RNN (Recurrent Neural Network) operator and how it is implemented in PaddlePaddle. The RNN op requires that all instances in a mini-batch have the same length. We will have a more flexible dynamic RNN operator in the future.

              -
              -

              RNN Algorithm Implementation

              -

              - -

              The above diagram shows an RNN unrolled into a full network.

              -

              There are several important concepts here:

              -
                -
              • step-net: the sub-graph that runs at each step.
              • -
              • memory, $h_t$, the state of the current step.
              • -
              • ex-memory, $h_{t-1}$, the state of the previous step.
              • -
              • initial memory value, the memory of the first (initial) step.
              • -
              -
              -

              Step-scope

              -

              There could be local variables defined in each step-net. PaddlePaddle runtime realizes these variables in step-scopes which are created for each step.

              -

              -
              -Figure 2 illustrates the RNN's data flow -

              Please be aware that every step runs the same step-net. Each step does the following:

              -
                -
              1. Creates the step-scope.
              2. -
              3. Initializes the local variables including step-outputs, in the step-scope.
              4. -
              5. Runs the step-net, which uses the above mentioned variables.
              6. -
              -

              The RNN operator will compose its output from step outputs in each of the step scopes.

              -
              -
              -

              Memory and Ex-memory

              -

              Let’s give more details about memory and ex-memory using a simple example:

              -

              $$ -h_t = U h_{t-1} + W x_t -$$,

              -

              where $h_t$ and $h_{t-1}$ are the memory and ex-memory (previous memory) of step $t$ respectively.

              -

              In the implementation, we can make an ex-memory variable either “refer to” the memory variable of the previous step, -or copy the memory value of the previous step to the current ex-memory variable.

              -
              -
              -

              Usage in Python

              -

              For more information on Block, please refer to the design doc.

              -

              We can define an RNN’s step-net using a Block:

              -
              import paddle as pd
              -
              -X = some_op() # x is some operator's output and is a LoDTensor
              -a = some_op()
              -
              -# declare parameters
              -W = pd.Variable(shape=[20, 30])
              -U = pd.Variable(shape=[20, 30])
              -
              -rnn = pd.create_rnn_op(output_num=1)
              -with rnn.stepnet():
              -    x = rnn.add_input(X)
              -    # declare a memory (rnn's step)
              -    h = rnn.add_memory(init=a)
              -    # h.pre_state(), the previous memory of rnn
              -    new_state = pd.add_two( pd.matmul(W, x) + pd.matmul(U, h.pre_state()))
              -    # update current memory
              -    h.update(new_state)
              -    # indicate that h variables in all step scopes should be merged
              -    rnn.add_outputs(h)
              -
              -out = rnn()
              -
              -
              -

              Python API functions in above example:

              -
                -
              • rnn.add_input: indicates that the parameter is a variable that will be segmented into step-inputs.
              • -
              • rnn.add_memory: creates a variable used as the memory.
              • -
              • rnn.add_outputs: marks the variables that will be concatenated across steps into the RNN output.
              • -
              -
              -
              -

              Nested RNN and LoDTensor

              -

              An RNN whose step-net includes other RNN operators is known as an nested RNN.

              -

              For example, we could have a 2-level RNN, where the top level corresponds to paragraphs, and the lower level corresponds to sentences. Each step of the higher level RNN also receives an input from the corresponding step of the lower level, and additionally the output from the previous time step at the same level.

              -

              The following figure illustrates feeding in text into the lower level, one sentence at a step, and the feeding in step outputs to the top level. The final top level output is about the whole text.

              -

              - -

              import paddle as pd
              -
              -W = pd.Variable(shape=[20, 30])
              -U = pd.Variable(shape=[20, 30])
              -
              -W0 = pd.Variable(shape=[20, 30])
              -U0 = pd.Variable(shape=[20, 30])
              -
              -# a is output of some op
              -a = some_op()
              -
              -# chapter_data is a set of 128-dim word vectors
              -# the first level of LoD is sentence
              -# the second level of LoD is a chapter
              -chapter_data = pd.Variable(shape=[None, 128], type=pd.lod_tensor, level=2)
              -
              -def lower_level_rnn(paragraph):
              -    '''
              -    x: the input
              -    '''
              -    rnn = pd.create_rnn_op(output_num=1)
              -    with rnn.stepnet():
              -        sentence = rnn.add_input(paragraph, level=0)
              -        h = rnn.add_memory(shape=[20, 30])
              -        h.update(
              -            pd.matmul(W, sentence) + pd.matmul(U, h.pre_state()))
              -        # get the last state as sentence's info
              -        rnn.add_outputs(h)
              -    return rnn
              -
              -top_level_rnn = pd.create_rnn_op(output_num=1)
              -with top_level_rnn.stepnet():
              -    paragraph_data = rnn.add_input(chapter_data, level=1)
              -    low_rnn = lower_level_rnn(paragraph_data)
              -    paragraph_out = low_rnn()
              -
              -    h = rnn.add_memory(init=a)
              -    h.update(
              -        pd.matmul(W0, paragraph_data) + pd.matmul(U0, h.pre_state()))
              -    top_level_rnn.add_outputs(h)
              -
              -# output the last step
              -chapter_out = top_level_rnn(output_all_steps=False)
              -
              -
              -

              In the above example, the construction of the top_level_rnn calls lower_level_rnn. The input is an LoD Tensor. The top level RNN segments input text data into paragraphs, and the lower level RNN segments each paragraph into sentences.

              -

              By default, the RNNOp will concatenate the outputs from all the time steps. -If the output_all_steps is set to False, it will only output the final time step.

              -

              - -

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/ops/sequence_decoder.html b/develop/doc/design/ops/sequence_decoder.html deleted file mode 100644 index d0a58d5352f..00000000000 --- a/develop/doc/design/ops/sequence_decoder.html +++ /dev/null @@ -1,461 +0,0 @@ - - - - - - - - - - - - - Design: Sequence Decoder Generating LoDTensors — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design: Sequence Decoder Generating LoDTensors

              -

              In tasks such as machine translation and visual captioning, -a sequence decoder is necessary to generate sequences, one word at a time.

              -

              This documentation describes how to implement the sequence decoder as an operator.

              -
              -

              Beam Search based Decoder

              -

              The beam search algorithm is necessary when generating sequences. It is a heuristic search algorithm that explores the paths by expanding the most promising node in a limited set.

              -

              In the old version of PaddlePaddle, the C++ class RecurrentGradientMachine implements the general sequence decoder based on beam search, due to the complexity involved, the implementation relies on a lot of special data structures that are quite trivial and hard to be customized by users.

              -

              There are a lot of heuristic tricks in the sequence generation tasks, so the flexibility of sequence decoder is very important to users.

              -

              During the refactoring of PaddlePaddle, some new concepts are proposed such as: LoDTensor and TensorArray that can better support the sequence usage, and they can also help make the implementation of beam search based sequence decoder more transparent and modular .

              -

              For example, the RNN states, candidates IDs and probabilities of beam search can be represented all as LoDTensors; -the selected candidate’s IDs in each time step can be stored in a TensorArray, and Packed to the sentences translated.

              -
              -
              -

              Changing LoD’s absolute offset to relative offsets

              -

              The current LoDTensor is designed to store levels of variable-length sequences. It stores several arrays of integers where each represents a level.

              -

              The integers in each level represent the begin and end (not inclusive) offset of a sequence in the underlying tensor, -let’s call this format the absolute-offset LoD for clarity.

              -

              The absolute-offset LoD can retrieve any sequence very quickly but fails to represent empty sequences, for example, a two-level LoD is as follows

              -
              [[0, 3, 9]
              - [0, 2, 3, 3, 3, 9]]
              -
              -
              -

              The first level tells that there are two sequences:

              -
                -
              • the first’s offset is [0, 3)
              • -
              • the second’s offset is [3, 9)
              • -
              -

              while on the second level, there are several empty sequences that both begin and end at 3. -It is impossible to tell how many empty second-level sequences exist in the first-level sequences.

              -

              There are many scenarios that rely on empty sequence representation, for example in machine translation or visual captioning, one instance has no translation or the empty candidate set for a prefix.

              -

              So let’s introduce another format of LoD, -it stores the offsets of the lower level sequences and is called relative-offset LoD.

              -

              For example, to represent the same sequences of the above data

              -
              [[0, 3, 6]
              - [0, 2, 3, 3, 3, 9]]
              -
              -
              -

              the first level represents that there are two sequences, -their offsets in the second-level LoD is [0, 3) and [3, 5).

              -

              The second level is the same with the relative offset example because the lower level is a tensor. -It is easy to find out the second sequence in the first-level LoD has two empty sequences.

              -

              The following examples are based on relative-offset LoD.

              -
              -
              -

              Usage in a simple machine translation model

              -

              Let’s start from a simple machine translation model that is simplified from the machine translation chapter to draw a blueprint of what a sequence decoder can do and how to use it.

              -

              The model has an encoder that learns the semantic vector from a sequence, and a decoder which uses the sequence encoder to generate new sentences.

              -

              Encoder

              -
              import paddle as pd
              -
              -dict_size = 8000
              -source_dict_size = dict_size
              -target_dict_size = dict_size
              -word_vector_dim = 128
              -encoder_dim = 128
              -decoder_dim = 128
              -beam_size = 5
              -max_length = 120
              -
              -# encoder
              -src_word_id = pd.data(
              -    name='source_language_word',
              -    type=pd.data.integer_value_sequence(source_dict_dim))
              -src_embedding = pd.embedding(size=source_dict_size, size=word_vector_dim)
              -
              -src_word_vec = pd.lookup(src_embedding, src_word_id)
              -
              -encoder_out_seq = pd.gru(input=src_word_vec, size=encoder_dim)
              -
              -encoder_ctx = pd.last_seq(encoder_out_seq)
              -# encoder_ctx_proj is the learned semantic vector
              -encoder_ctx_proj = pd.fc(
              -    encoder_ctx, size=decoder_dim, act=pd.activation.Tanh(), bias=None)
              -
              -
              -

              Decoder

              -
              def generate():
              -    decoder = pd.while_loop()
              -    with decoder.step():
              -        decoder_mem = decoder.memory(init=encoder_ctx)  # mark the memory
              -        generated_ids = decoder.memory() # TODO init to batch_size <s>s
              -        generated_scores = decoder.memory() # TODO init to batch_size 1s or 0s
              -
              -        target_word = pd.lookup(trg_embedding, gendrated_ids)
              -        # expand encoder_ctx's batch to fit target_word's lod
              -        # for example
              -        # decoder_mem.lod is
              -        # [[0 1 3],
              -        #  [0 1 3 6]]
              -        # its tensor content is [a1 a2 a3 a4 a5]
              -        # which means there are 2 sentences to translate
              -        #   - the first sentence has 1 translation prefixes, the offsets are [0, 1)
              -        #   - the second sentence has 2 translation prefixes, the offsets are [1, 3) and [3, 6)
              -        # the target_word.lod is
              -        # [[0, 1, 6]
              -        #  [0, 2, 4, 7, 9 12]]
              -        # which means 2 sentences to translate, each has 1 and 5 prefixes
              -        # the first prefix has 2 candidates
              -        # the following has 2, 3, 2, 3 candidates
              -        # the encoder_ctx_expanded's content will be
              -        # [a1 a1 a2 a2 a3 a3 a3 a4 a4 a5 a5 a5]
              -        encoder_ctx_expanded = pd.lod_expand(encoder_ctx, target_word)
              -        decoder_input = pd.fc(
              -            act=pd.activation.Linear(),
              -            input=[target_word, encoder_ctx_expanded],
              -            size=3 * decoder_dim)
              -        gru_out, cur_mem = pd.gru_step(
              -            decoder_input, mem=decoder_mem, size=decoder_dim)
              -        scores = pd.fc(
              -            gru_out,
              -            size=trg_dic_size,
              -            bias=None,
              -            act=pd.activation.Softmax())
              -        # K is an config
              -        topk_scores, topk_ids = pd.top_k(scores, K)
              -        topk_generated_scores = pd.add_scalar(topk_scores, generated_scores)
              -
              -        selected_ids, selected_generation_scores = decoder.beam_search(
              -            topk_ids, topk_generated_scores)
              -
              -        # update the states
              -        decoder_mem.update(cur_mem)  # tells how to update state
              -        generated_ids.update(selected_ids)
              -        generated_scores.update(selected_generation_scores)
              -
              -        decoder.output(selected_ids)
              -        decoder.output(selected_generation_scores)
              -
              -translation_ids, translation_scores = decoder()
              -
              -
              -

              The decoder.beam_search is an operator that, given the candidates and the scores of translations including the candidates, -returns the result of the beam search algorithm.

              -

              In this way, users can customize anything on the input or output of beam search, for example:

              -
                -
              1. Make the corresponding elements in topk_generated_scores zero or some small values, beam_search will discard this candidate.
              2. -
              3. Remove some specific candidate in selected_ids.
              4. -
              5. Get the final translation_ids, remove the translation sequence in it.
              6. -
              -

              The implementation of sequence decoder can reuse the C++ class: RNNAlgorithm, -so the python syntax is quite similar to that of an RNN.

              -

              Both of them are two-level LoDTensors:

              -
                -
              • The first level represents batch_size of (source) sentences.
              • -
              • The second level represents the candidate ID sets for translation prefix.
              • -
              -

              For example, 3 source sentences to translate, and has 2, 3, 1 candidates.

              -

              Unlike an RNN, in sequence decoder, the previous state and the current state have different LoD and shape, and an lod_expand operator is used to expand the LoD of the previous state to fit the current state.

              -

              For example, the previous state:

              -
                -
              • LoD is [0, 1, 3][0, 2, 5, 6]
              • -
              • content of tensor is a1 a2 b1 b2 b3 c1
              • -
              -

              the current state is stored in encoder_ctx_expanded:

              -
                -
              • LoD is [0, 2, 7][0 3 5 8 9 11 11]
              • -
              • the content is
                  -
                • a1 a1 a1 (a1 has 3 candidates, so the state should be copied 3 times for each candidates)
                • -
                • a2 a2
                • -
                • b1 b1 b1
                • -
                • b2
                • -
                • b3 b3
                • -
                • None (c1 has 0 candidates, so c1 is dropped)
                • -
                -
              • -
              -

              The benefit from the relative offset LoD is that the empty candidate set can be represented naturally.

              -

              The status in each time step can be stored in TensorArray, and Packed to a final LoDTensor. The corresponding syntax is:

              -
              decoder.output(selected_ids)
              -decoder.output(selected_generation_scores)
              -
              -
              -

              The selected_ids are the candidate ids for the prefixes, and will be Packed by TensorArray to a two-level LoDTensor, where the first level represents the source sequences and the second level represents generated sequences.

              -

              Packing the selected_scores will get a LoDTensor that stores scores of each translation candidate.

              -

              Packing the selected_generation_scores will get a LoDTensor, and each tail is the probability of the translation.

              -
              -
              -

              LoD and shape changes during decoding

              -

              - -

              According to the image above, the only phase that changes the LoD is beam search.

              -
              -
              -

              Beam search design

              -

              The beam search algorithm will be implemented as one method of the sequence decoder and has 3 inputs:

              -
                -
              1. topk_ids, the top K candidate ids for each prefix.
              2. -
              3. topk_scores, the corresponding scores for topk_ids
              4. -
              5. generated_scores, the score of the prefixes.
              6. -
              -

              All of these are LoDTensors, so that the sequence affiliation is clear. Beam search will keep a beam for each prefix and select a smaller candidate set for each prefix.

              -

              It will return three variables:

              -
                -
              1. selected_ids, the final candidate beam search function selected for the next step.
              2. -
              3. selected_scores, the scores for the candidates.
              4. -
              5. generated_scores, the updated scores for each prefix (with the new candidates appended).
              6. -
              -
              -
              -

              Introducing the LoD-based Pack and Unpack methods in TensorArray

              -

              The selected_ids, selected_scores and generated_scores are LoDTensors that exist at each time step, -so it is natural to store them in arrays.

              -

              Currently, PaddlePaddle has a module called TensorArray which can store an array of tensors. It is better to store the results of beam search in a TensorArray.

              -

              The Pack and UnPack in TensorArray are used to pack tensors in the array to an LoDTensor or split the LoDTensor to an array of tensors. -It needs some extensions to support the packing or unpacking an array of LoDTensors.

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/optimizer.html b/develop/doc/design/optimizer.html deleted file mode 100644 index c594f2642d2..00000000000 --- a/develop/doc/design/optimizer.html +++ /dev/null @@ -1,341 +0,0 @@ - - - - - - - - - - - - - Optimizer Design — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Optimizer Design

              -
              -

              The Problem

              -

              A PaddlePaddle program, or a block, is a sequence of operators operating variables. A training program needs to do three kinds of works:

              -
                -
              1. the forward pass, which computes intermediate results and the cost(s),
              2. -
              3. the backward pass, which derives gradients from intermediate results and costs, and
              4. -
              5. the optimization pass, which update model parameters to optimize the cost(s).
              6. -
              -

              These works rely on three kinds of operators:

              -
                -
              1. forward operators,
              2. -
              3. gradient operators, and
              4. -
              5. optimization operators.
              6. -
              -

              It’s true that users should be able to create all these operators manually by calling some low-level API, but it would be much more convenient if they could only describe the forward pass and let PaddlePaddle create the backward and optimization operators automatically.

              -

              In this design, we propose a high-level API that automatically derives the optimisation pass and operators from the forward pass.

              -
              -
              -

              High-level Python API to describe the training process

              -
                -
              1. User write code to describe the network:

                -
                images = layer.data("images")
                -labels = layer.data("labels")
                -w1 = pd.var("w1")
                -b1 = pd.var("b1")
                -hidden = layer.fc(images, w=w1, b=b1)
                -cost = layer.mse(hidden, labels)
                -
                -
                -

                The above code snippet will create forward operators in Block.

                -
              2. -
              -
                -
              1. Users create a certain kind of Optimizer with some argument.

                -
                optimizer = AdagradOptimizer(learing_rate=0.001)
                -
                -
                -
              2. -
              3. Users use the optimizer to minimize a certain cost through updating parameters in parameter_list.

                -
                opt_op_list = optimizer.minimize(cost, parameter_list=[w1, b1])
                -
                -
                -

                The above code snippet will create gradient and optimization operators in Block. The return value of minimize() is list of optimization operators that will be run by session.

                -
              4. -
              5. Users use Session/Executor to run this opt_op_list as target to do training.

                -
                sess.run(target= opt_op_list, ...)
                -
                -
                -
              6. -
              -
              -

              Optimizer Python interface:

              -
              class Optimizer(object):
              -    """Optimizer Base class.
              -
              -    """
              -
              -    def __init__(self):
              -        pass
              -
              -    def create_optimization_pass(self, parameters_and_grads):
              -        """Add optimization operators to update gradients to variables.
              -
              -        Args:
              -          parameters_and_grads: a list of (variable, gradient) pair to update.
              -
              -        Returns:
              -          optmization_op_list: a list of optimization operator that will update parameter using gradient.
              -        """
              -        return None
              -
              -    def minimize(self, loss, parameter_list):
              -        """Add operations to minimize `loss` by updating `parameter_list`.
              -
              -        This method combines interface `append_backward()` and
              -        `create_optimization_pass()` into one.
              -        """
              -        params_grads = self.create_backward_pass(loss, parameter_list)
              -        update_ops = self.create_optimization_pass(params_grads)
              -        return update_ops
              -
              -
              -
              -

              Users can inherit the Optimizer above to create their own Optimizer with some special logic, such as AdagradOptimizer.

              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/paddle_nccl.html b/develop/doc/design/paddle_nccl.html deleted file mode 100644 index a3b4f33e294..00000000000 --- a/develop/doc/design/paddle_nccl.html +++ /dev/null @@ -1,319 +0,0 @@ - - - - - - - - - - - - - Design Doc: NCCL support in Paddle Fluid — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: NCCL support in Paddle Fluid

              -
              -

              Abstract

              -

              This Design Doc refers to the NCCL feature in paddle. We propose an approach to support NCCL library both on a single machine and multiple machines. We wrapper the NCCL primitives Broadcast, Allreduce, Reduce as operators to utilize Multi-GPU powers in one script.

              -
              -
              -

              Motivation

              -

              NCCL is a NVIDIA library support Multi-GPU communicating and optimized for NVIDIA GPUs, it provides routines such as all-gather, all-reduce, broadcast, reduce, reduce-scatter, that can achieve high bandwidth over PCIe and NVLink high-speed interconnect. With NCCL library, we can easily accelerate the training in parallel.

              -
                -
              • Pros
              • -
              -
                -
              1. easily plug-in with NCCL2 library.
              2. -
              3. high performance in NVIDIA GPUs.
              4. -
              5. MPI like primitives, which have low learning cost for users.
              6. -
              -
                -
              • Cons
              • -
              -
                -
              1. Only design for NVIDIA GPUs, not a general multi-device solution.
              2. -
              3. Although NCCL1 is opensourced under BSD license, but NCCL2 is not opensourced anymore.
              4. -
              -

              At the beginning of training, the framework needs to distribute the same parameters to every GPU, and merge the gradients at any time user interests.

              -

              As a result, during training, we need the operations of peer to peer copy between different GPUs, aggregating gradients/parameters from GPUs, and broadcasting parameters to GPUs. Every GPU only need to run the operator with correct place information.

              -

              Besides, it needs interfaces to synchronize model update with each different GPU Cards.

              -
              -
              -

              Implementation

              -

              As mentioned above, we wrap the NCCL routines as several kinds of operators. Need to note that NCCL need to create Communicator between gpu at the beginning, so there is a NCCLInit operator created.

              -
              -

              Transpiler

              -

              To be compatible with parameter server design doc, the transpiler compiles the user defined operation graph into sub-graphs to be executed on different devices.

              -
                -
              1. The user-defined model will be a single device program

                -
              2. -
              3. Broadcast/Reduce operators between GPUs will be inserted into the program, even for the multi-node, may insert the Send, Recv operator.

                -

                Broadcast, AllReduce in a single machine. And Broadcast, AllReduce, Send, Recv in multiple machines

                -

                -
              4. -
              -

              After compiling, the graph as shows

              -

              -

              Operators are added to the sub-graphs. Every GPU assigned a role of rank0, rank1 etc.

              -
                -
              • Broadcast. Broadcast operator distribute initialized parameter to all the GPUs from the GPU who owns it. e.g. fromrank0 GPU.
              • -
              • AllReduce. AllReduce operator synchronizes parameters/gradients between GPUs. AllReduce implemented in the Ring-Based communicating method, avoid of the bottle neck in a single GPU.
              • -
              -

              Need to notice that AllReduce operator force GPUs synchronized at that point. The whole training process in asynchronous or synchronous mode depends on the AllReduce point in the graph.

              -

              As it shown in the picture, when each GPU compute the gradient of W, followed with a AllReduce operator, accumulate the dW to full batch of data, then run the optimize process individually and apply the gradient to its W.

              -
                -
              • AllReduce -Need to note that our AllReduce operator is a ring-base AllReduce implementation. If we use the NCCL2 AllReduce primitive, every GPU optimized full batch of data, wasted (n-1) GPU compute resources. In addition, NCCL2 built-in AllReduce will only utilize the communicating resource during synchronization, then update the gradient will be a subsequent phase. In fact, we can amortize the update gradient time cost into the communicating phase. The process is
              • -
              -
                -
              1. Every parameter has its root card. That card will responsible for aggregating the gradients from GPUs.
              2. -
              3. The whole model’s parameter will be hashed to different root card, ensure the load balance between GPUs.
              4. -
              5. Logically neighberhood card will start send parameter to the next one. After one round, the parameter main card will aggregate the full gradients.
              6. -
              7. Then the root card will optimize the parameter.
              8. -
              9. This parameter card will send its optimized result to its neighberhood, then the neighberhood will send parameter to its next one.
              10. -
              11. Finish the sychronization round.
              12. -
              -

              The total time cost will be 2 * (n-1) * per-parameter-send-time, we reach the goal of amortize the upgrade time into communicating phase.

              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/parallel_do.html b/develop/doc/design/parallel_do.html deleted file mode 100644 index fd76e820d83..00000000000 --- a/develop/doc/design/parallel_do.html +++ /dev/null @@ -1,410 +0,0 @@ - - - - - - - - - - - - - Design Doc: Parallel_Do in PaddlePaddle — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Parallel_Do in PaddlePaddle

              -

              In PaddlePaddle, we use parallel_do primitive to represent multithread data parallel processing.

              -
              -

              Design overview

              -

              The definition of a parallel_do op looks like the following

              -
              AddInput(kInputs, "Inputs needed to be split onto different devices").AsDuplicable();
              -AddInput(kParameters, "Parameters are duplicated over different devices")
              -    .AsDuplicable();
              -AddInput(kPlaces, "Devices used for parallel processing");
              -AddOutput(kOutputs, "Outputs needed to be merged from different devices").AsDuplicable();
              -AddOutput(kParallelScopes,
              -          "Scopes for all local variables in forward pass. One scope for each device");
              -AddAttr<framework::BlockDesc *>(kParallelBlock,
              -                                "List of operaters to be executed in parallel");
              -
              -
              -

              A vanilla implementation of parallel_do can be shown as the following (| means single thread and -|||| means multiple threads)

              -
              In the forward pass
              -  |      Split input onto different devices
              -  |      Copy parameter onto different devices
              -  ||||   Compute forward pass in parallel
              -  |      Merge output from different devices
              -
              -In the backward pass
              -  |      Split output@grad onto different devices
              -  ||||   Compute backward pass in parallel
              -  |      accumulate param@grad from different devices to the first device
              -  |      Merge input@grad from different devices
              -  |      Copy param@grad to the place of parallel_do_op
              -
              -
              -

              This implementation allows to write mixed device program like this

              -
              W1 = fluid.tensor(size=[100,20], parameter=true)
              -W2 = fluid.tensor(size=[20,15], parameter=true)
              -
              -data = layers.data()
              -
              -gpu_places = layers.get_place(use_gpu=True)
              -# parallel processing on multiple GPUs
              -pd = ParallelDo(gpu_places)
              -with pd.do(input=data):
              -    prediction = softmax(fc(fc(data, W1), W2))
              -    write_output(prediction)
              -prediction = pd()
              -loss = cross_entropy(prediction, label)
              -
              -
              -

              And the programDesc are like the following

              -
              # start_program will be run by executor(CPUPlace), all w1, w2 will be allocated on CPU
              -start_program
              -{
              -  vars: w1, w2
              -  ops: init(w1), init(w2)
              -}
              -
              -main_program
              -{
              -block0 {
              -  vars: data, places, w1, w2, w1_grad, w2_grad,
              -  ops: data, get_place, parallel_do(block1),
              -       parallel_do_grad(block2),
              -       sgd(w2, w2_grad),
              -       sgd(w1, w1_grad)
              -}
              -block1 { # the forward pass
              -  parent_block: 0
              -  vars: data, h1, h2, loss
              -  ops: fc, fc, softmax
              -}
              -block2 { # the backward pass
              -  parent_block: 1
              -  vars: data_grad, h1_grad, h2_grad, loss_gard, local_w1_grad, local_w2_grad
              -  ops: softmax_grad,
              -       fc_grad
              -       fc_grad
              -}
              -}
              -
              -
              -
              -
              -

              Performance Imporvement

              -

              There are serial places we can make this parallel_do faster.

              -
              -

              forward: split input onto different devices

              -

              If the input of the parallel_do is independent from any prior opeartors, we can avoid this step by -prefetching the input onto different devices in a seperate background thread. And the python code -looks like this.

              -
              pd = ParallelDo(gpu_places)
              -with pd.do():
              -    feature = get_data_from_prefetch_queue(gpu_places)
              -    prediction = my_net(feature)
              -    write_output(activation)
              -
              -
              -
              -
              -

              forward: Copy parameter to onto different devices

              -

              We can avoid this step by making each device have a copy of the parameter. This requires:

              -
                -
              1. fluid.default_start_up_program() to be run on all devices
              2. -
              3. In the backward, allreduce param@grad at different devices, this requires
                  -
                1. backward.py add allreduce operators at parallel_do_grad
                2. -
                3. allreduce operators need to be called in async mode to achieve maximum throughput
                4. -
                -
              4. -
              5. apply gradients related op(i.e. cliping, normalization, decay, sgd) on different devices in parallel
              6. -
              -

              By doing so, we also avoided “backward: accumulate param@grad from different devices to the first device”. -And the ProgramDesc looks like the following

              -
              # w1, w2 will be allocated on all GPUs
              -start_program
              -{
              -block0 {
              -  parallel_do(block1)
              -}
              -block1 {
              -  parent_block: 0
              -  vars: w1, w2
              -  ops: init(w1), init(w2)
              -}
              -}
              -
              -main_program
              -{
              -block0 {
              -  vars: data, places, w1, w2
              -  ops: data, get_place, parallel_do(block1),
              -       parallel_do_grad(block2),      # append_backward
              -       parallel_do(block3)            # append_optimization
              -       
              -}
              -block1 {
              -  parent_block: 0
              -  vars: data, h1, h2, loss
              -  ops: fc, fc, softmax
              -}
              -block2 {
              -  parent_block: 1
              -  vars: data_grad, h1_grad, h2_grad, loss_gard, w1_grad, w2_grad
              -  ops: softmax_grad,
              -       fc_grad, allreduce(places, scopes, w1_grad),
              -       fc_grad, allreduce(places, scopes, w2_grad)
              -}
              -block3 {
              -  parent_block: 0
              -  vars: lr
              -  ops: sgd(w2, w2_grad),
              -       sgd(w1, w1_grad)
              -}
              -}
              -
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/parameter_average.html b/develop/doc/design/parameter_average.html deleted file mode 100644 index 35e5e47ac3b..00000000000 --- a/develop/doc/design/parameter_average.html +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - - - - - - - - Averaging Parameter in PaddlePaddle — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Averaging Parameter in PaddlePaddle

              -
              -

              Why Averaging

              -

              In a large scale machine learning setup where the size of the training data is huge, it could take us a large number of iterations over the training data before we can achieve the optimal values of parameters of our model. Looking at the problem setup, it is desirable if we can obtain the optimal values of parameters by going through the data in as few passes as we can.

              -

              Polyak and Juditsky (1992) showed that the test performance of simple average of parameters obtained by Stochastic Gradient Descent (SGD) is as good as that of parameter values that are obtained by training the model over and over again, over the training dataset.

              -

              Hence, to accelerate the speed of Stochastic Gradient Descent, Averaged Stochastic Gradient Descent (ASGD) was proposed in Polyak and Juditsky (1992). For ASGD, the running average of parameters obtained by SGD, is used as the estimator for
              . The averaging is done as follows:

              -


              -

              We propose averaging for any optimizer similar to how ASGD performs it, as mentioned above.

              -
              -

              How to perform Parameter Averaging in PaddlePaddle

              -

              Parameter Averaging in PaddlePaddle works in the following way during training :

              -
                -
              1. It will take in an instance of a normal optimizer as an input, e.g. RMSPropOptimizer
              2. -
              3. The optimizer itself is responsible for updating the parameters.
              4. -
              5. The ParameterAverageOptimizer maintains a separate copy of the parameters for itself:
                  -
                1. In concept, the values of this copy are the average of the values of the parameters in the most recent N batches.
                2. -
                3. However, saving all the N instances of the parameters in memory is not feasible.
                4. -
                5. Therefore, an approximation algorithm is used.
                6. -
                -
              6. -
              -

              Hence, overall we have have two copies of the parameters: one for the optimizer itself, and one for the ParameterAverageOptimizer. The former should be used in back propagation, while the latter should be used during testing and should be saved.

              -

              During the testing/ saving the model phase, we perform the following steps:

              -
                -
              1. Perform the delayed operations.
              2. -
              3. Save current values of the parameters to a temporary variable.
              4. -
              5. Replace the values of the parameters with the averaged values.
              6. -
              7. Perform testing and/or save the parameters.
              8. -
              9. Restore the values of the parameters once done.
              10. -
              -
              -
              -

              How to implement Averaging of Parameter in PaddlePaddle

              -

              We can add the ParameterAverageOptimizer op to the graph through Python API. Using this approach, we manually add this op to the graph and direct the output of the optimizer op to this op during training.

              -
              **Advantages**:
              -- Allows for greater flexibility to the users of PaddlePaddle. Using this approach, the users can plug different optimizers into ParameterAverageOptimizer by passing in the optimizer to the op.
              -- Makes it easy for the users to customize and extend the framework.
              -
              -**Disadvantages**:
              -- Implementation requires re-writing the averaging methodology in Python.  
              -
              -
              -
              -
              -

              Low-Level implementation

              -

              In the new design, we propose to create a new operation for averaging parameter updates (ParameterAverageOptimizer). For now, we can add an op that takes in the following as input:

              -
                -
              • the optimizer
              • -
              • the window_size to keep the updates
              • -
              -

              The ParameterAverageOptimizer op can be like any other operator with its own CPU/GPU implementation either using Eigen or separate CPU and GPU kernels. As the initial implementation, we can implement the kernel using Eigen following the abstraction pattern implemented for Operators. We also want to support the case when the Trainer/Optimizer runs on the GPU while ParameterAverageOptimizer runs on a CPU.

              -

              The idea of building an op for averaging is in sync with the refactored PaddlePaddle philosophy of using operators to represent any computation unit. The way the op will be added to the computation graph will be decided by the layer functions in Python API.

              -
              -
              -

              Python API implementation for ParameterAverageOptimizer

              -

              Based on Polyak and Juditsky (1992), we can generalize the averaging of updates to any optimizer. The input to the op would be the following:

              -
                -
              • Any optimizer (RMSProp , AdaGrad etc.)
              • -
              • A window size. The op keeps accumulating updated parameter values over a window of N batches and takes an average. Move the averaged value to a buffer when window is full to avoid loss of precision.
              • -
              -

              Using the ParameterAverageOptimizer op, any user can add the operation to their computation graphs. However, this will require a lot of lines of code and we should design Python APIs that support averaging. As per the PaddlePaddle Python API design, the layer functions are responsible for creating operators, operator parameters and variables. Since ParameterAverageOptimizer will be an operator, it makes sense to create it in the layer functions. -We will have a wrapper written in Python that will support the functionality and implement the actual core computation in C++ core as we have done for other Optimizers

              -
              -

              Creation of the ParameterAverageOptimizer operator

              -

              There are two ways for creating the ParameterAverageOptimizer op:

              -
                -
              1. We create the op immediately while building the computation graph.
              2. -
              3. We add the op in a lazy manner, just before the backward pass, similar to the way the optimization ops are added.
              4. -
              -

              The proposal is to add the op immediately while building the computation graph.

              -
              -
              -

              High-level API

              -

              In PaddlePaddle Python API, users will primarily rely on layer functions to create neural network layers. Hence, we also need to provide parameter average functionality in layer functions.

              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/parameters_in_cpp.html b/develop/doc/design/parameters_in_cpp.html deleted file mode 100644 index ca1f3e481c8..00000000000 --- a/develop/doc/design/parameters_in_cpp.html +++ /dev/null @@ -1,290 +0,0 @@ - - - - - - - - - - - - - Design Doc: The C++ Class Parameters — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: The C++ Class Parameters

              -

              Parameters is a concept we designed in PaddlePaddle V2 API. Parameters is a container of parameters, which makes PaddlePaddle capable of sharing parameter between topologies. We described usages of Parameter in api.md.

              -

              We used Python to implement Parameters when designing V2 API before. There are several defects for the current implementation:

              -
                -
              • We just use memcpy to share Parameters between topologies, but this is very inefficient.
              • -
              • We did not support sharing Parameters while training. We just trigger memcpy when start training.
              • -
              -

              It is necessary that we implement Parameters in CPP side. However, it could result a code refactoring for PaddlePaddle, because PaddlePaddle was designed for training only one topology before, i.e., each GradientMachine contains its Parameter as a data member. In current PaddlePaddle implementation, there are three concepts associated with Parameters:

              -
                -
              1. paddle::Parameter. A Parameters is a container for paddle::Parameter. -It is evident that we should use paddle::Parameter when developing Parameters. -However, the Parameter class contains many functions and does not have a clear interface. -It contains create/store Parameter, serialize/deserialize, optimize(i.e SGD), randomize/zero. -When we developing Parameters, we only use create/store Parameter functionality. -We should extract functionalities of Parameter into many classes to clean PaddlePaddle CPP implementation.
              2. -
              3. paddle::GradientMachine and its sub-classes, e.g., paddle::MultiGradientMachine, paddle::NeuralNetwork. -We should pass Parameters to paddle::GradientMachine when forward/backward to avoid memcpy between topologies. -Also, we should handle multi-GPU/CPU training, because forward and backward would perform on multi-GPUs and multi-CPUs. -Parameters should dispatch the parameter value to each device, and gather the parameter gradient from each device.
              4. -
              5. paddle::ParameterUpdater. The ParameterUpdater is used to update parameters in Paddle. -So Parameters should be used by paddle::ParameterUpdater, and paddle::ParameterUpdater should optimize Parameters (by SGD).
              6. -
              -

              The step by step approach for implementation Parameters in PaddlePaddle C++ core is listed below. Each step should be a PR and could be merged into PaddlePaddle one by one.

              -
                -
              1. Clean paddle::Parameter interface. Extract the functionalities of paddle::Parameter to prepare for the implementation of Parameters.
              2. -
              3. Implementation a Parameters class. It just stores the paddle::Parameter inside. Make GradientMachine uses Parameters as a class member.
              4. -
              5. Make Parameters support Multi-CPU and Multi-GPU training to prepare for sharing Parameter between topologies. -Because we need share Parameters between topologies, it is Parameters‘s response to exchange Parameters between GPUs. -GradientMachine should not handle how to exchange Parameters because GradientMachine only used to train one topology and we need to support train many topologies in Paddle, i.e., there could be many GradientMachines use one Parameters.
                  -
                • We should use a global function to exchange Parameters between GPUs, not a member function in Parameters. The MultiGradientMachine invoke this function, which uses Parameters as this function inputs.
                • -
                • The MultiGradientMachine contains many functionalities. Extracting the Parameters exchanging logic could make MultiGradientMachine clearer and simpler.
                • -
                -
              6. -
              7. Make Parameters as an argument for forward/backward function, not a data member for GradientMachine. For example, forward could be forward(const Parameters& params, ...) and backward could be backward(Parameters* params, ...). After this step, Paddle could share Parameters between topologies.
              8. -
              9. ParameterUpdater is invoked by GradientMachine and Trainer, but it updates Parameters. In the end of this code refactoring, we could change ParameterUpdater directly uses Parameters to make ParameterUpdater‘s implementation clear.
              10. -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/profiler.html b/develop/doc/design/profiler.html deleted file mode 100644 index 2c75b03fc2e..00000000000 --- a/develop/doc/design/profiler.html +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - - - - - - - Introduction — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Introduction

              -

              There are many performance analysis tools for different programming languages and different software frameworks. For most popular deep learning frameworks, they use several programming languages and adapt to heterogeneous platforms. Similar to most of the deep learning frameworks, PaddlePaddle also uses C++, CUDA and Python as the basic programming languages to adapt to run on CPU and GPU devices. The nvprof tools is usually used to analyse the CUDA program. We have a document to profile CPU and Python program by yep and Google’s perftools to profile only the CPU and Python program. But for PaddlePaddle fluid, the operator is the basic computing unit. The developers usually want to collect the time of each operator and locate bottlenecks. The nvprof usually collect the timeline of CUDA-related activities on both CPU and GPU, including kernel execution, memory transfers, memory set and CUDA API calls and events or metrics for CUDA kernels. And the yep and Google's perftools can’t collect the timeline for CUDA program. All these tools can’t collect time in the operator level. So we design this profiling tool.

              -
              -
              -

              Architecture

              -

              The work flow for most task is as follows. Each operator will run many times in the all iterations. So the profiler must collect the total time of each operator during the iteration. For more, sometimes, the developers may want to collect more detailed time span inside the operator or record time span for elsewhere, this requires that the profiler must support to record the nested time span. And in order to speedup training, all the deep learning frameworks support parallel computing, including multiple threads on CPU and multiple GPUs. So the profiler must be able to collect the timeline for each thread. In addition, the profiler also occupies certain resources. It must can be easily to be enabled or disabled by the developers. At last, the profiler should present a human-readable report.

              -
              for i in xrange(M):  # M is  the iteration number
              -  for op in operator_lists: # The `operator_lists` contains all the operators in the network.
              -    op.run();
              -
              -
              -

              In summary, the proflier should have following features:

              -
                -
              • records time span in loop.
              • -
              • supports nested time span.
              • -
              • supports multiple threads/multiple GPUs.
              • -
              • supports to be enabled and disabled by users.
              • -
              -

              But how to record the time for the mixed C++ and CUDA program? There many C++ APIs to get the current calendar time in host program. But for GPU, the CUDA kernels may be executed concurrently if they are in different streams and the CUDA kernels is asynchronous with the host program if there is no the synchronous aftern the CUDA kernels. CUDA provides event to monitor the device and perform accurate timing. Inspired by PyTorch and CUDA event, we also design and apply the events to record the timeline. Then summarize and present statistics based on these events.

              -

              The overall flow is shown as the following figure.

              -


              -
              -

              Event

              -

              In above work flow, a pair of events are needed before and after the piece of code to collect time. So the event has a flag to mark whether it is a starting event or an ending event. Except this two kinds of event, sometime, a only marker with a text message is needed, for example, a marker to specify the profiling start or end. There are three kinds of event:

              -
              enum EventKind {
              -  kMark,
              -  kPushRange,
              -  kPopRange};
              -
              -
              -
                -
              • kMark: only a marker without time range.
              • -
              • kPushRange: mark the starting event for time range.
              • -
              • kPopRange: mark the ending event for time range.
              • -
              -

              For the CPU code, the events only need to record the current time. For the CUDA code, the event management functions of CUDA are used. For many pieces of code, an event lists are used to record each piece.

              -
              class Event {
              - public:
              -  // The DeviceContext is used to get current  CUDA stream.
              -  Event(EventKind kind, std::string name, uint32_t thread_id,
              -        const platform::DeviceContext* dev_ctx = nullptr);
              -  double CpuElapsedUs(const Event& e) const;
              -  double CudaElapsedUs(const Event& e) const;
              -
              - private:
              -  EventKind kind_;
              -  std::string name_;
              -  uint32_t thread_id_;
              -  int64_t cpu_ns_;
              -#ifdef PADDLE_WITH_CUDA
              -  cudaEvent_t event_ = nullptr;
              -  int device_ = -1;
              -#endif
              -};
              -
              -struct EventList {
              -  std::forward_list<std::vector<Event>> event_blocks;
              -};
              -
              -
              -

              As mentioned above, there is no need to record the timeline when disabling the profiler. So there is a global state to enable or disable the profiler.

              -
              enum ProfilerState {
              -  kDisabled, 
              -  kCPU,
              -  kCUDA
              -};
              -ProfilerState g_state;
              -
              -
              -
                -
              • kDisabled: the disabled state.
              • -
              • kCPU: CPU profiling state.
              • -
              • kCUDA: GPU profiling state.
              • -
              -

              A pair of starting and ending events are pushed to event lists in constructor and destructor of RecordEvent. So the timeline is recorded for the code in the lifecycle of an object of RecordEvent.

              -
              struct RecordEvent {
              -  explicit RecordEvent(const std::string name,
              -                       platform::DeviceContext* dev_ctx = nullptr) {
              -    if (kState == ProfilerState::kDisabled) return;
              -    // push the starting event to the event lists.
              -  }
              -  ~RecordEvent() {
              -    if (kState == ProfilerState::kDisabled) return;
              -    // push the ending event to the event lists.
              -  }
              -};
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/program.html b/develop/doc/design/program.html deleted file mode 100644 index 932ee717b11..00000000000 --- a/develop/doc/design/program.html +++ /dev/null @@ -1,378 +0,0 @@ - - - - - - - - - - - - - Design Doc: PaddlePaddle Programs — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: PaddlePaddle Programs

              -
              -

              Compile and Execution

              -

              A PaddlePaddle program consists of two parts – the first generates a ProgramDesc protobuf message that describes the program, and the second runs this message using a C++ class Executor.

              -

              A simple example PaddlePaddle program can be found in graph.md:

              -
              x = layer.data("images")
              -l = layer.data("label")
              -y = layer.fc(x)
              -cost = layer.mse(y, l)
              -optimize(cost)
              -train(cost, reader=mnist.train())
              -
              -
              -

              The first five lines of the following PaddlePaddle program generates, or, compiles, the ProgramDesc message. The last line runs it.

              -
              -
              -

              Programs and Blocks

              -

              The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.

              -
                -
              • program: some nested blocks
              • -
              • block:
                  -
                • some local variable definitions, and
                • -
                • a sequence of operators
                • -
                -
              • -
              -

              The concept of block comes from usual programs. For example, the following C++ program has three blocks:

              -
              int main() { // block 0
              -  int i = 0;
              -  if (i < 10) { // block 1
              -    for (int j = 0; j < 10; j++) { // block 2
              -    }
              -  }
              -  return 0;
              -}
              -
              -
              -

              The following PaddlePaddle program has three blocks:

              -
              import paddle as pd  // block 0
              -
              -x = minibatch([10, 20, 30]) # shape=[None, 1]
              -y = var(1) # shape=[1], value=1
              -z = minibatch([10, 20, 30]) # shape=[None, 1]
              -cond = larger_than(x, 15) # [false, true, true]
              -
              -ie = pd.ifelse()
              -with ie.true_block():  // block 1
              -    d = pd.layer.add_scalar(x, y)
              -    ie.output(d, pd.layer.softmax(d))
              -with ie.false_block():  // block 2
              -    d = pd.layer.fc(z)
              -    ie.output(d, d+1)
              -o1, o2 = ie(cond)
              -
              -
              -
              -
              -

              BlockDesc and ProgramDesc

              -

              All protobuf messages are defined in framework.proto.

              -

              BlockDesc is straight-forward – it includes local variable definitions, vars, and a sequence of operators, ops.

              -
              message BlockDesc {
              -  required int32 parent = 1;
              -  repeated VarDesc vars = 2;
              -  repeated OpDesc ops = 3;
              -}
              -
              -
              -

              The parent ID indicates the parent block so that operators in a block can refer to variables defined locally and also those defined in their ancestor blocks.

              -

              All hierarchical blocks in a program are flattened and stored in an array. The block ID is the index of the block in this array.

              -
              message ProgramDesc {
              -  repeated BlockDesc blocks = 1;
              -}
              -
              -
              -
              -

              Global Block

              -

              The global block is the first one in the above array.

              -
              -
              -
              -

              Operators that Use Blocks

              -

              In the above example, the operator IfElseOp has two blocks – the true branch and the false branch.

              -

              The definition of OpDesc shows that an operator could have some attributes:

              -
              message OpDesc {
              -  AttrDesc attrs = 1;
              -  ...
              -}
              -
              -
              -

              and an attribute could be of type block, which is, in fact, a block ID as described above:

              -
              message AttrDesc {
              -  required string name = 1;
              -
              -  enum AttrType {
              -    INT = 1,
              -    STRING = 2,
              -    ...
              -    BLOCK = ...
              -  }
              -  required AttrType type = 2;
              -
              -  optional int32 block = 10; // when type == BLOCK
              -  ...
              -}
              -
              -
              -
              -
              -

              InferShape

              -

              With this design, the InferShape function should take the following parameters:

              -
              void InferShape(int current_block,
              -                int current_operator,
              -                ProgramDesc* program // might change VarDesc values.
              -                ) {
              -  ...
              -}
              -
              -
              -

              where

              -
                -
              • current_block indices into ProgramDesc::blocks,
              • -
              • current_operator indices into BlockDesc::ops.
              • -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/prune.html b/develop/doc/design/prune.html deleted file mode 100644 index 01e876d86d8..00000000000 --- a/develop/doc/design/prune.html +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - - - - Prune — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Prune

              -
              -

              Motivation

              -

              We want to support running inference, training and checkpointing in one ProgramDesc. We implement -void Prune(const ProgramDesc* input, ProgramDesc* output) function, which takes a ProgramDesc -and generate a pruned ProgramDesc.

              -
              -
              -

              Challenge

              -

              Pruning need to support both variables and operators being evaluation targets. Consider the following -different situations.

              -
              # Case 1: run foward pass.
              -cost_np = session.run(target=cost)
              -# Case 2: run backward passing.
              -opts_np, _ = session.run(target=[cost, opt])
              -# Case 3: run checkpointing
              -_ = session.run(target=checkpoint)
              -
              -
              -
              -
              -

              Solution

              -

              To support evaluation of operators, we add is_target field in the OpDesc.

              -
              message OpDesc {
              -  required string type = 3;
              -  repeated Var inputs = 1;
              -  repeated Var outputs = 2;
              -  repeated Attr attrs = 4;
              -  optional bool is_target = 5 [ default = false ];
              -};
              -
              -
              -

              To support evaluation of variables, we add fetch_op. -For each variable in the target, we insert a fetch_op into the ProgramDesc with variable being -fetch_op‘s input. Then we also set fetch_op is a target.

              -
              -

              Algorithm

              -

              If an operator needs to be run, it must fall into one of the following cases:

              -
                -
              1. It is the target.
              2. -
              3. It is depended by some other ops, meaning its output is some other op’s input.
              4. -
              -

              The first case can be checked by op_desc.is_traget() . The second case can be implement as

              -
              bool HasDependentVar(const OpDesc& op_desc, const std::set<string>& dependent_vars) {
              -  for (auto& var : op_desc.outputs()) {
              -    for (auto& argu : var.arguments()) {
              -      if (dependent_vars.count(argu) != 0) {
              -        return true;
              -      }
              -    }
              -  }
              -  return false;
              -}
              -
              -
              -

              Then the whole algorithm can be implemented as the following code.

              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/python_api.html b/develop/doc/design/python_api.html deleted file mode 100644 index 5a364d04b9e..00000000000 --- a/develop/doc/design/python_api.html +++ /dev/null @@ -1,526 +0,0 @@ - - - - - - - - - - - - - Design Doc: Python API — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Python API

              -

              Due to the refactorization of the PaddlePaddle core, we need Python classes to construct corresponding protobuf messages that describe a DL program.

              -

              | Python classes | Protobuf messages | -| — | — | -| Program | ProgramDesc | -| Block | BlockDesc | -| Operator | OpDesc | -| Variable | VarDesc |

              -

              Please be aware that these Python classes need to maintain some construction-time information, which are not part of the protobuf messages.

              -
              -

              Core Concepts

              -
              -

              Program

              -

              A ProgramDesc describes a DL program, which is composed of an array of BlockDescs. The BlockDescs in a ProgramDesc can have a tree-like hierarchical structure. However, the ProgramDesc onlys stores a flattened array of BlockDescs. A BlockDesc refers to its parent block by its index in the array. For example, operators in the step block of an RNN operator need to be able to access variables in its ancestor blocks.

              -

              Whenever we create a block, we need to set its parent block to the current block, hence the Python class Program needs to maintain a data member current_block.

              -
              class Program(objects):
              -    def __init__(self):
              -        self.desc = core.NewProgram() # a C++ ProgramDesc pointer.
              -        self.blocks = vector<Block>()
              -        self.blocks.append(Block(self, -1)) # the global block
              -        self.current_block = 0          # initialized to the global block
              -
              -    def global_block():
              -        return self.blocks[0]
              -
              -    def current_block():
              -        return self.get_block(self.current_block)
              -
              -    def rollback():
              -        self.current_block = self.current_block().parent_idx
              -
              -    def create_block():
              -        new_block_idx = len(self.block)
              -        self.blocks.append(Block(self, self.current_block))
              -        self.current_block = new_block_idx
              -        return current_block()
              -
              -
              -

              Program is an accessor to the protobuf message ProgramDesc, which is created in C++ space, because the InferShape function is in C++, which manipulates VarDesc messages, which are in turn members of BlockDesc, which is a member of ProgramDesc.

              -

              Program creates the first block as the global block in its constructor. All parameters and their initializer operators are in the global block.

              -
              -
              -

              Block

              -

              A Block includes

              -
                -
              1. a map from variable names to an instance of the Python Variable class, and
              2. -
              3. a list of Operator instances.
              4. -
              -
              class Block(objects):
              -    def __init__(self, program, parent_idx):
              -        self.desc = core.NewBlock(program.desc)
              -        self.program = program
              -        self.vars = map<string, Variable>()
              -        self.ops = vector<Operator>()
              -        self.parent_idx = parent_idx
              -
              -    def create_var(self, ...):
              -        return Variable(self, ...)
              -
              -    def _create_global_var(self, ...):
              -        program.global_block().create_var(...)
              -
              -    def create_parameter(self, name, ...):
              -        # Parameter is a subclass of variable. See Parameter section for details.
              -        self.vars[name] = Parameter(self._create_global_var(...), ...)
              -        return self.vars[name]
              -
              -    def append_operator(self, ...):
              -        self.ops.append(Operator(self, ...))
              -
              -    def prepend_operator(self, ...): # Parameter's ctor prepands initialize operators.
              -       self.ops.prepend(Operator(self, ...))
              -
              -
              -

              create_parameter is necessary because parameters are global variables, defined in the global block, but can be created in some sub-blocks. For example, an FC layer in the step block of an RNN operator.

              -

              prepend_operator is necessary because the constructor of Parameter needs to create the initialize (or load) operator of the parameter, and would like to put it in the preamble of the global block.

              -
              -
              -

              Operator

              -

              The Operator class fills in the OpDesc message and calls the C++ function InferShape to infer the output shapes from the input shapes.

              -
              class Operator(object):
              -    def __init__(self,
              -                 block,  # Block
              -                 type,   # string
              -                 inputs, # dict<string, Variable>
              -                 outputs,# dict<stirng, Variable>
              -                 attrs   # dict<string, Any>
              -                 ):
              -        self.desc = core.NewOpDesc(block.desc, type, inputs, outputs, attrs)
              -        core.infer_shape(self.desc, inputs, outputs)
              -
              -    def type(self):
              -        return self.desc.type()
              -
              -
              -

              Operator creates the OpDesc message in C++ space, so that it can call the InferShape function, which is in C++.

              -
              -
              -

              Variable

              -

              Operators take Variables as its inputs and outputs.

              -
              class Variable(object):
              -    def __init__(self,
              -                 block=None,      # Block
              -                 name=None,       # string
              -                 shape,           # tuple
              -                 dtype="float32", # string
              -                 lod_level=None   # int
              -                 ):
              -        if name is None:
              -            name = unique_name_generator()
              -        self.name = name
              -        self.block = block
              -        self.desc = core.NewVarDesc(block.desc, name, shape, lod_level)
              -        self.writer = None
              -
              -
              -

              Please be aware of self.writer, that tracks operator who creates the variable. It possible that there are more than one operators who write a variable, but in Python space, each write to a variable is represented by a Variable class. This is guaranteed by the fact that core.NewVarDesc must NOT create a new VarDesc message if its name already exists in the specified block.

              -
              -
              -

              Parameter

              -

              A parameter is a global variable with an initializer (or load) operator.

              -
              class Parameter(Variable):
              -    def __init__(self,
              -                 block=None,      # Block
              -                 name=None,       # string
              -                 shape,           # tuple
              -                 dtype="float32", # string
              -                 lod_level=None   # int
              -                 trainable,       # bool
              -                 initialize_op_attrs,
              -                 optimize_op_attrs):
              -        super(Parameter, self).__init__(block, name, shape, dtype, lod_level)
              -        self.trainable = trainable
              -        self.optimize_op_attrs = optimize_op_attrs
              -        block.prepend(Operator(block,  # Block
              -                               initialize_op_attrs['type'],   # string
              -                               None,   # no inputs
              -                               self,   # output is the parameter
              -                               initialize_op_attrs)
              -
              -
              -

              When users create a parameter, they can call

              -
              program.create_parameter(
              -  ...,
              -  init_attr={
              -    type: "uniform_random",
              -    min: -1.0,
              -    max: 1.0,
              -  })
              -)
              -
              -
              -

              In above example, init_attr.type names an initialize operator. It can also name the load operator

              -
              init_attr={
              - type: "load",
              - filename: "something.numpy",
              -}
              -
              -
              -

              optimize_op_attrs is not in the VarDesc message, but kept in the Python instance, as it will be used in the Python space when creating the optimize operator’s OpDesc, and will be in the OpDesc message.

              -
              -
              -
              -

              Layer Function

              -

              A layer is a Python function that creates some operators and variables. Layers simplify the work of application programmers.

              -

              Layer functions take Variable and configuration parameters as its input and return the output variable(s).

              -

              For example, FullyConnected take one or more variable as its input. The input could be input data or another layer’s output. There are many configuration options for a FullyConnected layer, such as layer size, activation, parameter names, initialization strategies of parameters, and so on. The FullyConnected layer will return an output variable.

              -
              -

              Necessity for reusing code between layer functions

              -

              There are a lot of code that can be reused. Such as

              -
                -
              • Give the default value of configuration. e.g., default initialize strategy for parameters is uniform random with min = -1.0, max = 1.0. and default initialize strategy for bias is to fill zero.
              • -
              • Append the activation operator.
              • -
              • Create a temporary variable.
              • -
              • Create parameter.
              • -
              • Generate a unique name.
              • -
              • Add a bias.
              • -
              • ...
              • -
              -

              A mechanism to reuse code between layer functions is necessary. It will be around 150 lines of code if we write a FullyConnected layer without any helper functions.

              -
              -
              -

              Comparision between global functions and helper class

              -

              The FullyConnected layer will be as follow when we provide global functions:

              -
              def fc_layer(input, size, param_attr=None, bias_attr=None, act=None, name=None):
              -  if name is None:
              -    name = unique_name("fc")
              -  input = multiple_input(input)
              -  param_attr = default_param_attr(param_attr)
              -  param_attr = multiple_param_attr(param_attr, len(input))
              -
              -  # mul
              -  mul_results = []
              -  for ipt, attr in zip(input, param_attr):
              -    shape = ipt.shape[1:] + [size]
              -    w = g_program.global_block().create_parameter(shape, ipt.dtype, name, attr)
              -    tmp = create_tmp_var(name)
              -    g_program.current_block().append_op("mul", {ipt, w}, {tmp})
              -  mul_results.append(tmp)
              -
              -  # add sum
              -  ...
              -  # add bias
              -  ...
              -  # add activation
              -  ...
              -  return out
              -
              -
              -

              We can provide many helpers functions for layer developers. However, there are several disadvantages for global helper functions:

              -
                -
              1. We need a namespace for these methods, then layer developers can quickly figure out what method they can use.
              2. -
              3. Global functions will force layer developers to pass its parameter time by time.
              4. -
              -

              So we provide a helper class, LayerHelper, to share code between layer functions. The FullyConnected Layer will be as follow.

              -
              def fc_layer(input, size, param_attr=None, bias_attr=None, act=None, name=None):
              -  helper = LayerHelper(locals())  # pass all parameter to LayerHelper
              -
              -  mul_results = []
              -  for ipt, param in helper.iter_multiple_input_and_param():
              -    w = helper.create_parameter(shape=ipt.shape[1:] + [size], dtype = ipt.dtype)
              -    tmp = helper.create_tmp_variable()
              -    helper.append_op('mul', {ipt, w}, {tmp})
              -    mul_results.append(tmp)
              -
              -  pre_bias = helper.add_sum(mul_results)
              -  pre_activation = helper.add_bias(pre_bias)
              -  return helper.add_activation(pre_activation)
              -
              -
              -

              We not only use the fewer lines of code to write fc_layer but also make the code clearer to understand. At the same time, layer developers can figure out what function they can invoke by typing helper. in a python editor.

              -
              -
              -

              Implementation of layer helper

              -

              We just keep all parameters of a layer function as a dictionary in layer helper as a private data member. Every method of layer helper will look up the dictionary after it is invoked. In that way, we can implement a layer helper for all layer functions even some layer does not contain some operator. For example, The activation is used by the FullyConnected layer or convolution layers, but a cross-entropy layer does not use it. The example code of add_activation are:

              -
              class LayerHelper(object):
              -  def __init__(self, **kwargs):  # kwargs is short for `keyword arguments`
              -    self.kwargs = kwargs
              -
              -  def add_activation(self, input_var):
              -    act = self.kwargs.get("act", None)  # default value is None
              -    if act is None:  # do nothing if no act
              -      return input_var
              -
              -    tmp = self.create_tmp_var(self)
              -    self.append_op(type=act, input=input_var, output=tmp)
              -    return tmp
              -
              -
              -
              -
              -

              Return value of layer functions

              -

              The layer will return a Variable, which is also the output of an operator. However, outputs of a layer function have more attributes than an operator. There are parameter variables, and their gradient variables need to return. To return them is useful. For example,

              -
                -
              1. Users can debug the network by printing parameter gradients.
              2. -
              3. Users can append attributes to a parameter, such as, param.stop_gradient=True will make a parameter stop generate the gradient. We can fix the parameter value during training by using this attribute.
              4. -
              -

              However, it is good to return a Variable for layers, since all layers and operators use Variables as their parameters. We can just append a param field and a grad field for layer function since the Python is dynamic typing.

              -

              The sample usage is

              -
              data = fluid.layers.data(...)
              -hidden = fluid.layers.fc(data, ...)
              -...
              -
              -executor.run(fetch_list=[hidden.param, hidden.param.grad], ...)
              -
              -
              -
              -
              -
              -

              Optimizer

              -

              Optimizer Design Doc

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/reader/README.html b/develop/doc/design/reader/README.html deleted file mode 100644 index d97481c00d8..00000000000 --- a/develop/doc/design/reader/README.html +++ /dev/null @@ -1,438 +0,0 @@ - - - - - - - - - - - - - Python Data Reader Design Doc — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Python Data Reader Design Doc

              -

              During the training and testing phases, PaddlePaddle programs need to read data. To help the users write code that performs reading input data, we define the following:

              -
                -
              • A reader: A function that reads data (from file, network, random number generator, etc) and yields the data items.
              • -
              • A reader creator: A function that returns a reader function.
              • -
              • A reader decorator: A function, which takes in one or more readers, and returns a reader.
              • -
              • A batch reader: A function that reads data (from reader, file, network, random number generator, etc) and yields a batch of data items.
              • -
              -

              and also provide a function which can convert a reader to a batch reader, frequently used reader creators and reader decorators.

              -
              -

              Data Reader Interface

              -

              Data reader doesn’t have to be a function that reads and yields data items. It can just be any function without any parameters that creates an iterable (anything can be used in for x in iterable) as follows:

              -
              iterable = data_reader()
              -
              -
              -

              The item produced from the iterable should be a single entry of data and not a mini batch. The entry of data could be a single item or a tuple of items. Item should be of one of the supported types (e.g., numpy 1d array of float32, int, list of int etc.)

              -

              An example implementation for single item data reader creator is as follows:

              -
              def reader_creator_random_image(width, height):
              -    def reader():
              -        while True:
              -            yield numpy.random.uniform(-1, 1, size=width*height)
              -    return reader
              -
              -
              -

              An example implementation for multiple item data reader creator is as follows:

              -
              def reader_creator_random_image_and_label(width, height, label):
              -    def reader():
              -        while True:
              -            yield numpy.random.uniform(-1, 1, size=width*height), label
              -    return reader
              -
              -
              -
              -
              -

              Batch Reader Interface

              -

              Batch reader can be any function without any parameters that creates an iterable (anything can be used in for x in iterable). The output of the iterable should be a batch (list) of data items. Each item inside the list should be a tuple.

              -

              Here are some valid outputs:

              -
              # a mini batch of three data items. Each data item consist three columns of data, each of which is 1.
              -[(1, 1, 1),
              -(2, 2, 2),
              -(3, 3, 3)]
              -
              -# a mini batch of three data items, each data item is a list (single column).
              -[([1,1,1],),
              -([2,2,2],),
              -([3,3,3],)]
              -
              -
              -

              Please note that each item inside the list must be a tuple, below is an invalid output:

              -
               # wrong, [1,1,1] needs to be inside a tuple: ([1,1,1],).
              - # Otherwise it is ambiguous whether [1,1,1] means a single column of data [1, 1, 1],
              - # or three columns of data, each of which is 1.
              -[[1,1,1],
              -[2,2,2],
              -[3,3,3]]
              -
              -
              -

              It is easy to convert from a reader to a batch reader:

              -
              mnist_train = paddle.dataset.mnist.train()
              -mnist_train_batch_reader = paddle.batch(mnist_train, 128)
              -
              -
              -

              It is also straight forward to create a custom batch reader:

              -
              def custom_batch_reader():
              -    while True:
              -        batch = []
              -        for i in xrange(128):
              -            batch.append((numpy.random.uniform(-1, 1, 28*28),)) # note that it's a tuple being appended.
              -        yield batch
              -
              -mnist_random_image_batch_reader = custom_batch_reader
              -
              -
              -
              -
              -

              Usage

              -

              Following is how we can use the reader with PaddlePaddle: -The batch reader, a mapping from item(s) to data layer, the batch size and the number of total passes will be passed into paddle.train as follows:

              -
              # two data layer is created:
              -image_layer = paddle.layer.data("image", ...)
              -label_layer = paddle.layer.data("label", ...)
              -
              -# ...
              -batch_reader = paddle.batch(paddle.dataset.mnist.train(), 128)
              -paddle.train(batch_reader, {"image":0, "label":1}, 128, 10, ...)
              -
              -
              -
              -
              -

              Data Reader Decorator

              -

              The Data reader decorator takes in a single reader or multiple data readers and returns a new data reader. It is similar to a python decorator, but it does not use @ in the syntax.

              -

              Since we have a strict interface for data readers (no parameters and return a single data item), a data reader can be used in a flexible way using data reader decorators. Following are a few examples:

              -
              -

              Prefetch Data

              -

              Since reading data may take some time and training can not proceed without data, it is generally a good idea to prefetch the data.

              -

              Use paddle.reader.buffered to prefetch data:

              -
              buffered_reader = paddle.reader.buffered(paddle.dataset.mnist.train(), 100)
              -
              -
              -

              buffered_reader will try to buffer (prefetch) 100 data entries.

              -
              -
              -

              Compose Multiple Data Readers

              -

              For example, if we want to use a source of real images (say reusing mnist dataset), and a source of random images as input for Generative Adversarial Networks.

              -

              We can do the following :

              -
              def reader_creator_random_image(width, height):
              -    def reader():
              -        while True:
              -            yield numpy.random.uniform(-1, 1, size=width*height)
              -    return reader
              -
              -def reader_creator_bool(t):
              -    def reader:
              -        while True:
              -            yield t
              -    return reader
              -
              -true_reader = reader_creator_bool(True)
              -false_reader = reader_creator_bool(False)
              -
              -reader = paddle.reader.compose(paddle.dataset.mnist.train(), data_reader_creator_random_image(20, 20), true_reader, false_reader)
              -# Skipped 1 because paddle.dataset.mnist.train() produces two items per data entry.
              -# And we don't care about the second item at this time.
              -paddle.train(paddle.batch(reader, 128), {"true_image":0, "fake_image": 2, "true_label": 3, "false_label": 4}, ...)
              -
              -
              -
              -
              -

              Shuffle

              -

              Given the shuffle buffer size n, paddle.reader.shuffle returns a data reader that buffers n data entries and shuffles them before a data entry is read.

              -

              Example:

              -
              reader = paddle.reader.shuffle(paddle.dataset.mnist.train(), 512)
              -
              -
              -
              -
              -
              -

              Q & A

              -
              -

              Why does a reader return only a single entry, and not a mini batch?

              -

              Returning a single entry makes reusing existing data readers much easier (for example, if an existing reader returns 3 entries instead if a single entry, the training code will be more complicated because it need to handle cases like a batch size 2).

              -

              We provide a function: paddle.batch to turn (a single entry) reader into a batch reader.

              -
              -
              -

              Why do we need a batch reader, isn’t is sufficient to give the reader and batch_size as arguments during training ?

              -

              In most of the cases, it would be sufficient to give the reader and batch_size as arguments to the train method. However sometimes the user wants to customize the order of data entries inside a mini batch, or even change the batch size dynamically. For these cases using a batch reader is very efficient and helpful.

              -
              -
              -

              Why use a dictionary instead of a list to provide mapping?

              -

              Using a dictionary ({"image":0, "label":1}) instead of a list (["image", "label"]) gives the advantage that the user can easily reuse the items (e.g., using {"image_a":0, "image_b":0, "label":1}) or even skip an item (e.g., using {"image_a":0, "label":2}).

              -
              -
              -

              How to create a custom data reader creator ?

              -
              def image_reader_creator(image_path, label_path, n):
              -    def reader():
              -        f = open(image_path)
              -        l = open(label_path)
              -        images = numpy.fromfile(
              -            f, 'ubyte', count=n * 28 * 28).reshape((n, 28 * 28)).astype('float32')
              -        images = images / 255.0 * 2.0 - 1.0
              -        labels = numpy.fromfile(l, 'ubyte', count=n).astype("int")
              -        for i in xrange(n):
              -            yield images[i, :], labels[i] # a single entry of data is created each time
              -        f.close()
              -        l.close()
              -    return reader
              -
              -# images_reader_creator creates a reader
              -reader = image_reader_creator("/path/to/image_file", "/path/to/label_file", 1024)
              -paddle.train(paddle.batch(reader, 128), {"image":0, "label":1}, ...)
              -
              -
              -
              -
              -

              How is paddle.train implemented

              -

              An example implementation of paddle.train is:

              -
              def train(batch_reader, mapping, batch_size, total_pass):
              -    for pass_idx in range(total_pass):
              -        for mini_batch in batch_reader(): # this loop will never end in online learning.
              -            do_forward_backward(mini_batch, mapping)
              -
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/refactorization.html b/develop/doc/design/refactorization.html deleted file mode 100644 index e2d59e486e1..00000000000 --- a/develop/doc/design/refactorization.html +++ /dev/null @@ -1,583 +0,0 @@ - - - - - - - - - - - - - Design Doc: Refactorization Overview — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Refactorization Overview

              -

              The goals of refactoring include:

              -
                -
              1. Making it easy for external contributors to write new elementary computation operations.
              2. -
              3. Making the codebase clean and readable.
              4. -
              5. Designing a new computation representation – a computation graph of operators and variables.
              6. -
              7. Implementing auto-scalability and auto fault recoverable distributed computing with the help of computation graphs.
              8. -
              -
              -

              Computation Graphs

              -
                -
              1. PaddlePaddle represents the computation, training and inference of Deep Learning models, by computation graphs.
              2. -
              3. Please refer to computation graphs for a concrete example.
              4. -
              5. Users write Python programs to describe the graphs and run them (locally or remotely).
              6. -
              7. A graph is composed of variables and operators.
              8. -
              9. The description of graphs must be serializable/deserializable, so that:
                  -
                1. It can be sent to the cloud for distributed execution, and
                2. -
                3. It can be sent to clients for mobile or enterprise deployment.
                4. -
                -
              10. -
              11. The Python program does two things
                  -
                1. Compilation runs a Python program to generate a protobuf message representation of the graph and send it to
                    -
                  1. the C++ library libpaddle.so for local execution,
                  2. -
                  3. the master process of a distributed training job for training, or
                  4. -
                  5. the server process of a Kubernetes serving job for distributed serving.
                  6. -
                  -
                2. -
                3. Execution executes the graph by constructing instances of class Variable and OperatorBase, according to the protobuf message.
                4. -
                -
              12. -
              -
              -
              -

              Description and Realization of Computation Graph

              -

              At compile time, the Python program generates a protobuf message representation of the graph, or a description of the graph.

              -

              At runtime, the C++ program realizes the graph and runs it.

              -

              | | Representation (protobuf messages) | Realization (C++ class objects) | -|—|—|—| -|Data|VarDesc|Variable| -|Operation|OpDesc|Operator| -|Block|BlockDesc|Block|

              -

              The word graph is interchangeable with block in this document. A graph consists of computation steps and local variables similar to a C++/Java program block, or a pair of parentheses({ and }).

              -
              -
              -

              Compilation and Execution

              -
                -
              1. Run a Python program to describe the graph. In particular, the Python application program does the following:
                  -
                1. Create VarDesc to represent local/intermediate variables,
                2. -
                3. Create operators and set attributes,
                4. -
                5. Validate attribute values,
                6. -
                7. Infer the type and the shape of variables,
                8. -
                9. Plan memory-reuse for variables,
                10. -
                11. Generate the backward graph
                12. -
                13. Add optimization operators to the computation graph.
                14. -
                15. Optionally, split the graph for distributed training.
                16. -
                -
              2. -
              3. The invocation of train or infer methods in the Python program does the following:
                  -
                1. Create a new Scope instance in the scope hierarchy for each run of a block,
                    -
                  1. realize local variables defined in the BlockDesc message in the new scope,
                  2. -
                  3. a scope is similar to the stack frame in programming languages,
                  4. -
                  -
                2. -
                3. Create an instance of class Block, in which,
                    -
                  1. realize operators in the BlockDesc message,
                  2. -
                  -
                4. -
                5. Run the Block by calling
                    -
                  1. Block::Eval(vector<Variable>* targets) for forward and backward computations, or
                  2. -
                  3. Block::Eval(vector<Operator>* targets) for optimization.
                  4. -
                  -
                6. -
                -
              4. -
              -
              -
              -

              Intermediate Representation (IR)

              -
              Compile Time -> IR -> Runtime
              -
              -
              -
              -

              Benefits of IR

              -
                -
              • Optimization

                -
                Compile Time -> IR -> Optimized IR -> Runtime
                -
                -
                -
              • -
              • Automatically send partitioned IR to different nodes.

                -
                  -
                • Automatic Data Parallelism

                  -
                  Compile Time
                  -|-> Single GPU IR
                  -    |-> [trainer-IR-0, trainer-IR-1, pserver-IR]
                  -        |-> Node-0 (runs trainer-IR-0)
                  -        |-> Node-1 (runs trainer-IR-1)
                  -        |-> Node-2 (runs pserver-IR)
                  -
                  -
                  -
                • -
                • Automatic Model Parallelism (planned for future)

                  -
                • -
                -
              • -
              -
              -
              -
              -
              -
              -

              Operator/OpWithKernel/OpKernel

              -

              class_diagram

              -
              -
              -
              -

              Operator

              -

              class_diagram

              -
                -
              • Operator is the fundamental building block of the user interface.
                  -
                • Operator stores input/output variable names and attributes.
                • -
                • The InferShape interface is used to infer the shape of the output variables based on the shapes of the input variables.
                • -
                • Use Run to compute the output variables from the input variables.
                • -
                -
              • -
              -
              -
              -
              -

              OpWithKernel/Kernel

              -

              class_diagram

              -
                -
              • OpWithKernel inherits Operator.
              • -
              • OpWithKernel contains a Kernel map.
                  -
                • OpWithKernel::Run get device’s kernel, and invoke OpKernel::Compute.
                • -
                • OpKernelKey is the map key. Only device place now, but may be data type later.
                • -
                -
              • -
              -
              -
              -
              -

              Why separate Kernel and Operator

              -
                -
              • Separate GPU and CPU code.
                  -
                • Make Paddle capable of running without GPU.
                • -
                -
              • -
              • Make one operator (which is a user interface) and create many implementations.
                  -
                • For example, same multiplication op can have different implementations kernels such as FP16 kernel, FP32 kernel, MKL, eigen kernel.
                • -
                -
              • -
              -
              -
              -
              -

              Libraries for Kernel development

              -
                -
              • Eigen::Tensor contains basic math and element-wise functions.
                  -
                • Note that Eigen::Tensor has broadcast implementation.
                • -
                • Limit the number of tensor.device(dev) = in your code.
                • -
                -
              • -
              • thrust::transform and std::transform.
                  -
                • thrust has the same API as C++ standard library. Using transform, one can quickly implement customized element-wise kernels.
                • -
                • thrust, in addition, supports more complex APIs, like scan, reduce, reduce_by_key.
                • -
                -
              • -
              • Hand-writing GPUKernel and CPU code
                  -
                • Do not write in header (.h) files. CPU Kernel should be in cpp source (.cc) and GPU kernels should be in cuda (.cu) files. (GCC cannot compile GPU code.)
                • -
                -
              • -
              -
              -
              -
              -

              Operator Registration

              -
              -

              Why is registration necessary?

              -

              We need a method to build mappings between Op type names and Op classes.

              -
              -
              -

              How is registration implemented?

              -

              Maintaining a map, whose key is the type name and the value is the corresponding Op constructor.

              -
              -
              -
              -
              -

              The Registry Map

              -
              -

              OpInfoMap

              -

              op_type(string) -> OpInfo

              -

              OpInfo:

              -
                -
              • creator: The Op constructor.
              • -
              • grad_op_type: The type of the gradient Op.
              • -
              • proto: The Op’s Protobuf, including inputs, outputs and required attributes.
              • -
              • checker: Used to check attributes.
              • -
              -
              -
              -
              - -
              -
              -

              Registration Process

              -
                -
              1. Write an Op class and its gradient Op class, if required.
              2. -
              3. Write an Op maker class. In the constructor of this class, describe the inputs, outputs and attributes of the operator.
              4. -
              5. Invoke the macro REGISTER_OP. This macro will
                  -
                1. Call maker class to complete proto and checker
                2. -
                3. Using the completed proto and checker, it will add a new key-value pair to the OpInfoMap
                4. -
                -
              6. -
              -
              -
              -
              -

              Backward Module (1/2)

              -
              -

              Create Backward Operator

              -
                -
              • Mapping from forward Op to backward Op -backward
              • -
              -
              -
              -
              -
              -

              Backward Module (2/2)

              -
              -

              Build Backward Network

              -
                -
              • Input: a graph of forward operators
              • -
              • Output: a graph of backward operators
              • -
              • Corner cases in construction
                  -
                • Shared Variables => insert an Add operator to combine gradients
                • -
                • No Gradient => insert a fill_zero_grad operator
                • -
                • Recursive NetOp => call Backward recursively
                • -
                • RNN Op => recursively call Backward on stepnet
                • -
                • RNN Op => recursively call Backward on stepnet
                • -
                -
              • -
              -
              -
              -
              -
              -

              Scope, Variable, Tensor

              -
                -
              • Tensor is an n-dimension array with type.
                  -
                • Only dims and data pointers are stored in Tensor.
                • -
                • All operations on Tensor are written in Operator or global functions.
                • -
                • Variable length Tensor design LoDTensor
                • -
                -
              • -
              • Variable instances are the inputs and the outputs of an operator, not just Tensor.
                  -
                • step_scopes in RNN is a variable and not a tensor.
                • -
                -
              • -
              • Scope is where variables are stored.
                  -
                • map<string var name, Variable>
                • -
                • Scope has a hierarchical structure. The local scope can get variables from its parent scope.
                • -
                -
              • -
              -
              -
              -
              -

              Block (in design)

              -
              -

              the difference between original RNNOp and Block

              -
                -
              • As an operator is more intuitive than RNNOp,
              • -
              • Offers a new interface Eval(targets) to deduce the minimal block to Run,
              • -
              • Fits the compile-time/ runtime separation design paradigm.
                  -
                • During the compilation, SymbolTable stores VarDescs and OpDescs and serialize to a BlockDesc
                • -
                • When graph executes, a Block with BlockDesc is passed. It then creates Op and Var instances and then invokes Run.
                • -
                -
              • -
              -
              -
              -
              -
              -

              Milestone

              -
                -
              • Take Paddle/books as the main line, the requirement of the models motivates framework refactoring,
              • -
              • Model migration
                  -
                • Framework development gives priority support to model migration, for example,
                    -
                  • the MNIST demo needs a Python interface,
                  • -
                  • the RNN models require the framework to support LoDTensor.
                  • -
                  -
                • -
                • Determine some timelines,
                • -
                • Frequently used Ops need to be migrated first,
                • -
                • Different models can be migrated in parallel.
                • -
                -
              • -
              • Improve the framework at the same time
              • -
              • Accept imperfection, concentrate on solving the specific problem at the right price.
              • -
              -
              -
              -
              -

              Control the migration quality

              -
                -
              • Compare the performance of migrated models with old ones.
              • -
              • Follow the google C++ style guide.
              • -
              • Build the automatic workflow of generating Python/C++ documentations.
                  -
                • The documentation of layers and ops should be written inside the code.
                • -
                • Take the documentation quality into account when submitting pull requests.
                • -
                • Preview the documentations, read and improve them from a user’s perspective.
                • -
                -
              • -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/register_grad_op.html b/develop/doc/design/register_grad_op.html deleted file mode 100644 index ef87753f2f0..00000000000 --- a/develop/doc/design/register_grad_op.html +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - - - - - - - - Design Doc: Gradient Operators Registration — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Gradient Operators Registration

              -
              -

              The Problem Posed

              -

              Currently, for each C++ operator class definition, a gradient operator creator function is registered, which takes as input a C++ operator instance and returns the corresponding gradient operator instance.

              -

              However, we noticed two problems with the current design:

              -
                -
              1. As we decided to separate the compilation and the execution phases, we need to change the creator to take an OpDesc protobuf message in a ProgramDesc and inserts corresponding OpDesc messages into the ProgramDesc message.
              2. -
              3. For some operators, the gradient computation can be written in terms of existing operators. For example, the gradient of minus operator consists of two operators – an identity operator followed by a scale operator. Hence the registration mechanism needs to support mapping from an operator to a set of operators for the gradient computation.
              4. -
              -
              -
              -

              The Current Implementation

              -

              Instances of the C++ class OpInfo are stored an associative map whose key is the operator type. The grad_op_type indicates the associated gradient operator type. An operator can create the gradient operator by invoking OpInfo::creator_ of the gradient operator. The pseudo code is as follows

              -
              struct OpInfo {
              -  std::function<OperatorBase*(...)> creator_;
              -  std::string grad_op_type_;
              -  ...
              -};
              -
              -map<string, OpInfo> OpInfoMap;
              -
              -OperatorBase* CreateGradientOperator(const OperatorBase& op) {
              -  return OpInfoMap.at(op.Type()).creator_(...);
              -}
              -
              -
              -
              -
              -

              Proposed Solution

              -

              The mapping relationship between an operator and its gradient operators is a function. The interface of this function is:

              -
              // (OpDesc) --> vector<OpDesc>
              -std::function<std::vector<OpDescBind>(const OpDescBind&)>;
              -
              -
              -

              The function takes an OpDescBind of the forward operator and returns one or many gradient operator descriptions. OpDescBind is a C++ wrapper for the protobuf message OpDesc for rapid manipulation of OpDesc.

              -

              The GradOpDescMaker will be registered in OpInfo and will replace the grad_op_type_ field. The OpInfo should look like

              -
              struct OpInfo {
              -  std::function<std::vector<std::unique_ptr<OpDescBind>>(const OpDescBind&)>  grad_op_maker_;
              -  ...
              -};
              -
              -
              -

              The grad_op_maker_ is a nullptr if the operator does not have any associated gradient operators.

              -

              We propose a base class called GradOpDescMakerBase to let operator developers generate Gradient Operators easily. The public interface of that class is

              -
              class GradOpDescMakerBase {
              -public:
              -  GradOpDescMakerBase(const OpDescBind& );
              -  virtual std::vector<std::unique_ptr<OpDescBind>> operator()()const = 0;
              -};
              -
              -
              -

              We can convert GradOpDescMakerBase to std::function<std::vector<std::unique_ptr<OpDescBind>>(const OpDescBind&)> by

              -
              using GradOpMaker = ...;
              -std::function<std::vector<OpDescBind>(const OpDescBind&)> func;
              -func = [] (const OpDescBind& fwd_op) {
              -  GradOpMaker maker(fwd_op);
              -  return maker();
              -};
              -
              -
              -

              We can write many helper functions since the GradOpDescMakerBase is a class now. The basic helper functions get the variables of Input, Output, InputGradient and OutputGradient in the forwarding operator.

              -

              We should change register macros at the same time. In the current solution, there is no difference between forwarding operators and backward operators. So REGISTER_OP just register one operator. If the REGISTER_OPERATOR contains OpProtoAndCheckerMaker and GradOpDescMaker, we just list them in the same macro. It can be done by a macro contains __VA_ARGS__.

              -

              The user interface should be

              -
              vector<OpDesc> MinusOpGradMaker(OpDesc) {...}
              -REGISTER_OPERATOR(minus, MinusOp, MinusOpProtoAndCheckerMaker, SumOpGradMaker);
              -// Developers can still manually implement gradient operator.
              -REGISTER_OPERATOR(minus_grad, MinusGradOp);
              -
              -
              -

              The interface of current REGISTER_OP macro could not be changed. In REGISTER_OP, it will invoke REGISTER_OPERATOR two times and generate GradOpDescMaker inside.

              -
              REGISTER_OP(minus, MinusOp, MinusOpProtoAndCheckerMaker, minus_grad, MinusGradOp);
              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/regularization.html b/develop/doc/design/regularization.html deleted file mode 100644 index ad59a4acd7b..00000000000 --- a/develop/doc/design/regularization.html +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - Regularization in PaddlePaddle — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Regularization in PaddlePaddle

              -
              -

              Introduction to Regularization

              -

              A central problem in machine learning is how to design an algorithm that will perform well not just on the training data, but also on new data. A frequently faced problem is the problem of overfitting, where the model does not make reliable predictions on new unseen data. Regularization is the process of introducing additional information in order to prevent overfitting. This is usually done by adding extra penalties to the loss function that restricts the parameter spaces that an optimization algorithm can explore.

              -
              -

              Parameter Norm Penalties

              -

              Most common regularization approaches in deep learning are based on limiting the capacity of the models by adding a parameter norm penalty to the objective function J. This is given as follows:

              -


              -

              The parameter alpha is a hyperparameter that weights the relative contribution of the norm penalty term, omega, relative to the standard objective function J.

              -

              The most commonly used norm penalties are the L2 norm penalty and the L1 norm penalty. These are given as follows:

              -
              -

              L2 Regularization:

              -


              -
              -
              -

              L1 Regularization

              -


              -

              A much more detailed mathematical background of regularization can be found here.

              -
              -
              -
              -
              -

              Regularization Survey

              -

              A detailed survey of regularization in various deep learning frameworks can be found here.

              -
              -
              -

              Proposal for Regularization in PaddlePaddle

              -
              -

              Low-Level implementation

              -

              In the new design, we propose to create new operations for regularization. For now, we can add 2 ops that correspond to the most frequently used regularizations:

              -
                -
              • L2_regularization_op
              • -
              • L1_regularization_op
              • -
              -

              These ops can be like any other ops with their own CPU/GPU implementations either using Eigen or separate CPU and GPU kernels. As the initial implementation, we can implement their kernels using Eigen following the abstraction pattern implemented for Activation Ops. This abstraction pattern can make it very easy to implement new regularization schemes other than L1 and L2 norm penalties.

              -

              The idea of building ops for regularization is in sync with the refactored Paddle philosophy of using operators to represent any computation unit. The way these ops will be added to the computation graph, will be decided by the layer functions in Python API.

              -
              -
              -

              Computation Graph

              -

              Below is an example of a really simple feed forward neural network.

              -


              -

              The Python API will modify this computation graph to add regularization operators. The modified computation graph will look as follows:

              -


              -
              -
              -

              Python API implementation for Regularization

              -

              Using the low level ops, L2_regularization_op and L1_regularization_op, any user can add regularization to their computation graphs. However, this will require a lot of lines of code and we should design Python APIs that support regularization. An example of such an API can be seen in Keras. As per the PaddlePaddle Python API design, the layer functions are responsible for creating operators, operator parameters and variables. Since regularization is a property of parameters, it makes sense to create these in the layer functions.

              -
              -

              Creation of Regularization ops

              -

              There are two possibilities for creating the regularization ops:

              -
                -
              1. We create these ops immediately while building the computation graph.
              2. -
              3. We add these ops in a lazy manner, just before the backward, similar to the way the optimization ops are added.
              4. -
              -

              The proposal is to add these ops in a lazy manner just before the backward pass.

              -
              -
              -

              Storage of Regularization attributes

              -

              Since we want to create the regularization ops in a lazy manner, the regularization attributes (type of regularization and weight of regularization penalty) can be stored as attributes of the Parameter class. This is because regularization is a property of the parameters and storing regularization properties with Parameters also allows for shared parameters.

              -
              -
              -

              High-level API

              -

              In PaddlePaddle Python API, users will primarily rely on layer functions to create neural network layers. Hence, we also need to provide regularization functionality in layer functions. The design of these APIs can be postponed for later right now. A good reference for these APIs can be found in Keras and also by looking at Tensorflow in tf.contrib.layers.

              -
              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/releasing_process.html b/develop/doc/design/releasing_process.html deleted file mode 100644 index 285714af17a..00000000000 --- a/develop/doc/design/releasing_process.html +++ /dev/null @@ -1,363 +0,0 @@ - - - - - - - - - - - - - PaddlePaddle发行规范 — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              PaddlePaddle发行规范

              -

              PaddlePaddle使用git-flow branching model做分支管理,使用Semantic Versioning标准表示PaddlePaddle版本号。

              -

              PaddlePaddle每次发新的版本,遵循以下流程:

              -
                -
              1. develop分支派生出新的分支,分支名为release/版本号。例如,release/0.10.0
              2. -
              3. 将新分支的版本打上tag,tag为版本号rc.Patch号。第一个tag为0.10.0rc1,第二个为0.10.0rc2,依次类推。
              4. -
              5. 对这个版本的提交,做如下几个操作:
              6. -
              -
                -
              • 使用Regression Test List作为检查列表,测试本次release的正确性。

                -
                  -
                • 如果失败,记录下所有失败的例子,在这个release/版本号分支中,修复所有bug后,Patch号加一,到第二步

                  -
                • -
                • 修改python/setup.py.in中的版本信息,并将istaged字段设为True

                  -
                • -
                • 编译这个版本的python wheel包,并发布到pypi。

                  -
                    -
                  • 由于pypi.python.org目前遵循严格的命名规范PEP 513,在使用twine上传之前,需要重命名wheel包中platform相关的后缀,比如将linux_x86_64修改成manylinux1_x86_64

                    -
                  • -
                  • pypi上的package名称为paddlepaddle和paddlepaddle_gpu,如果要上传GPU版本的包,需要修改build/python/setup.py中,name: “paddlepaddle_gpu”并重新打包wheel包:python setup.py bdist_wheel

                    -
                  • -
                  • 上传方法:

                    -
                    cd build/python
                    -pip install twine
                    -twine upload dist/[package to upload]
                    -
                    -
                    -
                  • -
                  • 编译这个版本的Docker发行镜像,发布到dockerhub。如果失败,修复Docker编译镜像问题,Patch号加一,返回第二步

                    -
                  • -
                  -
                • -
                -
              • -
              -
                -
              1. 第三步完成后,将release/版本号分支合入master分支,并删除release/版本号分支。将master分支的合入commit打上tag,tag为版本号。同时再将master分支合入develop分支。最后删除release/版本号分支。
              2. -
              3. 协同完成Release Note的书写
              4. -
              -

              需要注意的是:

              -
                -
              • release/版本号分支一旦建立,一般不允许再从develop分支合入release/版本号。这样保证release/版本号分支功能的封闭,方便测试人员测试PaddlePaddle的行为。
              • -
              • release/版本号分支存在的时候,如果有bugfix的行为,需要将bugfix的分支同时merge到master, developrelease/版本号这三个分支。
              • -
              -
              -

              发布wheel包到pypi

              -

              使用PaddlePaddle CI -完成自动化二进制编译,参考下图,选择需要发布的版本(通常包含一个CPU版本和一个GPU版本),点击”run”右侧的”...”按钮,可以 -弹出下面的选择框,在第二个tab (Changes)里选择需要发布的分支,这里选择0.11.0,然后点击”Run Build”按钮。等待编译完成后 -可以在此页面的”Artifacts”下拉框中找到生成的3个二进制文件,分别对应CAPI,cp27mcp27mu的版本。然后按照上述的方法 -使用twine工具上传即可。

              -

              -
                -
              • 注:CI环境使用 https://github.com/PaddlePaddle/buildtools 这里的DockerImage作为编译环境以支持更多的Linux -发型版,如果需要手动编译,也可以使用这些镜像。这些镜像也可以从 https://hub.docker.com/r/paddlepaddle/paddle_manylinux_devel/tags/ 下载得到。
              • -
              • pypi不支持覆盖上传,所以一个版本号的wheel包发布之后,不可以更改。下一个wheel包需要更新版本号才可以上传。
              • -
              -
              -
              -

              发布Docker镜像

              -

              上述PaddlePaddle CI编译wheel完成后会自动将Docker镜像push到DockerHub,所以,发布Docker镜像只需要对自动push的镜像打上 -版本号对应的tag即可:

              -
                -
              1. 进入 https://hub.docker.com/r/paddlepaddle/paddle/tags/ 查看latest tag的更新时间是否在上述编译wheel包完成后是否最新。
              2. -
              3. 执行 docker pull paddlepaddle/paddle:[latest tag],latest tag可以是latest或latest-gpu等。
              4. -
              5. 执行 docker tag paddlepaddle/paddle:[latest tag] paddlepaddle/paddle:[version]
              6. -
              7. 执行 docker push paddlepaddle/paddle:[version]
              8. -
              -
              -
              -

              PaddlePaddle 分支规范

              -

              PaddlePaddle开发过程使用git-flow分支规范,并适应github的特性做了一些区别。

              -
                -
              • PaddlePaddle的主版本库遵循git-flow分支规范。其中:
                  -
                • master分支为稳定(stable branch)版本分支。每一个master分支的版本都是经过单元测试和回归测试的版本。
                • -
                • develop分支为开发(develop branch)版本分支。每一个develop分支的版本都经过单元测试,但并没有经过回归测试。
                • -
                • release/版本号分支为每一次Release时建立的临时分支。在这个阶段的代码正在经历回归测试。
                • -
                -
              • -
              • 其他用户的fork版本库并不需要严格遵守git-flow分支规范,但所有fork的版本库的所有分支都相当于特性分支。
                  -
                • 建议,开发者fork的版本库使用develop分支同步主版本库的develop分支
                • -
                • 建议,开发者fork的版本库中,再基于develop版本fork出自己的功能分支。
                • -
                • 当功能分支开发完毕后,向PaddlePaddle的主版本库提交Pull Reuqest,进而进行代码评审。
                    -
                  • 在评审过程中,开发者修改自己的代码,可以继续在自己的功能分支提交代码。
                  • -
                  -
                • -
                -
              • -
              • BugFix分支也是在开发者自己的fork版本库维护,与功能分支不同的是,BugFix分支需要分别给主版本库的masterdevelop与可能有的release/版本号分支,同时提起Pull Request
              • -
              -
              -
              -

              PaddlePaddle回归测试列表

              -

              本列表说明PaddlePaddle发版之前需要测试的功能点。

              -
              -

              PaddlePaddle Book中所有章节

              -

              PaddlePaddle每次发版本首先要保证PaddlePaddle Book中所有章节功能的正确性。功能的正确性包括验证PaddlePaddle目前的paddle_trainer训练和纯使用Python训练模型正确性。

              -

              | | 新手入门章节 | 识别数字 | 图像分类 | 词向量 | 情感分析 | 语意角色标注 | 机器翻译 | 个性化推荐 | -| — | — | — | — | — | — | — | — | — | -| API.V2 + Docker + GPU | | | | | | | | | -| API.V2 + Docker + CPU | | | | | | | | | -| paddle_trainer + Docker + GPU | | | | | | | | | -| paddle_trainer + Docker + CPU | | | | | | | | | -| API.V2 + Ubuntu + GPU | | | | | | | | | -| API.V2 + Ubuntu + CPU | | | | | | | | | -| paddle_trainer + Ubuntu + GPU | | | | | | | | | -| paddle_trainer + Ubuntu + CPU | | | | | | | | |

              -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/scope.html b/develop/doc/design/scope.html deleted file mode 100644 index 25ed677b285..00000000000 --- a/develop/doc/design/scope.html +++ /dev/null @@ -1,373 +0,0 @@ - - - - - - - - - - - - - Design of Scope in Paddle — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design of Scope in Paddle

              -
              -

              Overview

              -

              Scope is an important concept in programming languages, which defines a program region that a set of bindings between names and entities applies. In a specific scope, a valid name is uniquely associated with an entity, such as a variable. And in another scope, this name may refer to other entity or nothing at all. It clearly restricts the visibility and validity of names in a program. Hence Scope is introduced to PaddlePaddle to manage variables in context. But different from the original abstract concept, Scope now becomes an object with two important attributes:

              -
                -
              • Scope is an association of a name to variable.
              • -
              • Variables in a parent scope can be retrieved from local scope.
              • -
              -

              A detailed explanation of these two attributes goes as following.

              -
              -
              -

              Scope is an association of a name to variable.

              -

              Scope is an association of a name to variable. All variables belong to Scope. You need to specify a scope to run a Net, i.e., net.Run(&scope). One net can run in different scopes and update different variable in the scope.

              -
                -
              1. Scope only contains a map of a name to variable.

                -

                All parameters, data, states in a Net should be variables and stored inside a scope. Each op should get inputs and outputs to do computation from a scope, such as data buffer, state (momentum) etc.

                -
              2. -
              3. Variable can only be created by Scope and a variable can only be got from Scope. User cannot create or get a variable outside a scope. This is a constraints of our framework, and will keep our framework simple and clear.

                -
              4. -
              5. Scope only contains methods that are used to Create and Get Variables. Scope do not contain Operators and have no information to run them. -Net is designed to drive the computation and Scope only contains a map of variables. There is no computation logic inside a Scope. Scope just handles the lifetime management of variables.

                -
                  -
                • Create is used to create a Variable by its name and add the mapping relation.
                • -
                • Get is used to find a Variable by name.
                • -
                -
              6. -
              7. Every variable only belongs to one certain Scope.

                -

                Variable can not belong to many scopes. If you want to use variables from parent scope, you can use parent scope.

                -
              8. -
              9. Scope should destruct all Variables inside it when itself is destructed. User can never store Variable pointer somewhere else.

                -

                Because Variable can only be got from Scope. When destroying Scope, we also need to destroy all the Variables in it. If user store Variable pointer to private data member or some global variable, the pointer will be an invalid pointer when associated Scope is destroyed.

                -
              10. -
              -
              class Scope {
              - public:
              -  Variable* Var(const std::string& name);
              -  const Variable* FindVar(const std::string& name) const;
              -
              - private:
              -    std::unordered_map<std::string, std::unique_ptr<Variable>> vars_;
              -};
              -
              -
              -
              -
              -

              Parent scope and local scope

              -

              Just like scope in programming languages, Scope in the neural network can also be a local scope. There are two attributes about local scope.

              -
                -
              1. We can create local variables in a local scope. When that local scope is destroyed, all local variables should also be destroyed.
              2. -
              3. Variables in a parent scope can be retrieved from local scopes of that parent scope, i.e., when user get a variable from a scope, it will try to search this variable in current scope. If there is no such variable in the local scope, scope will keep searching from its parent, until the variable is found or there is no parent.
              4. -
              -
              class Scope {
              - public:
              -  Scope(const std::shared_ptr<Scope>& scope): parent_(scope) {}
              -
              -  Variable* FindVar(const std::string& name) const {
              -    auto it = vars_.find(name);
              -    if (it != vars_.end()) {
              -      return it->second.get();
              -    } else if (parent_ != nullptr) {
              -      return parent_->FindVar(name);
              -    } else {
              -      return nullptr;
              -    }
              -  }
              -
              - private:
              -  std::shared_ptr<Scope> parent_ {nullptr};
              -};
              -
              -
              -

              In Scope class, there is a private data member called parent_. parent_ is a smart pointer to its parent scope. When user Get a variable by its name, the name will be searched inside the current scope. If the variable cannot be found locally and parent scope is not a nullptr, the variable will be searched inside that parent scope. parent_ pointer’s default value is nullptr. It means that the scope is a global scope when parent_ is nullptr.

              -

              A local scope is very useful when we implement Recurrent Neural Network. Each timestep of an RNN should be a Net. Each Net of timestep (StepNet for short) should use an independent local scope. Just like variables in a while loop is inside a local scope in programming languages. By using a single StepNet and changing local scope, we can implement an RNN easily.

              -
              -
              -
              -

              Interface Design

              -
              class Variable {
              - private:
              -  Variable() = default;
              -  friend class Scope;
              -};
              -
              -class Scope {
              - private:
              -  Scope(const std::shared_ptr<Scope>& parent = nullptr);
              -
              - public:
              -  static std::shared_ptr<Scope> Create(const std::shared_ptr<Scope>& parent = nullptr);
              -
              -  // return nullptr if not found.
              -  Variable* FindVar(const std::string& name) const;
              -
              -  // return if already contains same name variable.
              -  Variable* Var(const std::string& name);
              -
              - private:
              -  std::shared_ptr<Scope> parent_;
              -  std::unordered_map<std::string, std::unique_ptr<Variable>> vars_;
              -};
              -
              -
              -
              -

              Only scope can create a variable

              -

              To ensure only scope can create a variable, we should mark Variable‘s constructor as a private member function, and Scope is a friend class of Variable. And then only Var can construct Variable.

              -
              -
              -

              When scope destroyed, all variables inside this scope should be destroyed together

              -

              The scope hold unique pointers for all variables. User can FindVar from scope, but he should not hold this pointer as a member variable. Because when scope is destroyed, all variables inside this scope will be destroyed together.

              -
              -
              -

              Sharing a parent scope

              -

              Local scope contains a parent_ pointer. It is a linked-list for scopes. Using a shared_ptr because when a local scope is using, its parents cannot be destroyed.

              -

              Also, as the parent scope is a shared_ptr, we can only Create() a scope shared pointer. We cannot construct a scope variable, because it cannot be passed to other scope as parent pointer.

              -
              -
              -

              Orthogonal interface

              -

              FindVar will return nullptr when name is not found. It can be used as Contains method. Var will return an Error when there is a name conflict locally. Combine FindVar and Var, we can implement Var easily.

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/selected_rows.html b/develop/doc/design/selected_rows.html deleted file mode 100644 index 82a5f897bb5..00000000000 --- a/develop/doc/design/selected_rows.html +++ /dev/null @@ -1,319 +0,0 @@ - - - - - - - - - - - - - Design Doc: Selected Rows — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Selected Rows

              -

              SelectedRows is a type of sparse tensor data type, which is designed to support embedding operators. The gradient of embedding table is a sparse tensor. Only a few rows are non-zero values in this tensor. It is straight-forward to represent a sparse tensor by the following sparse tensor data structure:

              -
              class SelectedRows {
              - private:
              -  vector<int> rows_;
              -  Tensor value_;
              -  int height_;
              -};
              -
              -
              -

              The field height_ is the first dimension of SelectedRows. The rows are the indices of the non-zero rows of SelectedRows. The value_ field is an N-dim tensor of shape [rows.size() /* NUM_ROWS */, ...], which supplies values for each row. The dimension of SelectedRows satisfies [height_] + value_.shape[1:].

              -

              Suppose that a SelectedRows-typed variable x has many rows, but only two of them have values – row 73 is [1, 2] and row 84 is [3, 4], the SelectedRows representation would be:

              -
              x = SelectedRow {
              -  rows = [73, 84],
              -  value = [[1, 2], [3,4]]
              -}
              -
              -
              -
              -

              SelectedRows in Protobuf

              -

              SelectedRows is a type of Variable. VarDesc in protobuf should describe the SelectedRows information. Only the tensor dimension of a SelectedRows will be described in compile-time because the rows_ and value_ are dependent on the training data. -So we use TensorDesc to unify data_type and dims. A LodTensorDesc contains a TensorDesc and lod_level. The description of SelectedRows is a Tensor description.

              -
              message TensorDesc {
              -  required DataType data_type = 1;
              -  repeated int64 dims = 2; // [UNK, 640, 480] is saved as [-1, 640, 480]
              -}
              -
              -message LodTensorDesc {
              -  required TensorDesc tensor = 1;
              -  optional int lod_level = 2;
              -}
              -
              -message VarDesc {
              -  required string name = 1;
              -  enum VarType { 
              -    LOD_TENSOR = 0;
              -    SELECTED_ROWS = 1;
              -  }
              -  required VarType type = 2;
              -  optional LodTensorDesc lod_desc = 3;
              -  optional TensorDesc selected_rows_desc = 4;
              -  optional bool persistable = 5 [ default = false ];
              -}
              -
              -
              -
              -
              -

              InferShape for Selected Rows

              -

              Just like LoD information, InferShape method will infer the output tensor type as well. The operator should decide whether its output is a SelectedRows or Dense tensor.

              -

              For example, the gradient operator of TableLookup will always generate SelectedRows. Its InferShape method should be like following

              -
              void TableLookupGrad::InferShape(context) {
              -  ...
              -  context.SetDataType("Embedding.Grad", kSelectedRows);
              -}
              -
              -
              -
              -
              -

              Sparse Operators

              -

              There are several operators that need to be written to support SelectedRows. These are:

              -
                -
              1. Operators which generate SelectedRows gradient. e.g. Gradient of TableLookupOp.
              2. -
              3. Optimize operators which support SelectedRows gradient. e.g. SGD or AdaGrad for SelectedRows. However, there should be only one SGD operator. OpWithKernel::Run should select a suitable kernel for both dense tensor or SelectedRows.
              4. -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/simple_op_design.html b/develop/doc/design/simple_op_design.html deleted file mode 100644 index ab16e08a0b7..00000000000 --- a/develop/doc/design/simple_op_design.html +++ /dev/null @@ -1,441 +0,0 @@ - - - - - - - - - - - - - Interaction between C++ and Python — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Interaction between C++ and Python

              -

              Users employ API in Python to describe their own network, however, the network construction actually happens in C++. so Protobuf is introduced to send the message between Python and C++.

              -

              The Interaction between Python and C++ can be simplified as two steps:

              -
                -
              1. C++ tells Python how many Ops there are, and what parameter do users need to offer to initialize a new Op. Python then builds API for each Op at compile time.
              2. -
              3. Users invoke APIs built by Python and provide necessary parameters. These parameters will be sent to C++ for finishing the Op construction task.
              4. -
              -
              -

              Message from C++ to Python

              -

              We define a Protobuf message class OpProto to hold message needed in the first step. What should an OpProto contain? This question is equivalent to “What message do we need to offer, to build a Python API which is legal and user oriented and can use to describe a whole Op.”

              -

              Following message are necessary:

              -
                -
              1. Op’s name, and its simple comment.
              2. -
              3. Input and output variable number; each variable’s name, type, and comment.
              4. -
              5. Op’s attributes; each attribute includes name, type, comment, default value and value range.
              6. -
              -

              So OpProto can be defined as follows:

              -
              enum AttrType {
              -    INT = 1;
              -    FLOAT = 2;
              -    STRING = 3;
              -    INTS = 4;
              -    FLOATS = 5;
              -    STRINGS = 6;
              -};
              -
              -message AttrValue {
              -    AttrType type = 1;
              -    optional int iv = 2;
              -    optional float fv = 3;
              -    optional string sv = 4;
              -    repeated int ivs = 5;
              -    repeated float fvs = 6;
              -    repeated string svs = 7;
              -};
              -
              -message AttrProto {
              -    required string name = 1;
              -    required string comment = 2;
              -    required AttrType type = 3;
              -};
              -
              -message VarProto {
              -    required string name = 1;
              -    required string comment = 2;
              -    required bool is_tensor = 3;
              -};
              -
              -message OpProto {
              -    repeated VarProto inputs = 1;
              -    repeated VarProto outputs = 2;
              -    repeated AttrProto attrs = 3;
              -    required string type = 4;
              -    required string comment = 5;
              -};
              -
              -
              -

              To generate Python code automatically:

              -
              def create_python_ops_creatation_functions():
              -    op_protos = paddle.framework.OpRegistry.get_all_op_proto()
              -    for type_name in op_protos:
              -        op_proto = op_protos[type_name]
              -        def __impl__(**kwargs):  # User must use key word args in Paddle API
              -            inputs = [kwargs.get(ipt.name, "") for ipt in op_proto.inputs]
              -            outputs = [kwargs.get(opt.name, "") for opt in op_proto.outputs]
              -            attrs = [cast_to_op_attr(attr, kwargs.get(attr.name, None)) for attr in op_proto.attrs]
              -            opdesc = (input, outputs, type_name, attrs)
              -            return paddle.framework.OpRegistry.CreateOp(opdesc)
              -        __impl__.__doc__ = create_doc_string(op_proto)
              -        globals()[type_name] = __impl__
              -
              -create_python_ops_creatation_functions()
              -
              -
              -
              -
              -

              Message from Python to C++

              -

              To hold message needed in the above second step, we define Protobuf message class OpDesc. It is used to hold user-specified parameters in Op describing.

              -
              message OpDesc {
              -    required string type = 1;   
              -    repeated string inputs = 2;
              -    repeated string outputs = 3;
              -    map<string, AttrValue> attrs = 4;
              -};
              -
              -
              -
              -
              -
              -

              OpProto Register

              -

              Every Op has its own OpProto. For using convenience, we need to register them and record all their messages. For each Op class, we define a corresponding OpMaker class, in whose constructor we implement the OpProto‘s building process. OpMaker‘s constructor will be invoked by another function OpRegistry::RegisterOp().

              -
              class OpProtoMaker {
              -public:
              -    OpProtoMaker(OpProto* proto): proto_(proto) {}
              -protected:
              -    OpProto* proto_;
              -    void AddInput(const std::string& name, const std::string& desc) {...}
              -    void AddAttr(const std::string& name, const std::string& desc, TypeId type) {...}
              -    void AddComment(const std::string& comment) { ... }
              -};
              -
              -class OpRegistry {
              -public:
              -    using OpCreator = std::function<OperatorBase* (OpDesc& desc)>;
              -    
              -    template <typename OpType, typename OpMaker>
              -    static void RegisterOp(const std::string& name) {
              -        gCreators_[name] = [](const OpDesc& desc) {
              -            return new OpType(desc);
              -        };
              -        OpProto& opProto = gProtos_[name];
              -        OpMaker()(&opProto);
              -    }
              -
              -    static map<string, OpCreator> gCreators_;
              -    static map<string, OpProto> gProtos_;
              -};
              -
              -template <typename OpType, typename OpMaker>
              -class OpRegister {
              -  public:
              -    OpRegister(std::string type) {
              -        OpRegistry::RegisterOp<OpType, OpMaker>(type);
              -    }
              -};
              -
              -#define REGISTER_OP(op_class, op_maker_class, type_name)         \
              -    class op_class##Register {                                   \
              -      private:                                                   \
              -        const static OpRegister<#op_class, #op_maker_class> reg; \
              -    };                                                           \
              -    const Register op_class##Register::reg(#type_name);
              -    
              -class CosineOp {
              -// ...
              -}
              -
              -struct CosineOpProtoMaker : public OpProtoMaker {
              -    CosineOpProtoMaker(OpProto* proto) : OpProtoMaker(proto) {
              -        AddInput("input", "input of cosine op");
              -        AddAttr("scale", "scale of cosine op", float).Default(1.0).GreaterThan(0.0);
              -        AddType("cos");
              -        AddComment("This is cos op");
              -    }
              -}
              -
              -REGISTER_OP(CosineOp, CosineOpProtoMaker, cos);
              -
              -
              -

              In REGISTER_OP(CosineOp, CosineOpProtoMaker, cos), we register not only CosineOp but also CosineOpProto. As fields of CosineOpProto, the default value and value range of scale are also registered here.

              -
              -
              -

              Python API

              -

              Python APIs are divided into two types, high-level API and low-level API.

              -
              -

              High-Level API

              -

              High-level API is called by users directly, so it should keep its style consistent with existing V2 APIs.

              -

              Here is a sample about how a define a fc layer:

              -
              hd = fc_layer(input=data, size=56, with_bias=True, activation="sigmoid");
              -
              -
              -

              hd is the output of fc_layer and it’s a variable. It can be further sent into other layers as input.

              -

              The definition of fc_layer():

              -
              def fc_layer(input, size, with_bias, activation):
              -    attr_map = {"size":size}
              -    check_attrs(attr_map)
              -    w = make_variable('w')
              -    if with_bias:
              -        b = make_variable('b')
              -    else:
              -        b = None
              -    fc_output = make_variable('fc_output');
              -    fc_op(input, w, b, fc_output, attr_map)
              -    act_output = make_variable('sigmod_output');
              -    if activation == "sigmod":
              -        sigmod_op(fc_output, act_output);
              -    elif:
              -        # ...
              -    return act_output;
              -
              -
              -
              -
              -

              Low Leval API

              -

              In above sample, fc_op and sigmod_op are low-level API. They build OpDesc and invoke corresponding C++ code.

              -

              TODO

              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/speech/deep_speech_2.html b/develop/doc/design/speech/deep_speech_2.html deleted file mode 100644 index 9bad78759bb..00000000000 --- a/develop/doc/design/speech/deep_speech_2.html +++ /dev/null @@ -1,460 +0,0 @@ - - - - - - - - - - - - - DeepSpeech2 on PaddlePaddle: Design Doc — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              DeepSpeech2 on PaddlePaddle: Design Doc

              -

              We are planning to build Deep Speech 2 (DS2) [1], a powerful Automatic Speech Recognition (ASR) engine, on PaddlePaddle. For the first-stage plan, we have the following short-term goals:

              -
                -
              • Release a basic distributed implementation of DS2 on PaddlePaddle.
              • -
              • Contribute a chapter of Deep Speech to PaddlePaddle Book.
              • -
              -

              Intensive system optimization and low-latency inference library (details in [1]) are not yet covered in this first-stage plan.

              - -
              -

              Tasks

              -

              We roughly break down the project into 14 tasks:

              -
                -
              1. Develop an audio data provider:
                  -
                • Json filelist generator.
                • -
                • Audio file format transformer.
                • -
                • Spectrogram feature extraction, power normalization etc.
                • -
                • Batch data reader with SortaGrad.
                • -
                • Data augmentation (optional).
                • -
                • Prepare (one or more) public English data sets & baseline.
                • -
                -
              2. -
              3. Create a simplified DS2 model configuration:
                  -
                • With only fixed-length (by padding) audio sequences (otherwise need Task 3).
                • -
                • With only bidirectional-GRU (otherwise need Task 4).
                • -
                • With only greedy decoder (otherwise need Task 5, 6).
                • -
                -
              4. -
              5. Develop to support variable-shaped dense-vector (image) batches of input data.
                  -
                • Update DenseScanner in dataprovider_converter.py, etc.
                • -
                -
              6. -
              7. Develop a new lookahead-row-convolution layer (See [1] for details):
                  -
                • Lookahead convolution windows.
                • -
                • Within-row convolution, without kernels shared across rows.
                • -
                -
              8. -
              9. Build KenLM language model (5-gram) for beam search decoder:
                  -
                • Use KenLM toolkit.
                • -
                • Prepare the corpus & train the model.
                • -
                • Create infererence interfaces (for Task 6).
                • -
                -
              10. -
              11. Develop a beam search decoder with CTC + LM + WORDCOUNT:
                  -
                • Beam search with CTC.
                • -
                • Beam search with external custom scorer (e.g. LM).
                • -
                • Try to design a more general beam search interface.
                • -
                -
              12. -
              13. Develop a Word Error Rate evaluator:
                  -
                • update ctc_error_evaluator(CER) to support WER.
                • -
                -
              14. -
              15. Prepare internal dataset for Mandarin (optional):
                  -
                • Dataset, baseline, evaluation details.
                • -
                • Particular data preprocessing for Mandarin.
                • -
                • Might need cooperating with the Speech Department.
                • -
                -
              16. -
              17. Create standard DS2 model configuration:
                  -
                • With variable-length audio sequences (need Task 3).
                • -
                • With unidirectional-GRU + row-convolution (need Task 4).
                • -
                • With CTC-LM beam search decoder (need Task 5, 6).
                • -
                -
              18. -
              19. Make it run perfectly on clusters.
              20. -
              21. Experiments and benchmarking (for accuracy, not efficiency):
                  -
                • With public English dataset.
                • -
                • With internal (Baidu) Mandarin dataset (optional).
                • -
                -
              22. -
              23. Time profiling and optimization.
              24. -
              25. Prepare docs.
              26. -
              27. Prepare PaddlePaddle Book chapter with a simplified version.
              28. -
              -
              -
              -

              Task Dependency

              -

              Tasks parallelizable within phases:

              -

              Roadmap | Description | Parallelizable Tasks -———– | :———————————— | :——————– -Phase I | Simplified model & components | Task 1 ~ Task 8 -Phase II | Standard model & benchmarking & profiling | Task 9 ~ Task 12 -Phase III | Documentations | Task13 ~ Task14

              -

              Issue for each task will be created later. Contributions, discussions and comments are all highly appreciated and welcomed!

              -
              -
              -

              Design Details

              -
              -

              Overview

              -

              Traditional ASR (Automatic Speech Recognition) pipelines require great human efforts devoted to elaborately tuning multiple hand-engineered components (e.g. audio feature design, accoustic model, pronuncation model and language model etc.). Deep Speech 2 (DS2) [1], however, trains such ASR models in an end-to-end manner, replacing most intermediate modules with only a single deep network architecture. With scaling up both the data and model sizes, DS2 achieves a very significant performance boost.

              -

              Please read Deep Speech 2 [1,2] paper for more background knowledge.

              -

              The classical DS2 network contains 15 layers (from bottom to top):

              -
                -
              • Two data layers (audio spectrogram, transcription text)
              • -
              • Three 2D convolution layers
              • -
              • Seven uni-directional simple-RNN layers
              • -
              • One lookahead row convolution layers
              • -
              • One fully-connected layers
              • -
              • One CTC-loss layer
              • -
              -
              -
              -Figure 1. Archetecture of Deep Speech 2 Network. -

              We don’t have to persist on this 2-3-7-1-1-1 depth [2]. Similar networks with different depths might also work well. As in [1], authors use a different depth (e.g. 2-2-3-1-1-1) for final experiments.

              -

              Key ingredients about the layers:

              -
                -
              • Data Layers:
                  -
                • Frame sequences data of audio spectrogram (with FFT).
                • -
                • Token sequences data of transcription text (labels).
                • -
                • These two type of sequences do not have the same lengthes, thus a CTC-loss layer is required.
                • -
                -
              • -
              • 2D Convolution Layers:
                  -
                • Not only temporal convolution, but also frequency convolution. Like a 2D image convolution, but with a variable dimension (i.e. temporal dimension).
                • -
                • With striding for only the first convlution layer.
                • -
                • No pooling for all convolution layers.
                • -
                -
              • -
              • Uni-directional RNNs
                  -
                • Uni-directional + row convolution: for low-latency inference.
                • -
                • Bi-direcitional + without row convolution: if we don’t care about the inference latency.
                • -
                -
              • -
              • Row convolution:
                  -
                • For looking only a few steps ahead into the feature, instead of looking into a whole sequence in bi-directional RNNs.
                • -
                • Not nessesary if with bi-direcitional RNNs.
                • -
                • Row” means convolutions are done within each frequency dimension (row), and no convolution kernels shared across.
                • -
                -
              • -
              • Batch Normalization Layers:
                  -
                • Added to all above layers (except for data and loss layer).
                • -
                • Sequence-wise normalization for RNNs: BatchNorm only performed on input-state projection and not state-state projection, for efficiency consideration.
                • -
                -
              • -
              -

              Required Components | PaddlePaddle Support | Need to Develop -:————————————- | :————————————– | :———————– -Data Layer I (Spectrogram) | Not supported yet. | TBD (Task 3) -Data Layer II (Transcription) | paddle.data_type.integer_value_sequence | - -2D Convolution Layer | paddle.layer.image_conv_layer | - -DataType Converter (vec2seq) | paddle.layer.block_expand | - -Bi-/Uni-directional RNNs | paddle.layer.recurrent_group | - -Row Convolution Layer | Not supported yet. | TBD (Task 4) -CTC-loss Layer | paddle.layer.warp_ctc | - -Batch Normalization Layer | paddle.layer.batch_norm | - -CTC-Beam search | Not supported yet. | TBD (Task 6)

              -
              -
              -

              Row Convolution

              -

              TODO by Assignees

              -
              -
              -

              Beam Search with CTC and LM

              -
              -
              -Figure 2. Algorithm for CTC Beam Search Decoder. -
                -
              • The Beam Search Decoder for DS2 CTC-trained network follows the similar approach in [3] as shown in Figure 2, with two important modifications for the ambiguous parts:
                  -
                  1. -
                  2. in the iterative computation of probabilities, the assignment operation is changed to accumulation for one prefix may comes from different paths;
                  3. -
                  -
                • -
                  1. -
                  2. the if condition if l^+ not in A_prev then after probabilities’ computation is deprecated for it is hard to understand and seems unnecessary.
                  3. -
                  -
                • -
                -
              • -
              • An external scorer would be passed into the decoder to evaluate a candidate prefix during decoding whenever a white space appended in English decoding and any character appended in Mandarin decoding.
              • -
              • Such external scorer consists of language model, word count or any other custom scorers.
              • -
              • The language model is built from Task 5, with parameters should be carefully tuned to achieve minimum WER/CER (c.f. Task 7)
              • -
              • This decoder needs to perform with high efficiency for the convenience of parameters tuning and speech recognition in reality.
              • -
              -
              -
              -
              -

              Future Work

              -
                -
              • Efficiency Improvement
              • -
              • Accuracy Improvement
              • -
              • Low-latency Inference Library
              • -
              • Large-scale benchmarking
              • -
              -
              - -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/support_new_device.html b/develop/doc/design/support_new_device.html deleted file mode 100644 index 76d9ea85ee9..00000000000 --- a/develop/doc/design/support_new_device.html +++ /dev/null @@ -1,453 +0,0 @@ - - - - - - - - - - - - - Design Doc: Supporting new Device/Library — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Supporting new Device/Library

              -
              -

              Background

              -

              Deep learning has a high demand for computing resources. New high-performance devices and computing libraries are appearing very frequently. Deep learning frameworks have to integrate these high-performance devices and computing libraries in a flexible and efficient manner.

              -

              On one hand, hardware and computing libraries usually do not have a one-to-one correspondence. For example, Intel CPUs support Eigen and MKL computing libraries while Nvidia GPUs support Eigen and cuDNN computing libraries. We have to implement operator specific kernels for each computing library.

              -

              On the other hand, users usually do not want to care about the low-level hardware and computing libraries when writing a neural network configuration. In Fluid, Layer is exposed in Python, and Operator is exposed in C++. Both Layer and Operator are hardware independent.

              -

              So, how to support a new Device/Library in Fluid becomes a challenge.

              -
              -
              -

              Basic: Integrate A New Device/Library

              -

              For a general overview of fluid, please refer to the overview doc.

              -

              There are mainly three parts that we have to consider while integrating a new device/library:

              -
                -
              • Place and DeviceContext: indicate the device id and manage hardware resources
              • -
              • Memory and Tensor: malloc/free data on certain device
              • -
              • Math Functor and OpKernel: implement computing unit on certain devices/libraries
              • -
              -
              -

              Place and DeviceContext

              -

              Please note that device and computing library are not one-to-one corresponding. A device can have a lot of computing libraries and a computing library can also support several devices.

              -
              -

              Place

              -

              Fluid uses class Place to represent the device memory where data is located. If we add another device, we have to add the corresponding DevicePlace.

              -
                      |   CPUPlace
              -Place --|   CUDAPlace
              -        |   FPGAPlace
              -
              -
              -

              And Place is defined as follows:

              -
              typedef boost::variant<CUDAPlace, CPUPlace, FPGAPlace> Place;
              -
              -
              -
              -
              -

              DeviceContext

              -

              Fluid uses class DeviceContext to manage the resources in different libraries, such as CUDA stream in CDUADeviceContext. There are also inheritance relationships between different kinds of DeviceContext.

              -
                              /->  CPUDeviceContext   
              -DeviceContext ---->  CUDADeviceContext  
              -                \->  FPGADeviceContext
              -
              -
              -

              An example of Nvidia GPU is as follows:

              -
                -
              • DeviceContext
              • -
              -
              class DeviceContext {
              -  virtual Place GetPlace() const = 0;
              -};  
              -
              -
              -
                -
              • CUDADeviceContext
              • -
              -
              class CUDADeviceContext : public DeviceContext {
              -  Place GetPlace() const override { return place_; }
              -private:
              -  CUDAPlace place_;
              -  cudaStream_t stream_; 
              -  cublasHandle_t cublas_handle_;
              -  std::unique_ptr<Eigen::GpuDevice> eigen_device_;  // binds with stream_
              -};
              -
              -
              -
              -
              -
              -

              Memory and Tensor

              -
              -

              memory module

              -

              Fluid provides the following memory interfaces:

              -
              template <typename Place>
              -void* Alloc(Place place, size_t size);
              -
              -template <typename Place>
              -void Free(Place place, void* ptr);
              -
              -template <typename Place>
              -size_t Used(Place place);
              -
              -
              -

              To implement these interfaces, we have to implement MemoryAllocator for different Devices.

              -
              -
              -

              Tensor

              -

              Tensor holds data with some shape in a specific Place.

              -
              class Tensor {
              - public:
              -  /*! Return a pointer to mutable memory block. */
              -  template <typename T>
              -  inline T* data();
              -
              -  /**
              -   * @brief   Return a pointer to mutable memory block.
              -   * @note    If not exist, then allocation.
              -   */
              -  template <typename T>
              -  inline T* mutable_data(platform::Place place);
              -
              -  /**
              -   * @brief     Return a pointer to mutable memory block.
              -   *
              -   * @param[in] dims    The dimensions of the memory block.
              -   * @param[in] place   The place of the memory block.
              -   *
              -   * @note      If not exist, then allocation.
              -   */
              -  template <typename T>
              -  inline T* mutable_data(DDim dims, platform::Place place);
              -
              -  /*! Resize the dimensions of the memory block. */
              -  inline Tensor& Resize(const DDim& dims);
              -
              -  /*! Return the dimensions of the memory block. */
              -  inline const DDim& dims() const;
              -
              - private:
              -  /*! holds the memory block if allocated. */
              -  std::shared_ptr<Placeholder> holder_;
              -
              -  /*! points to dimensions of memory block. */
              -  DDim dim_;
              -};
              -
              -
              -

              Placeholder is used to delay memory allocation; that is, we can first define a tensor, using Resize to configurate its shape, and then call mutuable_data to allocate the actual memory.

              -
              paddle::framework::Tensor t;
              -paddle::platform::CPUPlace place;
              -// set size first
              -t.Resize({2, 3});
              -// allocate memory on CPU later
              -t.mutable_data(place);
              -
              -
              -
              -
              -
              -

              Math Functor and OpKernel

              -

              Fluid implements computing units based on different DeviceContexts. Some computing units are shared between operators. This common part will be put in operators/math directory as basic Functors.

              -

              Let’s take MaxOutFunctor as an example:

              -

              The interface is defined in the header file.

              -
              template <typename DeviceContext, typename T>
              -class MaxOutFunctor {
              - public:
              -  void operator()(const DeviceContext& context, const framework::Tensor& input,
              -                  framework::Tensor* output, int groups);
              -};
              -
              -
              -

              CPU implementation is in .cc file

              -
              template <typename T>
              -class MaxOutFunctor<platform::CPUDeviceContext, T> {
              -  public:
              -  void operator()(const platform::CPUDeviceContext& context,
              -                  const framework::Tensor& input, framework::Tensor* output,
              -                  int groups) {
              -                  ...
              -                  }
              -};
              -
              -
              -

              CUDA implementation is in .cu file

              -
              template <typename T>
              -class MaxOutFunctor<platform::CUDADeviceContext, T> {
              - public:
              -  void operator()(const platform::CUDADeviceContext& context,
              -                  const framework::Tensor& input, framework::Tensor* output,
              -                  int groups) {
              -                  ...
              -                  }
              -};                  
              -
              -
              -

              We first obtain the computing handle from a concrete DeviceContext and then compute on tensors.

              -

              The implementation of OpKernel is similar to math functors, the extra thing we need to do is to register the OpKernel in a global map.

              -

              Fluid provides different register interfaces in op_registry.h

              -

              Let’s take Crop operator as an example:

              -

              In .cc file:

              -
              REGISTER_OP_CPU_KERNEL(crop, ops::CropKernel<float>);
              -REGISTER_OP_CPU_KERNEL(
              -    crop_grad, ops::CropGradKernel<paddle::platform::CPUDeviceContext, float>);
              -
              -
              -

              In .cu file:

              -
              REGISTER_OP_CUDA_KERNEL(crop, ops::CropKernel<float>);
              -REGISTER_OP_CUDA_KERNEL(
              -    crop_grad, ops::CropGradKernel<paddle::platform::CUDADeviceContext, float>);
              -
              -
              -
              -
              -
              -

              Advanced topics: How to switch between different Device/Library

              -

              Generally, we will implement OpKernel for all Device/Library of an Operator. We can easily train a Convolutional Neural Network in GPU. However, some OpKernel is not suitable on a specific Device. For example, crf operator can only run on CPU, whereas most other operators can run on GPU. To achieve high performance in such circumstance, we have to switch between different Device/Library.

              -

              For more details, please refer to following docs:

              -
                -
              • operator kernel type doc
              • -
              • switch kernel doc
              • -
              -
              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/switch.html b/develop/doc/design/switch.html deleted file mode 100644 index 3ab75f90388..00000000000 --- a/develop/doc/design/switch.html +++ /dev/null @@ -1,283 +0,0 @@ - - - - - - - - - - - - - Design Doc: Switch — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design Doc: Switch

              -
              -
              -

              Background

              -

              Many programming languages provide switch as a generalization of if-elif-else. We want to add it to Fluid.

              -

              The following example shows the usage of fluid.switch.

              -
              a = fluid.Var(10)
              -b = fluid.Var(0)
              -
              -with switch() as switch:
              -    with switch.case(fluid.less_equal(a, 10)):
              -        fluid.print("Case 1")
              -    with switch.case(fluid.larger(a, 0)):
              -        fluid.print("Case 2")
              -    with switch.default():
              -        fluid.print("Case 3")
              -
              -
              -
              -
              -

              The Semantics

              -
                -
              1. A switch control-flow checks cases one-by-one.
              2. -
              3. The condition of each case is a boolean value, which is a scalar, and differs from the fluid.if_else control-flow, which condition could be a vector of boolean values.
              4. -
              5. It runs the first matched case, or the default case if there is one.
              6. -
              7. Once it matches a case, it runs the corresponding branch and only that branch. It’s like there is a C’s break keyword at the end of each case.
              8. -
              -

              The above program should print and print only “Case 1”.

              -

              The implementation of the backward pass of the switch control-flow is easier than the backward of the if_else, because switch runs at most one branch, whereas if-else could run more than one branches.

              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/tensor_array.html b/develop/doc/design/tensor_array.html deleted file mode 100644 index 54efa977bc1..00000000000 --- a/develop/doc/design/tensor_array.html +++ /dev/null @@ -1,503 +0,0 @@ - - - - - - - - - - - - - Design for TensorArray — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Design for TensorArray

              -

              This design doc presents the necessity of a new C++ class TensorArray. -In addition to the very simple C++ implementation

              -
              class TensorArray {
              - public:
              -  explicit TensorArray(const LoDTensor&);
              -  explicit TensorArray(size_t size);
              -
              - private:
              -  vector<LoDTensor> values_;
              -};
              -
              -
              -

              We also need to expose it to PaddlePaddle’s Python API, -because users would want to use it with our very flexible operators WhileLoop. -An example for a RNN based on dynamic operators is

              -
              input = pd.data(...)
              -num_steps = Var(12)
              -
              -TensorArray states(size=num_steps)
              -TensorArray step_inputs(unstack_from=input)
              -TensorArray step_outputs(size=num_steps)
              -
              -W = Tensor(...)
              -U = Tensor(...)
              -default_state = some_op()
              -
              -step = Var(1)
              -
              -wloop = paddle.create_whileloop(loop_vars=[step])
              -with wloop.frame():
              -    wloop.break_if(pd.equal(step, num_steps)
              -    pre_state = states.read(step-1, default_state)
              -    step_input = step_inputs.read(step)
              -    state = pd.sigmoid(pd.matmul(U, pre_state) + pd.matmul(W, step_input))
              -    states.write(step, state)
              -    step_outputs.write(step, state) # output state
              -    step.update(state+1)
              -
              -output = step_outputs.stack()
              -
              -
              -
              -

              Background

              -

              Steps are one of the core concepts of RNN. In each time step of RNN, there should be several input segments, states, and output segments; all these components act like arrays, for example, call states[step_id] will get the state in step_idth time step.

              -

              An RNN can be implemented with the following pseudocode

              -
              Array states;
              -Array input_segments;
              -Array output_segments;
              -Parameter W, U;
              -
              -step = 1
              -seq_len = 12
              -while_loop {
              -   if (step == seq_len) break;
              -    states[step] = sigmoid(W * states[step-1] + U * input_segments[step]);
              -    output_segments[step] = states[step] // take state as output
              -   step++;
              -}
              -
              -
              -

              According to the RNN roadmap, there are several different RNNs that PaddlePaddle will eventually support.

              -

              Currently, the basic RNN implementation supported by PaddlePaddle is the recurrent_op which takes tensors as input and splits them into input_segments.

              -

              Since a tensor cannot store variable-length sequences directly, PaddlePaddle implements the tensor with level of details (LoDTensor for short). -Segmenting the LoDTensor is much more complicated than splitting a tensor, that makes it necessary to refactor the recurrent_op with LoDTensor segmenting support.

              -

              As the next step in RNN support, dynamic_recurrent_op should be introduced to handle inputs with variable-length sequences.

              -

              The implementation is similar to recurrent_op. -The key difference is the way the original input LoDTensors and outupts are split to get the input_segments and the output_segments.

              -

              Though it can’t be built over recurrent_op or dynamic_recurrent_op directly, -the logic behind splitting a tensor or a LoD tensor into input_segments remains the same.

              -
              -
              -

              Why TensorArray

              -

              The logic behind splitting the inputs to segments, states and outputs is similar and can be shared in a seperate module.

              -

              The array of states, input_segments and output_segments would be exposed to users when writing a dynamic RNN model similar to the above pseudo codes.

              -

              So there should be an array-like container, which can store the segments of a tensor or LoD tensor.

              -

              This container can store an array of tensors and provides several methods to split a tensor or a LoD tensor . -This is where the notion of TensorArray comes from.

              -
              -
              -

              Introduce TensorArray to uniform all the three RNNs

              -

              TensorArray as a new concept is borrowed from TensorFlow, -it is meant to be used with dynamic iteration primitives such as while_loop and map_fn.

              -

              This concept can be used to support our new design of dynamic operations, and help to refactor some existing variant-sentence-related layers, -such as recurrent_op, RecurrentGradientMachine.

              -

              In our design for dynamic RNN, -TensorArray is used to segment inputs and store states in all time steps. -By providing some methods similar to a C++ array, -the definition of some state-based dynamic models such as RNN can be more natural and highly flexible.

              -
              -
              -

              Dynamic-operations on TensorArray

              -

              TensorArray will be used directly when defining dynamic models, so some operators listed below should be implemented

              -
              # several helper operators for TensorArray
              -def tensor_array_stack(ta, tensor):
              -    '''
              -    get a tensor array `ta`, return a packed `tensor`.
              -    '''
              -    pass
              -
              -def tensor_array_unstack(tensor, ta):
              -    '''
              -    get a `tensor`, unstack it and get a tensor array `ta`.
              -    '''
              -    pass
              -
              -def tensor_array_write(ta, index, tensor, data_shared):
              -    '''
              -    get a `tensor` and a scalar tensor `index`, write `tensor` into index-th
              -    value of the tensor array `ta`.
              -    `data_shared` is an attribute that specifies whether to copy or reference the tensors.
              -    '''
              -    pass
              -
              -def tensor_array_read(ta, index, tensor):
              -    '''
              -    get a tensor array `ta`, a scalar tensor `index`, read the index-th value of
              -    `ta` and return as the `tensor`.
              -    '''
              -    pass
              -
              -def tensor_array_size(ta, tensor):
              -    '''
              -    get a tensor array `ta`, return the size of `ta` and return as the scalar `tensor`.
              -    '''
              -    pass
              -
              -
              -

              It is trivial for users to use so many low-level operators, so some helper methods should be proposed in python wrapper to make TensorArray easier to use, -for example

              -
              class TensorArray:
              -    def __init__(self, name):
              -        self.name = name
              -        self.desc = TensorArrayDesc()
              -
              -    def stack(self, name=None):
              -        '''
              -        Pack the values in a `TensorArray` into a tensor with rank one higher
              -        than each tensor in `values`.
              -        `stack` can be used to split tensor into time steps for RNN or whileloop.
              -
              -        @name: str
              -            the name of the variable to output.
              -        '''
              -        tensor = Var(name)
              -        tensor_array_stack(self.name, tensor)
              -        return tensor
              -
              -    def unstack(self, input):
              -        '''
              -        Unpacks the given dimension of a rank-`R` tensor into rank-`(R-1)` tensors.
              -        `unstack` can be used to concatenate all the time steps for RNN or whileloop.
              -
              -        @input: str
              -            the name of input tensor
              -        '''
              -        tensor_array_unstack(tensor, self.name)
              -
              -    def write(self, index, value, data_shared=True):
              -        '''
              -        Write value into index of the TensorArray.
              -        If `data_shared` is set to True, than the index-th value in TensorArray will
              -        be shared with the tensor passed in.
              -
              -        @index: str
              -            name of a scalar tensor
              -        @value: str
              -            name of a tensor
              -        @data_shared: bool
              -        '''
              -        tensor_array_write(self.name, index, value, data_shared)
              -
              -    def read(self, index, output):
              -        '''
              -        Read the value at location `index` in the `TensorArray`.
              -
              -        @index: str
              -            name of a scalar tensor
              -        @output:
              -            name of a output variable
              -        '''
              -        tensor_array_read(self.name, index, output)
              -
              -
              -    def size(self, output):
              -        '''
              -        Return the number of values.
              -
              -        @output: str
              -            name of a scalar tensor
              -        '''
              -        tensor_array_size(self.name, output)
              -
              -
              -
              - -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/design/var_desc.html b/develop/doc/design/var_desc.html deleted file mode 100644 index 54b60cbff43..00000000000 --- a/develop/doc/design/var_desc.html +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - Background — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              - - - - -
              - - - - - - -
              -
              - - - - - - -
              - -
              -
              -
              -
              - -
              -

              Background

              -

              PaddlePaddle divides the description of neural network computation into two stages: compile time and runtime. At compile time, the neural network computation is described as a ProgramDesc whereas at runtime an Executor interprets the ProgramDesc to compute the operations.

              -

              PaddlePaddle uses proto message to describe compile time program because :

              -
                -
              1. The computation program description must be serializable and saved in a file.
              2. -
              3. During distributed training, the serialized program will be sent to multiple workers. It should also be possible to break the program into different components, each of which can be executed on a different worker.
              4. -
              -

              The computation Program consists of nested Blocks. Each Block will consist of data(i.e. Variable) and Operations. The concept to represent them is in the table below.

              -

              | |compile time|runtime| -|—|—|—| -|Data|VarDesc(proto)|Variable(cpp)| -|Operation|OpDesc(proto)|Operator(cpp)|

              -
              -
              -

              Definition of VarType

              -

              A VarDesc should have a name, type and whether or not it is persistable. The are different kinds of variable types supported in PaddlePaddle, apart from the POD_Types like: LOD_TENSOR, SELECTED_ROWS, FEED_MINIBATCH, FETCH_LIST, STEP_SCOPES, LOD_RANK_TABLE, LOD_TENSOR_ARRAY, PLACE_LIST, READER and CHANNEL. These are declared inside VarType. A VarDesc then looks as the following:

              -
              message VarDesc {
              -  required string name = 1;
              -  required VarType type = 2;
              -  optional bool persistable = 3 [ default = false ];
              -}
              -
              -
              -
              -
              -

              Definition of TensorDesc

              -
              message TensorDesc {
              -  // Should only be PODType. Is enforced in C++
              -  required Type data_type = 1;
              -  repeated int64 dims = 2; // [UNK, 640, 480] is saved as [-1, 640, 480]
              -}
              -
              -
              -

              The Type here comes from the enum defined inside of VarType :

              -
              enum Type {
              -  // Pod Types
              -  BOOL = 0;
              -  INT16 = 1;
              -  INT32 = 2;
              -  INT64 = 3;
              -  FP16 = 4;
              -  FP32 = 5;
              -  FP64 = 6;
              -
              -  // Other types that may need additional descriptions
              -  LOD_TENSOR = 7;
              -  SELECTED_ROWS = 8;
              -  FEED_MINIBATCH = 9;
              -  FETCH_LIST = 10;
              -  STEP_SCOPES = 11;
              -  LOD_RANK_TABLE = 12;
              -  LOD_TENSOR_ARRAY = 13;
              -  PLACE_LIST = 14;
              -  READER = 15;
              -  CHANNEL = 16;
              -}
              -
              -
              -

              A TensorDesc describes SelectedRows and LoDTensor. For details of SelectedRows, please reference SelectedRows.

              -
              -
              -

              Definition of LodTensorDesc

              -
              message LoDTensorDesc {
              -  required TensorDesc tensor = 1;
              -  optional int32 lod_level = 2 [ default = 0 ];
              -}
              -
              -
              -

              A LoDTensorDesc contains a tensor and a lod_level.

              -
              -
              -

              Definition of Variable in Python

              -

              For Variable in Python, please reference Python API.

              -
              - - -
              -
              -
              - - -
              - -
              -

              - © Copyright 2016, PaddlePaddle developers. - -

              -
              - Built with Sphinx using a theme provided by Read the Docs. - -
              - -
              -
              - -
              - -
              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/dev/contribute_to_paddle_en.html b/develop/doc/dev/contribute_to_paddle_en.html index eb34f2236a3..c57f7cb7c4e 100644 --- a/develop/doc/dev/contribute_to_paddle_en.html +++ b/develop/doc/dev/contribute_to_paddle_en.html @@ -124,6 +124,12 @@ var _hmt = _hmt || [];
          • +
          • C-API Prediction Library +
          • RNN Models
            • RNN Configuration
            • Recurrent Group Tutorial
            • @@ -137,6 +143,7 @@ var _hmt = _hmt || [];
            • Development
            • FAQ
                diff --git a/develop/doc/dev/index_en.html b/develop/doc/dev/index_en.html index 1d451b4c23b..569ec5c5ca1 100644 --- a/develop/doc/dev/index_en.html +++ b/develop/doc/dev/index_en.html @@ -123,6 +123,12 @@ var _hmt = _hmt || [];
            • +
            • C-API Prediction Library +
            • RNN Models
              • RNN Configuration
              • Recurrent Group Tutorial
              • @@ -136,6 +142,7 @@ var _hmt = _hmt || [];
              • Development
              • FAQ
                  @@ -196,6 +203,7 @@ var _hmt = _hmt || []; diff --git a/develop/doc/dev/new_layer_en.html b/develop/doc/dev/new_layer_en.html index 4a11afd9280..58eeb6ad109 100644 --- a/develop/doc/dev/new_layer_en.html +++ b/develop/doc/dev/new_layer_en.html @@ -35,7 +35,10 @@ - + + + + - - - - - - - - - -
                  - - - - -
                  - - - - - - -
                  -
                  - - - - - - -
                  - -
                  -
                  -
                  -
                  - -
                  -

                  How to write a new operator

                  - -
                  -

                  Background

                  -

                  Here are the base types needed. For details, please refer to the design docs.

                  -
                    -
                  • class OpProtoAndCheckerMaker: Describes an Operator’s input, output, attributes and description, mainly used to interface with Python API.
                  • -
                  • framework::OperatorBase: Operator (Op)base class.
                  • -
                  • framework::OpKernel: Base class for Op computation kernel.
                  • -
                  • framework::OperatorWithKernel: Inherited from OperatorBase, describing an operator with computation kernels.
                  • -
                  -

                  Operators can be categorized into two groups: operator with kernel(s) and operator without kernel(s). An operator with kernel(s) inherits from OperatorWithKernel while the one without kernel(s) inherits from OperatorBase. This tutorial focuses on implementing operators with kernels. In short, an operator includes the following information:

                  -

                  Information | Where is it defined -————– | :———————- -OpProtoMake definition | .ccfiles, Backward Op does not need an OpProtoMake interface. -Op definition | .cc files -Kernel implementation | The kernel methods shared between CPU and CUDA are defined in .h files. CPU-specific kernels live in .cc files, while CUDA-specific kernels are implemented in .cufiles. -Registering the Op | Ops are registered in .cc files; For Kernel registration, .cc files contain the CPU implementation, while .cu files contain the CUDA implementation.

                  -

                  New Operator implementations are added to the list paddle/operators, with file names in the format *_op.h (if applicable), *_op.cc, *_op.cu (if applicable).** The system will use the naming scheme to automatically build operators and their corresponding Python extensions.**

                  -

                  Let’s take matrix multiplication operator, MulOp, as an example to introduce the writing of an Operator with Kernel.

                  -
                  -
                  -

                  Implementing C++ Types

                  -
                  -

                  Defining ProtoMaker

                  -

                  Matrix Multiplication can be written as $Out = X * Y$, meaning that the operation consists of two inputs and pne output.

                  -

                  First, define ProtoMaker to describe the Operator’s input, output, and additional comments:

                  -
                  class MulOpMaker : public framework::OpProtoAndCheckerMaker {
                  - public:
                  -  MulOpMaker(OpProto *proto, OpAttrChecker *op_checker)
                  -      : OpProtoAndCheckerMaker(proto, op_checker) {
                  -    AddInput("X", "(Tensor), 2D tensor of size (M x K)");
                  -    AddInput("Y", "(Tensor), 2D tensor of size (K x N)");
                  -    AddOutput("Out", "(Tensor), 2D tensor of size (M x N)");
                  -    AddComment(R"DOC(
                  -Two Element Mul Operator.
                  -The equation is: Out = X * Y
                  -)DOC");
                  -  }
                  -};
                  -
                  -
                  -

                  MulOpMakeris inherited fromframework::OpProtoAndCheckerMaker, consisting of 2 variables in the constructor:

                  -
                    -
                  • framework::OpProto stores Operator input and variable attribute, used for generating Python API interfaces.
                  • -
                  • framework::OpAttrChecker is used to validate variable attributes.
                  • -
                  -

                  The constructor utilizes AddInput, AddOutput, and AddComment, so that the corresponding information will be added to OpProto.

                  -

                  The code above adds two inputs X and Y to MulOp, an output Out, and their corresponding descriptions, in accordance to Paddle’s naming convention.

                  -

                  An additional example ScaleOp is implemented as follows:

                  -
                  template <typename AttrType>
                  -class ScaleOpMaker : public framework::OpProtoAndCheckerMaker {
                  - public:
                  -  ScaleOpMaker(OpProto *proto, OpAttrChecker *op_checker)
                  -      : OpProtoAndCheckerMaker(proto, op_checker) {
                  -    AddInput("X", "The input tensor of scale operator.").NotInGradient();
                  -    AddOutput("Out", "The output tensor of scale operator.").NotInGradient();
                  -    AddComment(R"DOC(Scale operator
                  -The equation is: Out = scale*X
                  -)DOC");
                  -    AddAttr<AttrType>("scale", "scale of scale operator.").SetDefault(1.0);
                  -  }
                  -};
                  -
                  -
                  -

                  There are two changes in this example:

                  -
                    -
                  • AddInput("X","...").NotInGradient() expresses that input X is not involved in ScaleOp‘s corresponding computation. If an input to an operator is not participating in back-propagation, please explicitly set .NotInGradient().
                  • -
                  • AddAttr<AttrType>("scale", "...").SetDefault(1.0); adds scaleconstant as an attribute, and sets the default value to 1.0.
                  • -
                  -
                  -
                  -

                  Defining Operator

                  -

                  The following code defines the interface for MulOp:

                  -
                  class MulOp : public framework::OperatorWithKernel {
                  - public:
                  -  using framework::OperatorWithKernel::OperatorWithKernel;
                  -
                  - protected:
                  -  void InferShape(const framework::InferShapeContext &ctx) const override {
                  -    auto dim0 = ctx.Input<Tensor>("X")->dims();
                  -    auto dim1 = ctx.Input<Tensor>("Y")->dims();
                  -    PADDLE_ENFORCE_EQ(dim0.size(), 2,
                  -                      "input X(%s) should be a tensor with 2 dims, a matrix",
                  -                      ctx.op_.Input("X"));
                  -    PADDLE_ENFORCE_EQ(dim1.size(), 2,
                  -                      "input Y(%s) should be a tensor with 2 dims, a matrix",
                  -                      ctx.op_.Input("Y"));
                  -    PADDLE_ENFORCE_EQ(
                  -        dim0[1], dim1[0],
                  -        "First matrix's width must be equal with second matrix's height.");
                  -    ctx.Output<Tensor>("Out")->Resize({dim0[0], dim1[1]});
                  -  }
                  -};
                  -
                  -
                  -

                  MulOp is inherited from OperatorWithKernel. Its public member

                  -
                  using framework::OperatorWithKernel::OperatorWithKernel;
                  -
                  -
                  -

                  expresses an operator constructor using base class OperatorWithKernel, alternatively written as

                  -
                  MulOp(const std::string &type, const framework::VariableNameMap &inputs,
                  -      const framework::VariableNameMap &outputs,
                  -      const framework::AttributeMap &attrs)
                  -  : OperatorWithKernel(type, inputs, outputs, attrs) {}
                  -
                  -
                  -

                  InferShape interface needs to be re-written.InferShape is a constant method and cannot modify Op’s member variables, its constant member const framework::InferShapeContext &ctx can be used to extract input, output, and attributes. It functions to

                  -
                    -
                  • 1). validate and error out early: it checks input data dimensions and types.
                  • -
                  • 2). configures the tensor shape in the output.
                  • -
                  -

                  Usually OpProtoMaker and Op‘s type definitions are written in .cc files, which also include the registration methods introduced later.

                  -
                  -
                  -

                  Defining OpKernel

                  -

                  MulKernel inherits framework::OpKernel, which includes the following templates:

                  -
                    -
                  • typename DeviceContext denotes device context type. When different devices, namely the CPUDeviceContext and the CUDADeviceContext, share the same kernel, this template needs to be added. If they don’t share kernels, this must not be added. An example of a non-sharing kernel is OnehotCrossEntropyOpKernel.
                  • -
                  • typename T denotes data type, such as float or double.
                  • -
                  -

                  MulKernel types need to rewrite the interface for Compute.

                  -
                    -
                  • Compute takes one input parameter: const framework::ExecutionContext& context.
                  • -
                  • Compared with InferShapeContext, ExecutionContext includes device types, and can similarly extract input, output, and attribute variables.
                  • -
                  • Compute implements the computation logics of an OpKernel.
                  • -
                  -

                  MulKernel‘s implementation of Compute is as follows:

                  -
                  template <typename DeviceContext, typename T>
                  -class MulKernel : public framework::OpKernel {
                  -public:
                  -void Compute(const framework::ExecutionContext& context) const override {
                  -  auto* X = context.Input<Tensor>("X");
                  -  auto* Y = context.Input<Tensor>("Y");
                  -  auto* Z = context.Output<Tensor>("Out");
                  -  Z->mutable_data<T>(context.GetPlace());
                  -  auto& device_context = context.template device_context<DeviceContext>();
                  -  math::matmul<DeviceContext, T>(*X, false, *Y, false, 1, Z, 0, device_context);
                  -}
                  -};
                  -
                  -
                  -

                  Note that different devices (CPU, CUDA)share one Op definition; whether or not they share the same OpKernel depends on whether Compute calls functions can support both devices.

                  -

                  MulOp‘s CPU and CUDA share the same Kernel. A non-sharing OpKernel example can be seen in OnehotCrossEntropyOpKernel.

                  -

                  To ease the writing of OpKernel compute, and for reusing code cross-device, Eigen-unsupported Tensor module is used to implement Compute interface. To learn about how the Eigen library is used in PaddlePaddle, please see usage document.

                  -

                  This concludes the forward implementation of an operator. Next its operation and kernel need to be registered in a .cc file.

                  -

                  The definition of its corresponding backward operator, if applicable, is similar to that of an forward operator. Note that a backward operator does not include a ProtoMaker.

                  -
                  -
                  -

                  Registering Operator and OpKernel

                  -
                    -
                  • In .cc files, register forward and backward operator classes and the CPU kernel.

                    -
                    namespace ops = paddle::operators;
                    -REGISTER_OP(mul, ops::MulOp, ops::MulOpMaker, mul_grad, ops::MulOpGrad);
                    -
                    -REGISTER_OP_CPU_KERNEL(mul, ops::MulKernel<paddle::platform::CPUDeviceContext, float>);
                    -REGISTER_OP_CPU_KERNEL(mul_grad,
                    -              ops::MulGradKernel<paddle::platform::CPUDeviceContext, float>);
                    -
                    -
                    -

                    In that code block,

                    -
                      -
                    • REGISTER_OP registers the ops::MulOp class, type named mul, its type ProtoMaker is ops::MulOpMaker, registering ops::MulOpGrad as mul_grad.
                    • -
                    • REGISTER_OP_WITHOUT_GRADIENT registers an operator without gradient.
                    • -
                    • REGISTER_OP_CPU_KERNEL registers ops::MulKernel class and specialized template types paddle::platform::CPUPlace and float, which also registers ops::MulGradKernel.
                    • -
                    -
                  • -
                  -
                    -
                  • Registering CUDA Kernel in .cu files

                    -
                      -
                    • Note that if CUDA Kernel is implemented using the Eigen unsupported module, then on top of .cu, a macro definition #define EIGEN_USE_GPU is needed, such as
                    • -
                    -
                    // if use Eigen unsupported module before include head files
                    -#define EIGEN_USE_GPU
                    -
                    -namespace ops = paddle::operators;
                    -REGISTER_OP_CUDA_KERNEL(mul, ops::MulKernel<paddle::platform::CUDADeviceContext, float>);
                    -REGISTER_OP_CUDA_KERNEL(mul_grad,
                    -                       ops::MulGradKernel<paddle::platform::CUDADeviceContext, float>);
                    -
                    -
                    -
                  • -
                  -
                  -
                  -

                  Compilation

                  -

                  Run the following commands to compile.

                  -
                  # maybe you need to rerun cmake
                  -make mul_op
                  -
                  -
                  -
                  -
                  -
                  -

                  Python Binding

                  -

                  The system will automatically bind to Python and link it to a generated library.

                  -
                  -
                  -

                  Unit Tests

                  -

                  Unit tests for an operator include

                  -
                    -
                  1. comparing a forward operator’s implementations on different devices,
                  2. -
                  3. comparing a backward operator’s implementation on different devices, and
                  4. -
                  5. a scaling test for the backward operator.
                  6. -
                  -

                  Here, we introduce the unit tests for MulOp.

                  -
                  -

                  Testing Forward Operators

                  -

                  A forward operator unit test inherits unittest.TestCase and defines metaclass __metaclass__ = OpTestMeta. More concrete tests are performed in OpTestMeta. Testing a forward operator requires the following:

                  -
                    -
                  1. Defining input, output and relevant attributes in setUp method.
                  2. -
                  3. Generating random input data.
                  4. -
                  5. Implementing the same computation logic in a Python script.
                  6. -
                  7. Call check gradient function to check the backward operator.
                  8. -
                  -
                  import unittest
                  -import numpy as np
                  -from op_test import OpTest
                  -
                  -
                  -class TestMulOp(OpTest):
                  -    def setUp(self):
                  -        self.op_type = "mul"
                  -        self.inputs = {
                  -            'X': np.random.random((32, 84)).astype("float32"),
                  -            'Y': np.random.random((84, 100)).astype("float32")
                  -        }
                  -        self.outputs = {'Out': np.dot(self.inputs['X'], self.inputs['Y'])}
                  -
                  -    def test_check_output(self):
                  -        self.check_output()
                  -        
                  -    def test_check_grad_normal(self):
                  -        self.check_grad(['X', 'Y'], 'Out', max_relative_error=0.5)
                  -
                  -    def test_check_grad_ingore_x(self):
                  -        self.check_grad(
                  -            ['Y'], 'Out', max_relative_error=0.5, no_grad_set=set("X"))
                  -
                  -    def test_check_grad_ingore_y(self):
                  -        self.check_grad(
                  -            ['X'], 'Out', max_relative_error=0.5, no_grad_set=set('Y'))
                  -
                  -
                  -

                  Get its output, and compare it with the forward operator’s own output.

                  -

                  The code above first loads required packages. In addition, we have

                  -
                    -
                  • self.op_type = "mul" defines the type that is identical to what the operator’s registered type.
                  • -
                  • self.inputs defines input, with type numpy.array and initializes it.
                  • -
                  • self.outputs defines output and completes the same operator computation in the Python script, and returns its result from the Python script.
                  • -
                  -
                  -
                  -

                  Testing Backward Operators

                  -

                  Some key points in checking gradient above include:

                  -
                    -
                  • test_normal calls check_grad to validate scaling tests’ correctness and stability through numeric methods.
                      -
                    • The first variable ["X", "Y"] appoints X and Y to be scale tested.
                    • -
                    • The second variable "Out" points to the network’s final output target Out.
                    • -
                    • The third variable max_relative_error points to the maximum relative tolerance error during scaling tests.
                    • -
                    -
                  • -
                  • test_check_grad_ingore_x and test_check_grad_ingore_ybranches test the cases where there is only one scaling input.
                  • -
                  -
                  -
                  -

                  Compiling and Running

                  -

                  Any new unit testing file of the format test_*.py added to the director python/paddle/v2/framework/tests is automatically added to the project to compile.

                  -

                  Note that unlike the compile test for Ops, running unit tests requires compiling the entire project and requires compiling with flag WITH_TESTING on i.e. cmake paddle_dir -DWITH_TESTING=ON.

                  -

                  After successfully compiling the project, run the following command to run unit tests:

                  -
                  make test ARGS="-R test_mul_op -V"
                  -
                  -
                  -

                  Or,

                  -
                  ctest -R test_mul_op
                  -
                  -
                  -
                  -
                  -
                  -

                  Remarks

                  -
                    -
                  • Every *_op.h (if applicable), *_op.cc, and *_op.cu (if applicable) must be created for a unique Op. Compiling will fail if multiple operators are included per file.
                  • -
                  • The type with which an operator is registered needs to be identical to the Op’s name. Registering REGISTER_OP(B, ...) in A_op.cc will cause unit testing failures.
                  • -
                  • If the operator does not implement a CUDA kernel, please refrain from creating an empty *_op.cu file, or else unit tests will fail.
                  • -
                  • If multiple operators rely on some shared methods, a file NOT named *_op.* can be created to store them, such as gather.h.
                  • -
                  -
                  -
                  - - -
                  -
                  -
                  - - -
                  - -
                  -

                  - © Copyright 2016, PaddlePaddle developers. - -

                  -
                  - Built with Sphinx using a theme provided by Read the Docs. - -
                  - -
                  -
                  - -
                  - -
                  - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/dev/new_op_kernel_en.html b/develop/doc/dev/new_op_kernel_en.html deleted file mode 100644 index f2e1d255fe9..00000000000 --- a/develop/doc/dev/new_op_kernel_en.html +++ /dev/null @@ -1,366 +0,0 @@ - - - - - - - - - - - - - Add Kernels for a New Device — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                  - - - - -
                  - - - - - - -
                  -
                  - - - - - - -
                  - -
                  -
                  -
                  -
                  - -
                  -

                  Add Kernels for a New Device

                  -
                  -

                  Background

                  -

                  PaddlePaddle Fluid have hundreds of operators. Each operator could have one or more kernels. A kernel is an implementation of the operator for a certain device, which could be a hardware device, e.g., the CUDA GPU, or a library that utilizes a device, e.g., Intel MKL that makes full use of the Xeon CPU.

                  -

                  This document explains how to add an operator, and its kernels. The kernels of an operator are indexed by a C++ type OpKernelType. An operator chooses the right kernel at runtime. This choosing mechanism is described here.

                  -
                  -
                  -

                  Write Kernels for A New Device

                  -
                  -

                  Add A New Device

                  -

                  For some historical reaons, we misuse the word library for device. For example, we call the deivce type by library type. An example is the header file library_type.h. We will correct this ASAP.

                  -

                  To register a new device, we need to add an enum value to LibraryType:

                  -
                  enum class LibraryType {
                  -  kPlain = 0,
                  -  kMKLDNN = 1,
                  -  kCUDNN = 2,
                  -};
                  -
                  -
                  -
                  -
                  -

                  Add A New Place

                  -

                  If you have a new kind of Device, firstly you need to add a new kind of Place. For example CUDAPlace:

                  -
                  struct CUDAPlace {
                  -  CUDAPlace() : CUDAPlace(0) {}
                  -  explicit CUDAPlace(int d) : device(d) {}
                  -
                  -  inline int GetDeviceId() const { return device; }
                  -  // needed for variant equality comparison
                  -  inline bool operator==(const CUDAPlace &o) const {
                  -    return device == o.device;
                  -  }
                  -  inline bool operator!=(const CUDAPlace &o) const { return !(*this == o); }
                  -
                  -  int device;
                  -};
                  -
                  -typedef boost::variant<CUDAPlace, CPUPlace> Place;
                  -
                  -
                  -
                  -
                  -

                  Add device context

                  -

                  After a new kind of Device is added, you should add a corresponding DeviceContext for it.

                  -
                  class DeviceContext {
                  - public:
                  -  virtual ~DeviceContext() {}
                  -  virtual Place GetPlace() const = 0;
                  -
                  -  virtual void Wait() const {}
                  -};
                  -
                  -
                  -
                  -
                  -

                  Implement new OpKernel for your Device.

                  -

                  A detailed documentation can be found in new_op_and_kernel

                  -
                  class OpKernelBase {
                  - public:
                  -  /**
                  -   * ExecutionContext is the only parameter of Kernel Run function.
                  -   * Run will get input/output variables, state such as momentum and
                  -   * device resource such as CUDA stream, cublas handle, etc. from
                  -   * ExecutionContext. User should construct it before run the Operator.
                  -   */
                  -
                  -  virtual void Compute(const ExecutionContext& context) const = 0;
                  -
                  -  virtual ~OpKernelBase() = default;
                  -};
                  -
                  -template <typename T>
                  -class OpKernel : public OpKernelBase {
                  - public:
                  -  using ELEMENT_TYPE = T;
                  -};
                  -
                  -
                  -
                  -
                  -

                  Register the OpKernel to framework

                  -

                  After writing the components described above, we should register the kernel to the framework.

                  -

                  We use REGISTER_OP_KERNEL to do the registration.

                  -
                  REGISTER_OP_KERNEL(
                  -    op_type,
                  -    library_type,
                  -    place_type,
                  -    kernel0, kernel1, ...)
                  -
                  -
                  -

                  kernel0, kernel1 are kernels that have the same op_type, library_type, place_type but different data_types.

                  -

                  take conv2d as an example:

                  -
                  ```cpp
                  -REGISTER_OP_KERNEL(conv2d, CPU, paddle::platform::CPUPlace,
                  -        paddle::operators::GemmConvKernel<paddle::platform::CPUDeviceContext, float>,
                  -        paddle::operators::GemmConvKernel<paddle::platform::CPUDeviceContext, double>);
                  -
                  -REGISTER_OP_KERNEL(conv2d, CUDNN, ::paddle::platform::CUDAPlace,
                  -       paddle::operators::CUDNNConvOpKernel<float>,
                  -       paddle::operators::CUDNNConvOpKernel<double>);
                  -```
                  -
                  -
                  -

                  In the code above:

                  -
                    -
                  • conv2d is the type/name of the operator
                  • -
                  • CUDNN/CPU is library
                  • -
                  • paddle::platform::CUDAPlace/CPUPlace is place
                  • -
                  • template parameter float/double on CUDNNConvOpKernel<T> is data_type.
                  • -
                  -
                  -
                  -
                  - - -
                  -
                  -
                  - - -
                  - -
                  -

                  - © Copyright 2016, PaddlePaddle developers. - -

                  -
                  - Built with Sphinx using a theme provided by Read the Docs. - -
                  - -
                  -
                  - -
                  - -
                  - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/dev/use_eigen_en.html b/develop/doc/dev/use_eigen_en.html deleted file mode 100644 index d36f5d2c5ad..00000000000 --- a/develop/doc/dev/use_eigen_en.html +++ /dev/null @@ -1,380 +0,0 @@ - - - - - - - - - - - - - How to use Eigen in Paddle — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                  - - - - -
                  - - - - - - -
                  -
                  - - - - - - -
                  - -
                  -
                  -
                  -
                  - -
                  -

                  How to use Eigen in Paddle

                  -

                  Essentially, a neural network is a compute graph. T data needed for the computation is stored in Tensors and its computation procedure is described by Operators. An Operator calls the Compute interface in its corresponding OpKernel and operates on the Tensor.

                  -
                  -

                  Eigen Tensor Module

                  -

                  The Eigen Tensor module supports powerful element-wise computation. In addition, a piece of code written using it can be run on both the CPU and the GPU.

                  -

                  Note that Eigen Tensor is still being actively developed, so its tests are not completely covered and its documentation may be sparse.

                  -

                  For details on Eigen Tensor module, please see doc 1 and doc 2.

                  -
                  -
                  -

                  paddle::framework::Tensor

                  -

                  Paddle Tensor’s is defined in the framework directory with the following interface:

                  -
                  class Tensor {
                  - public:
                  -  /*! Return a pointer to mutable memory block. */
                  -  template <typename T>
                  -  inline T* data();
                  -
                  -  /**
                  -   * @brief   Return a pointer to mutable memory block.
                  -   * @note    If not exist, then allocation.
                  -   */
                  -  template <typename T>
                  -  inline T* mutable_data(platform::Place place);
                  -
                  -  /**
                  -   * @brief     Return a pointer to mutable memory block.
                  -   *
                  -   * @param[in] dims    The dimensions of the memory block.
                  -   * @param[in] place   The place of the memory block.
                  -   *
                  -   * @note      If not exist, then allocation.
                  -   */
                  -  template <typename T>
                  -  inline T* mutable_data(DDim dims, platform::Place place);
                  -
                  -  /*! Resize the dimensions of the memory block. */
                  -  inline Tensor& Resize(const DDim& dims);
                  -
                  -  /*! Return the dimensions of the memory block. */
                  -  inline const DDim& dims() const;
                  -
                  - private:
                  -  /*! holds the memory block if allocated. */
                  -  std::shared_ptr<Placeholder> holder_;
                  -
                  -  /*! points to dimensions of memory block. */
                  -  DDim dim_;
                  -};
                  -
                  -
                  -

                  Placeholder is used to delay memory allocation; that is, we can first define a tensor, using Resize to configure its shape, and then call mutuable_data to allocate the actual memory.

                  -
                  paddle::framework::Tensor t;
                  -paddle::platform::CPUPlace place;
                  -// set size first
                  -t.Resize({2, 3});
                  -// allocate memory on CPU later
                  -t.mutable_data(place);
                  -
                  -
                  -
                  -
                  -

                  paddle::framework::Tensor Usage

                  -

                  AddOp demonstrates Tensor’s usage.

                  -
                    -
                  • InferShape
                  • -
                  -

                  When computing a neural network’s compute graph, first call every Operator‘s InferShape method, and use Resize to configure the size of the output tensor.

                  -
                  void InferShape(const framework::InferShapeContext &ctx) const override {
                  -  PADDLE_ENFORCE_EQ(ctx.Input<Tensor>("X")->dims(),
                  -                    ctx.Input<Tensor>("Y")->dims(),
                  -                    "Two input of Add Op's dimension must be same.");
                  -  ctx.Output<Tensor>("Out")->Resize(ctx.Input<Tensor>("X")->dims());
                  -}
                  -
                  -
                  -
                    -
                  • Run
                  • -
                  -
                  void Compute(const framework::ExecutionContext& context) const override {
                  -  auto* input0 = context.Input<Tensor>("X");
                  -  auto* input1 = context.Input<Tensor>("Y");
                  -  auto* output = context.Output<Tensor>("Out");
                  -
                  -  output->mutable_data<T>(context.GetPlace());
                  -
                  -  auto x = EigenVector<T>::Flatten(*input0);
                  -  auto y = EigenVector<T>::Flatten(*input1);
                  -  auto z = EigenVector<T>::Flatten(*output);
                  -
                  -  auto place = context.GetEigenDevice<Place>();
                  -
                  -  z.device(place) = x + y;
                  -}
                  -
                  -
                  -
                  -
                  -

                  paddle::framework::Tensor到EigenTensor的转换

                  -

                  As shown above, in actual computation, we need to transform the input and output Tensors into formats Eigen supports. We show some functions in eigen.h to implement the transformation from paddle::framework::Tensorto EigenTensor/EigenMatrix/EigenVector/EigenScalar.

                  -

                  Using EigenTensor as an example:

                  -
                  Tensor t;
                  -float* p = t.mutable_data<float>(make_ddim({1, 2, 3}), platform::CPUPlace());
                  -for (int i = 0; i < 1 * 2 * 3; i++) {
                  -  p[i] = static_cast<float>(i);
                  -}
                  -
                  -EigenTensor<float, 3>::Type et = EigenTensor<float, 3>::From(t);
                  -
                  -
                  -

                  From is an interfacing method provided by the EigenTensor template, which implements the transformation from a paddle::framework::Tensor object to an EigenTensor. Since rank is a template parameter, it needs to be explicitly specified at the time of the transformation.

                  -

                  In Eigen, tensors with different ranks are different types, with Vector bring a rank-1 instance. Note that EigenVector<T>::From uses a transformation from an 1-dimensional Paddle tensor to a 1-dimensional Eigen tensor while EigenVector<T>::Flatten reshapes a paddle tensor and flattens it into a 1-dimensional Eigen tensor. Both resulting tensors are still typed EigenVector.

                  -

                  For more transformations, see the unit tests in the eigen_test.cc file.

                  -
                  -
                  -

                  Implementing Computation

                  -

                  While computing, the device interface is needed from the EigenTensors on the left hand side of the assignments. Note that the computation between EigenTensors only changes the data originally inthe Tensor and does not change all the shape information associated with the Tensor.

                  -
                  auto x = EigenVector<T>::Flatten(*input0);
                  -auto y = EigenVector<T>::Flatten(*input1);
                  -auto z = EigenVector<T>::Flatten(*output);
                  -auto place = context.GetEigenDevice<Place>();
                  -z.device(place) = x + y;
                  -
                  -
                  -

                  In this code segment, input0/input1/output can be Tensors of arbitrary dimension. We are calling Flatten from EigenVector, transforming a tensor of any dimension into a 1-dimensional EigenVector. After completing computation, input0/input1/output will retain the same shape information, and they can be resized using the Resize interface.

                  -

                  Because the Eigen Tensor module is under-documented, please refer to OpKernel‘s computation code in TensorFlow’s kernel module documentation.

                  -
                  -
                  - - -
                  -
                  -
                  - - -
                  - -
                  -

                  - © Copyright 2016, PaddlePaddle developers. - -

                  -
                  - Built with Sphinx using a theme provided by Read the Docs. - -
                  - -
                  -
                  - -
                  - -
                  - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/dev/write_docs_en.html b/develop/doc/dev/write_docs_en.html index f5ef67b519f..808f96d6f10 100644 --- a/develop/doc/dev/write_docs_en.html +++ b/develop/doc/dev/write_docs_en.html @@ -37,7 +37,7 @@ - + - - - - - - - - - -
                  - - - - -
                  - - - - - - -
                  -
                  - - - - - - -
                  - -
                  -
                  -
                  -
                  - -
                  -

                  Fluid Distributed Training

                  -
                  -

                  Introduction

                  -

                  In this article, we’ll explain how to configure and run distributed training jobs with PaddlePaddle Fluid in a bare metal cluster.

                  -
                  -
                  -

                  Preparations

                  -
                  -

                  Getting the cluster ready

                  -

                  Prepare the compute nodes in the cluster. Nodes in this cluster can be of any specification that runs PaddlePaddle, and with a unique IP address assigned to it. Make sure they can communicate to each other.

                  -
                  -
                  -

                  Have PaddlePaddle installed

                  -

                  PaddlePaddle must be installed on all nodes. If you have GPU cards on your nodes, be sure to properly install drivers and CUDA libraries.

                  -

                  PaddlePaddle build and installation guide can be found here.

                  -

                  In addition to above, the cmake command should be run with the option WITH_DISTRIBUTE set to on. An example bare minimum cmake command would look as follows:

                  -
                  cmake .. -DWITH_DOC=OFF -DWITH_GPU=OFF -DWITH_DISTRIBUTE=ON -DWITH_SWIG_PY=ON -DWITH_PYTHON=ON
                  -
                  -
                  -
                  -
                  -

                  Update the training script

                  -
                  -

                  Non-cluster training script

                  -

                  Let’s take Deep Learning 101‘s first chapter: “fit a line” as an example.

                  -

                  The non-cluster version of this demo with fluid API is as follows:

                  -
                  import paddle.v2 as paddle
                  -import paddle.fluid as fluid
                  -
                  -x = fluid.layers.data(name='x', shape=[13], dtype='float32')
                  -y_predict = fluid.layers.fc(input=x, size=1, act=None)
                  -y = fluid.layers.data(name='y', shape=[1], dtype='float32')
                  -
                  -cost = fluid.layers.square_error_cost(input=y_predict, label=y)
                  -avg_cost = fluid.layers.mean(x=cost)
                  -
                  -sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.001)
                  -sgd_optimizer.minimize(avg_cost)
                  -
                  -BATCH_SIZE = 20
                  -
                  -train_reader = paddle.batch(
                  -    paddle.reader.shuffle(
                  -        paddle.dataset.uci_housing.train(), buf_size=500),
                  -    batch_size=BATCH_SIZE)
                  -
                  -place = fluid.CPUPlace()
                  -feeder = fluid.DataFeeder(place=place, feed_list=[x, y])
                  -exe = fluid.Executor(place)
                  -
                  -exe.run(fluid.default_startup_program())
                  -
                  -PASS_NUM = 100
                  -for pass_id in range(PASS_NUM):
                  -    fluid.io.save_persistables(exe, "./fit_a_line.model/")
                  -    fluid.io.load_persistables(exe, "./fit_a_line.model/")
                  -    for data in train_reader():
                  -        avg_loss_value, = exe.run(fluid.default_main_program(),
                  -                                  feed=feeder.feed(data),
                  -                                  fetch_list=[avg_cost])
                  -
                  -        if avg_loss_value[0] < 10.0:
                  -            exit(0)  # if avg cost less than 10.0, we think our code is good.
                  -exit(1)
                  -
                  -
                  -

                  We created a simple fully-connected neural network training program and handed it to the fluid executor to run for 100 passes.

                  -

                  Now let’s try to convert it to a distributed version to run on a cluster.

                  -
                  -
                  -

                  Introducing parameter server

                  -

                  As we can see from the non-cluster version of training script, there is only one role in the script: the trainer, that performs the computing as well as holds the parameters. In cluster training, since multi-trainers are working on the same task, they need one centralized place to hold and distribute parameters. This centralized place is called the Parameter Server in PaddlePaddle.

                  -

                  parameter server architecture

                  -

                  Parameter Server in fluid not only holds the parameters but is also assigned with a part of the program. Trainers communicate with parameter servers via send/receive OPs. For more technical details, please refer to this document.

                  -

                  Now we need to create programs for both: trainers and parameter servers, the question is how?

                  -
                  -
                  -

                  Slice the program

                  -

                  Fluid provides a tool called “Distributed Transpiler” that automatically converts the non-cluster program into cluster program.

                  -

                  The idea behind this tool is to find the optimize OPs and gradient parameters, slice the program into 2 pieces and connect them with send/receive OP.

                  -

                  Optimize OPs and gradient parameters can be found from the return values of optimizer’s minimize function.

                  -

                  To put them together:

                  -
                  ... #define the program, cost, and create sgd optimizer
                  -
                  -optimize_ops, params_grads = sgd_optimizer.minimize(avg_cost) #get optimize OPs and gradient parameters
                  -
                  -t = fluid.DistributeTranspiler() # create the transpiler instance
                  -# slice the program into 2 pieces with optimizer_ops and gradient parameters list, as well as pserver_endpoints, which is a comma separated list of [IP:PORT] and number of trainers
                  -t.transpile(optimize_ops, params_grads, pservers=pserver_endpoints, trainers=2)
                  -
                  -... #create executor
                  -
                  -# in pserver, run this
                  -#current_endpoint here means current pserver IP:PORT you wish to run on
                  -pserver_prog = t.get_pserver_program(current_endpoint)
                  -pserver_startup = t.get_startup_program(current_endpoint, pserver_prog)
                  -exe.run(pserver_startup)
                  -exe.run(pserver_prog)
                  -
                  -# in trainer, run this
                  -... # define data reader
                  -exe.run(fluid.default_startup_program())
                  -for pass_id in range(100):
                  -    for data in train_reader():
                  -        exe.run(t.get_trainer_program())
                  -
                  -
                  -
                  -
                  -
                  -
                  -
                  -

                  E2E demo

                  -

                  Please find the complete demo from here. -First cd into the folder that contains the python files. In this case:

                  -
                  cd /paddle/python/paddle/fluid/tests/book_distribute
                  -
                  -
                  -

                  In parameter server node run the following in the command line:

                  -
                  PSERVERS=192.168.1.2:6174 SERVER_ENDPOINT=192.168.1.2:6174 TRAINING_ROLE=PSERVER python notest_dist_fit_a_line.py
                  -
                  -
                  -

                  please note we assume that your parameter server runs at 192.168.1.2:6174

                  -

                  Wait until the prompt Server listening on 192.168.1.2:6174

                  -

                  Then in 2 of your trainer nodes run this:

                  -
                  PSERVERS=192.168.1.2:6174 SERVER_ENDPOINT=192.168.1.2:6174 TRAINING_ROLE=TRAINER python notest_dist_fit_a_line.py
                  -
                  -
                  -

                  the reason you need to run this command twice in 2 nodes is because: in the script we set the trainer count to be 2. You can change this setting on line 50

                  -

                  Now you have 2 trainers and 1 parameter server up and running.

                  -
                  -
                  -
                  - - -
                  -
                  -
                  - - -
                  - -
                  -

                  - © Copyright 2016, PaddlePaddle developers. - -

                  -
                  - Built with Sphinx using a theme provided by Read the Docs. - -
                  - -
                  -
                  - -
                  - -
                  - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/howto/cluster/index_en.html b/develop/doc/howto/cluster/index_en.html index 6fae0775490..689ae77232d 100644 --- a/develop/doc/howto/cluster/index_en.html +++ b/develop/doc/howto/cluster/index_en.html @@ -124,6 +124,12 @@ var _hmt = _hmt || [];
              • +
              • C-API Prediction Library +
              • RNN Models
                • RNN Configuration
                • Recurrent Group Tutorial
                • @@ -137,6 +143,7 @@ var _hmt = _hmt || [];
                • Development
                • FAQ
                    diff --git a/develop/doc/howto/cluster/multi_cluster/fabric_en.html b/develop/doc/howto/cluster/multi_cluster/fabric_en.html index a333bb0df7d..07faa05be66 100644 --- a/develop/doc/howto/cluster/multi_cluster/fabric_en.html +++ b/develop/doc/howto/cluster/multi_cluster/fabric_en.html @@ -124,6 +124,12 @@ var _hmt = _hmt || [];
                • +
                • C-API Prediction Library +
                • RNN Models
                  • RNN Configuration
                  • Recurrent Group Tutorial
                  • @@ -137,6 +143,7 @@ var _hmt = _hmt || [];
                  • Development
                  • FAQ
                      diff --git a/develop/doc/howto/cluster/multi_cluster/index_en.html b/develop/doc/howto/cluster/multi_cluster/index_en.html index e77cc07f6eb..d1fd7ba835c 100644 --- a/develop/doc/howto/cluster/multi_cluster/index_en.html +++ b/develop/doc/howto/cluster/multi_cluster/index_en.html @@ -124,6 +124,12 @@ var _hmt = _hmt || [];
                  • +
                  • C-API Prediction Library +
                  • RNN Models
                    • RNN Configuration
                    • Recurrent Group Tutorial
                    • @@ -137,6 +143,7 @@ var _hmt = _hmt || [];
                    • Development
                    • FAQ
                        diff --git a/develop/doc/howto/cluster/multi_cluster/k8s_aws_en.html b/develop/doc/howto/cluster/multi_cluster/k8s_aws_en.html index e4837cb0107..c5745f919e1 100644 --- a/develop/doc/howto/cluster/multi_cluster/k8s_aws_en.html +++ b/develop/doc/howto/cluster/multi_cluster/k8s_aws_en.html @@ -37,7 +37,7 @@ - + - - - - - - - - - -
                        - - - - -
                        - - - - - - -
                        -
                        - - - - - - -
                        - -
                        -
                        -
                        -
                        - -

                        This tutorial introduces techniques we use to profile and tune the -CPU performance of PaddlePaddle. We will use Python packages -cProfile and yep, and Google’s perftools.

                        -

                        Profiling is the process that reveals performance bottlenecks, -which could be very different from what’s in the developers’ mind. -Performance tuning is done to fix these bottlenecks. Performance optimization -repeats the steps of profiling and tuning alternatively.

                        -

                        PaddlePaddle users program AI applications by calling the Python API, which calls -into libpaddle.so. written in C++. In this tutorial, we focus on -the profiling and tuning of

                        -
                          -
                        1. the Python code and
                        2. -
                        3. the mixture of Python and C++ code.
                        4. -
                        -
                        -

                        Profiling the Python Code

                        -
                        -

                        Generate the Performance Profiling File

                        -

                        We can use Python standard -package, cProfile, -to generate Python profiling file. For example:

                        -
                        python -m cProfile -o profile.out main.py
                        -
                        -
                        -

                        where main.py is the program we are going to profile, -o specifies -the output file. Without -o, cProfile would outputs to standard -output.

                        -
                        -
                        -

                        Look into the Profiling File

                        -

                        cProfile generates profile.out after main.py completes. We can -use cprofilev to look into -the details:

                        -
                        cprofilev -a 0.0.0.0 -p 3214 -f profile.out main.py
                        -
                        -
                        -

                        where -a specifies the HTTP IP, -p specifies the port, -f -specifies the profiling file, and main.py is the source file.

                        -

                        Open the Web browser and points to the local IP and the specifies -port, we will see the output like the following:

                        -
                           ncalls  tottime  percall  cumtime  percall filename:lineno(function)
                        -        1    0.284    0.284   29.514   29.514 main.py:1(<module>)
                        -     4696    0.128    0.000   15.748    0.003 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/executor.py:20(run)
                        -     4696   12.040    0.003   12.040    0.003 {built-in method run}
                        -        1    0.144    0.144    6.534    6.534 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/v2/__init__.py:14(<module>)
                        -
                        -
                        -

                        where each line corresponds to Python function, and the meaning of -each column is as follows:

                        -

                        | column | meaning | -| — | — | -| ncalls | the number of calls into a function | -| tottime | the total execution time of the function, not including the execution time of other functions called by the function | -| percall | tottime divided by ncalls | -| cumtime | the total execution time of the function, including the execution time of other functions being called | -| percall | cumtime divided by ncalls | -| filename:lineno(function) | where the function is defined |

                        -
                        -
                        -

                        Identify Performance Bottlenecks

                        -

                        Usually, tottime and the related percall time is what we want to -focus on. We can sort above profiling file by tottime:

                        -
                             4696   12.040    0.003   12.040    0.003 {built-in method run}
                        -   300005    0.874    0.000    1.681    0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/v2/dataset/mnist.py:38(reader)
                        -   107991    0.676    0.000    1.519    0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:219(__init__)
                        -     4697    0.626    0.000    2.291    0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:428(sync_with_cpp)
                        -        1    0.618    0.618    0.618    0.618 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/__init__.py:1(<module>)
                        -
                        -
                        -

                        We can see that the most time-consuming function is the built-in method run, which is a C++ function in libpaddle.so. We will -explain how to profile C++ code in the next section. At this -moment, let’s look into the third function sync_with_cpp, which is a -Python function. We can click it to understand more about it:

                        -
                        Called By:
                        -
                        -   Ordered by: internal time
                        -   List reduced from 4497 to 2 due to restriction <'sync_with_cpp'>
                        -
                        -Function                                                                                                 was called by...
                        -                                                                                                             ncalls  tottime  cumtime
                        -/home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:428(sync_with_cpp)  <-    4697    0.626    2.291  /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:562(sync_with_cpp)
                        -/home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:562(sync_with_cpp)  <-    4696    0.019    2.316  /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:487(clone)
                        -                                                                                                                  1    0.000    0.001  /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:534(append_backward)
                        -
                        -
                        -Called:
                        -
                        -   Ordered by: internal time
                        -   List reduced from 4497 to 2 due to restriction <'sync_with_cpp'>
                        -
                        -
                        -

                        The lists of the callers of sync_with_cpp might help us understand -how to improve the function definition.

                        -
                        -
                        -
                        -

                        Profiling Python and C++ Code

                        -
                        -

                        Generate the Profiling File

                        -

                        To profile a mixture of Python and C++ code, we can use a Python -package, yep, that can work with Google’s perftools, which is a -commonly-used profiler for C/C++ code.

                        -

                        In Ubuntu systems, we can install yep and perftools by running the -following commands:

                        -
                        apt update
                        -apt install libgoogle-perftools-dev
                        -pip install yep
                        -
                        -
                        -

                        Then we can run the following command

                        -
                        python -m yep -v main.py
                        -
                        -
                        -

                        to generate the profiling file. The default filename is -main.py.prof.

                        -

                        Please be aware of the -v command line option, which prints the -analysis results after generating the profiling file. By examining the -the print result, we’d know that if we stripped debug -information from libpaddle.so at build time. The following hints -help make sure that the analysis results are readable:

                        -
                          -
                        1. Use GCC command line option -g when building libpaddle.so so to -include the debug information. The standard building system of -PaddlePaddle is CMake, so you might want to set -CMAKE_BUILD_TYPE=RelWithDebInfo.
                        2. -
                        3. Use GCC command line option -O2 or -O3 to generate optimized -binary code. It doesn’t make sense to profile libpaddle.so -without optimization, because it would anyway run slowly.
                        4. -
                        5. Profiling the single-threaded binary file before the -multi-threading version, because the latter often generates tangled -profiling analysis result. You might want to set environment -variable OMP_NUM_THREADS=1 to prevents OpenMP from automatically -starting multiple threads.
                        6. -
                        -
                        -
                        -

                        Examining the Profiling File

                        -

                        The tool we used to examine the profiling file generated by -perftools is pprof, which -provides a Web-based GUI like cprofilev.

                        -

                        We can rely on the standard Go toolchain to retrieve the source code -of pprof and build it:

                        -
                        go get github.com/google/pprof
                        -
                        -
                        -

                        Then we can use it to profile main.py.prof generated in the previous -section:

                        -
                        pprof -http=0.0.0.0:3213 `which python`  ./main.py.prof
                        -
                        -
                        -

                        Where -http specifies the IP and port of the HTTP service. -Directing our Web browser to the service, we would see something like -the following:

                        -

                        result

                        -
                        -
                        -

                        Identifying the Performance Bottlenecks

                        -

                        Similar to how we work with cprofilev, we’d focus on tottime and -cumtime.

                        -

                        kernel_perf

                        -

                        We can see that the execution time of multiplication and the computing -of the gradient of multiplication takes 2% to 4% of the total running -time, and MomentumOp takes about 17%. Obviously, we’d want to -optimize MomentumOp.

                        -

                        pprof would mark performance critical parts of the program in -red. It’s a good idea to follow the hints.

                        -
                        -
                        - - -
                        -
                        -
                        - - -
                        - -
                        -

                        - © Copyright 2016, PaddlePaddle developers. - -

                        -
                        - Built with Sphinx using a theme provided by Read the Docs. - -
                        - -
                        -
                        - -
                        - -
                        - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/howto/optimization/gpu_profiling_en.html b/develop/doc/howto/optimization/gpu_profiling_en.html index bbdfceba67c..cb9550bb59d 100644 --- a/develop/doc/howto/optimization/gpu_profiling_en.html +++ b/develop/doc/howto/optimization/gpu_profiling_en.html @@ -124,6 +124,12 @@ var _hmt = _hmt || [];
                    • +
                    • C-API Prediction Library +
                    • RNN Models
                      • RNN Configuration
                      • Recurrent Group Tutorial
                      • @@ -137,6 +143,7 @@ var _hmt = _hmt || [];
                      • Development
                      • FAQ
                      • +
                      • C-API Prediction Library +
                      • RNN Models
                        • RNN Configuration
                        • Recurrent Group Tutorial
                        • @@ -137,6 +143,7 @@ var _hmt = _hmt || [];
                        • Development
                        • FAQ
                            diff --git a/develop/doc/howto/rnn/hrnn_rnn_api_compare_en.html b/develop/doc/howto/rnn/hrnn_rnn_api_compare_en.html index 2cccff840a9..b31ecbbaa71 100644 --- a/develop/doc/howto/rnn/hrnn_rnn_api_compare_en.html +++ b/develop/doc/howto/rnn/hrnn_rnn_api_compare_en.html @@ -124,6 +124,12 @@ var _hmt = _hmt || [];
                        • +
                        • C-API Prediction Library +
                        • RNN Models
                          • RNN Configuration
                          • Recurrent Group Tutorial
                          • @@ -137,6 +143,7 @@ var _hmt = _hmt || [];
                          • Development
                          • FAQ
                              diff --git a/develop/doc/howto/rnn/index_en.html b/develop/doc/howto/rnn/index_en.html index 813bacef64a..2bc3dda8df7 100644 --- a/develop/doc/howto/rnn/index_en.html +++ b/develop/doc/howto/rnn/index_en.html @@ -38,7 +38,7 @@ - + - - - - - - - - - -
                              - - - - -
                              - - - - - - -
                              -
                              - - - - - - -
                              - -
                              -
                              -
                              -
                              - -
                              -

                              Build PaddlePaddle for Android

                              -

                              There are two approaches to build PaddlePaddle for Android:

                              - -
                              -

                              Cross-Compiling Using Docker

                              -

                              Docker-based cross-compiling is the recommended approach because Docker runs on all major operating systems, including Linux, Mac OS X, and Windows.

                              -
                              -

                              Build the Docker Image

                              -

                              The following steps pack all the tools that we need to build PaddlePaddle into a Docker image.

                              -
                              $ git clone https://github.com/PaddlePaddle/Paddle.git
                              -$ cd Paddle
                              -$ docker build -t paddle:dev-android . -f Dockerfile.android
                              -
                              -
                              -

                              Users can directly use the published Docker image.

                              -
                              $ docker pull paddlepaddle/paddle:latest-dev-android
                              -
                              -
                              -

                              For users in China, we provide a faster mirror.

                              -
                              $ docker pull docker.paddlepaddlehub.com/paddle:latest-dev-android
                              -
                              -
                              -
                              -
                              -

                              Build the Inference Library

                              -

                              We can run the Docker image we just created to build the inference library of PaddlePaddle for Android using the command below:

                              -
                              $ docker run -it --rm -v $PWD:/paddle -e "ANDROID_ABI=armeabi-v7a" -e "ANDROID_API=21" paddle:dev-android
                              -
                              -
                              -

                              The Docker image accepts two arguments ANDROID_ABI and ANDROID_API:

                              - -- - - - - - - - - - - - - - - - - - - - - - - -
                              ArgumentOptional ValuesDefault
                              ANDROID_ABIarmeabi-v7a, arm64-v8aarmeabi-v7a
                              ANDROID_API>= 1621

                              The ARM-64 architecture (arm64-v8a) requires at least level 21 of Android API.

                              -

                              The default entry-point of the Docker image, paddle/scripts/docker/build_android.sh generates the Android cross-compiling standalone toolchain based on the argument: ANDROID_ABI or ANDROID_API. For information about other configuration arguments, please continue reading.

                              -

                              The above command generates and outputs the inference library in $PWD/install_android and puts third-party libraries in $PWD/install_android/third_party.

                              -
                              -
                              -
                              -

                              Cross-Compiling on Linux

                              -

                              The Linux-base approach to cross-compile is to run steps in Dockerfile.android manually on a Linux x64 computer.

                              -
                              -

                              Setup the Environment

                              -

                              To build for Android’s, we need Android NDK:

                              -
                              wget -q https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip
                              -unzip -q android-ndk-r14b-linux-x86_64.zip
                              -
                              -
                              -

                              Android NDK includes everything we need to build the standalone toolchain, which in then used to build PaddlePaddle for Android. (We plan to remove the intermediate stage of building the standalone toolchain in the near future.)

                              -
                                -
                              • To build the standalone toolchain for armeabi-v7a and Android API level 21:
                              • -
                              -
                              your/path/to/android-ndk-r14b-linux-x86_64/build/tools/make-standalone-toolchain.sh \
                              -        --arch=arm --platform=android-21 --install-dir=your/path/to/arm_standalone_toolchain
                              -
                              -
                              -

                              The generated standalone toolchain will be in your/path/to/arm_standalone_toolchain.

                              -
                                -
                              • To build the standalone toolchain for arm64-v8a and Android API level 21:
                              • -
                              -
                              your/path/to/android-ndk-r14b-linux-x86_64/build/tools/make-standalone-toolchain.sh \
                              -        --arch=arm64 --platform=android-21 --install-dir=your/path/to/arm64_standalone_toolchain
                              -
                              -
                              -

                              The generated standalone toolchain will be in your/path/to/arm64_standalone_toolchain.

                              -
                              -
                              -

                              Cross-Compiling Arguments

                              -

                              CMake supports choosing the toolchain. PaddlePaddle provides android.cmake, which configures the Android cross-compiling toolchain for CMake. android.cmake is not required for CMake >= 3.7, which support Android cross-compiling. PaddlePaddle detects the CMake version, for those newer than 3.7, it uses the official version.

                              -

                              Some other CMake arguments you need to know:

                              -
                                -
                              • CMAKE_SYSTEM_NAME must be Android. This tells PaddlePaddle’s CMake system to cross-compile third-party dependencies. This also changes some other CMake arguments like WITH_GPU=OFF, WITH_AVX=OFF, WITH_PYTHON=OFF, WITH_RDMA=OFF, WITH_MKL=OFF and WITH_GOLANG=OFF.
                              • -
                              • WITH_C_API must be ON, to build the C-based inference library for Android.
                              • -
                              • WITH_SWIG_PY must be OFF because the Android platform doesn’t support SWIG-based API.
                              • -
                              -

                              Some Android-specific arguments:

                              -
                                -
                              • ANDROID_STANDALONE_TOOLCHAIN: the absolute path of the Android standalone toolchain, or the path relative to the CMake build directory. PaddlePaddle’s CMake extensions would derive the cross-compiler, sysroot and Android API level from this argument.
                              • -
                              • ANDROID_TOOLCHAIN: could be gcc or clang. The default value is clang.
                                  -
                                • For CMake >= 3.7, it should anyway be clang. For older versions, it could be gcc.
                                • -
                                • Android’s official clang requires glibc >= 2.15.
                                • -
                                -
                              • -
                              • ANDROID_ABI: could be armeabi-v7a or arm64-v8a. The default value is armeabi-v7a.
                              • -
                              • ANDROID_NATIVE_API_LEVEL: could be derived from the value of ANDROID_STANDALONE_TOOLCHAIN.
                              • -
                              • ANROID_ARM_MODE:
                                  -
                                • could be ON or OFF, and defaults to ON, when ANDROID_ABI=armeabi-v7a;
                                • -
                                • no need to specify when ANDROID_ABI=arm64-v8a.
                                • -
                                -
                              • -
                              • ANDROID_ARM_NEON: indicates if to use NEON instructions.
                                  -
                                • could be ON or OFF, and defaults to ON, when ANDROID_ABI=armeabi-v7a;
                                • -
                                • no need to specify when ANDROID_ABI=arm64-v8a.
                                • -
                                -
                              • -
                              -

                              Other useful arguments:

                              -
                                -
                              • USE_EIGEN_FOR_BLAS: indicates if using Eigen. Could be ON or OFF, defaults to OFF.
                              • -
                              • HOST_C/CXX_COMPILER: specifies the host compiler, which is used to build the host-specific protoc and target-specific OpenBLAS. It defaults to the value of the environment variable CC/C++, or cc/c++.
                              • -
                              -

                              Some frequent configurations for your reference:

                              -
                              cmake -DCMAKE_SYSTEM_NAME=Android \
                              -      -DANDROID_STANDALONE_TOOLCHAIN=your/path/to/arm_standalone_toolchain \
                              -      -DANDROID_ABI=armeabi-v7a \
                              -      -DANDROID_ARM_NEON=ON \
                              -      -DANDROID_ARM_MODE=ON \
                              -      -DUSE_EIGEN_FOR_BLAS=ON \
                              -      -DCMAKE_INSTALL_PREFIX=your/path/to/install \
                              -      -DWITH_C_API=ON \
                              -      -DWITH_SWIG_PY=OFF \
                              -      ..
                              -
                              -
                              -
                              cmake -DCMAKE_SYSTEM_NAME=Android \
                              -      -DANDROID_STANDALONE_TOOLCHAIN=your/path/to/arm64_standalone_toolchain \
                              -      -DANDROID_ABI=arm64-v8a \
                              -      -DUSE_EIGEN_FOR_BLAS=OFF \
                              -      -DCMAKE_INSTALL_PREFIX=your/path/to/install \
                              -      -DWITH_C_API=ON \
                              -      -DWITH_SWIG_PY=OFF \
                              -      ..
                              -
                              -
                              -

                              There are some other arguments you might want to configure.

                              -
                                -
                              • CMAKE_BUILD_TYPE=MinSizeRel minimizes the size of library.
                              • -
                              • CMAKE_BUILD_TYPE-Release optimizes the runtime performance.
                              • -
                              -

                              Our own tip for performance optimization to use clang and Eigen or OpenBLAS:

                              -
                                -
                              • CMAKE_BUILD_TYPE=Release
                              • -
                              • ANDROID_TOOLCHAIN=clang
                              • -
                              • USE_EIGEN_BLAS=ON for armeabi-v7a, or USE_EIGEN_FOR_BLAS=OFF for arm64-v8a.
                              • -
                              -
                              -
                              -

                              Build and Install

                              -

                              After running cmake, we can run make; make install to build and install.

                              -

                              Before building, you might want to remove the third_party and build directories including pre-built libraries for other architectures.

                              -

                              After building,in the directory CMAKE_INSTALL_PREFIX, you will find three sub-directories:

                              -
                                -
                              • include: the header file of the inference library,
                              • -
                              • lib: the inference library built for various Android ABIs,
                              • -
                              • third_party: dependent third-party libraries built for Android.
                              • -
                              -
                              -
                              -
                              - - -
                              -
                              -
                              - - -
                              - -
                              -

                              - © Copyright 2016, PaddlePaddle developers. - -

                              -
                              - Built with Sphinx using a theme provided by Read the Docs. - -
                              - -
                              -
                              - -
                              - -
                              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/mobile/cross_compiling_for_ios_en.html b/develop/doc/mobile/cross_compiling_for_ios_en.html deleted file mode 100644 index 681e9d9784b..00000000000 --- a/develop/doc/mobile/cross_compiling_for_ios_en.html +++ /dev/null @@ -1,369 +0,0 @@ - - - - - - - - - - - - - Build PaddlePaddle for iOS — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                              - - - - -
                              - - - - - - -
                              -
                              - - - - - - -
                              - -
                              -
                              -
                              -
                              - -
                              -

                              Build PaddlePaddle for iOS

                              -

                              This tutorial will walk you through cross compiling the PaddlePaddle library for iOS from the source in MacOS.

                              -
                              -

                              Preparation

                              -

                              Apple provides Xcode for cross-compiling and IDE for iOS development. Download from App store or here. To verify your installation, run command as follows

                              -
                              $ xcodebuild -version
                              -Xcode 9.0
                              -Build version 9A235
                              -
                              -
                              -
                              -
                              -

                              Cross-compiling configurations

                              -

                              PaddlePaddle provides cross-compiling toolchain configuration documentation cmake/cross_compiling/ios.cmake, which has some default settings for frequently used compilers.

                              -

                              There are some mandatory environment variables need to be set before cross compiling PaddlePaddle for iOS:

                              -
                                -
                              • CMAKE_SYSTEM_NAME, CMake compiling target platform name, has to be iOS. PaddlePaddle CMake will compile all the third party dependencies and enforce some parameters (WITH_C_API=ON, WITH_GPU=OFF, WITH_AVX=OFF, WITH_PYTHON=OFF,WITH_RDMA=OFF) when this variable is set with value iOS.
                              • -
                              • WITH_C_API, Whether to compile inference C-API library, has to be ON, since C-API is the only supported interface for inferencing in iOS.
                              • -
                              • WITH_SWIG_PY, has to be OFF. It’s not supported to inference or train via swig in iOS.
                              • -
                              -

                              Optional environment variables for iOS are:

                              -
                                -
                              • IOS_PLATFORM, either OS (default) or SIMULATOR.

                                -
                                  -
                                • OS, build targets ARM-based physical devices like iPhone or iPad.
                                • -
                                • SIMULATOR, build targets x86 architecture simulators.
                                • -
                                -
                              • -
                              • IOS_ARCH, target architecture. By default, all architecture types will be compiled. If you need to specify the architecture to compile for, please find valid values for different IOS_PLATFORM settings from the table below:

                                - - - - - - - - - - - - - - - - - - - - - -
                                IOS_PLATFORMIOS_ARCH
                                OSarmv7, armv7s, arm64
                                SIMULATORi386, x86_64
                              • -
                              • IOS_DEPLOYMENT_TARGET, minimum iOS version to deployment, 7.0 by default.

                                -
                              • -
                              • IOS_ENABLE_BITCODE, whether to enable Bitcode, values can be ON/OFF, ON by default.

                                -
                              • -
                              • IOS_USE_VECLIB_FOR_BLAS, whether to use vecLib framework for BLAS computing. values can be ON/OFF, OFF by default.

                                -
                              • -
                              • IOS_DEVELOPMENT_ROOT, the path to Developer directory, can be explicitly set with your /path/to/platform/Developer. If left blank, PaddlePaddle will automatically pick the Xcode corresponding platform‘s Developer directory based on your IOS_PLATFORM value.

                                -
                              • -
                              • IOS_SDK_ROOT, the path to SDK root, can be explicitly set with your /path/to/platform/Developer/SDKs/SDK. if left black, PaddlePaddle will pick the latest SDK in the directory of IOS_DEVELOPMENT_ROOT.

                                -
                              • -
                              -

                              other settings:

                              -
                                -
                              • USE_EIGEN_FOR_BLAS, whether to use Eigen for matrix computing. effective when IOS_USE_VECLIB_FOR_BLAS=OFF. Values can be ON/OFF, OFF by default.
                              • -
                              • HOST_C/CXX_COMPILER, host C/C++ compiler. Uses value from environment variable CC/CXX by default or cc/c++ if CC/CXX doesn’t exist.
                              • -
                              -

                              some typical cmake configurations:

                              -
                              cmake -DCMAKE_SYSTEM_NAME=iOS \
                              -      -DIOS_PLATFORM=OS \
                              -      -DIOS_ARCH="armv7;arm64" \
                              -      -DIOS_ENABLE_BITCODE=ON \
                              -      -DIOS_USE_VECLIB_FOR_BLAS=ON \
                              -      -DCMAKE_INSTALL_PREFIX=your/path/to/install \
                              -      -DWITH_C_API=ON \
                              -      -DWITH_TESTING=OFF \
                              -      -DWITH_SWIG_PY=OFF \
                              -      ..
                              -
                              -
                              -
                              cmake -DCMAKE_SYSTEM_NAME=iOS \
                              -      -DIOS_PLATFORM=SIMULATOR \
                              -      -DIOS_ARCH="x86_64" \
                              -      -DIOS_USE_VECLIB_FOR_BLAS=ON \
                              -      -DCMAKE_INSTALL_PREFIX=your/path/to/install \
                              -      -DWITH_C_API=ON \
                              -      -DWITH_TESTING=OFF \
                              -      -DWITH_SWIG_PY=OFF \
                              -      ..
                              -
                              -
                              -

                              You can set other compiling parameters for your own need. I.E. if you are trying to minimize the library size, set CMAKE_BUILD_TYPE with MinSizeRel; or if the performance is your concern, set CMAKE_BUILD_TYPE with Release. You can even manipulate the PaddlePaddle compiling procedure by manually set CMAKE_C/CXX_FLAGS values.

                              -

                              TIPS for a better performance:

                              -
                                -
                              • set CMAKE_BUILD_TYPE with Release
                              • -
                              • set IOS_USE_VECLIB_FOR_BLAS with ON
                              • -
                              -
                              -
                              -

                              Build and install

                              -

                              After CMake, run following commands, PaddlePaddle will download the compile 3rd party dependencies, compile and install PaddlePaddle inference library.

                              -
                              $ make
                              -$ make install
                              -
                              -
                              -

                              Please Note: if you compiled PaddlePaddle in the source directory for other platforms, do remove third_party and build directory within the source with rm -rf to ensure that all the 3rd party libraries dependencies and PaddlePaddle is newly compiled with current CMake configuration.

                              -

                              your/path/to/install directory will have following directories after make install:

                              -
                                -
                              • include, contains all the C-API header files.
                              • -
                              • lib, contains PaddlePaddle C-API static library.
                              • -
                              • third_party contains all the 3rd party libraries.
                              • -
                              -

                              Please note: if PaddlePaddle library need to support both physical devices and simulators, you will need to compile correspondingly, then merge fat library with lipo.

                              -

                              Now you will have PaddlePaddle library compiled and installed, the fat library can be used in deep learning related iOS APPs. Please refer to C-API documentation for usage guides.

                              -
                              -
                              - - -
                              -
                              -
                              - - -
                              - -
                              -

                              - © Copyright 2016, PaddlePaddle developers. - -

                              -
                              - Built with Sphinx using a theme provided by Read the Docs. - -
                              - -
                              -
                              - -
                              - -
                              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/mobile/cross_compiling_for_raspberry_en.html b/develop/doc/mobile/cross_compiling_for_raspberry_en.html deleted file mode 100644 index 1caf888d4ef..00000000000 --- a/develop/doc/mobile/cross_compiling_for_raspberry_en.html +++ /dev/null @@ -1,303 +0,0 @@ - - - - - - - - - - - - - Build PaddlePaddle for Raspberry Pi — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                              - - - - -
                              - - - - - - -
                              -
                              - - - - - - -
                              - -
                              -
                              -
                              -
                              - -
                              -

                              Build PaddlePaddle for Raspberry Pi

                              -

                              You may use any of the following two approaches to build the inference library of PaddlePaddle for Raspberry Pi:

                              -
                                -
                              1. Build using SSH: Log in to a Raspberry Pi using SSH and build the library. The required development tools and third-party dependencies are listed in here: /Dockerfile.
                              2. -
                              3. Cross-compile: We talk about how to cross-compile PaddlePaddle for Raspberry Pi on a Linux/x64 machine, in more detail in this article.
                              4. -
                              -
                              -

                              The Cross-Compiling Toolchain

                              -

                              Step 1. Clone the Github repo by running the following command.

                              -
                              git clone https://github.com/raspberrypi/tools.git
                              -
                              -
                              -

                              Step 2. Use the pre-built cross-compiler found in ./tools/tree/master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64. To run it on a Linux computer, glibc version >= 2.14 is needed.

                              -
                              -
                              -

                              CMake Arguments

                              -

                              CMake supports cross-compiling. All CMake configuration arguments required for the cross-compilation for Raspberry Pi can be found in cmake/cross_compiling/raspberry_pi.cmake.

                              -

                              Some important arguments that need to be set:

                              -
                                -
                              • CMAKE_SYSTEM_NAME: The target platform. Must be RPi.
                              • -
                              • RPI_TOOLCHAIN: The absolute path of the cross-compiling toolchain.
                              • -
                              • RPI_ARM_NEON: Use ARM NEON Intrinsics. This is a required argument and set default to ON.
                              • -
                              • HOST_C/CXX_COMPILER: The C/C++ compiler for the host. It is used to build building tools running on the host, for example, protoc.
                              • -
                              -

                              A commonly-used CMake configuration is as follows:

                              -
                              cmake -DCMAKE_SYSTEM_NAME=RPi \
                              -      -DRPI_TOOLCHAIN=your/path/to/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64 \
                              -      -DRPI_ARM_NEON=ON \
                              -      -DCMAKE_INSTALL_PREFIX=your/path/to/install \
                              -      -DWITH_GPU=OFF \
                              -      -DWITH_C_API=ON \
                              -      -DWITH_PYTHON=OFF \
                              -      -DWITH_SWIG_PY=OFF \
                              -      ..
                              -
                              -
                              -

                              To build the inference library, please set the argument WITH_C_API to ON: WITH_C_API=ON.

                              -

                              You can add more arguments. For example, to minimize the size of the generated inference library, you may use CMAKE_BUILD_TYPE=MinSizeRel. For performance optimization, you may use CMAKE_BUILD_TYPE=Release.

                              -
                              -
                              -

                              Build and Install

                              -

                              The following commands build the inference library of PaddlePaddle for Raspberry Pi and third-party dependencies.

                              -
                              make
                              -make install
                              -
                              -
                              -

                              The intermediate files will be stored in build. Third-party libraries will be located in build/third_party. If you have already built it for other platforms like Android or iOS, you may want to clear these directories by running the command: rm -rf build.

                              -

                              The infernece library will be in your/path/to/install/lib, with related header files in your/path/to/install/include.

                              -
                              -
                              - - -
                              -
                              -
                              - - -
                              - -
                              -

                              - © Copyright 2016, PaddlePaddle developers. - -

                              -
                              - Built with Sphinx using a theme provided by Read the Docs. - -
                              - -
                              -
                              - -
                              - -
                              - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc/objects.inv b/develop/doc/objects.inv index 0cf27ce29007a722b96735af9993999d6e9b1707..5d9d5336ec8a1178679138405df28be79e127d0b 100644 GIT binary patch delta 1410 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 bv_goqai-F*-K=Xh6arK*5Ig?|e&C4}nTcE( diff --git a/develop/doc/search.html b/develop/doc/search.html index 035c88f22e4..06b2c6b33db 100644 --- a/develop/doc/search.html +++ b/develop/doc/search.html @@ -121,6 +121,12 @@ var _hmt = _hmt || [];
                          • +
                          • C-API Prediction Library +
                          • RNN Models
                            • RNN Configuration
                            • Recurrent Group Tutorial
                            • @@ -134,6 +140,7 @@ var _hmt = _hmt || [];
                            • Development
                            • FAQ
                                diff --git a/develop/doc/searchindex.js b/develop/doc/searchindex.js index 090b33e0170..679fd3ca98f 100644 --- a/develop/doc/searchindex.js +++ b/develop/doc/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["build_and_install/build_from_source_en","build_and_install/docker_install_en","build_and_install/index_en","build_and_install/pip_install_en","design/api","design/auto_gradient_check","design/backward","design/block","design/build_system/README","design/cluster_train/README","design/cluster_train/checkpointing","design/cluster_train/data_dispatch","design/cluster_train/large_model_dist_train","design/cluster_train/master_server","design/cluster_train/pserver_client","design/cluster_train/remote_parameter_updater","design/cluster_train/save_model","design/cluster_train/submit-job","design/concurrent_programming","design/cpp_data_feeding","design/csp","design/dist_refactor/distributed_architecture","design/dist_refactor/multi_cpu","design/dist_refactor/parameter_server","design/error_clip","design/evaluator","design/executor","design/file_manager/README","design/file_manager/pfs/pfsclient","design/float16","design/fluid","design/fluid_compiler","design/functions_operators_layers","design/gan_api","design/graph","design/graph_survey","design/if_else_op","design/infer_var_type","design/kernel_hint_design","design/kernel_selection","design/memory_optimization","design/mkl/mkl_packed","design/mkl/mkldnn","design/mkl/mkldnn_fluid","design/model_format","design/multi_language_interface/00.why_plain_c","design/multi_language_interface/01.inference_implementation","design/operator_kernel_type","design/ops/rnn","design/ops/sequence_decoder","design/optimizer","design/paddle_nccl","design/parallel_do","design/parameter_average","design/parameters_in_cpp","design/profiler","design/program","design/prune","design/python_api","design/reader/README","design/refactorization","design/register_grad_op","design/regularization","design/releasing_process","design/scope","design/selected_rows","design/simple_op_design","design/speech/deep_speech_2","design/support_new_device","design/switch","design/tensor_array","design/var_desc","dev/contribute_to_paddle_en","dev/index_en","dev/new_layer_en","dev/new_op_en","dev/new_op_kernel_en","dev/use_eigen_en","dev/write_docs_en","faq/build_and_install/index_en","faq/cluster/index_en","faq/index_en","faq/local/index_en","faq/model/index_en","faq/parameter/index_en","getstarted/concepts/use_concepts_en","getstarted/index_en","getstarted/quickstart_en","howto/capi/compile_paddle_lib_en","howto/capi/index_en","howto/capi/organization_of_the_inputs_en","howto/capi/workflow_of_capi_en","howto/cluster/cmd_argument_en","howto/cluster/fluid_cluster_train_en","howto/cluster/index_en","howto/cluster/multi_cluster/fabric_en","howto/cluster/multi_cluster/index_en","howto/cluster/multi_cluster/k8s_aws_en","howto/cluster/multi_cluster/k8s_distributed_en","howto/cluster/multi_cluster/k8s_en","howto/cluster/multi_cluster/openmpi_en","howto/cluster/multi_cluster/src/k8s_data/README","howto/cluster/multi_cluster/src/k8s_train/README","howto/cluster/preparations_en","howto/cmd_parameter/arguments_en","howto/cmd_parameter/detail_introduction_en","howto/cmd_parameter/index_en","howto/cmd_parameter/use_case_en","howto/index_en","howto/optimization/cpu_profiling_en","howto/optimization/gpu_profiling_en","howto/read_source","howto/rnn/hierarchical_layer_en","howto/rnn/hrnn_rnn_api_compare_en","howto/rnn/index_en","howto/rnn/recurrent_group_en","howto/rnn/rnn_config_en","index_en","mobile/cross_compiling_for_android_en","mobile/cross_compiling_for_ios_en","mobile/cross_compiling_for_raspberry_en","survey/cluster_bootstrapping_tools"],envversion:50,filenames:["build_and_install/build_from_source_en.rst","build_and_install/docker_install_en.rst","build_and_install/index_en.rst","build_and_install/pip_install_en.rst","design/api.md","design/auto_gradient_check.md","design/backward.md","design/block.md","design/build_system/README.md","design/cluster_train/README.md","design/cluster_train/checkpointing.md","design/cluster_train/data_dispatch.md","design/cluster_train/large_model_dist_train.md","design/cluster_train/master_server.md","design/cluster_train/pserver_client.md","design/cluster_train/remote_parameter_updater.md","design/cluster_train/save_model.md","design/cluster_train/submit-job.md","design/concurrent_programming.md","design/cpp_data_feeding.md","design/csp.md","design/dist_refactor/distributed_architecture.md","design/dist_refactor/multi_cpu.md","design/dist_refactor/parameter_server.md","design/error_clip.md","design/evaluator.md","design/executor.md","design/file_manager/README.md","design/file_manager/pfs/pfsclient.md","design/float16.md","design/fluid.md","design/fluid_compiler.md","design/functions_operators_layers.md","design/gan_api.md","design/graph.md","design/graph_survey.md","design/if_else_op.md","design/infer_var_type.md","design/kernel_hint_design.md","design/kernel_selection.md","design/memory_optimization.md","design/mkl/mkl_packed.md","design/mkl/mkldnn.md","design/mkl/mkldnn_fluid.md","design/model_format.md","design/multi_language_interface/00.why_plain_c.md","design/multi_language_interface/01.inference_implementation.md","design/operator_kernel_type.md","design/ops/rnn.md","design/ops/sequence_decoder.md","design/optimizer.md","design/paddle_nccl.md","design/parallel_do.md","design/parameter_average.md","design/parameters_in_cpp.md","design/profiler.md","design/program.md","design/prune.md","design/python_api.md","design/reader/README.md","design/refactorization.md","design/register_grad_op.md","design/regularization.md","design/releasing_process.md","design/scope.md","design/selected_rows.md","design/simple_op_design.md","design/speech/deep_speech_2.md","design/support_new_device.md","design/switch.md","design/tensor_array.md","design/var_desc.md","dev/contribute_to_paddle_en.md","dev/index_en.rst","dev/new_layer_en.rst","dev/new_op_en.md","dev/new_op_kernel_en.md","dev/use_eigen_en.md","dev/write_docs_en.rst","faq/build_and_install/index_en.rst","faq/cluster/index_en.rst","faq/index_en.rst","faq/local/index_en.rst","faq/model/index_en.rst","faq/parameter/index_en.rst","getstarted/concepts/use_concepts_en.rst","getstarted/index_en.rst","getstarted/quickstart_en.rst","howto/capi/compile_paddle_lib_en.md","howto/capi/index_en.rst","howto/capi/organization_of_the_inputs_en.md","howto/capi/workflow_of_capi_en.md","howto/cluster/cmd_argument_en.md","howto/cluster/fluid_cluster_train_en.md","howto/cluster/index_en.rst","howto/cluster/multi_cluster/fabric_en.md","howto/cluster/multi_cluster/index_en.rst","howto/cluster/multi_cluster/k8s_aws_en.md","howto/cluster/multi_cluster/k8s_distributed_en.md","howto/cluster/multi_cluster/k8s_en.md","howto/cluster/multi_cluster/openmpi_en.md","howto/cluster/multi_cluster/src/k8s_data/README.md","howto/cluster/multi_cluster/src/k8s_train/README.md","howto/cluster/preparations_en.md","howto/cmd_parameter/arguments_en.md","howto/cmd_parameter/detail_introduction_en.md","howto/cmd_parameter/index_en.rst","howto/cmd_parameter/use_case_en.md","howto/index_en.rst","howto/optimization/cpu_profiling_en.md","howto/optimization/gpu_profiling_en.rst","howto/read_source.md","howto/rnn/hierarchical_layer_en.rst","howto/rnn/hrnn_rnn_api_compare_en.rst","howto/rnn/index_en.rst","howto/rnn/recurrent_group_en.md","howto/rnn/rnn_config_en.rst","index_en.rst","mobile/cross_compiling_for_android_en.md","mobile/cross_compiling_for_ios_en.md","mobile/cross_compiling_for_raspberry_en.md","survey/cluster_bootstrapping_tools.md"],objects:{},objnames:{},objtypes:{},terms:{"00m":110,"03m":110,"0424m":110,"055ee37d":97,"0630u":110,"06u":110,"0810u":110,"0957m":110,"0_cudnn5":0,"0_cudnn5_avx_mkl":[1,3],"0_cudnn7_avx_mkl":3,"0rc":103,"0rc1":63,"0rc2":63,"0x10f256d50":35,"0x7ffe4de00110":35,"100gb":110,"100gi":97,"10g":17,"10m":110,"1150u":110,"11\u5b9e\u73b0\u4e86c":46,"11e6":99,"124n":110,"12gb":40,"13m":99,"1490u":110,"1550u":110,"16u":110,"173n":110,"1770u":110,"18ad":97,"18e457ce3d362ff5f3febf8e7f85ffec852f70f3b629add10aed84f930a68750":99,"197u":110,"1gb":110,"210u":110,"215n":110,"228u":110,"2520u":110,"2680u":110,"279n":110,"27m":110,"285m":110,"2863m":110,"28m":110,"2977m":110,"2cbf7385":97,"302n":110,"30u":110,"328n":110,"32u":110,"331n":110,"3320u":110,"365e":97,"36u":110,"3710m":110,"3768m":110,"387u":110,"38u":110,"3920u":110,"39u":110,"3rd":119,"4035m":110,"4090u":110,"4096mb":105,"4279m":110,"43u":110,"448a5b355b84":99,"4560u":110,"4563m":110,"45u":110,"4650u":110,"4726m":110,"473m":99,"4gb":105,"50bd":97,"50gi":97,"514u":110,"525n":110,"526u":110,"536u":110,"5460u":110,"5470u":110,"54u":110,"5690m":110,"573u":110,"578n":110,"5798m":110,"586u":110,"58s":99,"5969m":110,"5_cudnn5_avx_mkl":3,"5_cudnn5_avx_openbla":[3,87],"6080u":110,"6140u":110,"6305m":110,"639u":110,"64m":44,"655u":110,"6780u":110,"6810u":110,"682u":110,"6970u":110,"6ce9":97,"704u":110,"7090u":110,"72u":110,"73u":110,"75u":110,"760u":110,"767u":110,"783n":110,"784u":110,"78m":110,"7kb":99,"8250u":110,"8300u":110,"830n":110,"849m":110,"861u":110,"8661m":110,"892m":110,"901n":110,"90u":110,"918u":110,"9247m":110,"924n":110,"9261m":110,"9330m":110,"94u":110,"9530m":110,"983m":110,"988u":110,"997u":110,"99u":110,"9a235":119,"9f18":99,"\u4e00\u4e2a\u5178\u578b\u7684chunk\u5982\u4e0b\u6240\u793a":27,"\u4e00\u4e2a\u795e\u7ecf\u7f51\u7edc\u7684\u6a21\u578b\u7531\u5927\u91cf\u7684\u53c2\u6570\u7ec4\u6210":10,"\u4e00\u4e2achunk\u7531\u6240\u5728\u7684\u6587\u4ef6\u504f\u79fb":27,"\u4e00\u4e2aposix\u517c\u5bb9\u7684\u6587\u4ef6\u7cfb\u7edf":27,"\u4e00\u822c\u4e0d\u5141\u8bb8\u518d\u4ece":63,"\u4e00\u822c\u7531mkl":42,"\u4e0a\u4f20\u5230cloud\u6216\u8005\u4e0b\u8f7d\u5230\u672c\u5730\u7684\u65f6\u95f4\u53ef\u80fd\u6bd4\u8f83\u957f":27,"\u4e0a\u4f20\u65b9\u6cd5":63,"\u4e0a\u6ce8\u518c\u4e00\u4e0b":27,"\u4e0a\u8ff0paddlepaddl":63,"\u4e0b\u4e00\u4e2awheel\u5305\u9700\u8981\u66f4\u65b0\u7248\u672c\u53f7\u624d\u53ef\u4ee5\u4e0a\u4f20":63,"\u4e0b\u5b58\u653e\u516c\u5171\u6570\u636e\u96c6\u5408":11,"\u4e0b\u62c9\u6846\u4e2d\u627e\u5230\u751f\u6210\u76843\u4e2a\u4e8c\u8fdb\u5236\u6587\u4ef6":63,"\u4e0b\u8f7d":27,"\u4e0b\u8f7d\u5230\u672c\u5730":27,"\u4e0b\u8f7d\u5f97\u5230":63,"\u4e0b\u9762\u5206\u522b\u4ecb\u7ecd\u67d0\u4e00\u7c7b\u6587\u4ef6\u7684\u5b9e\u73b0\u65b9\u5f0f":46,"\u4e0d\u4e00\u81f4\u7684\u7531pfsclient\u4e0b\u8f7d\u6216\u8005\u4f20\u8f93chunk\u5b8c\u6210":27,"\u4e0d\u4f7f\u7528\u9759\u6001\u5e93":45,"\u4e0d\u4f7f\u7528c":45,"\u4e0d\u4f7f\u7528swig":45,"\u4e0d\u53ef\u4ee5\u66f4\u6539":63,"\u4e0d\u540c":42,"\u4e0d\u540c\u7248\u672c\u7684\u7f16\u8bd1\u5668\u4e4b\u95f4":45,"\u4e0d\u540c\u8bed\u8a00\u7684\u63a5\u53e3\u9002\u5e94\u4e0d\u540c\u8bed\u8a00\u7684\u7279\u6027":45,"\u4e0d\u5728":46,"\u4e0d\u5bb9\u6613\u51fa\u9519":27,"\u4e0d\u5d4c\u5165\u5176\u4ed6\u8bed\u8a00\u89e3\u91ca\u5668":45,"\u4e0d\u5d4c\u5165python\u89e3\u91ca\u5668":45,"\u4e0d\u663e\u793a\u7684\u5199\u6bcf\u4e2a\u7c7b\u5177\u4f53\u5305\u542b\u4ec0\u4e48":45,"\u4e0d\u7528mount\u7684\u65b9\u5f0f\u6765\u8bbf\u95ee\u6570\u636e":11,"\u4e0e":42,"\u4e0e\u4e4b\u76f8\u5bf9\u7684\u662flocal":27,"\u4e0e\u5176\u4ed6\u7b2c\u4e09\u65b9\u5e93\u4e00\u6837":42,"\u4e0e\u529f\u80fd\u5206\u652f\u4e0d\u540c\u7684\u662f":63,"\u4e0e\u53ef\u80fd\u6709\u7684":63,"\u4e0ebatch":41,"\u4e14\u589e\u52a0\u4e00\u4e2a\u7b2c\u4e09\u65b9\u8bed\u8a00":45,"\u4e14\u8c03\u7528\u65f6\u4e0d\u80fd\u629b\u51fa\u5f02\u5e38\u6216\u51fa\u73b0\u8fd0\u884c\u65f6\u9519\u8bef":46,"\u4e14c99\u652f\u6301bool\u7c7b\u578b\u548c\u5b9a\u957f\u6574\u6570":45,"\u4e14c99\u76f8\u5bf9\u4e8ec11\u4f7f\u7528\u66f4\u52a0\u5e7f\u6cdb":45,"\u4e25\u683c\u7684\u547d\u540d\u89c4\u8303pep":63,"\u4e2a\u6027\u5316\u63a8\u8350":63,"\u4e2d":[41,42,45,46],"\u4e2d\u4f1a\u63d0\u4f9b\u4e00\u4e9b\u5fc5\u8981\u7684\u63a5\u53e3\u548c\u51fd\u6570":42,"\u4e2d\u5199\u5165json\u5185\u5bb9":10,"\u4e2d\u5b8c\u5168\u4e00\u81f4":45,"\u4e2d\u5b9e\u73b0\u4e86\u4e00\u4e2amerge\u7684\u65b9\u6cd5":42,"\u4e2d\u5b9e\u73b0\u7684\u7ed3\u6784\u4f53":46,"\u4e2d\u5bf9\u5e94\u7684layer\u5904":41,"\u4e2d\u5f15\u5165\u7684":41,"\u4e2d\u63d0\u4f9b\u4e00\u4e2a\u4e0emkl\u6709\u5173\u7684\u603b\u5f00\u5173":42,"\u4e2d\u6839\u636e":41,"\u4e2d\u6dfb\u52a0":41,"\u4e2d\u6dfb\u52a0\u4e00\u4e2a":42,"\u4e2d\u7684\u7248\u672c\u4fe1\u606f":63,"\u4e2d\u8fd0\u884c\u4efb\u52a1\u7684\u89d2\u5ea6":11,"\u4e3a":[41,42],"\u4e3a\u4e86\u5c3d\u53ef\u80fd\u5c11\u7684\u5728\u7236\u7c7blayer\u4e2d\u6dfb\u52a0\u53d8\u91cf\u6216\u8005\u51fd\u6570":42,"\u4e3a\u4e86\u5e94\u5bf9\u4ee5\u4e0a\u7684\u95ee\u9898":27,"\u4e3a\u4e86\u66b4\u9732\u7684\u63a5\u53e3\u5c3d\u91cf\u7b80\u5355":46,"\u4e3a\u4e86\u66f4\u597d\u7684\u7b26\u5408paddlepaddle\u7684\u4ee3\u7801\u98ce\u683c":42,"\u4e3a\u4e86\u6700\u5927\u7a0b\u5ea6\u51cf\u5c11\u591a\u6b21\u8c03\u7528":41,"\u4e3a\u4e86\u8fdb\u4e00\u6b65\u63d0\u5347paddlepaddle\u5728\u57fa\u672c\u6570\u5b66\u8fd0\u7b97\u7684\u8ba1\u7b97\u901f\u5ea6":42,"\u4e3b\u8981\u529f\u80fd\u5305\u62ec":27,"\u4e3b\u8981\u5305\u62ec":42,"\u4e3b\u8981\u5305\u62ec\u4e86\u6df1\u5ea6\u5b66\u4e60\u76f8\u5173\u7684\u6570\u5b66\u539f\u8bed\u4e0e\u64cd\u4f5c":42,"\u4e3b\u8981\u9488\u5bf9paddlepaddle\u5728\u91cd\u6784\u4e4b\u524d\u7684\u4ee3\u7801\u6846\u67b6\u4ee5\u53cav1\u7684api":42,"\u4e4b\u5916\u7684\u6240\u6709\u5934\u6587\u4ef6":46,"\u4e5f\u4e0d\u4f7f\u7528\u5176\u4ed6\u52a8\u6001\u5e93":45,"\u4e5f\u4e0d\u5e94\u8be5\u62a5\u9519":46,"\u4e5f\u4e0d\u751f\u6210":46,"\u4e5f\u53ef\u4ee5\u4f7f\u7528\u8fd9\u4e9b\u955c\u50cf":63,"\u4e5f\u5c31\u662f\u8bf4\u8f93\u51fa\u7684\u7ed3\u679c\u4e0d\u4f1a\u5728\u539f\u6765\u7684\u6570\u636e\u4e0a\u7d2f\u52a0":42,"\u4e66\u5199":45,"\u4eba\u8138\u8bc6\u522b":11,"\u4ec5\u4ec5\u4f7f\u7528":45,"\u4ec5\u4f1a\u5728\u652f\u6301avx2\u6307\u4ee4\u96c6\u53ca\u4ee5\u4e0a\u7684\u673a\u5668\u624d\u4f7f\u7528mkl":42,"\u4ece":63,"\u4ece\u78c1\u76d8\u6587\u4ef6\u4e2d\u52a0\u8f7duuid\u6587\u4ef6\u540d\u7684\u68c0\u67e5\u70b9\u5feb\u7167\u6587\u4ef6":10,"\u4ece\u800c\u907f\u514d\u4e86packing\u5197\u4f59":41,"\u4eceetcd\u4e2d\u8bfb\u53d6\u8282\u70b9":10,"\u4ed6\u4e3b\u8981\u5305\u542b\u4e86\u5b9e\u9645\u66b4\u9732\u7684\u7c7b\u578b\u7ed3\u6784":46,"\u4ed6\u662f\u5c06":46,"\u4ed6\u7684\u76ee\u6807\u662f\u4f7f\u7528c":45,"\u4ee3\u7801\u751f\u6210\u7684\u7b26\u53f7\u53ef\u80fd\u4e0d\u4e00\u81f4":45,"\u4ee3\u8868\u8fd9\u4e2alayer\u662f\u7528\u4e8e\u8dd1\u5728mkl":42,"\u4ee3\u8868\u8fd9\u4e2ashard\u7684\u6700\u5927index":11,"\u4ee3\u8868shard\u7684index":11,"\u4ee5\u4e0a\u4ee3\u7801\u7684reader\u8f93\u51fa\u7684data":11,"\u4ee5\u4e0a\u547d\u4ee4\u4f1a\u5728\u5f53\u524d\u76ee\u5f55\u4e0b\u751f\u6210100\u4e2a\u6587\u4ef6":11,"\u4ee5\u4e0b":11,"\u4ee5\u4e0b\u7b80\u79f0rnn":41,"\u4ee5\u4fbf\u6211\u4eec\u53ef\u4ee5\u628a\u66f4\u591a\u7684\u7cbe\u529b\u653e\u5230\u903b\u8f91\u672c\u8eab\u4e0a":27,"\u4ee5\u53ca":41,"\u4ee5\u53canumpi":11,"\u4ee5\u6b64\u8fbe\u5230\u6700\u597d\u7684\u6027\u80fd":42,"\u4ee5\u793a\u533a\u5206":[41,42],"\u4efb\u610f\u65f6\u523b\u53ea\u53ef\u80fd\u540c\u65f6\u6709\u4e00\u53f0\u670d\u52a1\u5668\u6545\u969c":10,"\u4f18\u5316\u524d":41,"\u4f18\u5316\u540e":41,"\u4f1a\u4ee5":[41,42],"\u4f1a\u4f7f\u7528\u76f8\u540c\u7684\u539f\u6570\u636e":41,"\u4f1a\u5148\u4e34\u65f6\u4fdd\u5b58\u5728":42,"\u4f1a\u5728":42,"\u4f1a\u5728\u7f16\u8bd1paddlepaddle\u7684\u65f6\u5019\u4e0b\u8f7d\u5e76\u7f16\u8bd1mkl":42,"\u4f1a\u5bfc\u81f4\u4e0d\u540c\u7248\u672cpython\u5728\u4e00\u4e2a\u8fdb\u7a0b\u91cc\u7684bug":45,"\u4f1a\u5f15\u5165":42,"\u4f1a\u628acpu\u7684buffer\u5bf9\u9f50\u4e3a4096":42,"\u4f1a\u6dfb\u52a0\u76f8\u5e94\u7684\u811a\u672c\u5728":42,"\u4f1a\u6dfb\u52a0\u76f8\u5e94\u7684\u811a\u672c\u7528\u4e8e\u6d4b\u8bd5\u548c\u5bf9\u6bd4\u5728\u4f7f\u7528mkl":41,"\u4f1a\u76f4\u63a5\u62a5\u9519\u9000\u51fa":45,"\u4f1a\u81ea\u52a8\u4f7f\u7528mklml\u5e93\u4f5c\u4e3apaddlepaddle\u7684cblas\u548clapack\u5e93":42,"\u4f1a\u81ea\u52a8\u6839\u636e\u786c\u4ef6\u914d\u7f6e":42,"\u4f1a\u88abpickle\u5e8f\u5217\u5316\u6210\u5b57\u7b26\u4e32":11,"\u4f20\u5165":11,"\u4f46":46,"\u4f46\u4e0d\u66b4\u9732":46,"\u4f46\u5e76\u6ca1\u6709\u7ecf\u8fc7\u56de\u5f52\u6d4b\u8bd5":63,"\u4f46\u6240\u6709fork\u7684\u7248\u672c\u5e93\u7684\u6240\u6709\u5206\u652f\u90fd\u76f8\u5f53\u4e8e\u7279\u6027\u5206\u652f":63,"\u4f46\u662f\u53c8\u8fc7\u4e8e\u7410\u788e":46,"\u4f46\u662f\u5728mkl":42,"\u4f46\u662f\u5728paddlepaddle\u4e2d":42,"\u4f46\u662f\u6574\u4e2a\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u4e0d\u9700\u8981\u4efb\u4f55\u8f6c\u6362":42,"\u4f46\u662f\u6ce8\u610f\u7684\u662f":42,"\u4f46\u662f\u89e3\u91ca\u6027\u8bed\u8a00":45,"\u4f5c\u4e3a\u53e6\u4e00\u4e2a\u7b2c\u4e09\u65b9\u5e93\u96c6\u6210\u8fdbpaddlepaddl":42,"\u4f5c\u4e3a\u5b58\u50a8\u7cfb\u7edf":11,"\u4f5c\u4e3a\u7c7b\u53e5\u67c4":45,"\u4f7f\u7528":[42,46,63],"\u4f7f\u7528\u4e0b\u9762\u547d\u4ee4":11,"\u4f7f\u7528\u52a8\u6001\u5e93":45,"\u4f7f\u7528\u540c\u6837\u7684\u8bad\u7ec3\u6570\u636eblock":10,"\u4f7f\u7528\u667a\u80fd\u6307\u9488\u7684\u539f\u56e0\u662f":46,"\u4f7f\u7528\u7684\u53c2\u6570\u4e0epaddlepaddle\u7533\u8bf7\u7684buffer\u5171\u7528\u4e00\u5757\u5185\u5b58":42,"\u4f7f\u7528\u76f8\u5bf9\u8def\u5f84\u7684\u5f15\u7528\u65b9\u5f0f":46,"\u4f7f\u7528\u8fd9\u4e2a\u795e\u7ecf\u7f51\u7edc\u53ef\u4ee5\u5b8c\u6210\u5bf9\u65b0\u6570\u636e\u7684\u9884\u6d4b":10,"\u4f7f\u7528\u9759\u6001\u5e93\u548c\u52a8\u6001\u5e93\u96be\u5ea6\u5dee\u4e0d\u591a":45,"\u4f7f\u7528c":46,"\u4f7f\u7528c99\u505a\u63a5\u53e3":45,"\u4f7f\u7528c99\u800c\u4e0d\u4f7f\u7528c11\u7684\u539f\u56e0\u662f":45,"\u4f7f\u7528c99\u800c\u4e0d\u4f7f\u7528c89":45,"\u4f7f\u7528regress":63,"\u4f7f\u7528swig\u53ea\u652f\u6301cpython\u89e3\u91ca\u5668":45,"\u4f7f\u7528swig\u9700\u8981\u591a\u8bed\u8a00\u7ed1\u5b9a\u7684\u5f00\u53d1\u4eba\u5458\u719f\u7ec3\u638c\u63e1swig\u914d\u7f6e":45,"\u4f7f\u7528void":45,"\u4f8b\u5982":[11,45,46,63],"\u4f8b\u5982\u5728deepspeech2":41,"\u4f8b\u5982\u5bf9\u4e8ejava\u6216\u8005python":45,"\u4f8b\u5982\u5bf9\u4e8ejava\u6765\u8bf4":45,"\u4f8b\u5982\u5bf9\u4e8epython":45,"\u4f8b\u5982c":45,"\u4f8b\u5982java\u4e0epython\u7684\u9519\u8bef\u5904\u7406\u662f\u76f4\u63a5\u6254\u51fa\u6765except":45,"\u4f8b\u5982python\u53ef\u4ee5\u4f7f\u7528":45,"\u4f8b\u5982python\u7684":45,"\u4f8b\u5982rnn":41,"\u4f9d\u6b21\u7c7b\u63a8":63,"\u4fbf\u662f\u5c06\u9759\u6001\u5e93\u52a0\u5165jvm\u4e2d":45,"\u4fee\u590d\u6240\u6709bug\u540e":63,"\u4fee\u590ddocker\u7f16\u8bd1\u955c\u50cf\u95ee\u9898":63,"\u4fee\u6539":[42,63],"\u4fee\u6539\u6210":63,"\u505a\u53ea\u8bfb\u6302\u8f7d":11,"\u505a\u5982\u4e0b\u51e0\u4e2a\u64cd\u4f5c":63,"\u505a\u63a5\u53e3":45,"\u505c\u6b62\u4fdd\u5b58\u68c0\u67e5\u70b9\u7684\u7ebf\u7a0b":10,"\u5145\u5206\u53d1\u6325\u82f1\u7279\u5c14\u5e73\u53f0\u7684\u4f18\u52bf":41,"\u5145\u5206\u5c55\u73b0\u82f1\u7279\u5c14\u5e73\u53f0\u7684\u4f18\u52bf":42,"\u5148\u5b8c\u6210\u5bf9\u6743\u91cd\u7684packing\u64cd\u4f5c":41,"\u5148\u5b9e\u73b0\u6a21\u578b\u63a8\u65ad\u7684api":46,"\u5171\u4eab\u5185\u5b58":42,"\u5171\u4eab\u540c\u4e00\u4e2a\u6743\u91cd":41,"\u5176\u4e2d":[45,63],"\u5176\u4ed6\u51fd\u6570\u5747\u8fd4\u56de":46,"\u5176\u4ed6\u7528\u6237\u7684fork\u7248\u672c\u5e93\u5e76\u4e0d\u9700\u8981\u4e25\u683c\u9075\u5b88":63,"\u5176\u8f6c\u6362\u6b21\u6570\u51cf\u5c11\u81f3":41,"\u5177\u4f53\u4f7f\u7528\u65b9\u6cd5\u4e3a":46,"\u5177\u4f53\u539f\u56e0\u53c2\u8003":46,"\u5177\u4f53\u53ef\u4ee5\u53c2\u8003mkl":42,"\u5177\u4f53\u5b9e\u73b0\u65b9\u5f0f\u6bd4\u5982":[41,42],"\u5177\u4f53\u7684\u5b8c\u6210\u72b6\u6001\u53ef\u4ee5\u53c2\u89c1":42,"\u5177\u4f53\u8bf7\u53c2\u8003":46,"\u5185\u90e8\u5b58\u50a8":42,"\u5185\u90e8\u9a71\u52a8python\u89e3\u91ca\u5668\u8fdb\u884c\u6a21\u578b\u914d\u7f6e\u89e3\u6790\u548c\u6570\u636e\u8bfb\u53d6":45,"\u518d\u5728\u6bcf\u4e00\u4e2aapi\u4e2d\u81ea\u5df1\u68c0\u67e5\u7c7b\u578b":45,"\u518d\u57fa\u4e8e":63,"\u518d\u628a\u5df2\u8f6c\u6362\u4e3apacked\u683c\u5f0f\u7684\u6570\u636e\u4f20\u9012\u7ed9\u90a3\u4e9b\u590d\u7528\u540c\u4e00\u6570\u636e\u7684gemm":41,"\u5199\u4ee3\u7801":45,"\u5199\u5165\u5feb\u7167\u6570\u636e":10,"\u51fd\u6570":[41,42],"\u51fd\u6570\u5373\u53ef\u5b8c\u6210\u8f6c\u6362":11,"\u51fd\u6570\u540d\u4e3a":46,"\u51fd\u6570\u547d\u540d":45,"\u5206\u522b\u4ee3\u8868\u8f93\u5165\u6570\u636e":42,"\u5206\u522b\u5bf9\u5e94capi":63,"\u5206\u5e03\u5f0f\u5b58\u50a8\u670d\u52a1":10,"\u5206\u652f":63,"\u5206\u652f\u4e00\u65e6\u5efa\u7acb":63,"\u5206\u652f\u4e2d":63,"\u5206\u652f\u4e3a\u5f00\u53d1":63,"\u5206\u652f\u4e3a\u6bcf\u4e00\u6b21release\u65f6\u5efa\u7acb\u7684\u4e34\u65f6\u5206\u652f":63,"\u5206\u652f\u4e3a\u7a33\u5b9a":63,"\u5206\u652f\u529f\u80fd\u7684\u5c01\u95ed":63,"\u5206\u652f\u5408\u5165":63,"\u5206\u652f\u5408\u5165master\u5206\u652f":63,"\u5206\u652f\u540c\u6b65\u4e3b\u7248\u672c\u5e93\u7684":63,"\u5206\u652f\u540d\u4e3a":63,"\u5206\u652f\u5b58\u5728\u7684\u65f6\u5019":63,"\u5206\u652f\u6d3e\u751f\u51fa\u65b0\u7684\u5206\u652f":63,"\u5206\u652f\u7684\u7248\u672c\u90fd\u662f\u7ecf\u8fc7\u5355\u5143\u6d4b\u8bd5\u548c\u56de\u5f52\u6d4b\u8bd5\u7684\u7248\u672c":63,"\u5206\u652f\u7684\u7248\u672c\u90fd\u7ecf\u8fc7\u5355\u5143\u6d4b\u8bd5":63,"\u5206\u7247":10,"\u5219\u4f7f\u7528\u542f\u52a8\u53c2\u6570\u5b9a\u4e49\u7684\u521d\u59cb\u5316\u65b9\u6cd5\u521d\u59cb\u5316\u53c2\u6570":10,"\u5219\u5ffd\u7565":10,"\u5219\u628a\u53e6\u4e00\u4e2a\u6162\u901f\u7684kill\u6389":10,"\u5219\u76f4\u63a5\u5f15\u5165\u53e6\u4e00\u79cd\u7c7b\u578b\u7684\u5934\u6587\u4ef6":46,"\u5219\u9700\u8981\u56de\u6eda\u5230\u4e0a\u4e00\u4e2a\u68c0\u67e5\u70b9":10,"\u521b\u5efa":42,"\u5220\u9664\u78c1\u76d8\u76ee\u5f55\u4e2d\u4e0d\u662f\u5f53\u524duuid\u7684\u5feb\u7167\u6587\u4ef6":10,"\u5230":10,"\u5230\u7b2c\u4e8c\u6b65":63,"\u524d\u540e\u7684\u7f51\u7edc\u6027\u80fd":41,"\u529f\u80fd":27,"\u529f\u80fd\u7684\u6b63\u786e\u6027\u5305\u62ec\u9a8c\u8bc1paddlepaddle\u76ee\u524d\u7684":63,"\u52a8\u6001\u5e93":45,"\u5305\u542b\u4e86\u67d0\u79cd\u7c7b\u578b\u7684\u7c7b\u578b\u5b9a\u4e49\u548c\u66b4\u9732\u7684\u5168\u90e8\u51fd\u6570":46,"\u5305\u62ec":[11,41,42],"\u5305\u62ec\u6743\u91cdw\u548c\u504f\u7f6eb":10,"\u5305\u62ecmkl":42,"\u534f\u540c\u5b8c\u6210releas":63,"\u5355\u4e2a\u503c":11,"\u5355\u70b9\u6545\u969c":10,"\u5373":46,"\u5373\u4f7f\u7528":46,"\u5373\u4f7f\u7528\u6237\u76f4\u63a5\u5f15\u7528\u67d0\u79cd\u7c7b\u578b\u7684\u5934\u6587\u4ef6":46,"\u5373\u4f7fc":46,"\u5373\u4f8b\u5982":46,"\u5373\u4fbfpaddl":46,"\u5373\u5b8c\u6210\u67d0\u4e00\u4e2a\u4efb\u52a1\u7684\u6700\u5c11\u51fd\u6570":46,"\u5373\u66b4\u9732":46,"\u5373\u8868\u793a\u4e0d\u9700\u8981\u8f6c\u6362":42,"\u5373\u8fd9\u4e2a\u52a8\u6001\u5e93\u662f\u4e0d\u4f9d\u8d56\u4e8e\u5176\u4ed6\u4efb\u4f55\u6587\u4ef6\u7684":45,"\u539f\u6765\u7684\u65b9\u6848":42,"\u53c2\u6570":45,"\u53c2\u8003":[27,45],"\u53c2\u8003\u4e0b\u56fe":63,"\u53c8\u53ef\u4ee5\u907f\u514d\u4e0d\u5fc5\u8981\u7684\u8f6c\u6362":42,"\u53cc\u5411\u9a8c\u8bc1":27,"\u53d1\u578b\u7248":63,"\u53d1\u5e03\u5230dockerhub":63,"\u53d1\u5e03docker\u955c\u50cf\u53ea\u9700\u8981\u5bf9\u81ea\u52a8push\u7684\u955c\u50cf\u6253\u4e0a":63,"\u53d8\u91cf\u6765\u533a\u5206layer\u7684\u5c5e\u6027":42,"\u53ea\u5bf9\u7279\u6b8a\u5728\u7ebf\u7cfb\u7edf\u8003\u8651\u4e24\u53f0\u4ee5\u4e0a\u540c\u65f6\u6545\u969c\u7684\u5bb9\u707e":10,"\u53ea\u66b4\u9732\u6982\u5ff5\u7684\u63a5\u53e3":46,"\u53ea\u80fd\u8c03\u7528paddle\u7684\u52a8\u6001\u5e93":45,"\u53ea\u9700\u8981\u6062\u590d\u8fd9\u53f0\u8282\u70b9":10,"\u53ef\u4ee5":63,"\u53ef\u4ee5\u51cf\u5c0f\u7cfb\u7edf\u590d\u6742\u6027":10,"\u53ef\u4ee5\u5728\u4efb\u4f55\u673a\u5668\u4e0a\u6267\u884c\u7684":45,"\u53ef\u4ee5\u5728\u6b64\u9875\u9762\u7684":63,"\u53ef\u4ee5\u628a\u672c\u5730\u7684\u6570\u636e\u4e0a\u4f20\u5230\u5b58\u50a8\u96c6\u7fa4\u4e2d":11,"\u53ef\u4ee5\u6709\u6548\u7684\u907f\u514dparamet":10,"\u53ef\u4ee5\u7528":27,"\u53ef\u4ee5\u7528\u4ee5\u4e0b\u6307\u4ee4":11,"\u53ef\u4ee5\u7ee7\u7eed\u5728\u81ea\u5df1\u7684\u529f\u80fd\u5206\u652f\u63d0\u4ea4\u4ee3\u7801":63,"\u53ef\u4ee5\u901a\u8fc7\u9636\u6bb5\u6027\u7684\u4fdd\u5b58\u6bcf\u4e2aparamet":10,"\u53ef\u80fd\u4f1a\u9020\u6210\u7f51\u7edc\u62e5\u585e":10,"\u53f3\u4fa7\u7684":63,"\u5404\u6b21\u524d\u5411\u4e4b\u95f4\u4e5f\u90fd\u4f7f\u7528\u4e86\u76f8\u540c\u7684\u6743\u91cd":41,"\u540c\u4e00\u6b21\u524d\u5411":41,"\u540c\u65f6":[41,42],"\u540c\u65f6\u4f1a\u5f00\u542fintel":42,"\u540c\u65f6\u518d\u5c06":63,"\u540c\u65f6\u53c8\u5c3d\u53ef\u80fd\u5c11\u7684\u727a\u7272mkl":42,"\u540c\u65f6\u63d0\u8d77":63,"\u540c\u65f6\u6570\u636e\u683c\u5f0f\u5c31\u662f":42,"\u540d\u5b57\u4fee\u9970":45,"\u540e\u5411":41,"\u540e\u5411\u65f6\u590d\u7528\u5df2\u7ecf\u8f6c\u6362\u8fc7\u7684\u6743\u91cd":41,"\u5411\u6307\u5b9a\u7684\u76ee\u5f55\u4e2d\u4e00\u4e2a\u65b0\u7684\u6587\u4ef6":10,"\u5411paddlepaddle\u7684\u4e3b\u7248\u672c\u5e93\u63d0\u4ea4":63,"\u5426\u5219\u5f97\u628apaddle\u9759\u6001\u5e93\u94fe\u63a5\u5230\u89e3\u91ca\u5668\u91cc":45,"\u542f\u52a8\u4e00\u4e2a\u65b0\u7684\u7ebf\u7a0b\u5f00\u59cb\u4fdd\u5b58\u68c0\u67e5\u70b9":10,"\u548c":[11,41,42,45,46,63],"\u548c\u672a\u6765\u53ef\u80fd\u8fd8\u4f1a\u7528\u5230":42,"\u548c\u79bb\u7ebf\u6570\u636e\u7684\u65b9\u5f0f":11,"\u54ea\u4e2atrainer\u5148\u5b8c\u6210block\u7684\u8bad\u7ec3":10,"\u56e0\u4e3a\u8fd9\u6837\u505a\u4e5f\u6ca1\u6cd5\u4fdd\u8bc1\u6d88\u9664\u968f\u673a\u6027":10,"\u56e0\u4e3aswig\u5728\u7b2c\u4e09\u65b9\u8bed\u8a00\u4e2d\u66b4\u9732\u7684\u51fd\u6570\u540d":45,"\u56e0\u6b64":41,"\u56fe\u50cf\u5206\u7c7b":63,"\u5728":[41,42,46,63],"\u5728\u4e00\u4e2a\u4e0d\u53ef\u4e2d\u65ad\u5e76\u7f3a\u5c11\u5907\u4efd\u7684\u8bad\u7ec3\u4efb\u52a1\u4e2d":10,"\u5728\u4e0a\u56fe\u4e2d\u663e\u793a\u4e86\u5728\u4e00\u4e2a\u5b9e\u9645\u751f\u4ea7\u73af\u5883\u4e2d\u7684\u5e94\u7528":11,"\u5728\u4f7f\u7528twine\u4e0a\u4f20\u4e4b\u524d":63,"\u5728\u51fa\u73b0\u5355\u70b9\u6545\u969c\u65f6":10,"\u5728\u5b9e\u73b0\u6bcf\u4e2a\u5b50\u7c7b\u7684\u65f6\u5019\u5c31\u4e0d\u9700\u8981\u5173\u5fc3\u5206\u652f\u7684\u4e8b\u60c5\u4e86":42,"\u5728\u5b9e\u73b0\u8fc7\u7a0b\u4e2d":46,"\u5728\u5bf9\u5e94\u7684":41,"\u5728\u5c42\u521d\u59cb\u5316\u7684\u65f6\u5019":41,"\u5728\u5f00\u59cb\u8bad\u7ec3\u4e4b\u524d":11,"\u5728\u5f02\u6784\u96c6\u7fa4\u4e2d":10,"\u5728\u5f15\u5165\u5176\u4ed6\u7c7b\u578b\u7684\u5934\u6587\u4ef6\u65f6":46,"\u5728\u5feb\u7167\u5199\u5165\u5b8c\u6210\u540e":10,"\u5728\u60a8\u7684\u5b9e\u9645\u73af\u5883\u4e2d":10,"\u5728\u6709\u666e\u901a\u7684cpu":42,"\u5728\u672c\u6587\u6863\u4e2d":27,"\u5728\u673a\u7fa4\u4e0a\u8fd0\u884c\u8f6c\u6362\u7a0b\u5e8f":11,"\u5728\u6837\u4f8b\u4e2d":46,"\u5728\u7528\u6237\u4f7f\u7528c":46,"\u5728\u7b2c\u4e8c\u4e2atab":63,"\u5728\u7ebf\u6a21\u578b\u9884\u6d4b\u670d\u52a1":11,"\u5728\u8bad\u7ec3\u7ed3\u675f\u7684\u65f6\u5019\u518d\u4fdd\u5b58\u4e3apaddlepaddle\u7684\u683c\u5f0f":42,"\u5728\u8bc4\u5ba1\u8fc7\u7a0b\u4e2d":63,"\u5728\u8fd9\u4e2a":63,"\u5728\u8fd9\u4e2a\u52a8\u6001\u5e93\u4e2d\u4e0d\u5d4c\u5165\u4efb\u4f55\u5176\u4ed6\u8bed\u8a00\u7684\u89e3\u91ca\u5668":45,"\u5728\u8fd9\u4e2a\u9636\u6bb5\u7684\u4ee3\u7801\u6b63\u5728\u7ecf\u5386\u56de\u5f52\u6d4b\u8bd5":63,"\u5728\u8fd9\u4e9b\u5934\u6587\u4ef6\u4e2d":46,"\u5728\u8fd9\u4e9b\u6587\u4ef6\u4e2d":46,"\u5728\u91cd\u6784\u524d\u7684paddlepaddle\u4e2d":42,"\u5728\u95ee\u9898\u672c\u8eab\u7684\u8ba1\u7b97\u91cf\u6bd4\u8f83\u5c0f\u7684\u65f6\u5019":41,"\u5728batch":41,"\u5728c":45,"\u5728c\u7684\u5934\u6587\u4ef6":45,"\u5728packing\u4e0a\u7684\u8017\u65f6":41,"\u5728paddle\u4e4b\u4e0a\u8fd0\u884c\u7684\u6df1\u5ea6\u5b66\u4e60\u8bad\u7ec3\u8f93\u51fa\u7684\u6a21\u578b\u4f1a\u63d0\u4f9b\u7ed9\u5728\u7ebf\u4eba\u8138\u8bc6\u522b\u7684\u5e94\u7528\u4f7f\u7528":11,"\u5728paramet":10,"\u5728rnn\u7684\u60c5\u51b5\u4e0b":41,"\u5747\u4f1a\u88ab\u5b89\u88c5\u5230includ":46,"\u5747\u662f\u5728":46,"\u57fa\u4e8e\u7c98\u6027\u4f1a\u8bdd\u7684\u8d1f\u8f7d\u5747\u8861\u529f\u80fd":27,"\u5916\u90e8\u5b58\u50a8":42,"\u591a\u4e2a\u503c":11,"\u591a\u4e2aparamet":10,"\u591a\u6b21\u8c03\u7528":41,"\u5927\u591a\u6570\u8bed\u8a00\u90fd\u652f\u6301\u4f7f\u7528c\u8bed\u8a00api":45,"\u5982\u56fe\u4e2dtrainer":10,"\u5982\u679c\u4e0a\u9762\u4e24\u6b65\u51fa\u73b0\u9519\u8bef":10,"\u5982\u679c\u4e0d\u9700\u8981\u5916\u90e8\u5b58\u50a8\u7528\u4e8e\u8f6c\u6362":42,"\u5982\u679c\u4f7f\u7528swig\u6211\u4eec\u9700\u8981\u5c06\u5728interface\u6587\u4ef6\u91cc":45,"\u5982\u679c\u5728\u4f7f\u7528mkl":42,"\u5982\u679c\u5931\u8d25":63,"\u5982\u679c\u5b58\u5728\u6570\u636e\u6392\u5217\u683c\u5f0f\u4e0d\u4e00\u6837\u7684\u60c5\u51b5\u65f6":42,"\u5982\u679c\u5b58\u5728\u67d0\u4e9btrainer\u6267\u884c\u901f\u5ea6\u8fc7\u6162\u4f1a\u5f71\u54cd\u6574\u4f53\u96c6\u7fa4\u7684\u901f\u5ea6":10,"\u5982\u679c\u5df2\u7ecf\u6b63\u5728\u6267\u884c\u4fdd\u5b58\u68c0\u67e5\u70b9\u7684\u7ebf\u7a0b":10,"\u5982\u679c\u662f\u5176\u5b83\u7c7b\u578b":11,"\u5982\u679c\u6709bugfix\u7684\u884c\u4e3a":63,"\u5982\u679c\u67d0\u4e00\u4e2a\u7c7b\u578b\u9700\u8981\u5f15\u7528\u53e6\u4e00\u4e2a\u7c7b\u578b":46,"\u5982\u679c\u67d0\u4e00\u4e2apaddl":46,"\u5982\u679c\u67d0\u4e00\u4e2apaddle\u6982\u5ff5\u5fc5\u987b\u8981\u66b4\u9732":46,"\u5982\u679c\u6ee1\u8db3\u6761\u4ef6":10,"\u5982\u679c\u7528\u6237\u8981\u628apaddle\u7684\u9759\u6001\u5e93":45,"\u5982\u679c\u8981\u4e0a\u4f20gpu\u7248\u672c\u7684\u5305":63,"\u5982\u679c\u8c03\u7528\u9759\u6001\u5e93\u53ea\u80fd\u5c06\u9759\u6001\u5e93\u4e0e\u89e3\u91ca\u5668\u94fe\u63a5":45,"\u5982\u679c\u9700\u8981\u624b\u52a8\u7f16\u8bd1":63,"\u5982\u679cmkl":42,"\u5982\u679cparamet":10,"\u5b50\u7c7b\u53ea\u9700\u8981\u4f7f\u7528\u5b9a\u4e49\u597d\u7684\u63a5\u53e3":42,"\u5b57\u6bb5\u8bbe\u4e3a":63,"\u5b57\u7b26\u4e32":11,"\u5b58\u50a8":11,"\u5b66\u4e60\u6210\u672c\u9ad8":45,"\u5b83\u4eec\u4e3b\u8981\u662f\u7528\u4e8e":42,"\u5b83\u4eec\u7684\u6587\u4ef6\u540d\u662f":11,"\u5b83\u53ea\u4f1a\u5305\u62ec\u751f\u6210\u597d\u7684\u52a8\u6001\u5e93\u548c\u5934\u6587\u4ef6":42,"\u5b83\u8d1f\u8d23\u51b3\u5b9a\u7f16\u8bd1\u65f6\u662f\u5426\u4f7f\u7528mklml\u548cmkl":42,"\u5b89\u88c5\u540e\u7684\u76ee\u5f55\u7ed3\u6784\u4e3a":46,"\u5b8c\u6210\u4e00\u4e2a\u4f20\u8f93\u52a8\u4f5c\u5b8c\u6210\u7684\u65f6\u95f4\u4e5f\u6bd4\u8f83\u77ed":27,"\u5b8c\u6210\u5e38\u7528layer\u7684mkl":42,"\u5b8c\u6210\u5e38\u89c1\u6df1\u5ea6\u795e\u7ecf\u7f51\u7edcvgg":42,"\u5b8c\u6210\u6570\u636e\u7684\u9884\u5904\u7406":11,"\u5b8c\u6210\u81ea\u52a8\u5316\u4e8c\u8fdb\u5236\u7f16\u8bd1":63,"\u5b9a\u4e49":42,"\u5b9a\u4e49\u4e00\u4e9b\u9664\u4e86layer\u548cmemory\u76f8\u5173\u7684\u7c7b\u548c\u51fd\u6570":42,"\u5b9e\u73b0\u5177\u4f53\u7684\u51fd\u6570\u529f\u80fd\u5373\u53ef":42,"\u5b9e\u73b0\u7b80\u5355":45,"\u5bf9\u4e8e\u4e0d\u540c\u8bed\u8a00":45,"\u5bf9\u4e8e\u540c\u4e00\u6bb5c":45,"\u5bf9\u4e8e\u540c\u6837\u8bbe\u7f6e\u7684\u7f51\u7edc\u6a21\u578b":41,"\u5bf9\u4e8e\u591a\u8bed\u8a00\u63a5\u53e3":45,"\u5bf9\u4e8e\u5927\u591a\u6570\u8bed\u8a00":45,"\u5bf9\u4e8e\u5e8f\u5217\u957f\u5ea6":41,"\u5bf9\u4e8e\u6709\u53c2\u6570\u7684\u5c42":42,"\u5bf9\u4e8e\u6bcf\u4e00\u4e2a\u65b0\u52a0\u7684rnn":41,"\u5bf9\u4e8e\u6bcf\u79cd\u7c7b\u578b":46,"\u5bf9\u4e8e\u6bcf\u79cdc":46,"\u5bf9\u65b0\u7684\u6743\u91cd\u8fdb\u884c\u8f6c\u6362\u7528\u4e8e\u4e0b\u6b21\u8fed\u4ee3":41,"\u5bf9\u6bd4":45,"\u5bf9\u6bd4\u4f18\u5316\u540elayer\u4e0e\u76f8\u5bf9\u5e94\u7684paddlepaddle\u539f\u6709lay":41,"\u5bf9\u6bd4\u4f18\u5316\u540elayer\u81ea\u8eab":41,"\u5bf9\u8f93\u5165\u53c2\u6570\u7684\u5b89\u5168\u6027\u8fdb\u884c\u4e86\u5fc5\u8981\u7684\u5224\u65ad":46,"\u5bf9\u8fd9\u4e2a\u7248\u672c\u7684\u63d0\u4ea4":63,"\u5bfb\u627e\u6709\u6ca1\u6709\u5176\u4ed6\u53ef\u4ee5\u4f18\u5316\u7684\u53ef\u80fd":42,"\u5bfc\u51fa\u8fd9\u4e9b\u63a5\u53e3":46,"\u5c06":63,"\u5c06\u4e00\u4e2a\u795e\u7ecf\u7f51\u7edc\u53c2\u6570\u62c6\u5206\u6210\u591a\u4efd":10,"\u5c06\u5927\u91cf\u7684":45,"\u5c06\u65b0\u5206\u652f\u7684\u7248\u672c\u6253\u4e0atag":63,"\u5c06master\u5206\u652f\u7684\u5408\u5165commit\u6253\u4e0atag":63,"\u5c0f\u4e8e\u67d0\u4e2a\u6bd4\u8f83\u5c0f\u7684\u9608\u503c\u8ba4\u4e3a\u901a\u8fc7":42,"\u5c31\u9700\u8981\u5bf9\u8fd9\u4e2a\u7b2c\u4e09\u65b9\u8bed\u8a00\u589e\u52a0\u4e00\u4e9b\u5b9a\u4e49":45,"\u5de5\u5177\u4e0a\u4f20\u5373\u53ef":63,"\u5e73\u5747\u6545\u969c\u4fee\u590d\u65f6\u95f4":10,"\u5e73\u5747\u6545\u969c\u7387":10,"\u5e76\u4e14\u4f1a\u5199\u597d":42,"\u5e76\u4e14\u4f7f\u7528":46,"\u5e76\u4e14\u53ea\u9700\u8981\u5728\u5fc5\u8981\u7684\u65f6\u5019\u8f6c\u6362\u8fd9\u79cd\u683c\u5f0f":42,"\u5e76\u4e14\u5728\u5e38\u89c1\u7684\u5e73\u53f0\u4e0a":45,"\u5e76\u4e14\u5f53\u7f16\u8bd1\u65f6":41,"\u5e76\u4e14\u628a\u7cfb\u7edf\u751f\u6210\u7684ca":27,"\u5e76\u4e14\u628a\u7ed3\u679c\u8fd4\u56depfsclient\u7aef":27,"\u5e76\u4e14\u8ba9\u63a5\u53e3\u8131\u79bb\u5b9e\u73b0\u7ec6\u8282":45,"\u5e76\u4e14\u8f93\u5165\u8f93\u51fa\u90fd\u662f\u5171\u7528\u4e00\u5757\u5185\u5b58":42,"\u5e76\u5220\u9664":63,"\u5e76\u5220\u9664\u66f4\u65e9\u7684\u5feb\u7167":10,"\u5e76\u52a0\u8f7d\u5176\u4e2d\u7684\u53c2\u6570":10,"\u5e76\u53d1\u5e03\u5230pypi":63,"\u5e76\u5728\u6bcf\u6b21\u6743\u91cd\u66f4\u65b0\u540e":41,"\u5e76\u5728\u96c6\u7fa4\u4e2d\u8fd0\u884c\u591a\u4e2a\u5206\u5e03\u5f0f\u6570\u636e\u5904\u7406\u4efb\u52a1":11,"\u5e76\u5c06":63,"\u5e76\u5c06c":46,"\u5e76\u628a\u5feb\u7167\u4fdd\u5b58\u5230\u8fd9\u4e2a\u76ee\u5f55\u4e0b":10,"\u5e76\u628a\u7ed3\u679c\u653e\u5230\u5f53\u524d\u5c42\u7684":42,"\u5e76\u6ca1\u6709paddle\u7279\u522b\u9700\u8981\u7684\u7279\u6027":45,"\u5e76\u6dfb\u52a0\u5934\u6587\u4ef6":41,"\u5e76\u88ab\u5b58\u50a8\u5728\u8bf8\u5982hadoop":11,"\u5e76\u9002\u5e94github\u7684\u7279\u6027\u505a\u4e86\u4e00\u4e9b\u533a\u522b":63,"\u5e76\u91cd\u65b0\u6253\u5305wheel\u5305":63,"\u5efa\u8bae":63,"\u5f00\u53d1\u4e86\u6a21\u578b\u9884\u6d4b\u7684\u6837\u4f8b\u4ee3\u7801":46,"\u5f00\u53d1\u8005\u4fee\u6539\u81ea\u5df1\u7684\u4ee3\u7801":63,"\u5f00\u53d1\u8005fork\u7684\u7248\u672c\u5e93\u4e2d":63,"\u5f00\u53d1\u8005fork\u7684\u7248\u672c\u5e93\u4f7f\u7528":63,"\u5f00\u5934":[41,42],"\u5f00\u59cb\u63d0\u4f9b\u670d\u52a1":10,"\u5f15\u5165\u4e86\u4ee5\u4e0b\u56db\u4e2aapi":41,"\u5f15\u5165\u4e86\u7c7b\u578b\u7684\u5934\u6587\u4ef6":46,"\u5f39\u51fa\u4e0b\u9762\u7684\u9009\u62e9\u6846":63,"\u5f53\u529f\u80fd\u5206\u652f\u5f00\u53d1\u5b8c\u6bd5\u540e":63,"\u5f53\u53ea\u505a\u63a8\u65ad":41,"\u5f53\u5f00\u542f":42,"\u5f53\u6253\u5f00":42,"\u5f53\u6570\u636e\u683c\u5f0f\u4e0epaddlepaddle\u9ed8\u8ba4\u7684":42,"\u5f53\u7136\u8fd9\u4e24\u8005\u4e5f\u53ef\u4ee5\u76f8\u7b49":42,"\u5f53\u7528\u6237\u4f7f\u7528\u5b8c\u8fd9\u4e2a\u53c2\u6570\u540e":46,"\u5f53\u7f51\u7edc\u51fa\u73b0\u5206\u652f\u4e14\u5728":42,"\u5f53destination\u6587\u4ef6\u4e0d\u5b58\u5728\u6216\u8005\u5927\u5c0f\u548csource\u6587\u4ef6\u4e0d\u4e00\u81f4\u65f6":27,"\u5f88\u96be\u4fdd\u8bc1\u591a\u8bed\u8a00\u4ee3\u7801\u98ce\u683c\u7684\u4e00\u81f4\u6027":45,"\u5f97\u4f7f\u7528":45,"\u5fc5\u8981":46,"\u5fc5\u987b\u5206\u522b\u4e0e":42,"\u60c5\u611f\u5206\u6790":63,"\u6211\u4eec\u4e5f\u53ef\u4ee5\u786e\u5b9a\u6bcf\u4e00\u4e2a\u53c2\u6570\u7684\u7c7b\u578b":46,"\u6211\u4eec\u4e5f\u5c06mklml\u5373":42,"\u6211\u4eec\u4f1a\u4fdd\u8bc1":42,"\u6211\u4eec\u4f1a\u5728\u7f51\u7edc\u8bad\u7ec3\u4e4b\u524d\u628a\u683c\u5f0f\u8f6c\u6362\u4e3amkl":42,"\u6211\u4eec\u4f1a\u5bf9\u6bd4\u5982\u4e0b2\u4e2a\u65b9\u9762":41,"\u6211\u4eec\u4f1a\u628amkl":42,"\u6211\u4eec\u4f1a\u6dfb\u52a0":[41,42],"\u6211\u4eec\u4f7f\u7528\u52a8\u6001\u5e93\u6765\u5206\u53d1paddl":45,"\u6211\u4eec\u51b3\u5b9a\u4f7f\u7528\u5df2\u6709\u7684":42,"\u6211\u4eec\u53ef\u4ee5\u5148\u5b8c\u6210\u5bf9\u539f\u6570\u636e\u7684packing\u64cd\u4f5c":41,"\u6211\u4eec\u603b\u7ed3\u51fa\u4e00\u4e9b\u7279\u522b\u9700\u8981\u6ce8\u610f\u7684\u70b9":42,"\u6211\u4eec\u63d0\u4f9b\u4e24\u4e2a\u8f6c\u6362\u65b9\u5f0f":11,"\u6211\u4eec\u63d0\u51fa\u4e86chunk\u7684\u6982\u5ff5":27,"\u6211\u4eec\u6700\u7ec8\u7684\u52a8\u6001\u5e93\u4e2d\u4e0d\u5d4c\u5165python\u6216\u8005\u5176\u4ed6\u4efb\u4f55\u8bed\u8a00\u7684\u89e3\u91ca\u5668":45,"\u6211\u4eec\u8ba1\u5212\u5c06":41,"\u6211\u4eec\u8ba1\u5212\u5c06\u82f1\u7279\u5c14\u6df1\u5ea6\u795e\u7ecf\u7f51\u7edc\u6570\u5b66\u5e93":42,"\u6211\u4eec\u8bbe\u8ba1\u8bf4\u660e\u4e86\u540d\u4e3afilemanager\u7cfb\u7edf":27,"\u6211\u4eec\u9009\u62e9":11,"\u6211\u4eec\u901a\u8fc7\u4f7f\u7528\u65b0\u5f15\u5165\u7684gemm":41,"\u6211\u4eec\u90fd\u63d0\u4f9bpython\u7684\u8f6c\u6362\u5e93":11,"\u6216\u8005":[42,45,46],"\u6216\u8005\u5c06\u8fd9\u53f0\u8282\u70b9\u8fc1\u79fb\u5230\u53e6\u4e00\u4e2a\u8282\u70b9\u5e76\u542f\u52a8\u5373\u53ef\u6062\u590d\u8bad\u7ec3\u4efb\u52a1":10,"\u6216\u8005\u7528tuple\u8868\u793a\u7684\u591a\u4e2a\u503c":11,"\u6216\u8005\u7531\u5b83\u4eec\u7ec4\u6210\u7684list":11,"\u6216activ":42,"\u6240\u4ee5":[42,63],"\u6240\u4ee5\u4e00\u4e2a\u7248\u672c\u53f7\u7684wheel\u5305\u53d1\u5e03\u4e4b\u540e":63,"\u6240\u4ee5\u4e0d\u5b58\u5728\u8fd9\u4e2a\u95ee\u9898":42,"\u6240\u4ee5\u5728":42,"\u6240\u4ee5\u5728\u5199\u5165\u5feb\u7167\u7684\u8fc7\u7a0b\u4e2d":10,"\u6240\u4ee5\u6211\u4eec\u5b9a\u4e49\u4e86\u4e00\u4e2a":42,"\u6240\u4ee5\u6574\u4f53\u4e0a":42,"\u6240\u4ee5\u6dfb\u52a0\u4e86\u5bf9\u5e94\u7684":42,"\u6240\u4ee5\u7528\u6237\u9700\u8981\u9996\u5148\u5728":27,"\u6240\u4ee5\u9700\u8981\u5f15\u5165\u4e00\u4e2a\u8f6c\u6362\u65b9\u6cd5":42,"\u6240\u6709\u4e0e\u7c7b\u578b\u76f8\u5173\u7684\u51fd\u6570":46,"\u6240\u6709\u5916\u90e8\u7684\u8f6c\u6362\u5de5\u4f5c\u90fd\u4f1a\u5728reset\u7cfb\u5217\u51fd\u6570\u4e2d\u90fd\u51c6\u5907\u597d":42,"\u6240\u6709\u7684":41,"\u6240\u6709\u7684\u63a5\u53e3\u5747\u4e3ac\u63a5\u53e3":46,"\u6240\u6709\u76f8\u5173\u7684":41,"\u6240\u6709\u7c7b\u578b\u540d\u4e3a":46,"\u6240\u6709mkl":42,"\u624b\u5199\u591a\u8bed\u8a00\u7ed1\u5b9a":45,"\u624d\u80fd\u66f4\u597d\u7684\u53d1\u6325mkl":42,"\u6253\u5f00\u8fd9\u4e2a\u7f16\u8bd1\u9009\u9879":46,"\u6267\u884c":63,"\u628a":11,"\u628a\u4e4b\u524d\u793a\u4f8b\u4e2d\u8f6c\u6362\u5b8c\u6bd5\u7684random":11,"\u6307\u6df1\u5ea6\u5b66\u4e60\u8bad\u7ec3\u4e4b\u540e\u5f97\u5230\u7684\u6240\u6709\u53c2\u6570":10,"\u6309\u94ae":63,"\u63a5\u53e3":[45,46],"\u63a5\u53e3\u5c42\u505a\u8fc7\u591a\u5c01\u88c5":46,"\u63a5\u53e3\u662f":11,"\u63a5\u6536\u5904\u7406pfsclient\u7aef\u7684\u6587\u4ef6\u7ba1\u7406\u8bf7\u6c42":27,"\u63a7\u5236\u662f\u5426\u4f7f\u7528mkl":42,"\u63a7\u5236\u662f\u5426\u4f7f\u7528mklml\u5e93":42,"\u63a7\u5236\u7528\u6237\u6743\u9650":11,"\u63d0\u4f9b\u4e03\u5c42\u534f\u8bae\u7684\u53cd\u5411\u4ee3\u7406":27,"\u63d0\u4f9b\u5e38\u7528\u7684\u547d\u4ee4\u884c\u7ba1\u7406\u547d\u4ee4\u7ba1\u7406\u6587\u4ef6\u548c\u76ee\u5f55":27,"\u63d0\u4f9b\u7528\u6237\u7ba1\u7406\u6587\u4ef6\u7684\u547d\u4ee4":27,"\u63d0\u4f9b\u7ed9paddle\u4f5c\u4e3a\u8bad\u7ec3\u6570\u636e":11,"\u652f\u6301\u5927\u6587\u4ef6\u7684\u65ad\u70b9\u4e0a\u4f20":27,"\u6570\u636e":27,"\u6570\u636e\u8bfb\u53d6\u5747\u4ea4\u7531\u5176\u4ed6\u8bed\u8a00\u5b8c\u6210":45,"\u6570\u636e\u957f\u5ea6\u53ca\u6821\u9a8c\u503c\u7ec4\u6210":27,"\u6570\u636e\u96c6\u9700\u8981\u9884\u5148\u88ab\u8f6c\u6362\u6210paddlepaddle\u5206\u5e03\u5f0f\u8bad\u7ec3\u4f7f\u7528\u7684\u5b58\u50a8\u683c":11,"\u6570\u636e\u9884\u5904\u7406\u4efb\u52a1":11,"\u6587\u4ef6":45,"\u6587\u4ef6\u4f20\u8f93\u7684\u7684\u5173\u952e\u5728\u4e8e\u9700\u8981pfsclient\u7aef\u5bf9\u6bd4source\u548cdestination\u7684\u6587\u4ef6chunks\u7684checksum\u662f\u5426\u4fdd\u6301\u4e00\u81f4":27,"\u6587\u4ef6\u5185\u5bb9\u4e3a":45,"\u6587\u4ef6\u540d\u4e3a\u6b64uuid":10,"\u6587\u4ef6\u5bf9\u5e94\u7684data":11,"\u6587\u4ef6\u7684\u4e0a\u4f20\u548c\u4e0b\u8f7d\u90fd\u662f\u901a\u8fc7\u5bf9chunk\u7684\u64cd\u4f5c\u6765\u5b9e\u73b0\u7684":27,"\u65b0\u624b\u5165\u95e8\u7ae0\u8282":63,"\u65b0\u7248\u672c":42,"\u65b9\u4fbf\u6d4b\u8bd5\u4eba\u5458\u6d4b\u8bd5paddlepaddle\u7684\u884c\u4e3a":63,"\u65b9\u4fbf\u7528\u6237\u4e0a\u4f20\u81ea\u5df1\u7684\u8bad\u7ec3\u6570\u636e\u4ee5\u8fdb\u884c\u5206\u5e03\u5f0f\u8bad\u7ec3":27,"\u65b9\u4fbf\u7528\u6237\u5728python\u7aef\u9009\u62e9\u662f\u5426\u542f\u7528\u8fd9\u4e2a\u529f\u80fd":41,"\u65b9\u4fbf\u7528\u6237\u9009\u62e9\u4f7f\u7528mkl":42,"\u65b9\u5f0f\u7c7b\u4f3c\u4e8e":42,"\u65e0\u6cd5\u505a\u5230\u5bf9\u4e8e\u5404\u79cd\u8bed\u8a00\u9519\u8bef\u5904\u7406\u65b9\u5f0f\u7684\u9002\u914d":45,"\u65e0\u8bba\u5728\u672c\u5730\u8fd8\u662f\u5728\u4e91\u7aef":11,"\u65e0\u8bba\u662f\u4ece":11,"\u65e0\u8bba\u662f\u5728\u672c\u5730\u6216\u662f\u4e91\u7aef\u8f6c\u6362":11,"\u65e0\u8bba\u662f\u91cd\u6784\u524d\u7684layer\u8fd8\u662f\u91cd\u6784\u540e\u7684op":42,"\u65f6":[10,41,42],"\u65f6\u4e00\u8d77\u66f4\u65b0":42,"\u662f":[27,42],"\u662f\u4e00\u4e2a\u591a\u8bed\u8a00\u63a5\u53e3\u7684\u4ee3\u7801\u751f\u6210\u5668":45,"\u662f\u4e00\u4e2a\u7c7b\u578b\u7684\u6807\u5fd7":46,"\u662f\u4e0d\u5e38\u89c1\u7684\u505a\u6cd5":45,"\u662f\u5404\u4e2a\u5b9e\u73b0\u4e2d\u5171\u4eab\u7684\u5934\u6587\u4ef6":46,"\u662f\u5426\u6253\u5f00":41,"\u662f\u56e0\u4e3ac99\u652f\u6301":45,"\u662f\u5bf9\u7528\u6237\u6587\u4ef6\u5b58\u50a8\u7a7a\u95f4\u7684\u62bd\u8c61":27,"\u662f\u6307":46,"\u662f\u7528\u6237\u4f7f\u7528c":46,"\u662fc":46,"\u663e\u5f97\u76f8\u5bf9\u6765\u8bf4\u8f83\u4e3a\u8017\u65f6":41,"\u6682\u65f6\u4e0d\u8003\u8651\u591a\u4e2aparamet":10,"\u66b4\u9732\u8fd9\u4e2a\u6982\u5ff5\u5fc5\u8981\u51fd\u6570":46,"\u6700\u540e\u5220\u9664":63,"\u6700\u5e38\u89c1\u7684\u9519\u8bef\u5904\u7406\u65b9\u5f0f\u662fexcept":45,"\u6709\u6548\u63d0\u5347paddlepaddle\u5728\u82f1\u7279\u5c14\u67b6\u6784\u4e0a\u7684\u6027\u80fd":[41,42],"\u6709\u6807\u51c6\u7684":45,"\u6709\u7684\u65f6\u5019":45,"\u672c\u5217\u8868\u8bf4\u660epaddlepaddle\u53d1\u7248\u4e4b\u524d\u9700\u8981\u6d4b\u8bd5\u7684\u529f\u80fd\u70b9":63,"\u672c\u6587\u6863\u63cf\u8ff0paddl":46,"\u673a\u5668\u7ffb\u8bd1":63,"\u6765\u4fdd\u8bc1\u8bad\u7ec3\u8fc7\u7a0b\u53ef\u4ee5\u4ece\u4e2d\u95f4\u72b6\u6001\u91cd\u65b0\u542f\u52a8":10,"\u6765\u51b3\u5b9a\u662f\u5426\u5f00\u542fmkl":41,"\u6765\u5b9e\u73b0":42,"\u6765\u786e\u4fdd\u628a":45,"\u6765\u8868\u793apaddle\u5185\u90e8\u7c7b":45,"\u6765\u8bbf\u95ee\u7528\u6237\u81ea\u5df1\u7684\u6570\u636e":11,"\u6765\u8fdb\u884c\u8ba8\u8bba":46,"\u67e5\u770blatest":63,"\u6807\u51c6\u8868\u793apaddlepaddle\u7248\u672c\u53f7":63,"\u683c\u5f0f\u4e0d\u5339\u914d\u65f6":42,"\u68c0\u67e5\u70b9\u4fdd\u5b58\u7a0b\u5e8f\u6d41\u7a0b":10,"\u6a21\u578b\u53c2\u6570\u68c0\u67e5\u70b9\u901a\u8fc7\u5b9a\u671f\u5411\u78c1\u76d8\u4e0a\u4fdd\u5b58\u4e00\u4efd\u5b58\u50a8\u5728paramet":10,"\u6a21\u578b\u6570\u636e\u68c0\u67e5\u70b9\u7684\u5b9e\u73b0":10,"\u6a21\u578b\u914d\u7f6e\u89e3\u6790":45,"\u6b21\u8fed\u4ee3\u6267\u884c\u7684\u8f6c\u6362\u6b21\u6570\u4e3a":41,"\u6b64\u65f6\u6bcf\u4e2a\u5c0f\u5206\u652f\u7684":42,"\u6b64\u65f6master\u5c06\u8d1f\u8d23\u542f\u52a8\u4e00\u4e2a\u65b0\u7684train":10,"\u6bcf\u4e00\u4e2a":63,"\u6bcf\u4e00\u4e2a\u6587\u4ef6\u662f\u6570\u636e\u96c6\u7684\u4e00\u4e2ashard":11,"\u6bcf\u4e2a":42,"\u6bcf\u4e2a\u503c\u7684\u7c7b\u578b\u53ef\u4ee5\u662f\u6574\u5f62":11,"\u6bcf\u4e2a\u6d4b\u8bd5\u4f1a\u5bf9\u6bd4paddlepaddle\u4e2dcpu\u7b97\u51fa\u7684\u7ed3\u679c\u4e0emkl":42,"\u6bcf\u4e2adata":11,"\u6bcf\u4e2amkldnnlayer\u90fd\u5305\u542b\u7528\u4e8e\u5185\u90e8\u5b58\u50a8\u548c\u5916\u90e8\u5b58\u50a8\u7684\u4e00\u7cfb\u5217mkldnnmatrix":42,"\u6bcf\u4e2aparamet":10,"\u6bcf\u4e2ashard\u5206\u522b\u5b58\u50a8\u5728\u5176\u4e2d\u4e00\u53f0paramet":10,"\u6bcf\u6b21\u8c03\u7528\u65f6\u5bf9\u539f\u6570\u636e\u7684\u91cd\u590dpacking\u4fbf\u6210\u4e3a\u4e86\u5197\u4f59":41,"\u6bcf\u6b21\u8f93\u51fa\u4e00\u4e2adata":11,"\u6bcf\u969410\u5206\u949f":10,"\u6bd4\u5982":[11,42],"\u6bd4\u5982\u53ef\u80fd\u4f1a\u7528openmp\u6539\u8fdbsgd\u7684\u66f4\u65b0\u6027\u80fd":42,"\u6bd4\u5982\u5c06":63,"\u6bd4\u5982\u6bcf\u969410\u5206\u949f\u6700\u65b0\u7684\u5feb\u7167":10,"\u6bd4\u5982\u6d41\u5f0f\u6570\u636e\u5904\u7406":11,"\u6bd4\u5982imagenet\u8fd9\u4e2a\u6570\u636e\u96c6\u53ef\u80fd\u88ab\u5206\u62101000\u4e2ashard":11,"\u6ca1\u6709\u5fc5\u8981\u5728\u6bcf\u6b21\u524d\u5411\u4e2d\u6bcf\u4e2a\u65f6\u95f4\u6b65\u7684\u8ba1\u7b97\u65f6\u5bf9\u6743\u91cd\u8fdb\u884c\u91cd\u590d\u7684packing\u64cd\u4f5c":41,"\u6ce8":[10,63],"\u6ce8\u518clayer\u7684\u65f6\u5019\u4fdd\u8bc1":[41,42],"\u6ce8\u610f":42,"\u6d4b\u8bd5\u5206\u4e3a\u6bcf\u4e2alayer":42,"\u6d4b\u8bd5\u672c\u6b21release\u7684\u6b63\u786e\u6027":63,"\u6d4b\u8bd5\u7684\u6027\u80fd\u5bf9\u6bd4\u7ed3\u679c\u4f1a\u5728":42,"\u6d6e\u70b9\u578b\u6570\u636e":11,"\u6df1\u5165paddlepaddl":42,"\u6dfb\u52a0":41,"\u6dfb\u52a0\u7684\u76f8\u5173\u6587\u4ef6\u548c\u76ee\u5f55\u7ed3\u6784\u5982\u4e0b":[41,42],"\u6fc0\u6d3b\u51fd\u6570\u662f\u72ec\u7acb\u4e8e":42,"\u70b9\u51fb":63,"\u7136\u540e\u5728\u524d\u5411":41,"\u7136\u540e\u5728etcd\u7684":10,"\u7136\u540e\u5c31\u53ef\u4ee5\u5e76\u53d1\u5199\u5165\u591a\u4e2achunk":27,"\u7136\u540e\u624d\u80fd\u4f7f\u7528pfsclient":27,"\u7136\u540e\u6309\u7167\u4e0a\u8ff0\u7684\u65b9\u6cd5":63,"\u7136\u540e\u70b9\u51fb":63,"\u7248\u672c\u5206\u652f":63,"\u7248\u672c\u53f7":63,"\u7248\u672c\u53f7\u5bf9\u5e94\u7684tag\u5373\u53ef":63,"\u7248\u672c\u53f7rc":63,"\u7248\u672cfork\u51fa\u81ea\u5df1\u7684\u529f\u80fd\u5206\u652f":63,"\u7279\u6709\u7684\u8bbe\u5907id":42,"\u73b0\u9636\u6bb5\u7684\u4f18\u5316\u4e3b\u8981\u9488\u5bf9":41,"\u73b0\u9636\u6bb5paddle\u6709\u4e00\u4e2a\u95ee\u9898\u662f":45,"\u751f\u4ea7\u73af\u5883\u4e2d\u7684\u8bad\u7ec3\u6570\u636e\u96c6\u901a\u5e38\u4f53\u79ef\u5f88\u5927":11,"\u751f\u4ea7\u73af\u5883\u7684\u65e5\u5fd7\u6570\u636e\u4f1a\u901a\u8fc7\u5b9e\u65f6\u6d41\u7684\u65b9\u5f0f":11,"\u751f\u6210\u5404\u79cd\u8bed\u8a00\u7684\u7ed1\u5b9a\u4ee3\u7801":45,"\u751f\u6210\u6587\u6863":45,"\u751f\u6210\u7684":11,"\u751f\u6210\u7ed9\u5b9a":11,"\u751f\u6210api\u6587\u6863":45,"\u751f\u6210pfsclient\u548cpfsserver\u7684\u6846\u67b6\u90e8\u5206":27,"\u7528":27,"\u7528\u4e8e\u6d4b\u8bd5\u548c\u5bf9\u6bd4\u5728\u4f7f\u7528mkl":42,"\u7528\u4e8e\u7ba1\u7406mkl":42,"\u7528\u4e8e\u9009\u62e9\u662f\u5426\u4f7f\u7528\u76f8\u5173\u529f\u80fd":41,"\u7528\u4e8e\u9009\u62e9\u662f\u5426\u4f7f\u7528mkl":42,"\u7528\u4e8emkl":[41,42],"\u7528\u6237\u4e0a\u4f20\u6570\u636e\u540e":11,"\u7528\u6237\u4e5f\u53ef\u4ee5\u4e0a\u4f20label":11,"\u7528\u6237\u53ef\u4ee5\u5b89\u5168\u7684\u91ca\u653e\u67d0\u4e2ac":46,"\u7528\u6237\u53ef\u4ee5\u628a\u81ea\u5df1\u7684\u6570\u636e\u5206\u4eab\u7ed9\u522b\u4eba":11,"\u7528\u6237\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528\u8fd9\u4e2a\u52a8\u6001\u5e93\u6765\u5f15\u5165paddl":46,"\u7528\u6237\u5728\u672c\u5730\u8f6c\u6362\u597d\u518d\u4e0a\u4f20":11,"\u7528\u6237\u6587\u4ef6\u53ef\u80fd\u662f\u6bd4\u8f83\u5927\u7684":27,"\u7528\u6237\u901a\u8fc7c":46,"\u7531\u4e8e\u5728\u73b0\u6709\u7684\u67d0\u4e9b\u60c5\u51b5\u4e0b":41,"\u7531\u4e8e\u5bf9parameters\u7684\u66f4\u65b0\u9700\u8981\u83b7\u53d6parameters\u5185\u5b58\u7684":10,"\u7531\u4e8e\u96c6\u7fa4\u4e2d\u540c\u65f6\u5b58\u5728\u4e24\u53f0\u673a\u5668\u6545\u969c\u7684\u6982\u7387\u6781\u4f4e":10,"\u7531\u4e8ec":45,"\u7531\u4e8echunk\u6bd4\u8f83\u5c0f":27,"\u7531\u4e8emkl":42,"\u7531\u4e8epypi":63,"\u7531\u5206\u652f\u5904\u7684layer\u8d1f\u8d23\u6c42\u548c":42,"\u7533\u8bf7\u7528\u6237\u7a7a\u95f4":27,"\u7684\u4e00\u4e2a\u5b50\u96c6":42,"\u7684\u4fe1\u606f":42,"\u7684\u5355\u5143\u6d4b\u8bd5\u548c\u7b80\u5355\u7f51\u7edc\u7684\u6574\u4f53\u6d4b\u8bd5":42,"\u7684\u547d\u540d\u98ce\u683c\u5e76\u4e0d\u80fd\u9002\u5e94\u5176\u4ed6\u7b2c\u4e09\u65b9\u8bed\u8a00":45,"\u7684\u57fa\u672c\u903b\u8f91":42,"\u7684\u5934\u6587\u4ef6":45,"\u7684\u5b50\u7c7b\u53ea\u9700\u8981\u4f7f\u7528\u5185\u90e8\u5b58\u50a8\u5c31\u53ef\u4ee5\u4e86":42,"\u7684\u60c5\u51b5\u4e0b":41,"\u7684\u63a5\u53e3\u6837\u5f0f":45,"\u7684\u6570\u636e\u6d41\u56fe":11,"\u7684\u65f6\u5019":42,"\u7684\u683c\u5f0f\u59cb\u7ec8\u662f":42,"\u7684\u683c\u5f0f\u5b58\u50a8":42,"\u7684\u6982\u5ff5":42,"\u7684\u6e90\u7801\u91cc\u4f7f\u7528\u4e86":45,"\u7684\u7248\u672c":63,"\u7684\u7ed3\u679c":41,"\u7684\u7f29\u5199":27,"\u7684\u7f51\u7edc\u6a21\u578b":41,"\u7684\u89c4\u8303":45,"\u7684\u89d2\u5ea6":11,"\u7684\u914d\u7f6e\u5199\u5230\u914d\u7f6e\u6587\u4ef6\u4e2d":11,"\u7684flag":[41,42],"\u7684vanilla":41,"\u76ee\u524d\u53ea\u8003\u8651":42,"\u76ee\u524d\u53ea\u8003\u8651\u52a8\u6001\u6269\u5bb9trainer\u6570\u91cf":10,"\u76ee\u524d\u5728paddlepaddle\u4e2d":42,"\u76ee\u524d\u5728paddlepaddle\u4e2d\u6570\u636e\u90fd\u662f\u4ee5":42,"\u76ee\u524d\u5d4c\u5165python\u89e3\u91ca\u5668":45,"\u76ee\u524d\u6211\u4eec\u7528cephfs\u6765\u642d\u5efa":27,"\u76ee\u524d\u7684\u4f18\u5316":42,"\u76ee\u524dpaddle\u7684\u8fdb\u7a0b\u6a21\u578b\u662fc":45,"\u76ee\u524dpaddlepaddle\u91c7\u7528\u4e86":41,"\u76ee\u5f55\u4e0b":46,"\u76ee\u5f55\u4e0b\u5bf9\u5e94\u7684\u5730\u65b9":42,"\u76f4\u63a5\u4f7f\u7528c\u8bed\u8a00\u7684":45,"\u76f4\u63a5\u5220\u9664\u8fd9\u4e2a\u53c2\u6570\u5373\u53ef":46,"\u76f4\u63a5\u5bfc\u51fa\u5230c\u7684\u63a5\u53e3\u6bd4\u8f83\u56f0\u96be":45,"\u76f8\u5173\u5c42":41,"\u77e9\u9635\u5927\u5c0f\u662f":41,"\u793e\u533a\u53c2\u4e0e\u56f0\u96be":45,"\u793e\u533a\u8d21\u732e\u4ee3\u7801\u5b66\u4e60\u6210\u672c\u9ad8":45,"\u795e\u7ecf\u7f51\u7edc\u4e2d\u7684\u53c2\u6570":10,"\u79bb\u7ebf\u6279\u5904\u7406":11,"\u7b2c\u4e00\u4e2atag\u4e3a":63,"\u7b2c\u4e09\u6b65\u5b8c\u6210\u540e":63,"\u7b2c\u4e8c\u4e2a\u4e3a":63,"\u7b49":[42,46],"\u7b49\u5168\u90e8\u9759\u6001\u5e93\u4e2d\u7684\u76ee\u6807\u6587\u4ef6\u5168\u90e8\u6253\u5305\u540e\u4ea7\u751f\u7684\u6587\u4ef6":46,"\u7b49\u5f85\u7f16\u8bd1\u5b8c\u6210\u540e":63,"\u7b49\u6587\u4ef6":46,"\u7c7b\u4f3c":46,"\u7c7b\u540d\u548cc":45,"\u7c7b\u578b":45,"\u7ed3\u8bba":45,"\u7edf\u4e00\u7528":11,"\u7f16\u8bd1\u5668\u6ca1\u6709":45,"\u7f16\u8bd1\u578b\u8bed\u8a00":45,"\u7f16\u8bd1\u65f6\u4f1a\u628a\u5bf9\u5e94\u7684\u5934\u6587\u4ef6\u548c\u5e93\u653e\u5728":42,"\u7f16\u8bd1\u8fd9\u4e2a\u7248\u672c\u7684docker\u53d1\u884c\u955c\u50cf":63,"\u7f16\u8bd1\u8fd9\u4e2a\u7248\u672c\u7684python":63,"\u7f16\u8bd1c":46,"\u800c\u4e0d\u5fc5\u5728\u610fpaddl":46,"\u800c\u4e0d\u652f\u6301pypy\u89e3\u91ca\u5668":45,"\u800c\u4e0d\u66b4\u9732\u6982\u5ff5\u7684\u5b9e\u73b0":46,"\u800c\u4e14\u5728\u4f20\u8f93\u7684\u8fc7\u7a0b\u4e2d\u4e5f\u53ef\u80fd\u51fa\u73b0\u7f51\u7edc\u4e0d\u7a33\u5b9a\u7684\u60c5\u51b5":27,"\u800c\u51fa\u73b0\u9636\u6bb5\u6027\u7684\u8fd0\u884c\u505c\u6ede":10,"\u800c\u5728cpp\u91cc\u9762\u5b9e\u73b0\u8fd9\u4e2ac\u7684\u63a5\u53e3":45,"\u800c\u591a\u8bed\u8a00\u63a5\u53e3\u9700\u8981\u76f4\u63a5\u8bfb\u53d6\u751f\u6210\u7684\u4e8c\u8fdb\u5236":45,"\u800c\u5bf9\u4e8egolang":45,"\u800c\u5bf9\u4e8egolang\u9519\u8bef\u5904\u7406\u5e94\u8be5\u4f7f\u7528\u8fd4\u56de\u503c":45,"\u800c\u662f\u76f4\u63a5\u4fee\u6539paddl":46,"\u800c\u662f\u76f4\u63a5\u7528api\u7684\u63a5\u53e3\u8fdc\u7a0b\u8bbf\u95ee":11,"\u800cswig\u53ea\u80fd\u7b80\u5355\u7684\u66b4\u9732c":45,"\u81ea\u52a8\u6302\u8f7d\u5206\u5e03\u5f0f\u5b58\u50a8\u76ee\u5f55":10,"\u81f3\u4e8e\u4e3a\u4ec0\u4e48\u9700\u8981c":46,"\u826f\u597d\u7684\u6587\u6863":45,"\u8282\u7701\u4e86\u4e0d\u5fc5\u8981\u7684\u64cd\u4f5c":42,"\u83b7\u53d6\u6700\u65b0\u7684\u68c0\u67e5\u70b9\u7684\u6587\u4ef6uuid":10,"\u867d\u7136\u4e0d\u9f13\u52b1\u8fd9\u6837":46,"\u8868\u793a\u5bf9\u8f93\u5165\u6570\u636e":42,"\u89e3\u91ca\u578b\u8bed\u8a00\u53ea\u80fd\u8c03\u7528\u52a8\u6001\u5e93":45,"\u89e3\u91ca\u6027\u8bed\u8a00\u5b9e\u9645\u8fd0\u884c\u7684\u4e8c\u8fdb\u5236\u662f\u89e3\u91ca\u5668\u672c\u8eab":45,"\u8ba1\u5212\u5728":[41,42],"\u8ba1\u7b97\u8fd9\u4e2a\u6587\u4ef6\u7684md5":10,"\u8ba9paddle\u6838\u5fc3\u4e2d":46,"\u8bad\u7ec3\u4efb\u52a1\u7684\u8fd0\u884c\u53ef\u80fd\u4f1a\u5360\u6ee1trainer\u548cparamet":10,"\u8bad\u7ec3\u548c\u7eaf\u4f7f\u7528":63,"\u8bad\u7ec3\u6a21\u578b\u6b63\u786e\u6027":63,"\u8bb0\u5f55\u4e0b\u6240\u6709\u5931\u8d25\u7684\u4f8b\u5b50":63,"\u8bbe\u7f6e":46,"\u8bc6\u522b\u6570\u5b57":63,"\u8bcd\u5411\u91cf":63,"\u8be5\u6587\u4ef6\u5bf9\u76f8\u5173gemm":41,"\u8be5\u7c7b\u7ee7\u627f\u4e8epaddlepaddle\u7684\u57fa\u7c7b":42,"\u8be6\u7ec6\u8bbe\u8ba1":27,"\u8bed\u610f\u89d2\u8272\u6807\u6ce8":63,"\u8bf4\u660e":10,"\u8bf7\u53c2\u8003":46,"\u8f6c\u6362\u5185\u5b58\u7684\u5de5\u4f5c":42,"\u8f6c\u6362\u5197\u4f59":41,"\u8f6c\u6362\u51fd\u6570":42,"\u8f6c\u6362\u751f\u6210\u7684\u6587\u4ef6\u540d\u4f1a\u662f\u4ee5\u4e0b\u683c\u5f0f":11,"\u8f6c\u6362\u8017\u65f6":41,"\u8f93\u5165\u68af\u5ea6":42,"\u8f93\u51fa\u6570\u636e\u548c\u8f93\u51fa\u68af\u5ea6":42,"\u8f93\u51fa\u6570\u636e\u548c\u8f93\u51fa\u68af\u5ea6\u7684\u8f6c\u6362":42,"\u8fbe\u5230\u5bb9\u707e\u7684\u76ee\u7684":10,"\u8fc7\u7a0b\u4e2d\u6240\u6709\u65f6\u95f4\u6b65":41,"\u8fd1\u671f\u76ee\u6807":42,"\u8fd4\u56de\u7b2c\u4e8c\u6b65":63,"\u8fd8\u662f\u4ece":11,"\u8fd9\u4e00\u5c42\u8fdb\u884c\u5c01\u88c5":46,"\u8fd9\u4e00\u6570\u636e\u683c\u5f0f\u7684\u8f6c\u6362\u64cd\u4f5c":41,"\u8fd9\u4e00\u6982\u5ff5\u4e0d\u518d\u7410\u788e":46,"\u8fd9\u4e09\u4e2a\u5206\u652f":63,"\u8fd9\u4e2a\u51fd\u6570\u672c\u8eab\u4f1a\u5728\u8ba1\u7b97\u524d\u5c06\u539f\u6570\u636e\u8f6c\u6362\u4e3a\u66f4\u9002\u5408\u82f1\u7279\u5c14\u5e73\u53f0\u7684\u5185\u90e8\u683c\u5f0f":41,"\u8fd9\u4e2a\u52a8\u6001\u5e93\u7684\u8fde\u63a5\u53c2\u6570\u4e0epaddle\u7684\u5176\u4ed6\u4e8c\u8fdb\u5236":46,"\u8fd9\u4e2a\u53c2\u6570\u4e5f\u4e0d\u4f1a\u4e00\u5e76\u5220\u9664":46,"\u8fd9\u4e2a\u5934\u6587\u4ef6\u4e0d\u5047\u8bbe\u5176\u4ed6\u6587\u4ef6\u7684\u5f15\u7528\u987a\u5e8f":46,"\u8fd9\u4e2a\u63a5\u53e3\u9700\u8981\u505a\u5230":45,"\u8fd9\u4e2a\u6587\u4ef6\u5177\u6709\u72ec\u7279\u7684\u8bed\u6cd5":45,"\u8fd9\u4e2a\u76ee\u5f55\u4e2d\u9664\u4e86":46,"\u8fd9\u4e2a\u7ed3\u6784\u4f53\u4e2d\u7684\u53e6\u4e00\u4e2a\u9879\u76ee\u662f":46,"\u8fd9\u4e2a\u7ed3\u6784\u4f53\u5305\u542b\u4e24\u4e2a\u9879\u76ee":46,"\u8fd9\u4e2a\u9009\u62e9":[41,42],"\u8fd9\u4e2a\u9759\u6001\u5e93\u5305\u542b\u4e86paddle\u7684\u5168\u90e8\u7b26\u53f7":46,"\u8fd9\u4e2ainstance\u53ef\u4ee5\u662f\u5355\u4e2a\u503c":11,"\u8fd9\u4e9b\u4f1a\u5728":[41,42],"\u8fd9\u4e9b\u51fd\u6570\u4f1a\u6839\u636e\u8f93\u5165\u53c2\u6570\u91cd\u65b0\u8bbe\u7f6e\u5185\u90e8\u548c\u5916\u90e8\u5b58\u50a8":42,"\u8fd9\u4e9b\u5206\u5e03\u5f0f\u5b58\u50a8\u670d\u52a1\u901a\u5e38\u4f1a\u628a\u6570\u636e\u5207\u5272\u6210\u591a\u4e2a\u5206\u7247\u5206\u5e03\u5f0f\u7684\u5b58\u50a8\u5728\u591a\u4e2a\u8282\u70b9\u4e4b\u4e0a":11,"\u8fd9\u4e9b\u955c\u50cf\u4e5f\u53ef\u4ee5\u4ece":63,"\u8fd9\u5bf9\u4e8e\u901a\u5e38\u7684java\u7684\u5f00\u53d1\u8005\u6765\u8bf4":45,"\u8fd9\u662f\u56e0\u4e3a":45,"\u8fd9\u6837":46,"\u8fd9\u6837\u4e0b\u4e00\u4e2acpu":42,"\u8fd9\u6837\u4fdd\u8bc1":63,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u5728\u4e91\u7aef\u6267\u884c\u591a\u79cd\u6570\u636e\u7c7b\u8ba1\u7b97\u4efb\u52a1":11,"\u8fd9\u6837\u5df2\u7ecf\u4f20\u8f93\u6210\u529f\u7684\u90e8\u5206\u5c31\u4e0d\u7528\u91cd\u65b0\u4f20\u8f93\u4e86":27,"\u8fd9\u6837\u5e26\u6765\u7684\u597d\u5904\u5c31\u662f\u4e0d\u9700\u8981\u4e00\u76f4\u6e05\u7a7amemori":42,"\u8fd9\u6837\u65e2\u4f7f\u5f97\u6700\u7ec8\u4fdd\u5b58\u7684\u53c2\u6570\u683c\u5f0f\u4e0epaddlepaddle\u4e00\u81f4":42,"\u8fd9\u90fd\u9700\u8981\u8fd9\u4e2a\u63a5\u53e3\u6309\u7167\u7ea6\u5b9a\u4fd7\u6210\u7684\u89c4\u5219\u6765\u6ce8\u91ca\u5b8c\u5907":45,"\u8fd9\u91cc":42,"\u8fd9\u91cc\u7684dockerimage\u4f5c\u4e3a\u7f16\u8bd1\u73af\u5883\u4ee5\u652f\u6301\u66f4\u591a\u7684linux":63,"\u8fd9\u91cc\u9009\u62e90":63,"\u8fd9\u91cc\u9700\u8981\u7528\u6237\u989d\u5916\u6ce8\u610f":10,"\u8fdb\u4e00\u6b65\u4f18\u5316":42,"\u8fdb\u5165":63,"\u8fdb\u800c\u8fdb\u884c\u4ee3\u7801\u8bc4\u5ba1":63,"\u9009\u62e9\u662f\u5426\u7f16\u8bd1mkl":42,"\u9009\u62e9\u9700\u8981\u53d1\u5e03\u7684\u7248\u672c":63,"\u900f\u4f20\u7528\u6237\u8eab\u4efd\u7684\u529e\u6cd5":27,"\u901a\u5e38":46,"\u901a\u5e38\u5305\u542b\u4e00\u4e2acpu\u7248\u672c\u548c\u4e00\u4e2agpu\u7248\u672c":63,"\u901a\u5e38\u6307\u5c06\u4e00\u4e2a\u6574\u4f53\u62c6\u5206\u6210\u591a\u4efd\u7684\u5176\u4e2d\u7684\u4e00\u4efd":10,"\u901a\u8fc7\u4f7f\u7528\u8fd9\u4e9bapi":41,"\u901a\u8fc7\u6a21\u578b\u63a8\u65adapi\u7684\u5b9e\u73b0\u4f5c\u4e3a\u4e00\u4e2a\u6837\u4f8b":46,"\u903b\u8f91\u5212\u4e0a\u6587\u4ef6\u5206\u5757\u7684\u5355\u4f4d":27,"\u9075\u5faa\u4ee5\u4e0b\u6d41\u7a0b":63,"\u90a3\u4e48":46,"\u90a3\u4e48\u5bf9\u5e94\u7684\u5185\u90e8\u5b58\u50a8\u4e5f\u4f1a\u4e0e\u5b83\u4eec\u5171\u4eab\u5185\u5b58":42,"\u90a3\u4e48\u5c31\u4f1a\u4f7f":42,"\u90fd\u4e0d\u4f1a\u60f3\u8981\u77e5\u9053next":42,"\u90fd\u662f\u4e94\u4f4d\u7684\u6570\u5b57":11,"\u90fd\u662f\u4ee5ext\u5f00\u5934":42,"\u90fd\u662fabi\u8c03\u7528\u6807\u51c6\u7684":45,"\u90fd\u7ee7\u627f\u4e8epaddlepaddle\u7684\u57fa\u7c7b":41,"\u914d\u7f6e\u7684\u65b9\u6cd5\u53c2\u8003":27,"\u91ca\u653e\u5bf9paramters\u5185\u5b58\u7684\u9501\u5b9a":10,"\u91cc\u6240\u6709\u7684\u7b26\u53f7\u90fd\u5199\u5165\u81ea\u5df1\u7684\u7a0b\u5e8f\u7684\u4e8c\u8fdb\u5236\u6587\u4ef6\u91cc":45,"\u91cc\u9009\u62e9\u9700\u8981\u53d1\u5e03\u7684\u5206\u652f":63,"\u91cc\u9762\u6dfb\u52a0":42,"\u91cd\u5199\u7236\u7c7blayer\u7684":42,"\u91cd\u547d\u540d\u6210":45,"\u94fe\u63a5\u5230\u81ea\u5df1\u7684\u7a0b\u5e8f\u91cc":45,"\u9519\u8bef\u5904\u7406":45,"\u9519\u8bef\u5904\u7406\u65b9\u5f0f\u662f\u8fd4\u56de\u503c":45,"\u9519\u8bef\u5904\u7406\u7684\u65b9\u5f0f\u4e5f\u4e0d\u5c3d\u76f8\u540c":45,"\u9664\u6784\u9020\u67d0\u79cd\u7c7b\u578b\u7684\u51fd\u6570":46,"\u96c6\u6210\u5230":41,"\u96c6\u6210\u5230paddlepaddl":42,"\u9700\u8981":11,"\u9700\u8981\u4fee\u6539build":63,"\u9700\u8981\u53ef\u4ee5\u8de8\u5e73\u53f0\u6267\u884c":27,"\u9700\u8981\u5728cmake\u7684\u65f6\u5019":46,"\u9700\u8981\u5c06bugfix\u7684\u5206\u652f\u540c\u65f6merge\u5230":63,"\u9700\u8981\u5f15\u7528":46,"\u9700\u8981\u6709\u7a33\u5b9a\u7684\u5bfc\u51fa\u7b26\u53f7":45,"\u9700\u8981\u6ce8\u610f\u7684\u662f":[42,63],"\u9700\u8981\u7d2f\u52a0\u4e0d\u540clayer\u4f20\u8fc7\u6765\u7684\u68af\u5ea6":42,"\u9700\u8981\u88ab\u66b4\u9732\u5230\u5176\u4ed6\u8bed\u8a00":46,"\u9700\u8981\u91cd\u547d\u540dwheel\u5305\u4e2dplatform\u76f8\u5173\u7684\u540e\u7f00":63,"\u9ed8\u8ba4256k":27,"\u9ed8\u8ba4\u8bbe\u7f6e\u4e3a":41,"abstract":[18,19,26,30,53,62,64,74,105],"api\u4e2d\u4f7f\u7528":45,"api\u5bfc\u51fa\u7684\u52a8\u6001\u5e93":46,"api\u5bfc\u51fa\u7684\u9759\u6001\u5e93":46,"api\u63a5\u53d7\u7684\u7c7b\u578b\u5168\u662f":46,"api\u63a5\u53e3":27,"api\u63a5\u53e3\u7684\u53c2\u6570\u8f6c\u53d1\u7ed9":46,"api\u65f6":46,"api\u65f6\u6240\u552f\u4e00\u9700\u8981\u5f15\u5165\u7684\u5934\u6587\u4ef6":46,"api\u662f\u591a\u8bed\u8a00api\u7684\u57fa\u7840\u90e8\u5206":46,"api\u66b4\u9732\u7684\u7c7b\u578b":46,"api\u751f\u6210\u7684\u4e8c\u8fdb\u5236\u6587\u4ef6\u4f1a\u88ab\u5b89\u88c5\u5230":46,"api\u7684\u5b9e\u4f8b":46,"api\u7684\u5b9e\u73b0\u7ec6\u8282":46,"api\u7684\u63a5\u53e3":46,"api\u7684\u65f6\u5019\u63a8\u8350paddle\u4e0d\u5d4c\u5165python\u89e3\u91ca\u5668":46,"api\u7684\u7f16\u8bd1\u9009\u9879\u9ed8\u8ba4\u5173\u95ed":46,"api\u76ee\u5f55\u7ed3\u6784\u5982\u4e0a\u56fe\u8868\u6240\u793a":46,"api\u83b7\u5f97\u4e86\u795e\u7ecf\u7f51\u7edc\u7684\u53c2\u6570\u5b9e\u4f8b":46,"apis\u505a\u4e86\u5c01\u88c5":41,"block\u6784\u6210\u4e00\u4e2amodel":10,"book\u4e2d\u6240\u6709\u7ae0\u8282\u529f\u80fd\u7684\u6b63\u786e\u6027":63,"boolean":[26,28,36,45,69],"break":[8,67,69,70,71],"bugfix\u5206\u652f\u4e5f\u662f\u5728\u5f00\u53d1\u8005\u81ea\u5df1\u7684fork\u7248\u672c\u5e93\u7ef4\u62a4":63,"bugfix\u5206\u652f\u9700\u8981\u5206\u522b\u7ed9\u4e3b\u7248\u672c\u5e93\u7684":63,"byte":[27,44],"c99\u662f\u76ee\u524dc\u6700\u5e7f\u6cdb\u7684\u4f7f\u7528\u6807\u51c6":45,"c\u6709\u6807\u51c6\u7684abi":45,"c\u8bed\u8a00\u662f\u6709\u5bfc\u51fa\u7b26\u53f7\u7684\u6807\u51c6\u7684":45,"case":[12,18,20,21,26,30,40,46,53,57,59,60,69,74,75,93,97,106,110,116,121],"char":14,"ci\u73af\u5883\u4f7f\u7528":63,"ci\u7f16\u8bd1wheel\u5b8c\u6210\u540e\u4f1a\u81ea\u52a8\u5c06docker\u955c\u50cfpush\u5230dockerhub":63,"class":[4,7,18,19,20,21,24,25,29,30,31,32,34,35,37,40,45,49,50,55,56,60,61,62,64,65,66,68,70,75,76,77,104,111],"compute\u51fd\u6570":41,"const":[7,12,14,19,29,31,37,38,39,54,55,57,61,64,66,68,70,74,75,76,77],"core\u4e2d\u7684\u6a21\u578b\u8fd8\u5728\u4f7f\u7528\u8fd9\u4e2a\u53c2\u6570":46,"core\u4e2d\u8fd9\u4e00\u7c7b\u578b\u63a5\u53e3\u7684\u667a\u80fd\u6307\u9488":46,"core\u662f\u5426\u8fd8\u5728\u4f7f\u7528\u8fd9\u4e2a\u5b9e\u4f8b":46,"core\u6982\u5ff5":46,"data\u5230\u5206\u5e03\u5f0f\u5b58\u50a8\u8865\u5145\u8bad\u7ec3\u6570\u636e":11,"default":[0,1,3,4,7,8,18,20,24,33,37,44,47,48,57,58,64,65,66,69,71,72,75,76,92,95,97,99,105,107,109,118,119,120,121],"device\u5c31\u80fd\u62ff\u5230\u6b63\u786e\u7684\u6570\u636e":42,"dnn\u4e09\u8005\u5173\u7cfb\u5982\u4e0b\u8868":42,"dnn\u4e2d\u7684":42,"dnn\u4e2d\u7684\u6392\u5217\u65b9\u5f0f\u4e0d\u6b62\u8fd9\u4e00\u79cd":42,"dnn\u4f1a\u4f5c\u4e3a\u7b2c\u4e09\u65b9\u5e93\u96c6\u6210\u8fdbpaddlepaddl":42,"dnn\u4f1a\u7528\u5230":42,"dnn\u5171\u540c\u4f7f\u7528":42,"dnn\u524d\u540e\u7684cnn\u7f51\u7edc\u6027\u80fd":42,"dnn\u5728\u53d1\u5e03":42,"dnn\u5b9e\u73b0":42,"dnn\u5e0c\u671b\u7684\u683c\u5f0f":42,"dnn\u6570\u636e\u7684\u4e0d\u540c\u683c\u5f0f\u4ee5\u53ca\u76f8\u4e92\u4e4b\u95f4\u7684\u8f6c\u6362":42,"dnn\u7684":42,"dnn\u7684\u5e93\u76ee\u524d\u53ea\u6709\u52a8\u6001\u5e93":42,"dnn\u7684\u6027\u80fd":42,"dnn\u7684\u60c5\u51b5\u4e0b":42,"dnn\u7684\u64cd\u4f5c\u90fd\u662f\u76f4\u63a5\u8986\u76d6\u7684\u5f62\u5f0f":42,"dnn\u7684\u6d4b\u8bd5":42,"dnn\u7684\u73af\u5883\u4e0b":42,"dnn\u7684\u76f8\u5173\u529f\u80fd":42,"dnn\u7684\u7ed3\u679c":42,"dnn\u7684\u9ad8\u6027\u80fd\u683c\u5f0f\u4e0epaddlepaddle\u539f\u6709\u7684":42,"dnn\u7684layer":42,"dnn\u7684layers\u90fd\u4f1a\u7ee7\u627f\u4e8e":42,"enum":[12,14,20,47,55,56,65,66,71,76],"export":[1,30,35,78,92],"final":[5,6,21,35,48,49,67,70,74,75],"float":[24,29,37,39,66,68,74,75,76,77,107,110],"function":[4,6,7,9,13,14,15,17,18,19,20,21,24,25,29,31,34,37,43,48,49,53,54,55,56,57,59,60,61,62,64,66,70,74,75,76,77,92,93,105,109,110,116,121],"golang\u53ef\u4ee5\u4f7f\u7528":45,"golang\u7684":45,"gpu\u7b49":63,"h\u5e76\u4e0d\u56f0\u96be":45,"images\u6570\u636e\u96c6\u4e0a\u4f20\u5230\u4e91\u7aef\u7684":11,"import":[3,4,7,8,18,20,23,31,33,35,36,43,48,49,56,64,67,75,87,92,93,97,110,116,120],"ingress\u9700\u8981\u628apfsclient\u7684\u8eab\u4efd\u4fe1\u606f\u4f20\u7ed9pfsserv":27,"instance\u4e0e\u751f\u6210\u6570\u636e\u96c6\u65f6":11,"instance\u5305\u6db5\u4e24\u4e2a\u503c":11,"instance\u662f\u4e00\u6a21\u4e00\u6837\u7684":11,"int":[6,7,12,13,14,17,18,20,22,36,37,41,42,43,45,46,55,56,58,59,65,66,68,70,74,76,77,92,107],"interface\u6587\u4ef6\u7684\u5199\u6cd5\u975e\u5e38":45,"layer\u65f6":42,"layer\u7684\u540e\u9762\u63a5\u6709cpu":42,"list\u4f5c\u4e3a\u68c0\u67e5\u5217\u8868":63,"long":[20,110],"mkl\u5e93\u7684":41,"mklml\u4ee5\u53camkl":42,"mklml\u53ef\u4ee5\u4e0emkl":42,"mklml\u7684\u5e93\u76ee\u524d\u90fd\u662f\u52a8\u6001\u5e93":42,"mode\u4e0b\u7684\u7ed3\u679c":41,"model\u505a\u5206\u652f\u7ba1\u7406":63,"ndarray\u7c7b\u578b\u7684\u503c\u548c\u6574\u578b\u7684\u503c":11,"new":[0,5,6,7,8,9,12,13,14,15,16,19,20,21,24,29,30,40,41,43,47,49,53,58,59,60,62,66,67,70,72,87,97,99,121],"note\u7684\u4e66\u5199":63,"null":[35,74,105],"op\u7684\u4fe1\u606f":42,"openmp\u7528\u4e8e\u63d0\u9ad8mklml\u7684\u6027\u80fd":42,"org\u76ee\u524d\u9075\u5faa":63,"packed\u4f18\u5316\u540elayer\u7684\u6d4b\u8bd5":41,"packed\u76f8\u5173\u529f\u80fd":41,"paddle\u4e00\u4e2a\u52a8\u6001\u5e93\u53ef\u4ee5\u5728\u4efb\u4f55linux\u7cfb\u7edf\u4e0a\u8fd0\u884c":45,"paddle\u5185\u5d4c\u7684python\u89e3\u91ca\u5668\u548c\u5916\u90e8\u4f7f\u7528\u7684python\u5982\u679c\u7248\u672c\u4e0d\u540c":45,"paddle\u5185\u90e8\u7684\u7c7b\u4e3ac":45,"paddle\u7684\u591a\u8bed\u8a00\u63a5\u53e3\u5b9e\u73b0\u5305\u62ec\u4e00\u4e0b\u51e0\u4e2a\u65b9\u9762":45,"paddle\u7684\u7c7b\u578b\u5168\u90e8\u9000\u5316\u6210":46,"paddle\u7684\u94fe\u63a5\u65b9\u5f0f\u6bd4\u8f83\u590d\u6742":45,"paddle\u7684c":46,"paddle\u8bad\u7ec3\u4efb\u52a1":11,"paddle\u8def\u5f84\u4e0b":46,"paddle\u9700\u8981\u4e00\u4e2a\u591a\u8bed\u8a00\u63a5\u53e3":45,"paddle\u9700\u8981\u66b4\u9732\u7684api\u5f88\u591a":46,"paddle\u9759\u6001\u5e93\u94fe\u63a5\u590d\u6742":45,"paddle_\u7c7b\u578b\u540d":46,"paddle_\u7c7b\u578b\u540d_\u51fd\u6570\u540d":46,"paddlepaddle\u4e2d\u7684cudnn\u90e8\u5206\u4f7f\u7528\u7684\u4e5f\u662f":42,"paddlepaddle\u4f7f\u7528git":63,"paddlepaddle\u5f00\u53d1\u8fc7\u7a0b\u4f7f\u7528":63,"paddlepaddle\u63d0\u4f9b\u4e13\u7528\u7684":11,"paddlepaddle\u6bcf\u6b21\u53d1\u65b0\u7684\u7248\u672c":63,"paddlepaddle\u6bcf\u6b21\u53d1\u7248\u672c\u9996\u5148\u8981\u4fdd\u8bc1paddlepaddl":63,"paddlepaddle\u7684\u4e3b\u7248\u672c\u5e93\u9075\u5faa":63,"paddlepaddle\u7684activation\u4f1a\u76f4\u63a5\u4f7f\u7528":42,"patch\u53f7":63,"patch\u53f7\u52a0\u4e00":63,"pfsclient\u9700\u8981\u548cingress\u4e4b\u95f4\u505a\u53cc\u5411\u9a8c\u8bc1":27,"pfsclient\u9700\u8981\u5728\u4f20\u8f93\u5b8c\u6bd5\u6700\u540e\u4e00\u4e2achunk\u7684\u65f6\u5019\u68c0\u67e5destination\u6587\u4ef6\u7684md5\u503c\u662f\u5426\u548csource\u6587\u4ef6\u4e00\u81f4":27,"pfsserver\u63d0\u4f9brest":27,"public":[7,19,29,32,37,55,61,64,66,67,68,70,74,75,76,77,92,97,99],"py\u4e2d":63,"pypi\u4e0a\u7684package\u540d\u79f0\u4e3apaddlepaddle\u548cpaddlepaddl":63,"pypi\u4e0d\u652f\u6301\u8986\u76d6\u4e0a\u4f20":63,"reader\u7684\u4f7f\u7528\u65b9\u5f0f\u90fd\u662f\u4e00\u81f4\u7684":11,"reader\u8f93\u51fa\u7684data":11,"resnet\u7684mkl":42,"return":[4,5,6,7,11,12,14,17,18,19,20,25,29,31,32,33,35,37,38,40,43,48,49,50,55,56,57,61,64,66,68,70,74,75,76,77,93,97,116],"rnn\u90e8\u5206\u4e2d":41,"s3\u4e4b\u7c7b\u7684\u5206\u5e03\u5f0f\u5b58\u50a8\u4e4b\u4e0a":11,"server\u4e4b\u4e0a":10,"server\u4e4b\u95f4\u7684\u7f51\u7edc\u5e26\u5bbd":10,"server\u4f1a\u6682\u505c\u53c2\u6570\u66f4\u65b0\u5e76\u7b49\u5f85":10,"server\u4f1a\u83b7\u53d6parameters\u5185\u5b58\u7684":10,"server\u5185\u5b58\u4e2d\u7684\u6a21\u578b\u6570\u636e\u7684\u5b8c\u6574\u955c\u50cf":10,"server\u540c\u6b65\u7684\u4fdd\u5b58\u4e00\u4e2a\u7279\u5b9a\u65f6\u95f4\u70b9\u7684\u5168\u5c40\u68c0\u67e5\u70b9":10,"server\u5728\u96c6\u7fa4\u4e2d\u542f\u52a8\u540e":10,"server\u6545\u969c\u540e\u88abkubernetes\u91cd\u65b0\u542f\u52a8":10,"server\u6b64\u65f6\u8fd8\u9700\u8981\u901a\u8fc7\u7f51\u7edc\u8bbf\u95ee\u5206\u5e03\u5f0f\u5b58\u50a8\u4ee5\u4fdd\u5b58\u5feb\u7167":10,"server\u751f\u6210\u4e00\u4e2auuid":10,"server\u7684\u5355\u70b9\u6216\u591a\u70b9\u540c\u65f6\u6545\u969c":10,"server\u7684\u6570\u636e\u5feb\u7167":10,"server\u7684\u68c0\u67e5\u70b9\u5404\u81ea\u72ec\u7acb\u4fdd\u5b58":10,"server\u7b2c\u4e00\u6b21\u542f\u52a8\u6216\u4efb\u610f\u65f6\u95f4paramet":10,"short":[29,33,58,64,67,70,75],"static":[14,46,64,66,97,119,121],"super":[58,74],"swig\u652f\u6301\u7684\u8bed\u8a00\u6216\u8005\u89e3\u91ca\u5668\u6709\u5c40\u9650":45,"swig\u66b4\u9732\u7684\u63a5\u53e3\u4fdd\u7559\u4e86c":45,"swig\u751f\u6210\u7684\u4ee3\u7801\u4e0d\u80fd\u4fdd\u8bc1\u591a\u8bed\u8a00\u4ee3\u7801\u98ce\u683c\u7684\u4e00\u81f4\u6027":45,"swig\u76f4\u63a5\u8bfb\u53d6c":45,"swig\u9700\u8981\u5199\u4e00\u4e2ainterface\u6587\u4ef6":45,"switch":[7,46,97],"tag\u4e3a":63,"tag\u53ef\u4ee5\u662flatest\u6216latest":63,"tag\u7684\u66f4\u65b0\u65f6\u95f4\u662f\u5426\u5728\u4e0a\u8ff0\u7f16\u8bd1wheel\u5305\u5b8c\u6210\u540e\u662f\u5426\u6700\u65b0":63,"throw":97,"true":[4,6,7,12,30,36,41,50,52,56,57,58,59,63,66,70,74,92,97,105,107,116],"try":[0,1,3,8,9,12,13,14,30,35,40,43,59,64,67,93,110,119],"type\u5b57\u6bb5\u5747\u4e0d\u5c3d\u76f8\u540c":46,"var":[6,7,18,19,20,24,31,32,34,36,39,50,52,56,57,58,60,64,69,70,78],"void":[7,12,14,19,26,29,31,32,37,39,43,44,45,46,56,57,65,66,68,74,75,76,77],"wheel\u5305":63,"while":[7,16,19,20,30,35,38,40,49,53,54,59,62,64,68,75,77,105,116],AGE:[97,99],AWS:[11,96,101,102],Added:67,And:[12,16,17,26,33,35,47,51,52,55,59,64,68,97,107,116],But:[3,5,32,38,47,55,64,72,94,121],For:[0,1,4,6,7,13,14,15,17,18,19,21,24,25,30,31,32,34,37,39,40,44,47,48,49,53,54,55,56,57,58,59,60,61,62,65,66,67,68,71,72,74,75,76,77,87,92,93,104,105,107,109,110,116,118,120,121],IDE:[0,119],IDs:[16,20,49],IPs:92,IRs:21,Into:97,Its:[31,65,75,97,116],K8s:121,NOT:[58,75],Not:[0,3,4,9,40,67,121],OPs:[21,23,93],One:[5,16,39,44,47,52,64,67,74,105,116],Ops:[60,62,66,75],PFS:27,PRs:78,QoS:99,Such:[37,58,67,70],TLS:[4,27,97],That:[1,19,51,105,107],The:[0,1,3,4,5,6,8,9,13,15,16,17,19,20,21,23,24,25,28,29,31,35,38,39,40,43,44,46,48,49,51,52,53,55,56,57,58,59,62,64,65,66,67,68,70,71,72,74,75,76,77,78,93,94,95,96,97,99,103,105,107,109,110,111,116,118],Their:9,Then:[1,3,18,21,32,37,40,51,55,57,74,93,94,97,99,100,109,110,116],There:[4,7,8,9,14,16,17,20,21,28,29,30,35,40,47,48,49,52,53,54,55,58,62,64,65,68,75,97,110,118,119],These:[0,6,7,19,24,29,34,50,62,65,66,67,71,96,107],Use:[0,4,22,28,59,60,67,74,92,94,97,105,106,109,110,120],Used:[60,68],Uses:[40,119],Using:[0,9,30,53,59,60,62,64,77,99],VMs:0,VPS:97,WITH:120,With:[18,19,24,30,51,56,67,70],YES:17,Yes:[0,1,42],___fc_layer_0__:97,__align__:29,__cuda_align__:29,__device__:29,__doc__:66,__file__:17,__forceinline__:29,__fp16:29,__global__:29,__hadd:29,__half:29,__half_raw:29,__impl__:66,__init__:[24,25,33,40,50,58,70,74,109],__main__:33,__metaclass__:75,__name__:33,__rnn_step__:116,__va_args__:61,__x:29,_addup_repetitive_outputs_:6,_append_backward_ops_:[6,24],_append_backward_vars_:6,_binari:8,_create_global_var:58,_def:40,_dtype:35,_filer:43,_filter:43,_fwd:43,_fwd_pd:43,_input:43,_librari:8,_live_in:40,_live_out:40,_loss:33,_op:[35,75],_output:43,_presucessor:40,_program:40,_remove_no_grad_branch_:6,_reorder_input:43,_source_language_embed:116,_src_input:43,_sucessor:40,_target_language_embed:116,_test:8,_update_op:25,_use:40,_value_index:35,a75:29,a_op:75,a_prev:67,aaaaa:11,aaaaaaaaaaaaa:97,abi:118,abil:33,abl:[4,6,19,20,21,37,50,55,58,121],about:[1,3,5,7,8,17,23,28,31,40,48,59,64,66,67,68,75,87,97,104,105,109,110,118,120],abov:[0,1,2,4,5,6,7,8,9,13,18,20,21,29,30,31,32,34,39,43,48,49,50,51,53,55,56,58,66,67,69,70,72,75,76,77,87,93,97,99,109,110,118,121],abs:[5,33],abs_numerical_grad:5,absolut:[1,5,118,120],acc:21,acceler:[1,10,42,51,53,107],accept:[4,60,118],access:[3,4,8,13,16,17,18,20,21,58,92,116],accessmod:97,accessor:58,accord:[5,6,14,21,23,34,49,60,70,75,92,104,105,107],accordingli:74,account:[60,72,121],accoust:67,accrodingli:12,accumul:[9,14,25,51,52,53,67],accur:[5,16,55],accuraci:[25,67,74],achiev:[19,23,51,52,53,67,68,110],ack:105,acquir:30,across:[6,21,48,67],act1:35,act2:35,act:[7,19,21,35,49,58,70,87,93,111,116],act_output:66,act_typ:35,action:[20,97],activ:[8,35,40,49,52,55,58,62,66,74,77,78,87,105,116],actual:[12,24,30,33,35,39,43,47,53,66,68,77],actual_layout:43,adagrad:[53,65,92],adagradoptim:50,adam:[4,14,21,33],adapt:[39,55],add:[0,5,6,7,8,12,16,19,20,21,23,25,29,32,36,38,50,52,53,57,58,60,62,64,68,69,72,74,75,77,107,110,111,120],add_activ:58,add_bia:58,add_depend:8,add_execut:8,add_input:[48,74],add_memori:48,add_output:48,add_scalar:[7,49,56],add_sum:58,add_test:[8,74],add_two:[7,48],add_unittest_without_exec:74,addattr:[52,66,75],addbia:74,addcom:[66,75],added:[7,23,24,29,47,51,53,62,72,74,75,76],adding:[62,72],addinput:[52,66,75],addit:[6,20,51,55,60,62,70,71,75,77,93],addition:48,addmemori:43,addop:[32,77],addoutput:[52,75],addprimit:43,addprimitivedesc:43,addr:9,address:[1,9,14,18,21,93,95,100,103,105,110,121],addrow:74,addtyp:66,adjust:[6,24],admin:121,administr:[0,16,121],adopt:[29,33],advanc:[5,105,110,116],advantag:[5,29,30,53,59,103],adversari:[33,59],advic:110,affect:7,affili:49,afford:13,aforement:8,after:[0,1,6,7,8,13,14,16,21,22,23,24,26,28,29,40,43,51,54,55,58,67,72,74,75,76,77,95,97,99,103,105,107,109,116,118,119],aftern:55,again:[4,5,9,53,110],against:97,aggreg:[25,51,97],ago:8,agre:72,agreement:72,ahead:67,aid:110,alexnet_pass1:107,alexnet_pass2:107,algo:43,algorithm:[6,13,24,39,40,43,49,53,62,67,116],all:[0,1,4,6,7,8,9,12,14,16,17,18,19,20,21,22,24,26,28,30,33,34,35,38,40,43,44,46,47,48,49,50,51,52,53,55,56,58,60,66,67,68,74,77,92,93,94,95,97,99,104,105,107,110,111,116,118,119,120,121],all_output_nam:6,alloc:[14,17,40,43,52,68,74,77,107,111],allow:[4,14,18,19,21,24,30,52,53,62,72,74,97,105,110],allow_only_one_model_on_one_gpu:[104,105,107],allreduc:[51,52],almost:[0,95],alpha:[8,62],alreadi:[1,8,9,30,43,58,64,95,97,105,110,120],alreali:104,also:[0,1,3,4,6,7,8,12,15,19,20,21,29,30,32,33,34,35,38,40,47,48,49,52,53,54,55,56,57,58,59,62,64,66,67,68,70,71,74,75,78,93,94,99,103,110,116,118,121],altern:[75,109],although:[6,51],altogeth:121,alwai:[8,20,44,65,97,105],amazon:[97,99],amazonaw:97,amazonec2fullaccess:97,amazonelasticfilesystemfullaccess:97,amazonroute53domainsfullaccess:97,amazonroute53fullaccess:97,amazons3fullaccess:97,amazonvpcfullaccess:97,ambigu:[59,67],amd64:97,amd:47,amend:72,amodei:67,among:97,amort:51,amount:110,analys:55,analysi:[55,109,110],analyz:40,ancestor:[56,58],andd:97,andrew:40,android:120,android_abi:118,android_api:118,android_arm_neon:118,android_native_api_level:118,android_standalone_toolchain:118,android_toolchain:118,ani:[0,4,8,9,14,16,17,18,20,21,26,29,30,37,39,40,44,49,51,52,53,58,59,61,62,67,75,77,93,97,100,110,120],annoi:95,announc:29,anoth:[0,4,6,7,17,19,20,30,31,39,43,49,58,64,66,68,97,105],anroid_arm_mod:118,ans:97,answer:[18,30,72,97],anymor:51,anyth:[49,59,97],anytim:33,anywai:[109,118],apach:42,apart:71,api:[0,3,4,6,8,14,15,17,18,19,25,27,32,33,35,48,54,55,60,63,70,71,74,75,92,93,96,97,109,110,114,118,119,120,121],api_shar:8,api_test:8,api_trainer_config_helpers_lay:116,apiserv:97,apivers:[97,99],app:119,appar:6,appear:[18,30,34,68],appel:40,append:[6,24,25,49,58,59,67,72,74,92,116],append_backward:[6,50,52,109],append_clip_op:24,append_op:[24,38,58],append_oper:58,append_optim:52,appl:119,appleyard:110,appli:[33,34,51,52,55,64,74,116],applic:[18,20,29,30,31,34,58,60,72,75,96,97,99,109,110,121],applyl1:12,appoint:75,appreci:[67,72],approach:[21,22,23,51,53,54,62,67,118,120,121],approxim:53,apt:[1,109],arbitrari:[21,44,77],arch:118,archetectur:67,architectur:[0,29,67,94,118,119],archiv:[45,46],area:33,arg:[6,35,50,66,75,104],argu:57,argument:[0,6,7,12,13,21,50,54,57,58,72,74,94,105,106,116],arithmet:29,arm64:[118,119],arm64_standalone_toolchain:118,arm:[29,118,119,120],arm_standalone_toolchain:118,armeabi:118,armv7:[29,119],armv8:29,arn:97,around:[16,40,58,97,121],arrai:[14,18,20,34,49,56,58,59,60,70,75],arrang:70,array_to_lod_tensor:40,arrow:33,articl:[0,31,34,93,99,120],artifact:[3,63,97],artifici:40,arxiv:[33,67],as_step_input:7,asap:76,asduplic:52,asgd:53,ask:[6,9,16],asr:67,assgin:40,assign:[6,13,18,22,24,29,31,51,67,77,92,93,97,103,105,121],assigne:67,assignmemt:40,associ:[54,61,77],assum:[1,7,21,43,93,107,116],assumpt:21,ast:18,astyp:[59,75],asyc:9,async:[9,23,52,104],async_count:105,async_lagged_grad_discard_ratio:[92,105],async_lagged_ratio_default:[104,105],async_lagged_ratio_min:[104,105],asynchron:[9,20,51,55,94,105],atom:22,attr:[7,18,35,38,43,56,57,58,66,75,116],attr_map:66,attrdesc:56,attribu:43,attribut:[6,7,23,24,38,56,58,60,64,66,70,74,75],attributemap:75,attrproto:66,attrtyp:[56,66,75],attrvalu:66,auc:[25,104],aucvalidationlay:105,audio:67,augment:67,authent:97,author:[27,67,97],auto:[0,7,12,22,31,39,43,45,57,60,64,70,72,74,75,77,110],autom:[96,97],automat:[0,4,6,14,21,23,24,32,50,60,66,67,72,74,75,93,95,97,104,105,109,116,119],avail:[3,9,14,23,29,30,40,97,121],averag:[13,105],average_test_period:[104,105],avg:[93,110],avg_cost:[21,93,111],avg_loss_valu:93,avoid:[0,5,7,9,20,21,38,43,51,52,53,54,110],avx2:0,avx:[0,1],awai:30,await:99,awar:[4,18,20,25,31,48,58,97,109],awk:100,awni:67,aws:27,aws_account_id:97,awsaccountid:97,awskeymanagementservicepowerus:97,axiom:20,b363:99,b8561f5c79193550d64fa47418a9e67ebdd71546186e840f88de5026b8097465:99,ba5f:97,back:[1,6,9,21,29,33,53,75],background:[52,62,67,92],backpropag:[5,6],backward:[5,7,12,14,24,33,41,42,50,52,53,54,57,61,62,69,74,105,107,111,116],backward_first:116,backward_op:5,backwardactiv:74,bacth:19,baidu:[30,67,99],bake:21,balanc:[23,51,97,105],bandwidth:[29,51],bare:[93,99,121],barrier:[94,105],barrierstatset:110,basci:35,base:[4,13,19,24,25,29,30,37,43,47,50,51,53,55,60,61,62,68,70,74,75,97,105,109,110,111,116,118,119],baseerrorclipattr:24,baselin:67,basematrix:74,bash:[0,1,97,99,103],basic:[21,35,43,55,56,60,61,67,70,74,86],batch:[4,7,9,11,12,19,20,21,25,26,30,33,36,47,48,49,51,53,67,70,72,74,93,97,99,105],batch_id:33,batch_im:33,batch_label:33,batch_norm:[33,67],batch_read:[11,19,59],batch_siz:[21,33,41,49,93],batch_szi:33,batch_z:33,batchnorm:[33,67],batchread:19,batchsiz:74,bazel:8,bbbbb:11,bcm2708:120,bdist_wheel:63,beacus:35,beam:[105,116],beam_gen:116,beam_search:[49,116],beam_siz:[49,104,105,107,116],becaus:[0,4,5,7,8,9,14,29,39,49,54,58,59,62,64,65,69,70,71,74,77,93,97,107,109,116,118],becom:[22,23,64,68,110],been:[6,8,13,20,30,72],befor:[0,1,6,9,16,20,24,28,31,34,47,53,54,55,59,62,72,75,76,97,109,118,119,121],begin:[6,12,14,19,25,28,34,49,51,74,92],beginiter:4,beginn:116,beginpass:4,begintrain:4,behavior:[20,110],behind:[30,70,93],being:[6,16,24,30,57,59,77,109],belong:[19,21,64],below:[0,3,7,9,14,21,23,29,30,44,54,59,62,70,71,74,92,94,97,103,110,116,118,119],benchmark:[44,67],benefit:[16,17,49],besid:[3,21,40,47,51],best:[0,1,8,43,105],besteffort:99,beta:33,better:[8,30,39,40,43,49,97,119,121],between:[1,6,8,9,14,21,23,29,30,43,46,51,54,61,64,75,77,97,114],bia:[49,58,74,116],bias:74,bias_attr:[58,116],biases_:74,biasparameter_:74,biassiz:74,bidi:99,bidirect:[67,116],big:[18,23,40,110,121],bigger:9,bilinearfwdbwd:110,bin:[0,1,92,97,99,103],binari:[0,2,3,8,17,21,29,31,33,44,97,109,110],bind:[18,20,29,32,64,68],bit:29,bitcod:119,bla:[1,119],black:[33,119],blank:[97,119],blob:0,block0:[40,52],block1:[40,52],block2:[40,52],block3:52,block:[6,10,12,14,18,20,21,22,23,24,25,26,30,37,40,47,48,50,68,71,74,75,77,105,110],block_expand:67,block_id:[18,26],blockdesc:[7,34,52,58,60],blockdescbind:37,blockingcount:22,blueprint:49,book:[60,67,78,111,116],book_distribut:93,bool:[7,19,29,36,38,41,42,43,57,58,65,66,70,71,74,76,105,107],boost:[47,67,68,76],boot:[116,121],boot_lay:116,boot_stat:70,bootstrapp:121,borrow:[33,70],bos_id:116,both:[4,7,8,9,16,19,20,21,23,29,30,33,37,40,47,49,51,55,57,65,67,68,74,75,77,78,93,94,97,110,116,119],bottl:51,bottleneck:[55,110],bottom:67,bound:40,boundari:21,box:[33,110],brace:[7,34],brain:16,branch:[3,4,7,8,21,30,36,56,63,69,72,75,78],breadth:105,break_if:70,brief:[8,14,29,68,77],briefli:110,bring:[30,40,77],broadcast:[9,51,60,121],broken:72,browser:[1,78,97,109],bsd:[0,20,51],bsp:20,bucket_nam:97,buddy_alloc:72,buf:12,buf_siz:[21,93],buffer:[12,20,43,44,53,59,64,105,111],buffer_s:20,buffered_read:59,bug:[72,97],build:[1,3,8,17,21,34,35,40,42,53,62,63,66,67,72,75,81,87,89,93,97,101,102,103,105,109,117],build_android:118,build_model:33,builder:72,buildtool:63,built:[0,3,8,18,21,29,31,40,47,51,66,67,70,109,118,120,121],bulk:20,bunch:[44,103,110],button:[72,78,97],c11:45,c703c041:72,c99:46,c99e:97,cach:[0,29],cacul:[25,92],caff:[7,30],caffe2:[7,18,20,30],calcul:[1,5,6,9,14,22,25,29,40,74,94,105,107,110,116],calcut:40,calendar:55,call:[0,4,5,6,7,12,13,14,15,17,18,20,21,24,31,33,34,40,48,49,50,52,55,58,60,61,64,66,68,70,74,75,76,77,87,93,97,103,105,109,110,116],callback:[24,74],caller:[5,97,109],can:[0,1,2,3,4,5,6,7,8,9,12,13,16,17,18,19,20,21,23,24,26,29,30,31,32,33,34,35,37,38,39,40,43,47,48,49,50,51,52,53,55,56,57,58,59,60,61,62,66,68,70,71,72,74,75,76,77,78,87,92,93,94,95,96,97,99,100,103,104,105,107,109,110,116,118,119,120,121],cancel:16,candid:[49,67],cannot:[19,39,60,64,70,74,75],cantain:35,capabl:[29,54,60],capac:[62,97],capi:[0,45],capi_prvi:46,caption:49,captur:95,card:[51,93,103],care:[1,17,40,59,67,68,104,105,121],carefulli:[67,105],carpedm20:33,cast:[29,39],cast_to_op_attr:66,cat:[1,100],categor:75,categori:9,categoryfil:99,caus:[3,9,28,75],caution:[97,99],cbla:41,cc_:8,cc_binari:8,cc_test:8,cclient:15,cduadevicecontext:[47,68],cento:[0,3,87,121],central:[62,93],ceph:[11,99],cephf:[11,17,27],cer:67,certain:[19,38,47,50,55,64,68,76,104],certif:[4,27,97],cffi:45,cfg:[40,99],cgo:45,ch1:20,ch2:20,chain:[6,34,74],challeng:[5,9,30,36,68],chan:20,chanc:[4,29,74],chang:[0,8,13,17,21,30,43,54,56,59,61,63,64,67,72,74,75,77,92,93,97,105,110,116,118],changes:43,channel:[18,71,110],chapter:[48,49,67,93],chapter_data:48,chapter_out:48,charact:[20,67],characterist:107,check:[0,3,6,7,8,24,43,57,60,69,72,75,78,97,103,105,107],check_attr:66,check_eq:74,check_grad:[5,75],check_l:74,check_output:75,check_sparse_distribution_batch:[104,105],check_sparse_distribution_in_pserv:[104,105],check_sparse_distribution_ratio:[104,105],check_sparse_distribution_unbalance_degre:[104,105],check_styl:72,checker:[5,60],checkgrad:105,checkgrad_ep:105,checkmark:121,checkout:72,checkpoint:[23,57],checksum:27,child:7,china:[1,118],chines:78,chip:30,chmod:97,choic:[1,8,30],choos:[0,1,2,20,38,76,105,118],chosen:[33,47],chunk:[13,27],circl:34,circular:20,circumst:68,claim:97,claimnam:97,clang:[29,45,72,118],clariti:49,classic:[40,67],classif:[34,107],classifi:33,claster:97,clean:[0,7,8,26,54,60,72],clear:[8,39,49,54,64,120],clearer:[54,58],clearli:64,cli:97,click:[3,72,78,97,109,110],client:[12,15,60],clip:105,clip_op:24,clip_op_desc:24,clipe:52,clone:[0,72,78,109,118,120],close:[20,59,72],close_channel:20,cloud:[8,9,17,27,28,60,121],cludform:97,cluster:[4,7,9,14,21,67,81,92,94,99,103,104,105],cluster_test_fil:92,cluster_train:95,cluster_train_fil:92,cluster_train_v2:[95,96,100],cm469:97,cmake:[0,46,72,74,75,78,93,109,110,118,119],cmake_build_typ:[109,118,119,120],cmake_c:119,cmake_install_prefix:118,cmake_system_nam:[118,119,120],cmakelist:[8,41,42,74],cmatrix:[45,46],cmd:99,cname:97,cnn:99,coars:32,code:[0,1,3,4,6,8,16,19,20,21,23,26,29,32,33,34,38,44,47,50,52,53,54,55,57,59,60,61,62,66,70,73,74,75,76,77,78,87,92,93,97,99,110,116],codebas:[60,72],collabor:9,collect:55,collectbia:74,column:[34,59,74,109],com:[0,1,8,33,63,72,78,97,99,109,111,118,120,121],combin:[40,50,60,64],come:[21,25,40,56,67,70,71],comma:[14,93,105],command:[0,1,3,8,12,17,28,72,74,75,78,87,93,94,95,97,99,100,101,102,103,108,109,110,118,119,120],commandlin:110,comment:[8,35,66,67,72,75],commit:[8,72,92],common:[11,62,68,74,104,116],commonli:[28,62,107,109,110,116,120],commun:[9,14,15,20,21,23,51,72,74,92,93,97],compani:30,compar:[0,5,8,18,60,74,75],comparis:114,comparison:[8,30,76],compat:[29,32,51],compil:[8,21,30,35,37,40,47,51,61,65,66,71,74,78,103],complaint:8,complet:[2,6,7,9,13,14,24,27,34,44,47,60,74,75,77,93,97,99,109,121],complex:[16,20,40,49,60,110,116],complic:[21,32,39,59,70],compon:[20,21,35,67,70,71,74,76],compos:[4,20,32,35,48,58,60],composit:32,compress:13,compris:6,compromis:0,comput:[0,1,4,5,9,20,21,23,26,29,30,31,35,39,40,44,47,50,51,52,53,55,61,64,67,68,71,72,74,75,76,93,96,97,103,107,109,110,111,116,118,119,120],computation:116,computationgraph:35,con:51,concat:[33,116],concaten:[33,48,70],concentr:60,concept:[4,18,19,20,30,32,33,35,43,48,49,53,54,56,64,70,71,86,116],conceptu:[20,26,30,33,35],concern:[4,20,25,119],concis:[33,70],conclud:75,concret:[60,68,75],concurr:[9,16,23,55,94],concurrentremoteparameterupdat:105,cond:[7,30,36,56],condit:[13,21,30,36,43,67,69,99,116],condtion:33,conduct:110,conf:95,conf_paddle_gradient_num:97,conf_paddle_n:97,conf_paddle_port:97,conf_paddle_ports_num:97,conf_paddle_ports_num_spars:97,config:[11,28,49,74,97,99,104,105,121],config_:[12,105],config_arg:[104,105,107],config_lay:74,config_len:14,config_pars:[41,42,74],config_proto:14,configmap:21,configur:[0,6,12,14,16,17,21,23,30,35,38,39,58,67,68,72,74,75,77,81,87,92,93,105,110,114,118,120,121],confirm:28,conflict:[64,72],confus:[33,38],congest:105,connect:[17,18,21,23,67,74,92,93,97,99,103,121],consid:[0,6,57,68,107,110,121],consider:[47,67],consist:[13,19,20,31,44,56,59,60,61,66,67,71,75],consol:[97,110],consolid:[7,78],constant:[35,37,38,47,74,75],constraint:64,construct:[4,26,35,40,48,58,60,64,66,76,116],constructbackwardgraph:34,constructoptimizationgraph:34,constructor:[24,29,55,58,60,64,66,74,75],consum:[9,109],consumpt:40,contact:16,contain:[0,2,3,4,6,7,13,26,33,35,43,44,47,54,55,58,60,61,64,65,66,67,70,71,75,92,93,97,100,103,116,119],container:96,containerport:97,content:[14,28,44,49,78,99],content_dir:78,content_len:14,context:[24,43,64,65,68,75,77,111,116],contin:97,continu:[6,9,44,67,94,105,118],contrib:62,contribut:[62,67,73],contributor:[60,72],control:[7,18,20,69,92,97,99,105,121],controlflowgraph:40,conv2d:[33,76],conv:[33,39,43],conv_fwd:43,conv_pool_2:21,conveni:[4,6,35,50,66,67],convent:[6,14,72,75],converg:95,convers:[29,30],convert:[11,21,22,23,29,30,31,43,59,61,67,93],convlut:67,convolut:[33,47,58,68],convolution_algorithm_opt:43,cool:72,cooper:67,coordin:[9,14],copi:[0,4,13,16,28,34,48,49,51,53,70,72,92,97,100],copy_from:24,copyvariablewithtensor:39,core:[0,6,35,38,46,53,54,70,105,111],coreo:[97,121],corner:60,corpu:67,correct:[5,6,29,51,74,75,76,97],correctli:[6,29,33,74],corresond:29,correspoind:4,correspond:[4,6,7,8,24,29,35,36,43,47,48,49,58,60,61,62,66,68,69,74,75,76,77,109,119],correspondingli:119,corss_entropi:4,cortex:29,cos:66,cosin:66,cosineop:66,cosineopproto:66,cosineopprotomak:66,cost:[4,6,21,34,39,50,51,56,57,93,105,111],cost_np:57,could:[0,4,5,13,18,20,21,22,23,29,30,31,48,50,53,54,56,58,59,61,69,76,95,97,109,110,118],count:[9,17,25,57,59,67,92,93,99,105,107,110],counter:[9,13,22,34],cours:[0,17,47],cover:[30,67,77],cp27:3,cp27m:[3,63],cp27mu:[3,63],cpp:[5,12,32,41,42,45,46,54,60,71,74,76,110],cprofil:109,cprofilev:109,cpu:[0,1,5,17,29,38,39,47,52,53,54,55,60,62,63,68,75,76,77,99,105,109,110,111],cpu_avx_mkl:[1,3],cpu_avx_openbla:[3,87],cpu_kernel:38,cpu_noavx_openbla:3,cpu_ns_:55,cpu_per_pserv:21,cpu_per_train:21,cpudevicecontext:[47,68,75,76],cpuelapsedu:55,cpuengin:42,cpuinfo:1,cpuplac:[21,38,39,43,47,52,68,75,76,77,93,111],cpusparsematrix:46,crash:[9,95,105,110],creat:[1,4,5,7,9,14,18,19,22,24,25,26,27,28,29,30,32,33,34,43,47,48,50,51,53,54,58,61,62,67,72,74,75,78,87,92,93,100,105,118,121],create_backward_pass:50,create_bias_paramet:74,create_block:58,create_doc_str:66,create_input_paramet:74,create_local_scop:26,create_oper:32,create_optimization_pass:50,create_paramet:58,create_python_ops_creatation_funct:66,create_rnn:7,create_rnn_op:48,create_tmp_var:58,create_tmp_vari:58,create_var:58,create_whileloop:70,creategradientoper:61,creatememori:43,createop:66,createoper:7,createprimitivedesc:43,createstack:97,createvari:7,creation:[32,97],creationd:97,creator:[11,60,61],creator_:61,credenti:28,crf:[39,68],critic:[33,109],crlf:72,crop:68,crop_grad:68,cropgradkernel:68,cropkernel:68,cross:[58,75],cross_compil:120,cross_entropi:[4,21,33,39,40,52],crt:27,csc:74,csr:74,ctc_error_evalu:67,ctest:[0,75],ctor:58,ctrl:[0,95],ctx:[39,43,75,77],cubla:[47,76],cublas_handle_:68,cublashandle_t:68,cuda7:[3,87],cuda8:[0,1,3],cuda:[1,3,8,31,47,55,60,68,75,76,93,103,105,110],cuda_context:31,cuda_dir:[104,105],cuda_fp16:29,cuda_so:1,cudaconfigurecal:110,cudadevicecontext:[31,47,68,75],cudadevicegetattribut:110,cudaelapsedu:55,cudaevent_t:55,cudaeventcr:110,cudaeventcreatewithflag:110,cudafre:110,cudagetdevic:110,cudagetdevicecount:110,cudagetdeviceproperti:110,cudagetlasterror:110,cudahostalloc:110,cudalaunch:110,cudamalloc:110,cudamemcpi:110,cudaplac:[39,47,68,76],cudaprofilerstart:110,cudaprofilerstop:110,cudaruntimegetvers:110,cudasetdevic:110,cudasetupargu:110,cudastream_t:68,cudastreamcr:110,cudastreamcreatewithflag:110,cudastreamsynchron:110,cudeviceget:110,cudevicegetattribut:110,cudevicegetcount:110,cudevicegetnam:110,cudevicetotalmem:110,cudnn:[8,38,39,43,47,68,76,105],cudnn_conv_workspace_limit_in_mb:[104,105],cudnn_dir:[104,105],cudnn_kernel:38,cudnnconvopkernel:76,cudnnv5:0,cudrivergetvers:110,cuinit:110,cumtim:109,cur_mem:49,curl:97,curli:[7,34],current:[0,1,3,6,7,8,9,12,14,18,23,25,30,38,39,47,48,49,53,54,55,58,64,70,74,78,92,93,95,97,105,116,119],current_block:[56,58],current_endpoint:93,current_oper:56,current_word:116,curv:4,custom:[4,17,29,33,49,53,60,67,74,97],custom_batch_read:59,cut:70,cxx:119,cxx_compil:[118,119,120],cxx_flag:119,cxxabi_1:3,cycl:9,cython:45,d3e0:97,d_b0:33,d_b1:33,d_b2:33,d_block:33,d_f:33,d_g:33,d_h0:33,d_h0_bn:33,d_h0_relu:33,d_h1:33,d_h1_bn:33,d_h1_relu:33,d_h2:33,d_loss:33,d_loss_fak:33,d_loss_real:33,d_optim:33,d_step:33,d_t:33,d_w0:33,d_w1:33,d_w2:33,daili:72,dandroid_abi:118,dandroid_arm_mod:118,dandroid_arm_neon:118,dandroid_standalone_toolchain:118,dangl:0,dario:67,darwin:97,dash:33,dat:11,data:[4,5,7,11,12,13,20,23,25,27,29,30,33,34,35,37,38,40,43,44,47,48,49,50,51,52,53,54,56,58,60,62,64,65,66,67,68,70,71,74,75,77,87,89,92,93,94,100,101,104,105,107,110,111,116],data_grad:52,data_i:33,data_lay:12,data_layout_:39,data_read:59,data_reader_creator_random_imag:59,data_shar:70,data_typ:[39,44,65,67,71,76,87,116],data_type_:[38,39,47],data_x:33,datacent:[11,28],datacenter1:11,datacenter2:11,datacenter_1:11,datacenter_2:11,datacenter_nam:11,datafeed:[93,111],dataflow:35,dataflow_analysi:40,datalayout:39,dataparallel:21,dataprovider_convert:67,dataset:[11,17,21,53,59,67,87,93,94,105,109,116],datatransform:39,datatyp:[38,39,43,65,67],date:92,dcgan:33,dcmake_install_prefix:[118,119,120],dcmake_system_nam:[118,119,120],dcuda_arch_nam:0,dcudnn_root:0,ddim:[19,47,68,77],dead:9,deal:[6,121],debug:[1,5,6,21,28,30,58,72,109],debug_str:35,decai:52,decayr:12,decent:13,decid:[4,16,33,44,53,61,62,65],declar:[7,33,48,71],decod:[67,116],decoder_boot:116,decoder_dim:49,decoder_group_nam:116,decoder_input:[49,116],decoder_mem:[49,116],decoder_s:116,decoder_st:116,deconv:33,decor:[19,74],decrement:22,decrementcount:22,decrypt:97,deduc:60,deep:[1,6,16,20,26,33,34,40,42,55,60,62,67,68,93,110,119],deeper:[1,31],deepspeech2:41,def:[4,5,6,11,17,24,25,32,33,35,38,40,48,49,50,58,59,66,70,74,75,116],def_block:33,defalut:[105,107],default_block:33,default_devic:107,default_main_program:[93,111],default_param_attr:58,default_st:70,default_start_up_program:52,default_startup_program:[93,111],default_valu:107,defaultdict:40,defaultinfervartyp:37,defect:54,defer:16,defin:[4,6,7,8,9,16,18,19,22,23,24,29,30,31,32,33,35,38,40,47,48,51,56,58,59,60,64,66,68,70,71,74,77,92,93,95,105,109,111,116],definit:[1,6,7,9,13,21,26,31,38,52,56,61,66,70,75,109,111],definiton:32,deivc:76,delai:[53,68,77,105],delet:[17,27,72],deletestack:97,deliv:121,delta:5,demand:[9,68],demo:[60,95,99,101],demolish:99,demonstr:[77,116],denot:[75,107],dens:[14,15,65,67,74,97],dense_vector:87,densescann:67,dep:8,depart:67,depend:[1,7,8,9,17,19,20,21,23,35,51,57,65,75,92,94,107,118,119,120,121],dependent_var:57,deploi:[95,107,121],deploy:[35,44,60,95,96,97,119,121],deprec:67,depth:[7,30,67],dequeu:23,deriv:[4,19,21,24,36,50,118],desc:[7,24,43,44,58,66,70],desc_:7,descend:70,descent:[9,53,94],descproto:44,describ:[4,6,7,8,13,18,21,26,31,38,39,43,44,48,49,54,56,58,60,65,66,71,74,75,76,77,97,99],describestack:97,describestackev:97,describestackresourc:97,descripotor:43,descript:[0,3,7,8,37,39,42,44,47,61,65,67,71,72,75,92,97,106],descriptor:[20,39,43],deseri:[44,54],deserializ:60,desgin:34,design:[6,12,19,38,40,45,53,55,62,75,121],desir:[9,21,53,97,99],destin:[14,28],destroi:[7,26],destruct:64,destructor:[55,74],detail:[0,5,6,13,17,21,23,28,30,33,35,39,40,43,44,47,48,55,58,62,64,68,70,71,74,75,76,77,78,87,93,95,97,99,106,107,109,110,116,120,121],detect:[0,37,72,118],determin:[7,21,40,47,60,74],dev:[0,1,60,109,118,121],dev_ctx:[7,43,55],devel:63,develop:[0,1,3,6,8,30,37,54,55,58,61,63,67,72,77,78,92,104,105,109,111,117,119,120],deverlop:105,devic:[1,5,18,21,25,29,35,39,42,43,47,51,54,55,60,75,77,92,105,111,119],device_:55,device_context:[43,75],devicecontext:[7,47,55,75,76],deviceid:[42,107],deviceid_:42,deviceplac:68,devid:105,devot:67,devtools2:0,dhcp:121,diagnos:95,diagram:[48,94],diamond:33,dict:[6,58,92,100],dict_siz:[12,49],dictionari:[4,5,58,107],did:[1,54],diff_mat:5,differ:[1,5,6,7,8,9,14,16,19,21,22,23,24,25,26,29,30,33,35,36,39,40,43,47,49,51,53,55,57,61,64,67,69,70,71,74,75,76,77,92,94,95,97,99,105,109,116,119],differenti:32,difficult:[0,5,30],dig:[1,97,110],digit:92,digraph:35,dilat:43,dim0:75,dim1:75,dim:[12,43,44,48,60,65,68,71,74,75,77],dim_:[68,77],dimens:[33,60,65,67,68,70,74,75,77,107],dimension:[74,77,116],dios_arch:119,dios_enable_bitcod:119,dios_platform:119,dios_use_veclib_for_bla:119,dir:118,direcit:67,direct:[30,40,53,67,109],directli:[0,2,8,15,17,19,21,29,38,39,54,66,70,95,99,118],director:75,directori:[0,1,8,11,16,27,28,68,77,78,92,95,99,100,105,110,118,119,120],disabl:55,disadvantag:[53,58],discard:[9,13,49,92,105],discov:9,discoveri:97,discrep:110,discrim:33,discuss:[4,7,13,14,15,21,43,67],disk:[0,44,99],dispatch:[21,54,95,96,105],displai:[17,28,72],dist:[0,63],dist_train:[4,17],distinguish:[8,95],distribut:[3,7,13,14,15,16,18,20,25,31,51,60,67,71,92,95,99,101,102,108,121],distribute_test:[104,105],distributedli:[21,74],distributetranspil:93,disucss:4,divid:[6,25,66,71,104,109],diy_beam_search_prob_so:[104,105],django:78,dnn:[0,43,67],dns:97,do_forward_backward:59,doc:[0,35,48,70,75,77,78,92],doc_cn:78,docker:[0,2,63,72,78,97,101,102,103,121],docker_build:4,docker_clust:[95,100],docker_push:4,dockerfil:[118,120],dockerhub:1,document:[0,5,19,21,27,34,48,49,55,60,67,72,73,75,76,77,93,103,107,119],doe:[0,3,9,13,14,16,17,18,19,21,23,26,29,35,40,48,54,58,60,61,62,74,75,77,110,111],doesn:[0,1,4,7,18,20,59,72,99,109,110,118,119],doing:[12,16,21,34,52,110],domain:97,don:[0,1,4,8,32,34,40,59,67,72,75,78,97],done:[6,8,9,13,14,21,22,37,40,44,53,61,62,67,72,97,109,110],dot:[75,105],dot_period:[105,107],doubl:[0,21,29,34,39,55,75,76,105],down:[67,110],download:[0,1,3,8,9,12,16,27,92,94,119,121],dozen:8,draw:49,drive:64,driver:[1,93,103],drop:[19,49],dropout:74,drpi_arm_neon:120,drpi_toolchain:120,drwxr:99,ds2:67,dst:[14,43],dst_primitive_desc:43,dtoh:110,dtype:[20,21,35,58,93,111],due:[13,16,33,40,49,58,109],dummi:13,dump:44,duplic:[23,52],durat:[13,110],dure:[6,7,9,13,16,17,25,30,40,51,53,55,58,60,67,71,74,75,97,104,105,121],duse_eigen_for_bla:118,dwith_c_api:[46,118,119,120],dwith_distribut:93,dwith_doc:93,dwith_gpu:[0,93,120],dwith_profil:110,dwith_python:[46,93,120],dwith_swig_pi:[46,93,118,119,120],dwith_test:[0,75,119],dwith_tim:110,dynam:[0,14,46,48,58,59,105,110],dynamic_cast:74,dynamic_recurrent_op:70,e2e:121,each:[5,6,8,9,12,13,14,16,17,18,19,20,21,24,25,26,31,34,37,39,40,43,47,48,49,51,52,54,55,57,58,59,60,61,64,65,66,67,68,69,70,71,74,76,92,93,94,95,97,103,105,107,109,116,121],eager:30,earli:[29,31,72,75],eas:[37,75],easi:[5,6,49,53,59,60,62,72,74,95],easier:[0,4,23,29,30,59,69,70,72,74],easili:[4,33,51,55,59,61,64,68],echo:1,edg:40,edit:[0,1,20,97],editor:[0,58],edu:[97,99],eeoi3ezpr86c:97,effect:[0,97,105,119],effici:[0,21,44,59,67,68,74,116],effort:[21,67],efs:97,efs_dns_nam:97,efsvol:97,egd:40,eigen:[29,47,53,60,62,68,75,118,119],eigen_device_:68,eigen_test:77,eigen_use_gpu:75,eigenmatrix:77,eigenscalar:77,eigentensor:77,eigenvector:77,either:[2,4,21,33,36,37,48,53,62,110,119],elabor:67,elb:97,elbapis:97,electr:40,electron:99,element:[5,13,20,23,35,49,60,75,77],element_typ:[14,76],elementari:60,elif:[4,66,69],els:[0,1,4,12,17,20,21,23,24,30,33,36,37,38,40,64,66,69,74,75],elsewher:55,emac:0,email:72,emailweixu:8,emb1:12,emb2:12,emb:99,embed:[4,7,12,23,37,49,65,70,92,116],embedding_lay:12,embedding_nam:116,embedding_s:116,emphas:110,emplace_back:74,emploi:[6,24,66,116],empti:[6,9,19,20,49,75],emul:29,enabl:[7,8,13,18,23,24,35,55,72,92,97,105,110,119],enable_grad_shar:[104,105],enable_parallel_vector:105,enc_proj:116,enc_vec:116,encapsul:14,encod:[13,49,116],encoded_proj:116,encoded_sequ:116,encoded_vector:116,encoder_ctx:49,encoder_ctx_expand:49,encoder_ctx_proj:49,encoder_dim:49,encoder_out_seq:49,encoder_s:116,encount:12,encourag:[21,26],encrypt:97,encrypt_decrypt:97,end2end:121,end:[3,6,7,21,24,31,35,40,49,54,55,59,64,67,69,72,105,116],end_pass:4,endian:44,endif:[47,55],enditer:4,endpass:4,endpoint:[11,97],endtrain:4,enforc:[71,119],engin:[17,42,43,67,110],english:[67,78],enjoi:1,enough:[0,6,7,38,40,47],enqueu:23,ensur:[0,1,3,9,43,51,64,74,119],enter:[7,26],enterpris:60,entir:[14,16,75],entiti:[7,64],entranc:26,entri:[0,13,17,37,72,74,97,118],entropi:58,entry_point:17,enumer:47,env:[78,97,109],environ:[0,3,4,19,21,72,92,96,97,99,104,105,109,110,119],environmenterror:92,eos_id:116,epoch:33,epol:20,equal:[9,70,75,76,105],equat:[40,75],equip:116,equival:[4,7,18,20,24,30,36,66,121],eras:19,erlang:20,error:[4,5,13,28,29,30,43,64,67,74,75,95,97,105],error_clip:24,error_clip_callback:24,errorclipbyvalu:24,especi:[0,42],essenc:[4,6],essenti:[4,26,29,77],establish:18,estim:[4,23,53],eta:99,etc:[0,7,20,21,25,43,51,53,59,64,67,76,96,97,104,107,121],etcd:[9,13,14,16],etcd_addr:14,eth0:[92,97],etyp:20,eval:[7,25,33,60],eval_program:25,eval_result:25,evalu:[16,35,57,67,110,111],even:[0,4,29,51,58,59,72,105,110,119],evenli:[14,97],event:99,event_:55,event_block:55,event_handl:4,eventkind:55,eventlist:55,eventu:[21,70],everi:[4,9,13,14,16,24,25,34,35,37,39,40,43,47,48,51,58,64,66,72,74,75,77,92,94,100,103,105,111,116],everyon:72,everyth:[21,23,33,118],everywher:0,evid:54,evolv:30,exactli:[19,97],exampl:[0,7,17,19,21,23,25,28,30,31,32,33,34,35,37,39,40,43,47,48,49,54,55,56,58,59,60,61,62,65,68,69,70,72,74,75,76,77,92,93,96,97,99,104,105,107,109,110,111,116,120],except:[16,18,30,34,55,67,70,107],excess:40,exchang:54,exe:[21,93,111],exec:105,execut:[8,9,13,17,18,19,20,21,25,26,31,33,35,40,43,51,52,55,61,71,74,97,109,110],executioncontext:[39,43,75,76,77],executor:[18,21,25,29,30,31,33,39,50,52,56,58,71,93,109,111],exist:[0,3,4,7,9,19,28,30,49,58,59,61,66,68,70,74,77,97,105,119],exit:[14,28,93,99,105],expand:[1,49,74],expect:[39,110],expected_desc:43,expected_kernel_kei:39,experi:[44,67,107],experienc:72,expert:8,expir:9,explain:[9,18,30,32,34,72,76,93,94,109],explan:[17,18,21,39,64],explicit:[19,55,70,74,76],explicitli:[4,21,26,75,77,119],explod:24,explor:[49,62],expos:[6,15,20,43,44,68,70,97],express:[4,23,25,35,40,75,97],extend:[53,70],extens:[16,23,49,75,118],extent:46,extern:[8,42,45,46,60,67],external_librari:8,extingrad_:42,extinval_:42,extoutgrad_:42,extoutval_:42,extra:[21,62,68,121],extraattr:107,extract:[30,54,67,75,97],extrem:[18,30,110],f120da72:99,f7e3:97,fa0wx:99,fabric:96,face:[8,62],fact:[18,30,51,56,58],factori:45,fail:[9,13,49,75,99,105,107],failur:[9,14,75],fake:33,fake_imag:59,faked_imag:33,fall:[29,57],falloc:27,fals:[5,6,7,30,36,38,41,48,56,57,59,65,71,74,75,87,92,99,105,107,116],false_block:[7,36,56],false_label:59,false_neg:25,false_posit:25,false_read:59,familiar:20,faq:117,far:[24,70],fashion:21,fast:[13,30,110],faster:[1,9,30,52,110,116,118],fastest:30,fastli:72,fat:119,father:6,fault:[0,13,60],favorit:0,fbd1f2bb71f4:99,fc1:[35,74,107],fc1_bia:35,fc1_weight:35,fc2:[35,107],fc3:[35,107],fc4:107,fc8a365:97,fc8a:97,fc_grad:52,fc_layer:[58,66,74,107],fc_op:66,fc_out:7,fc_output:66,fc_without_b:7,fclayer:74,fcop:32,feasibl:53,featur:[6,21,29,35,51,52,55,67,72,105],feed:[4,21,34,48,62,93,111],feed_dict:33,feed_list:[93,111],feed_minibatch:71,feeder:[21,93,111],feel:72,fetch:[9,12,19,21,57,74,111,116],fetch_list:[21,58,71,93,111],fetch_op:57,few:[0,8,9,20,21,40,53,59,65,67],fewer:[20,58],fft:67,field:[7,35,37,44,57,58,61,65,66,97,110],fifth:34,figur:[4,8,21,23,33,42,48,55,58,67,74,110,116],file:[0,1,3,4,6,8,9,11,13,14,16,17,19,20,27,28,30,31,35,44,46,59,60,67,68,71,72,74,75,76,77,87,92,93,95,100,105,111,116,118,119,120,121],filelist:67,filenam:[11,58,109],fileoffset:27,filesystem:[16,17,21,27,97],fill:[9,13,47,58,97],fill_zero_grad:60,fill_zeros_like_op:6,filter:[24,43],find:[0,3,7,9,16,20,29,35,39,43,49,64,93,100,110,118,119],find_var:5,findmemori:43,findop:7,findprimit:43,findprimitivedesc:43,findvar:[7,64],fine:[13,32],fingerprint:97,finish:[0,9,13,16,17,26,40,51,66,92,94,95,97,99],finit:74,finnal:1,first:[0,4,6,7,9,13,16,17,18,21,26,28,30,33,34,35,43,48,49,52,56,57,58,60,65,66,67,68,69,70,72,74,75,77,93,97,105,107,110,116,121],first_seq:116,firstli:76,firstseen:99,fit:[29,38,40,44,49,60,93],fit_a_lin:93,five:[56,110],fix:[21,40,45,58,67,72,109],flag:[41,42,55,72,75,78,105],flatten0:35,flatten:[35,56,58,77],flexibl:[4,14,21,30,34,38,48,49,53,59,68,70,116],flist:92,fliud:18,float16:20,float16_t:29,float32:[21,29,32,33,58,59,75,93,111],float_to_half_rn:29,flow:[7,18,20,48,55,63,69],fluid:[6,19,21,23,26,39,47,52,55,58,68,69,76,109],fluid_cuda_create_tensor:31,fluid_cuda_mult:31,fluid_cuda_read:31,fly:6,fmt:20,fnt03:97,focu:[20,35,109,110],focus:75,folder:[8,11,17,28,93,97],follow:[0,1,3,4,5,6,7,8,9,13,17,18,19,20,21,23,26,29,30,31,32,33,34,35,36,37,39,40,43,47,48,49,51,52,53,55,56,57,58,59,60,61,62,64,65,66,67,68,69,70,71,72,74,75,77,78,87,93,97,99,100,101,102,107,109,110,111,116,118,119,120,121],footprint:31,forbid:4,forc:[39,51,58],force_cpu:38,force_cudnn:38,force_load:45,forest:7,forev:20,forget:4,fork:72,form:[3,19,20,25,110],formal:39,format:[5,13,19,21,29,30,47,49,67,70,72,74,75,77,87,92,97,105],former:[4,8,30,40,53],formula:[5,40],forth:33,forward:[5,6,7,12,14,24,30,33,41,42,43,44,50,54,56,59,60,61,62,65,74,107,116],forward_infer:43,forward_list:55,forward_op:5,forward_train:43,forwardactiv:74,found:[29,56,62,64,76,93,96,116,120],four:[20,25,30,34,43,47],foward:57,fp16:[29,60,71],fp32:[39,47,60,71],fp64:[47,71],fpga:[47,111],fpgadevicecontext:68,fpgaengin:42,fpgaplac:[47,68],frame:[26,60,67,70],framework:[4,6,7,20,24,25,29,30,35,47,51,52,53,55,56,60,62,64,66,68,72,74,75,96,109,111,119],free:[31,68,72,121],freememoryop:31,frequenc:[67,110],frequent:[13,59,60,62,68,95,118,119],fresh:16,friend:64,friendli:33,from:[1,3,5,6,7,8,9,11,12,13,14,18,19,20,21,23,24,25,28,29,30,32,33,34,35,36,38,39,40,43,48,49,50,51,52,54,56,58,59,60,61,64,67,68,69,70,71,72,74,75,76,77,92,93,94,96,97,99,105,107,109,110,116,118,119,121],fromfil:59,front:[35,40],fulfil:110,full:[9,16,20,48,51,53,74,76,116,121],full_matrix_project:116,fulli:[21,23,67,74,93,110,121],fullsiz:12,fullyconnect:[35,58],fullyconnectedlay:74,func:[13,18,31,61],functor:[32,35],fundament:[19,20,23,29,60],further:[19,66,121],futur:[16,21,29,40,48,60,118],fvs:66,fwd_desc:43,fwd_op:61,fwd_primit:43,fwd_primitive_desc:43,fwd_var:24,g_b0:33,g_b1:33,g_b2:33,g_block:33,g_command_config_arg:[41,42],g_h0:33,g_h0_bn:33,g_h0_relu:33,g_h1:33,g_h1_bn:33,g_h1_relu:33,g_h2:33,g_im:33,g_loss:33,g_optim:33,g_program:58,g_state:55,g_step:33,g_w0:33,g_w1:33,g_w2:33,gan:4,gangliao:8,gap:105,gatedrecurrentlay:41,gather:[6,40,51,54,74,75],gaussian_normal_random:33,gcc:[0,29,31,45,60,109,118,120],gcc_3:3,gcreators_:66,gemm:41,gemmconvkernel:76,gendrated_id:49,gener:[0,4,5,6,7,8,9,11,13,14,16,18,21,30,32,37,40,43,47,51,53,56,57,58,59,60,61,65,66,67,68,69,70,72,75,97,100,105,107,110,118,120],generated_id:49,generated_scor:49,generatedinput:116,get:[0,1,3,5,6,7,8,9,13,14,16,17,19,27,30,33,35,38,39,40,41,42,43,47,48,49,55,58,60,61,64,66,70,72,74,75,76,92,95,97,100,109,110,116,117],get_all_op_proto:66,get_block:58,get_config_arg:107,get_data:99,get_data_from_prefetch_queu:52,get_dim:5,get_float_el:5,get_grad_op_desc:6,get_input_lay:74,get_numeric_gradi:5,get_numerical_gradi:5,get_output:5,get_plac:52,get_program:40,get_pserver_program:93,get_startup_program:93,get_support:3,get_symbol:35,get_tensor:5,get_trainer_program:93,get_vari:7,get_worker_addr:18,getactualkerneltyp:38,getattr:24,getbatchs:74,getdeviceid:76,geteigendevic:77,getengin:43,getenv:[4,17,92],getexpectedkerneltyp:[38,39,43],getinfervartyp:37,getinput:74,getinputgrad:74,getinputvalu:74,getkerneltyp:29,getkerneltypeforvar:39,getlibrari:43,getmat:12,getoptconfig:12,getoutputgrad:74,getoutputvalu:74,getparam:12,getparameterconfig:12,getparameterptr:74,getparameterspars:12,getparametersremot:12,getplac:[43,68,75,76,77],getsiz:74,gettask:13,gettempl:97,gettensor:39,gettranspos:74,getw:74,getweight:74,getwgrad:74,git:[0,63,72,78,118,120],github:[0,8,33,47,63,72,78,109,111,118,120],give:[0,9,39,48,58,60,72,74,97,110],given:[6,14,16,20,23,24,30,32,33,49,59,62,70,74,105],glibc:[3,118,120],glibc_2:3,glibcxx_3:3,glide:8,global:[0,4,7,8,9,31,35,38,39,54,55,60,64,66,68,97,105,110],global_block:58,globalstat:110,globalstatinfo:110,glog:72,glog_v:72,glog_vmodul:72,gnueabihf:120,go_librari:8,go_test:8,goal:[19,20,23,29,34,51,60,67,110],gob:13,godep:8,godoc:45,goe:[9,30,36,64,111],going:[6,32,53,103,109,121],golang:8,good:[20,33,53,58,59,62,93,109,110,121],googl:[4,55,60,72,96,109,118],googleapi:97,googlenet:42,goroutin:[18,20],got:[38,64],gpg2:97,gpg:97,gprotos_:66,gpu:[0,3,5,17,20,25,29,39,40,47,51,52,53,54,55,60,62,63,68,76,77,87,92,93,103,108,111,121],gpu_id:[105,107],gpu_per_train:21,gpu_plac:52,gpudevic:68,gpugpu_id:104,gpukernel:60,grab:9,grad:[5,6,14,24,42,52,58,65,105],grad_info_map:6,grad_n:24,grad_nam:24,grad_op:24,grad_op_class:60,grad_op_desc:24,grad_op_maker_:61,grad_op_typ:[60,61],grad_op_type_:61,grad_s_block:6,grad_share_block_num:[104,105],grad_to_var:[6,24],grad_var_nam:5,gradient:[9,13,20,22,24,34,37,50,51,52,53,54,58,60,65,75,92,93,94,105,109],gradient_flat:5,gradient_machin:46,gradientmachin:[46,54],gradientmachine_:12,gradopdescmak:[37,61],gradopdescmakerbas:61,gradopmak:61,gradual:110,grain:32,gram:67,grant:97,graph:[6,7,8,9,18,20,21,22,23,25,30,33,48,51,53,56,77],great:[23,67,121],greater:[24,53,92],greaterthan:66,greedi:67,green:[18,33],grep:[1,100],groudtruth:116,group:[13,35,43,68,75,114,121],group_input1:116,group_input2:116,group_input:116,grow:72,grpc:121,gru:[49,67,116],gru_decod:116,gru_decoder_with_attent:116,gru_out:49,gru_step:[49,116],grumemori:116,gserver:[41,42,74],gsizex:110,gtx:40,guarante:[43,58,74],guard:12,guest:[0,3],gui:[109,110],guid:[27,40,60,72,74,93,97,99,110,116,119],gzip:[13,99],h0_bn:33,h1_grad:52,h2_grad:52,h_prev:7,hadoop:4,half:[29,97],half_to_float:29,hand:[40,60,67,68,77,93,94],handi:8,handl:[4,6,17,18,21,35,40,43,47,54,59,64,68,70,76,111],handler:7,hannun:67,happen:[13,66],hard:[0,21,30,49,67,70,97],hardwar:[0,30,31,68,76,110],has:[0,4,5,6,7,8,9,13,14,16,19,20,21,23,24,25,29,30,33,35,39,40,44,47,49,51,55,56,60,65,66,68,72,74,97,99,110,111,116,119,121],has_kei:[6,24],has_var_recurs:6,hasdependentvar:57,hash:[47,51],hasn:30,hasnext:19,have:[0,1,4,5,6,7,8,9,13,14,16,17,19,20,21,23,24,26,29,30,31,32,33,34,38,39,40,43,44,47,48,49,51,52,53,54,55,56,58,59,60,61,64,65,67,68,71,72,74,75,76,92,97,105,107,110,116,119,120,121],haven:[0,30],hdf:11,head:[72,75,92,100],header:[14,44,46,60,68,74,76,118,119,120],headip:100,heard:0,heavi:95,height:[7,45,59,74,75],height_:65,held:9,hello:4,help:[0,7,28,30,35,43,49,59,60,70,72,95,109],helper:[21,43,61,70,74],henc:[21,53,58,61,62,64],here:[0,1,3,4,8,9,15,20,23,24,26,28,30,34,35,43,47,48,59,62,66,71,72,75,76,78,92,93,95,97,99,104,107,116,119,120,121],heterogen:[21,23,55],heurist:[23,49,105],hidden:[50,58,97,116],hidden_out:7,hierarch:[56,58,60,114,116],hierarchi:60,high:[29,51,67,68,74,96,121],higher:[32,48,70,72],highest:7,highli:[67,70,107,116],him:4,hint:[38,109],histor:[32,76],hl_get_sync_flag:74,hold:[4,6,9,13,15,19,20,29,33,35,37,39,40,64,66,68,77,93,97],holder_:[68,77],home:[1,11,28,97,99,100,109],honor:13,host:[8,17,55,97,99,118,119,120],host_c:[118,119,120],hostfil:100,hostnam:97,hostpath:99,hostport:97,hour:0,hourli:72,hous:87,how:[4,7,9,13,18,19,20,21,26,28,30,32,35,38,39,43,48,49,54,55,62,66,76,93,94,97,99,105,109,116,117,120],howev:[5,6,16,20,21,26,30,39,40,47,53,54,58,59,61,62,65,66,67,68,97,104,105,116],howto:92,hpp:[29,45],htod:110,http:[0,1,8,17,33,63,72,78,97,99,109,111,118,120,121],hub:63,huge:53,human:[55,67],hundr:76,hyper:[33,74],hyperparamet:62,i1117:110,i386:119,iOS:120,iamfullaccess:97,iamusersshkei:97,icc:31,icml:67,id_rsa:100,idea:[8,20,30,31,53,59,62,93,109],ideal:[21,39],ident:[61,75,97],identifi:[36,47,74],ids:[49,74],idx:[13,19,33,40,74],ies:28,if_els:69,if_else_op:6,ifdef:[47,55],ifels:[7,56],ifelseop:56,ignor:105,iii:67,illustr:[9,14,20,21,32,48,74,110,116],im_siz:33,imag:[0,4,21,30,33,34,49,50,56,59,67,72,97,101,102,107,121],image_a:59,image_b:59,image_conv_lay:67,image_fil:59,image_lay:59,image_nam:4,image_path:59,image_reader_cr:59,imagenet:11,imagepullpolici:97,images_reader_cr:59,imagin:34,imgsiz:110,imgsizei:110,imgsizex:110,imikolov:92,immedi:[0,40,43,53,62,97],immutable_paramet:4,imper:18,imperfect:60,implement:[7,13,14,15,16,17,18,20,21,23,30,32,35,36,37,39,40,43,45,46,47,49,52,54,57,64,66,67,68,69,70,116],implemet:12,impli:8,implicitli:18,imposs:[19,49,121],impractic:39,improv:[22,23,40,60,67,97,109,110],inarg:12,inbound:97,includ:[0,3,4,7,8,14,17,19,20,29,30,33,35,40,45,46,48,49,55,56,58,60,66,74,75,96,97,99,105,109,110,116,118,119,120],inclus:49,incom:[18,38],increas:[9,13,29,94,105],increment:[20,25,34,40,105],incupd:74,inde:20,independ:[5,6,14,22,52,64,68,121],index:[5,6,7,9,13,18,56,58,70,76,97],indic:[6,7,14,26,33,48,56,61,65,68,70,95,97,118],indice_map:70,indices_map:70,individu:[9,51,97],industri:[9,44,121],ineffici:[39,54],infer:[4,6,7,9,25,30,36,37,38,39,40,41,45,47,57,58,60,65,67,87,119,120],infer_shap:58,infer_var_type_:37,inferenc:119,inferer:67,inferfac:37,inferior:16,infernec:120,infershap:[7,58,60,75,77],infershapecontext:[75,77],infervartypefn:37,info:[29,48,74,95,121],inform:[7,17,28,35,38,40,43,44,47,48,51,58,62,64,65,72,74,75,77,97,105,109,110,118],infrastructur:[30,97],ingor:105,ingrad_:42,ingredi:[20,67],inherit:[7,19,50,60,68,75],ininst:4,init:[7,22,33,42,48,49,52,74,87,92,97,107],init_attr:58,init_model_path:[104,105,107],initi:[6,8,13,18,21,22,23,25,34,48,51,53,58,62,66,70,74,75,87,105,111,116],initialize_op_attr:58,initrd:121,inlin:[68,76,77,97],inner:74,input0:77,input1:77,input:[5,6,7,12,16,18,19,21,22,23,24,25,29,30,31,32,33,34,35,37,38,39,40,42,43,47,48,49,53,54,57,58,59,60,61,64,66,67,68,70,72,74,75,76,77,87,89,93,100,107,111,114,116],input_data:74,input_data_target:74,input_hassub_sequence_data:74,input_index:74,input_label:74,input_lay:74,input_nam:4,input_seg:70,input_sequence_data:74,input_sequence_label:74,input_sparse_float_value_data:74,input_sparse_non_value_data:74,input_t:74,input_to_check:5,input_valu:5,input_var:[5,58],inputbuff:12,inputdef:74,inputgradi:61,inputlayers_:74,inputs_to_check:5,inputsizechang:43,insert:[6,24,31,51,57,60,61,72],insid:[0,1,6,9,21,23,24,25,38,43,54,55,59,60,61,71,97],inspir:55,instal:[0,1,17,42,63,72,78,81,89,99,103,109,117],install_android:118,instanc:[5,7,9,11,15,18,19,21,22,24,26,31,36,43,48,49,53,58,60,61,74,77,93,105,110,116],instance_ip:97,instanti:[9,26,111],instead:[0,5,6,8,12,17,18,20,21,29,30,34,35,67,72],instrins:29,instruct:[1,7,34,110,118],int16:71,int32:[47,56,70,71,105],int64:[21,27,39,47,65,71],int64_t:55,int8:47,integ:[13,17,18,20,29,45,49,74],integer_value_sequ:[49,67,116],integr:[0,121],intel:[30,47,68,76],intellig:40,inteloptimizedpaddl:42,intend:0,intens:67,inter:21,interact:[1,21,97],interchang:[34,60],interconnect:51,interest:[18,29,51,110],interfac:[0,7,13,17,19,28,35,51,54,60,61,67,68,75,77,97,119,121],intermedi:[0,21,28,31,33,40,50,67,118,120],intern:[29,67,94,95,97,109],internel:42,internet:[8,9,121],interpret:[0,26,30,31,71,110],inth:77,intrins:[18,26,29,120],introduc:[7,9,19,33,41,44,62,64,66,75,92,94,96,99,109],introductori:0,intuit:[16,60],inval_:42,invalid:[59,64],invent:30,invoc:[8,32,60],invok:[6,19,21,24,39,54,58,60,61,66,72,97,110],involv:[49,75],ios:119,ios_arch:119,ios_deployment_target:119,ios_development_root:119,ios_enable_bitcod:119,ios_platform:119,ios_sdk_root:119,ios_use_veclib_for_bla:119,ipad:119,iphon:119,ips:97,ipt:[58,66,116],ipx:121,ipython:4,is_async:92,is_cpu_plac:43,is_mkldnn_librari:43,is_seq:116,is_target:57,is_tensor:66,is_test:43,is_traget:57,isinst:24,ismkldnnkernel:43,isn:110,isspars:74,issu:[0,1,3,8,33,67,72,110],istag:63,item:[16,29,59,87,121],iter:[4,9,21,30,31,40,43,53,55,59,67,70],iter_multiple_input_and_param:58,its:[3,4,6,7,9,13,18,19,20,23,24,25,30,31,33,34,35,37,39,40,44,48,49,51,53,54,57,58,60,61,64,65,66,68,74,75,76,77,94,97,105,110],itself:[6,9,16,19,31,43,53,64],ivs:66,java:[7,45,56,60],jeremi:110,job:[1,6,16,18,21,24,60,92,93,94,96,104,105,107],job_desc:21,job_dispatch_packag:95,job_nam:[17,97],job_namespac:97,job_path:97,job_workspac:95,jobdesc:21,jobnam:21,jobpath:97,jobport0:97,jobport1:97,jobport2:97,jobport3:97,jobserv:17,join:9,journei:1,jpg:19,json:[35,67,97,99],juditski:53,jupyt:[1,17],just:[3,8,13,14,18,21,30,31,33,37,43,53,54,58,59,60,61,62,64,65,72,95,97,107,118],jx4xr:97,jypyt:4,k8s:[18,121],k8s_data:97,k8s_job:4,k8s_token:4,k8s_train:97,k8s_user:4,kafka:11,kcpu:55,kcuda:55,kcudnn:76,kdisabl:55,kebilinearinterpbw:110,kebilinearinterpfw:110,keep:[0,9,20,30,31,34,49,53,58,64,66,72,121],kei:[0,5,6,7,9,11,13,27,29,38,43,60,61,66,67,70,72,75,110],kenlm:67,kept:[40,58],kera:62,kernel0:76,kernel1:76,kernel:[5,20,29,31,38,39,42,53,55,62,65,67,68,75,77,110],kernel_hint:38,kernel_type_for_var:39,kerneltyp:[38,43],key1:105,key2:105,key_pair_nam:97,keyid:97,keymetadata:97,keypair:97,keyserv:97,keystat:97,keyusag:97,keyword:[58,69],kforcecpu:38,kill:[9,97],kind:[1,4,5,9,15,19,21,24,31,34,38,39,43,50,51,55,68,71,76,97,99],kind_:55,kinput:52,kmark:55,kmkldnn:76,kms:97,knchw8c:47,knchw:47,knhwc:47,know:[4,13,18,19,40,44,72,74,92,97,109,110,118],knowledg:67,known:[6,7,20,30,32,48],koutput:52,kparallelblock:52,kparallelscop:52,kparamet:52,kplace:52,kplain:76,kpoprang:55,kpushrang:55,kqueue:20,kselectedrow:65,kstate:55,kube_cluster_tl:4,kube_ctrl_start_job:4,kube_get_workers_addr:18,kube_list_containers_in_job_and_return_current_containers_rank:4,kubeconfig:97,kubectl:[95,99,100],kuberent:[9,97],kubernet:[4,9,18,21,60,96,101,102,121],kubernetes_service_host:4,kusecudnn:38,kusemkldnn:38,kwarg:[25,35,58,66],l1_regularization_op:62,l2_regularization_op:62,l2regular:92,l93:12,label:[21,25,30,33,34,35,39,50,52,56,59,67,93,99,111],label_fil:59,label_lay:59,label_path:59,lag:105,lambda:[18,24],lan:103,languag:[18,20,30,34,40,55,60,64,67,69,107],larg:[21,23,24,40,44,53,67,72],larger:[40,69],larger_than:[7,36,56],last:[0,6,24,40,48,55,56,105,116],last_seq:49,lastseen:99,latenc:[29,67,95,97],later:[0,3,8,60,62,67,68,75,77,97],latest:[0,1,3,7,8,9,16,63,78,99,118,119],latter:[53,70,109],launch:[43,97,105],launcher:4,layer:[6,7,12,18,20,21,23,30,33,34,36,50,52,53,56,59,60,62,66,67,68,70,87,93,104,105,111,114,116],layer_0:74,layer_attr:[107,116],layer_help:38,layer_num:107,layer_typ:[41,42],layerbas:74,layerconfig:74,layergradutil:74,layerhelp:[38,58],layermap:74,layout:[39,43],layout_:[38,47],layouttyp:38,lazi:[53,62],lead:[19,40,47,110],leaki:33,learing_r:50,learn:[0,1,4,6,14,16,20,21,23,26,33,34,40,42,49,51,53,55,59,60,62,68,74,75,78,93,110,116,119],learning_r:[14,21,92,93,111],leas:9,least:[3,9,118],leav:[7,97],lectur:40,left:[7,77,119],legaci:1,legal:66,len:[14,18,27,30,58,74,87],length:[14,29,41,44,48,49,60,67,70,99,105,116],leran:40,less:[4,24,93,121],less_equ:69,less_than:[4,40],let02:99,let:[4,7,16,18,20,31,32,34,38,39,43,47,48,49,50,61,68,75,93,97,109],level:[29,32,35,44,48,49,55,68,70,71,72,95,105,118],lgtest:8,lgtest_main:8,lib64:[1,105],lib:[0,1,46,92,109,118,119,120],libapi:8,libari:46,libc:3,libcuda:1,libgcc_:3,libgoogl:109,libiomp5:42,libmkldnn:42,libmklml_intel:42,libnvidia:1,libpaddl:[45,46,60,109],libpaddle_capi:46,libpaddle_gserv:46,libpaddle_math:46,libpython2:0,librari:[0,3,8,15,20,21,39,42,43,46,51,67,75,76,92,93,103,105,119,120],library_:47,library_typ:76,library_type_:39,librarydevicecontext:47,librarytyp:[39,76],libstdc:3,licens:[42,51,72],life:9,lifecycl:[55,121],lifetim:[3,64],lightweight:32,like:[0,3,6,7,8,9,12,17,18,20,26,30,31,32,33,34,35,37,39,43,47,51,52,53,58,59,60,61,62,64,65,67,69,70,71,72,92,96,97,104,107,109,110,111,116,118,119,120,121],limit:[30,40,44,49,60,62,105,110],linaro:120,line:[0,8,12,17,20,28,34,53,56,58,60,62,72,93,94,95,97,107,108,109,110],linear:[49,87],lineno:109,link1:29,link2:29,link:[3,8,27,28,64,75,97,121],linux:[0,1,3,20,27,72,97,103,120],linux_x86_64:[3,63],lipo:119,list:[0,4,6,7,8,13,17,18,26,28,30,33,47,50,52,54,55,58,61,64,70,74,75,87,92,93,97,105,107,109,116,120],listdir:92,listen:[9,18,21,92,93,105],listen_and_do:18,listenanddo:18,littl:[14,38,44,105],live:[75,111],live_in:40,live_out:40,load:[0,4,9,21,33,51,58,75,97,105],load_missing_parameter_strategi:[104,105,107],load_mnist:33,load_persist:93,loadsave_parameters_in_pserv:[12,104,105],local:[0,1,5,7,9,15,16,20,34,40,48,52,56,58,60,72,81,95,99,104,105,109],local_scop:5,local_w1_grad:52,local_w2_grad:52,localhost:[1,78],localpath:28,locat:[8,30,47,55,68,70,74,92,116,120],lock:[8,9,13,14],lod:[20,44,48,65,70,71],lod_desc:65,lod_expand:49,lod_level:[58,65,71],lod_rank_t:71,lod_tensor:[48,65,71],lod_tensor_arrai:71,lodtenosr:19,lodtensor:[19,20,37,44,60,71],lodtensordesc:[44,65],log:[3,13,21,28,33,74,92,95,97,99,100,105,120],log_barrier_abstract:105,log_barrier_lowest_nod:[104,105],log_barrier_show_log:[104,105],log_clip:[104,105],log_error_clip:[104,105],log_period:[99,105,107],log_period_serv:[104,105],logic:[16,21,23,24,33,37,50,51,54,64,70,75],login:[3,100],logit:[33,39],longer:[9,21,40],look:[7,17,18,20,30,31,34,52,53,58,61,62,67,71,92,93,97,99,104,111],lookahead:67,lookup:[37,49,111],lookup_t:40,loop:[5,7,19,30,40,55,59,64],loop_var:70,loss:[6,21,33,35,50,52,53,62,67,74],loss_gard:52,lot:[21,47,49,53,58,62,68,92,104,121],low:[50,51,67,68,70],low_rnn:48,lower:[29,48,49,72,95],lower_level_rnn:48,lowest:105,lpaddle_capi_shar:46,lpaddle_capi_whol:46,lrelu:33,lstm:[99,116],lstmemori:116,lstmlayer:41,luckili:40,mac:[0,46,72,118],machin:[0,3,21,23,30,33,40,42,51,53,62,74,97,99,100,104,105,107,120,121],machine_transl:116,maco:[0,3,87,119],macro:[32,47,61,75],made:[9,14,30,116],mai:[0,1,5,7,21,25,29,31,38,39,40,43,51,55,59,60,64,67,71,77,78,92,97,110,120],main:[3,18,20,24,30,31,35,51,56,60,94,97,109],main_program:[6,25,52],mainli:[15,40,47,68,75,105],mainlin:3,maintain:[7,13,53,58,60,97],majel:8,major:[21,29,39,118],make:[0,4,6,7,8,9,13,14,16,20,21,22,29,30,34,48,49,52,53,54,58,59,60,62,67,70,72,74,75,76,92,93,94,97,109,110,118,119,120,121],make_chan:20,make_channel:20,make_ddim:77,make_function_oper:32,make_vari:66,maker:[60,61],malloc:[68,74],man:27,manag:[3,9,14,15,18,20,21,28,55,64,68,78,96],mandarin:67,mandatori:119,mani:[0,6,8,13,18,20,30,33,38,39,40,49,54,55,58,60,61,64,65,66,69,70,105],manili:35,manipul:[30,58,61,95,119],manner:[53,62,67,68],mantain:40,manual:[21,50,53,61,95,118,119,121],manufactur:30,manylinux1:3,manylinux1_x86_64:[3,63],manylinux:63,map:[4,7,13,24,43,47,58,61,64,66,68,70,105,121],map_fn:70,mapreduc:[4,92],mark:[6,23,33,34,48,49,55,64,109,116,121],marker:55,market:29,master:[4,16,60,63,105,120],mastermind:8,mat:[45,46],mat_cache_row:12,mat_norm:12,mat_normal_shar:12,mat_sparse_row:12,mat_sparse_row_auto_grow:12,mat_sparse_row_id:12,mat_sparse_row_prefetch:12,mat_sparse_row_prefetch_full_s:12,mat_value_shar:12,match:[3,8,29,69,110],matchbox:121,math:[42,45,60,72,74,75,110],mathemat:62,matmul:[7,35,48,70,75],matric:[74,116],matrix:[12,45,46,74,75,104,107,119],matrixptr:74,matrixtyp:46,mattyp:12,matur:96,max:[5,22,24,40,58,105,107,110],max_diff:5,max_length:[49,116],max_relative_error:[5,75],maxim:24,maximum:[7,14,52,75,105,110,116],maxoutfunctor:68,mayb:[7,43,75],md5:10,mean:[0,1,6,8,21,22,24,35,39,49,52,57,59,64,67,75,93,97,105,107,109,110,111,116,121],meant:70,measur:[25,110],mechan:[6,15,19,25,43,58,61,76,97,116],mem:[7,17,49],mem_per_pserv:21,mem_per_train:21,member:[4,24,34,35,47,54,58,64,75],memcpi:[54,110],memori:[0,6,7,12,13,17,29,31,39,42,43,44,47,49,53,55,60,72,74,77,99,105,107,110,111,116],memory_optim:40,memory_threshold_on_load_data:105,memoryalloc:68,memorydesc:43,mention:[0,6,8,13,21,23,30,48,51,53,55],merg:[14,16,22,25,42,48,51,52,54,72,78,105,119],messag:[7,18,20,26,30,31,34,44,55,56,57,58,60,61,65,71,72,99,105],metaclass:75,metadata:[27,97,99],metal:[93,121],metaphor:34,metaplotlib:4,method:[0,1,3,5,7,16,18,19,21,22,24,29,33,34,35,38,39,50,51,58,59,60,64,65,70,74,75,77,78,105,107,109,110],methodolog:53,metric:[25,55],microarchitectur:29,might:[0,7,8,18,20,30,40,56,67,72,74,97,109,118],mileag:110,million:107,min:[22,24,58,97,107,110],min_block:7,min_count:23,min_desc:7,mind:109,mini:[7,9,20,25,26,30,36,48],mini_batch:59,minibatch:[7,25,34,36,56],minim:[7,21,23,24,30,33,50,60,93,105,111,118,119,120],minimum:[67,93,119],minimun:105,minsizerel:[118,119,120],minu:61,minus_grad:61,minusgradop:61,minusop:61,minusopgradmak:61,minusopprotoandcheckermak:61,minut:[0,1,9,16,97],mirror:[1,8,118],mislead:14,miss:[33,105],mistak:30,misus:76,mit:97,mix:[52,55,70,116],mixtur:109,mkdir:[28,78,97,100],mkl:[0,1,39,43,60,68,76],mkl_packed_:41,mkldnn:[39,42,47],mkldnn_:42,mkldnnactiv:42,mkldnnbase:42,mkldnnlayer:42,mkldnnmatrix:42,mkldnnstream:42,mkldnntester:42,mklml:42,mklpack:41,mklpackedgatedrecurrentlay:41,mklpackedgemm:41,mklpackedlstmlay:41,mklpackedrecurrentlay:41,mlp:35,mnist:[11,21,33,34,56,59,60,109],mnist_random_image_batch_read:59,mnist_train:59,mnist_train_batch_read:59,mobil:[29,30,40,60,78],mod:92,mode:[29,41,51,52,72,105],model:[6,7,9,10,18,21,23,24,25,34,39,40,41,50,51,53,60,62,67,70,72,74,78,81,87,93,94,97,105,108],model_list:[105,107],model_path:107,modelparallel:21,modern:40,modif:[2,67],modifi:[21,29,35,62,74,75,92,95,97,116],modul:[21,32,33,49,67,70,75,109],modular:49,moment:109,momentum:[64,76],momentumop:109,mon:99,monitor:[20,55],month:8,more:[0,1,4,5,6,8,9,13,16,17,19,20,21,23,28,29,30,31,32,34,38,40,43,47,48,49,50,55,58,59,60,62,67,68,69,70,74,75,76,77,78,87,92,93,94,99,107,109,110,111,116,120,121],most:[3,4,6,8,16,20,21,31,34,35,47,49,53,55,59,62,67,68,69,74,104,109,110,111,116,121],mostli:[29,121],motiv:60,mount:[0,1,17,92,97,99],mountpath:[97,99],move:[1,9,13,19,28,30,53,97,110,121],movement:110,movidiu:30,mpi:[20,51,100],mpirun:100,mse:[30,34,50,56],much:[9,30,43,50,59,62,70,110],mul:[32,40,58,74,75],mul_grad:75,mul_op:75,mul_result:58,mulgradkernel:75,mulkernel:75,mulop:[32,75],mulopgrad:75,mulopmak:75,mult:[18,31],multi:[25,39,51,54,74,93,95,104,105,109,121],multigradientmachin:54,multipl:[4,5,13,14,16,18,20,21,23,25,30,31,32,38,39,51,52,55,60,67,71,74,75,92,94,97,105,107,109,116],multiple_input:58,multiple_param_attr:58,multipli:[18,74],multithread:52,must:[0,6,14,19,24,40,43,44,47,55,57,58,59,60,66,71,74,75,77,92,93,97,105,107,116,118,120],mutabl:[68,77],mutable_data:[43,68,75,77],mutex:20,mutuable_data:[68,77],mxnet:[7,18,20,30],my_cluster_nam:97,my_external_dns_nam:97,my_lib:92,my_net:52,myerrorclip:24,mypaddl:99,naiv:18,name:[1,3,4,5,6,7,9,11,12,14,17,18,19,21,25,29,32,35,38,42,43,44,46,47,49,55,56,58,60,63,65,66,70,71,74,75,76,87,92,93,99,101,102,105,107,110,111,116,119,121],name_:55,name_prefix:11,namespac:[7,36,45,58,74,75,99],nativ:[29,72],natur:[13,16,23,49,70,107],navig:78,ncall:109,nccl1:51,nccl2:51,ncclinit:51,nchw8:39,nchw8c:39,nchw:[42,47],ndarrai:11,ndk:118,nearest:29,nearli:[5,19],necess:70,necessari:[6,7,14,16,24,25,40,44,49,54,58,66,70,74,100],necessarili:[18,74],neck:51,need:[0,1,2,3,4,5,6,8,12,13,14,16,17,19,20,21,23,24,25,28,30,31,32,33,38,40,43,47,49,50,51,52,53,54,55,57,58,60,61,62,64,65,66,67,68,70,71,74,75,76,77,78,87,92,93,97,99,103,104,105,107,116,118,119,120,121],neighberhood:51,neon:[29,118,120],nervana:30,nessesari:67,nest:[6,7,55,56,71],net:[0,7,33,48,64],netop:[7,60],network:[4,5,6,7,9,12,21,23,25,33,35,39,40,41,42,48,50,53,55,58,59,62,64,66,67,68,71,74,75,77,87,92,93,94,105,110,121],network_config:107,networkadministr:97,neural:[4,6,7,9,21,35,39,40,41,42,48,53,62,64,68,71,77,87,93,94,105,110],neuralnetwork:54,neuron:74,never:[40,59,64,97,99],new_block_idx:58,new_op_and_kernel:76,new_op_desc:24,new_scop:39,new_stat:48,newblock:58,newbuff:43,newer:118,newest:14,newli:[29,119,121],newop:7,newopdesc:58,newprogram:58,newscop:39,newvardesc:58,next:[6,9,15,19,20,24,49,51,70,74,75,97,99,105,109,110,116],nextlay:42,nfs4:97,nfs:97,nfsver:97,nic:[92,104,105],nil:[13,20],nnz:74,no_grad_dict:6,no_grad_set:[5,6,75],no_gradi:6,node1ip:100,node2ip:100,node3ip:100,node:[8,16,18,21,23,35,40,49,51,60,74,92,93,95,96,97,99,100,103,105,121],node_0:97,node_1:97,node_2:97,node_id:92,nodeattr:35,nodeentri:35,nodefil:95,nodesep:35,nohup:92,nois:[9,33,94],noisi:33,non:[9,20,29,30,65,74,75,97,105],none:[4,5,6,7,20,24,25,33,35,36,48,49,50,56,58,66,70,93,111,116],noneedtran:43,nonlinear:74,nor:[0,18],norm:[33,47],normal:[52,53,67,74,99,103,105,116],notat:40,note:[0,1,4,6,7,12,13,17,39,40,44,47,51,59,60,68,75,77,78,92,93,97,105,107,110,119],notebook:[1,17],notest_dist_fit_a_lin:93,noteworthi:30,noth:[0,38,58,64,105],notic:[24,30,51,61,72,74,116],notif:72,notimplementederror:24,notin:39,notingradi:75,notion:70,notori:5,now:[6,8,9,19,20,23,33,44,47,53,60,61,62,64,93,97,105,119],nproc:0,nullptr:[43,55,61,64,74],num:[92,105],num_class:35,num_gradient_serv:[92,104,105],num_hidden:35,num_input:72,num_parameter_serv:4,num_pass:[99,104,105,107],num_pserv:21,num_row:65,num_shard:11,num_step:70,num_train:21,number:[0,7,9,11,23,25,40,53,55,59,60,66,70,74,92,93,96,97,105,109],numdevices_:107,numer:75,numeric_grad:5,numerical_grad:5,numlogicaldevices_:107,numpi:[0,11,29,33,58,59,75],numreal:12,numsampl:110,numtimeout:13,nv_:8,nv_librari:8,nv_test:8,nvcc:[8,29,31],nvidia:[1,29,47,51,68,105,110],nvlink:51,nvprof:55,object:[4,12,19,21,24,25,33,35,40,45,50,55,58,60,62,64,77,110],observ:[74,110],obtain:[16,19,53,68],obvious:[8,47,109],occup:40,occupi:[29,55],occur:40,occurr:7,oct:99,off:[0,1,46,93,103,118,119,120,121],offer:[7,60,66],offici:[8,72,78,97,118],offlin:[9,11,121],offset:12,often:[12,35,40,47,72,92,109],ograd:74,old:[5,14,16,49,60,105],older:[30,118],omega:62,omit:0,omp_num_thread:109,ompi_comm_world_rank:92,onc:[9,13,18,21,23,25,30,34,53,69,72,74,78,97],one:[0,1,4,5,6,7,9,12,13,14,16,17,18,19,20,21,24,25,26,29,30,31,32,33,35,37,38,39,43,44,47,48,49,50,51,53,54,56,57,58,59,60,61,64,65,67,68,69,70,72,74,75,76,93,95,97,99,100,105,107,111,121],onehotcrossentropyopkernel:75,ones:[32,33,60,72],onli:[0,2,3,4,5,6,8,12,13,14,15,16,17,18,19,21,23,24,25,26,28,29,30,33,34,39,40,43,48,49,50,51,54,55,58,60,65,66,67,68,69,70,71,74,75,76,77,78,93,97,99,104,105,107,110,116,119,121],onlin:[9,11,40,59],only_cpu:5,onnx:30,onto:[21,23,97,100],op1:[39,40],op1_2_op2:39,op1_to_op2:39,op2:[39,40],op3:40,op_:75,op_check:75,op_class:[60,66],op_desc:[24,37,57],op_info:111,op_kei:43,op_maker_class:[60,66],op_proto:66,op_registri:111,op_siz:24,op_test:75,op_typ:[60,75,76],op_unique_kei:43,opattrcheck:75,opcreat:66,opdesc:[7,24,34,56,57,58,60,61,66,71],opdescbind:[37,61],opdescbuild:7,opeartor:52,open:[4,11,30,33,42,59,72,96,97,109],openbla:[0,1,118],openmp:109,openmpi:96,opensourc:51,oper:[5,7,18,20,21,22,23,25,26,29,30,31,33,34,35,37,38,39,48,49,50,51,52,55,57,62,64,67,68,71,72,74,76,77,97,105,110,111,116,118],operand:29,operat:52,operator_grad:5,operator_list:55,operatorbas:[7,32,60,61,66,75],operatorwithkernel:[39,75],opinfo:[37,60,61],opinfomak:37,opinfomap:61,opkernel:77,opkernelbas:76,opkernelkei:60,opkerneltyp:[39,47,76],opmak:66,opproto:75,opprotoandcheckermak:[61,75],opprotomak:[66,75],opregist:66,opregistri:66,ops:[5,6,7,8,18,19,31,34,35,52,53,56,57,58,60,68,75,121],ops_:7,ops_test:8,opt:[0,4,50,57,66],opt_op_list:50,optest:75,optestmeta:75,optim:[5,6,21,22,23,31,33,51,53,54,56,60,62,65,67,74,92,93,94,109,110,111,118,120],optimis:50,optimize_op:93,optimize_op_attr:58,optimizer_op:93,option:[4,8,21,33,38,44,56,57,58,60,65,66,67,71,74,92,93,95,107,109,118,119,121],optmization_op_list:50,opts_np:57,optyp:[37,66],opwithkernel:65,order:[0,6,34,44,55,59,62,70,74,94,97,99,105,109,121],oregon:97,org:[11,27,33],organ:89,orient:66,origin:[5,29,33,64,70,72,77],other:[0,7,9,14,18,28,29,30,31,37,39,40,43,47,48,53,57,62,64,66,67,68,71,72,93,94,97,99,107,109,111,116,118,119,120,121],otherwis:[4,6,9,14,16,33,37,43,59,67,72,95,107,116],our:[0,3,4,6,8,19,20,21,23,33,37,40,47,51,53,64,70,72,74,93,97,99,109,116,118],out:[4,7,8,13,16,19,21,24,30,35,39,40,43,48,49,58,75,77,87,97,99,100,105,109,110,116],out_dir:97,out_mem:116,outgrad_:42,outlin:106,output:[0,4,5,6,7,11,16,18,19,23,24,28,31,32,33,34,35,36,37,39,40,43,44,48,49,52,53,56,57,58,59,60,61,64,65,66,68,70,72,74,75,76,77,89,92,99,105,107,109,110,116,118],output_:[42,74],output_all_step:48,output_arg_nam:24,output_lay:87,output_mem:116,output_nam:5,output_num:48,output_path:11,output_seg:70,outputbuff:12,outputgradi:61,outsid:[21,64],outupt:70,outv:74,outval_:42,over:[4,30,40,51,52,53,70,72,74,110],overal:[33,53,55,72,121],overfit:62,overhead:110,overlap:74,overload:[29,38],overrid:[7,9,28,43,68,74,75,77],overview:[13,14,15,68],overwhelm:72,overwrit:[28,92],own:[0,6,14,16,24,26,35,37,50,51,53,62,66,75,92,95,97,118,119],owner:[0,72],pack:[70,118],packag:[0,1,13,17,18,32,42,63,72,75,97,109],pad:[43,67],paddl:[0,1,3,4,7,8,9,11,17,19,21,28,31,32,33,36,41,42,43,44,45,46,48,49,54,56,60,62,63,66,67,68,70,72,74,75,76,78,87,92,93,95,97,99,100,103,105,107,109,110,111,116,118,121],paddle_begin_init_param:14,paddle_dir:75,paddle_element_typ:14,paddle_element_type_float32:14,paddle_element_type_float64:14,paddle_element_type_int32:14,paddle_element_type_int64:14,paddle_element_type_uint32:14,paddle_element_type_uint64:14,paddle_enforc:[7,19,43],paddle_enforce_eq:[75,77],paddle_error:[45,46],paddle_exampl:17,paddle_finish_init_param:14,paddle_get_param:14,paddle_gradi:14,paddle_init_num_gradient_serv:92,paddle_init_param:14,paddle_init_port:92,paddle_init_ports_num:92,paddle_init_ports_num_for_spars:92,paddle_init_pserv:92,paddle_init_trainer_count:92,paddle_init_trainer_id:92,paddle_init_use_gpu:92,paddle_job:17,paddle_manylinux_devel:0,paddle_matrix:[45,46],paddle_matrix_cr:46,paddle_matrix_get_shap:45,paddle_matrix_shap:45,paddle_new_etcd_pserver_cli:14,paddle_new_pserver_cli:14,paddle_on_cloud:17,paddle_output:99,paddle_paramet:14,paddle_pserver2:95,paddle_pserver_cli:14,paddle_pserver_client_releas:14,paddle_save_model:14,paddle_send_grad:14,paddle_train:[46,63,95],paddle_with_cuda:55,paddle_with_mkldnn:47,paddlepaddl:[2,8,9,11,14,15,16,17,18,21,27,28,32,33,34,36,38,44,48,49,50,54,55,58,59,60,64,70,71,72,74,75,76,87,92,94,95,96,100,101,102,103,109,110,116,121],paddlepaddle_gpu:3,paddlepaddlebook:1,paddlepaddlehub:[1,118],page:[72,97],pair:[6,7,21,34,50,55,60],pakcag:8,panic:20,paper:[33,67],para:12,paradigm:[18,26,60],paragraph:48,paragraph_data:48,paragraph_out:48,parallel:[0,18,20,21,23,39,51,52,55,60,92,94,96,97,99,105,107,110],parallel_do_grad:52,parallel_do_op:52,parallel_for:18,parallel_nn:[104,105],paralleldo:[22,52],parallelfor:18,paralleliz:67,param:[5,7,14,52,54,58,68,77],param_attr:[12,58,116],param_config_proto:14,paramattr:116,paramet:[0,5,6,7,8,10,12,16,18,21,22,24,26,28,30,31,33,34,35,37,44,48,50,51,56,59,64,66,67,70,72,74,75,76,77,81,87,94,95,107,108,111,119],parameter_block_s:[104,105],parameter_block_size_for_spars:[104,105],parameter_list:[6,50],parameter_nam:4,parameter_serv:4,parameter_valu:12,parameterattribut:12,parameterclient_:12,parametermap:74,parametermutex_:12,parameters_:74,parameters_and_grad:50,parameterserver2:12,parameterset:4,parameterupdat:54,parameterupdater_:12,params_grad:[50,93],paramt:[92,97],paraspars:74,parent:[7,18,56,58,60,74],parent_:[7,64],parent_block:52,parent_idx:58,parenthes:60,pars:[0,8,21,35,97,107],part:[6,7,16,21,30,43,44,56,58,67,68,74,92,93,94,109,110,116,121],parti:[110,118,119,120],particip:75,particular:[34,39,44,60,67,110],partit:[9,11,21,23,60,94,97],pass:[6,7,9,20,24,25,30,33,40,44,50,52,53,54,57,58,59,60,62,64,67,69,70,72,74,92,93,95,97,99,105,110],pass_id:[21,93],pass_idx:59,pass_num:93,passtyp:74,password:100,past:[1,4,87,97],patch:27,path:[0,1,9,13,14,17,40,49,59,67,92,97,99,105,107,118,119,120],path_to_paddlepaddle_working_directori:78,pattern:[9,45,53,62,97],paus:[9,16],pcie:51,peer:51,pem:[4,11,97],pend:[9,13],peopl:0,pep425tag:3,pep8:72,per:[9,14,51,53,59,62,75,105],percal:109,perf_test:109,perfectli:67,perfom:[105,107],perform:[0,5,14,20,21,25,29,30,33,39,40,51,54,55,59,60,62,67,68,74,75,93,96,104,108,116,118,119,120],perftool:[55,109],period:[9,16,105],permiss:97,persist:[26,65,67,71,97],persistentvolum:97,persistentvolumeclaim:97,person:[4,38],perspect:[60,110],perturb:[5,74],pex:121,pfs:[11,28],pfsclient:11,pfspath:28,pgp:97,phase:[43,49,51,53,59,61,67,121],philosophi:[53,62],photo:33,physic:[119,121],pick:[97,119],pickl:[92,100],pictur:51,piec:[18,55,77,93],pil:92,pillow:17,ping:72,pip:[0,2,63,72,78,87,109],pipelin:[25,67],pivot:43,pixel:21,place:[6,7,9,16,21,23,26,38,39,43,51,52,60,74,77,93,110,111],place_:[38,39,47,68],place_list:71,place_typ:76,placehold:[33,68,77],placement:23,plain:[17,44,46,47],plan:[9,18,43,60,67,74,118],platform:[3,7,31,39,43,47,55,68,72,75,76,77,92,96,97,111,118,119,120],pleas:[0,1,3,4,9,13,14,15,18,20,31,35,47,48,58,59,60,67,68,71,72,74,75,77,78,93,97,103,109,116,118,119,120],plot:4,plug:[51,53],pne:75,pnpairvalidationlay:105,pnpairvalidationpredict_fil:104,pod:[11,17,18,71,97,99],pod_nam:97,podtyp:71,point:[0,7,9,17,20,29,40,43,51,68,72,75,77,109,110,118,121],pointer:[7,14,35,40,47,58,60,64,68,77],polici:97,poll:20,pollut:16,polyak:53,ponit:35,pool3:74,pool:[22,40,67],pop:[7,26],popul:14,popular:[8,33,35,55],port:[8,18,92,93,97,99,104,105,109],port_num:104,portabl:35,portal:78,ports_num:[92,105],ports_num_for_spars:[12,92,104,105,107],pose:9,possibl:[4,7,13,20,23,40,58,62,71,110],post:[0,17,27],postpon:62,potenti:[29,110],power:[29,40,51,67,77,121],ppo_workspac:78,pprof:109,practic:[74,116],pre:[0,4,14,38,40,72,97,99,118,120],pre_activ:58,pre_bia:58,pre_stat:[48,70],preambl:58,precis:[0,25,29,53],precompil:26,pred:[35,40],predecessor:40,predetermin:105,predict:[21,52,62,81,87,105,116],predict_fil:105,predict_output_dir:[104,105],prefer:[30,38],prefetch:[12,52,74],prefix:[9,11,49,67,97],pregel:20,pregrad:74,prepand:58,prepar:[5,17,54,67,94,101,116],prepend:58,prepend_oper:58,preprocess:[67,70,99],present:[4,6,7,55,70],preserv:28,prev_batch_st:[104,105],prevent:[4,9,13,16,24,62,109],preview:[60,78],previou:[6,9,23,28,48,49,74,97,105,109],previous:99,previous_memori:7,price:[60,87],prim:43,primari:[30,34],primarili:[53,62],primer:72,primit:[29,42,43,51,52,70],primitive_desc:43,primitivedesc:43,principl:[4,8,47],print:[3,4,20,21,30,35,58,69,87,100,105,109],print_graphviz:35,printallstatu:110,println:20,printstatu:110,prior:52,prioriti:60,privat:[7,46,55,58,64,65,66,68,70,72,77],privileg:[0,97],pro:51,prob:87,probabl:[1,49,67,72,116],problem:[0,3,4,5,8,16,19,30,33,34,53,60,62],proc:1,proce:[1,9,59,97],procedur:[7,44,77,119],process:[0,4,6,7,11,12,13,16,18,19,20,21,25,26,30,31,35,39,40,42,44,51,52,62,66,72,95,96,97,99,105,107,109,116],processor:[29,110],produc:[9,30,35,59],product:[17,30,74,97,99],productgraph:99,prof:109,profil:[28,55,67],profilerst:55,proflier:[55,110],program:[4,6,11,14,16,21,23,26,34,36,40,50,51,52,55,59,60,64,69,71,95,105,109,110],programdesc:[18,21,26,30,40,44,52,57,58,61,71],programm:[21,30,58],progress:[9,13,105],project:[17,46,67,72,74,75,116],promis:49,prompt:[28,30,93],prone:4,pronunc:67,prop_kind:43,propag:[6,30,53,75,105,107],proper:[38,103],properli:[0,38,93],properti:[35,62,105],propos:[7,22,23,49,50,51,53,70],proprietari:42,protect:[19,29,66,74,75],proto:[20,38,44,47,56,60,66,71,75],proto_:66,protobuf:[7,17,18,21,26,30,31,34,35,40,44,56,58,60,61,66],protoc:[118,120],protocol:[105,111,121],provi:92,provid:[1,4,7,14,17,18,25,26,29,30,33,35,37,38,47,51,53,55,58,62,66,67,68,69,70,77,87,92,93,95,96,97,109,110,118,119,121],providermemory_threshold_on_load_data:104,provis:[97,121],prune:7,ps_desir:9,pserver:[12,14,15,17,60,92,93,97,104,105],pserver_addr:14,pserver_cpu:17,pserver_endpoint:93,pserver_id:10,pserver_mem:17,pserver_num_thread:[12,104,105],pserver_prog:93,pserver_startup:93,pserverstart_pserv:104,pseudo:[4,6,17,61,70],pseudocod:70,psize:74,ptr:[46,68],pub:100,publish:118,pull:[8,60,63,72,118],purpos:[9,21,23,38,110],push:[7,26,30,55,63,72],push_back:74,put:[8,9,12,23,40,43,58,68,74,93,99,118],pvc:97,pwd:[0,1,78,118],pxe:121,pybind:[7,20,29],pypi:3,python2:109,python3:3,python:[0,1,3,4,7,15,19,20,25,26,30,32,33,34,35,38,45,49,52,54,55,60,63,68,70,72,78,87,92,93,100,111,116],pytorch:[30,55],qualcomm:29,queri:97,question:[4,18,23,66,93,97],queue:[20,23],quick:[35,86,105],quick_start:[17,97,99,101],quick_start_data:99,quickli:[49,58,60],quickstart:99,quit:[49,110],r14b:118,rais:[24,35,92],rajathkmp:33,ran:[23,110],rand:[33,105,107,110],random:[11,20,33,47,54,58,59,75,94,105],random_imag:11,randomli:16,randomnumberse:104,rang:[11,18,21,29,33,40,55,59,66,72,93,105,107],rank0:51,rank1:51,rank:[4,70,77,97],rankdir:35,rapid:61,raspberry_pi:120,raspberrypi:120,raspbian:120,rate:[14,67,74],rather:[6,17,33,70,97],ratio:105,raw:44,rdma:105,rdma_tcp:[104,105],reach:[9,40,51,110],read:[0,1,4,6,9,11,18,19,20,21,23,30,31,59,60,67,70,78,94,97,103,116,118,121],read_from_arrai:40,read_from_realistic_imag:4,read_from_rng:4,read_lock:10,read_minibatch:30,read_mnist_imag:4,read_ranking_model_data:4,readabl:[55,60,109],reader:[11,21,29,33,34,56,67,71,92,93,109],reader_cr:11,reader_creator_bool:59,reader_creator_random_imag:59,reader_creator_random_image_and_label:59,readi:[9,20,97,99,121],readlockguard:12,readm:46,readnext:19,readwritebuffer_:12,readwritemani:97,real:[12,33,59,92],realist:4,realiti:67,realiz:[7,48],realli:[30,62],reaon:76,reason:[4,5,9,20,30,72,93,99],receiv:[9,17,20,21,23,48,93],recent:[40,53],reciev:105,recognit:67,recommend:[0,1,2,4,72,74,78,95,103,105,116,118],recompil:110,record:[13,43,55,66,97],recordev:55,recordio:[4,11,13,19],recov:[9,70],recover:60,recoveri:13,recurr:[41,48,64,67,114],recurrent_group:[67,116],recurrent_op:70,recurrentgradientmachin:[46,49,70],recurrentlay:[41,105],recurs:[6,7,8,28,40,60],recv:[18,21,23,51,97],recvparametertyp:12,red:[33,109],reduc:[1,23,29,51,60,72,95,105,107,109],reduce_by_kei:60,reduce_mean:33,refactor:[21,23,34,49,53,54,58,62,70],refer:[0,1,7,9,13,14,15,18,29,35,43,47,48,51,56,58,60,62,64,68,70,71,74,75,77,93,99,116,118,119],referenc:13,reflect:13,reformat:72,refrain:75,reg:66,regard:[19,121],region:[64,110],regist:[20,39,40,47,61,68,74,110],register_gpu_profil:110,register_lay:74,register_op:[32,60,61,66,75],register_op_cpu_kernel:[68,75],register_op_cuda_kernel:[68,75],register_op_kernel:76,register_op_without_gradi:[60,75],register_oper:[37,61],register_tim:12,register_timer_info:110,registerop:66,registr:[75,76,111],registri:[17,37,68,99,121],regular:[6,74,92,97],reinit:19,reiniti:[19,43],reinstal:0,rel:[5,16,62,75,118],relat:[9,16,17,29,39,47,52,55,64,72,99,109,119,120,121],relationship:[61,68],releas:[63,67,97,118,119,120],relev:75,reli:[5,18,49,50,53,62,75,109],reliabl:[9,62],relu1:35,relu2:35,relu:[33,35,40,74],relwithdebinfo:109,remain:70,rememb:72,remot:[8,12,21,60,72,74,97,105,107],remoteparameterupdat:[12,15,105],remov:[6,21,28,30,49,72,105,118,119],removing_docker_contain:0,renam:[3,6,28,29],reorder:43,reorder_primit:43,repeat:[7,34,56,57,65,66,71,109],repeatedli:[34,40],replac:[8,13,37,53,61,67],repli:72,replic:21,replicaset:17,repo:[8,72,78,120],report:[13,29,30,55,110],reportdataset:13,repositori:[78,118],repres:[6,7,13,18,21,23,24,30,35,44,47,49,52,53,58,60,62,65,68,70,71,74,97,116],represent:[14,21,31,33,34,40,47,49,65],reproduc:0,request:[8,9,12,16,18,60,63,72,97,99,121],requir:[3,4,6,9,14,16,17,19,21,23,24,28,29,35,40,42,48,52,53,55,56,57,60,62,65,66,67,71,72,74,75,78,92,97,99,118,120,121],requisit:40,rerun:75,research:[21,30],reserv:28,reserveoutput:74,reset:[9,25],reset_program:25,resetingrad:42,resetinvalu:42,resetoutgrad:42,resetoutvalu:42,resetxxx:42,reshap:[5,59,77],resid:0,residu:20,resiz:[12,68,75,77],resolv:[8,72,99],resourc:[21,26,51,55,68,76,97],respect:[5,19,24,29,33,48,74,105,116],respons:[12,20,21,25,33,51,53,54,62,97,99],rest:[7,17,27,31,39,121],restart:[9,14,97,99,121],restartpolici:[97,99],restor:[5,53],restrict:[62,64,105,109],result:[5,6,13,20,25,33,34,35,40,44,49,50,51,54,75,77,97,105,109,110,111],resum:16,retain:77,retran:97,retriev:[7,49,64,74,99,109],retriv:92,reuqest:63,reus:[7,16,49,59,60,74,75],rev:0,revamp:21,reveal:[4,109],revers:[6,116],review:[18,99],reviews_electronics_5:99,rewrit:[8,20,75],rid:[19,30],right:[5,6,7,8,17,25,40,60,62,72,76],ring:51,risk:6,rkt:[0,17],rmsprop:53,rmspropoptim:53,rnn:[7,30,33,49,58,60,64,67,104,108],rnn_bias_attr:116,rnn_layer_attr:116,rnn_out:116,rnn_output:70,rnn_use_batch:[41,104,105],rnnalgorithm:49,rnnstep:70,roadmap:[67,70],rocmplac:47,role:[4,13,14,21,51,93,97],rollback:58,root:[0,6,51,97,99,119],roughli:67,round:[29,51],routin:[29,42,51],row:[12,20,74],rows_:65,rpc:13,rpcserver:13,rpi:120,rpi_arm_neon:120,rpi_toolchain:120,rsize:97,rtk:121,rule:[6,21,24,30,34,74,97],run:[2,3,4,5,6,7,8,9,17,18,19,20,21,22,23,25,29,30,31,32,33,34,35,39,40,43,47,48,50,51,52,53,55,56,57,58,60,63,64,65,67,68,69,72,74,76,77,78,87,92,93,94,95,96,97,100,101,102,103,105,109,110,118,119,120,121],run_test:0,runinitfunct:110,runnabl:23,running_on_cloud:17,runserv:78,runtim:[1,7,18,20,21,37,48,60,71,76,95,118],runtime_table_:7,s_block:6,s_recurrent_group:116,safe:17,sai:[19,31,34,36,40,59,105,107],said:30,sake:74,same:[0,4,5,13,14,16,18,19,20,21,32,33,35,38,39,40,48,49,51,58,60,61,64,67,70,75,76,77,93,95,97,107,116],sampl:[1,25,33,58,66,92,95,105,107],sampler:33,satifi:40,satisfi:[3,8,43,65,97],save:[0,9,11,13,14,17,18,21,34,35,40,44,53,65,71,92,97,99,105,107],save_dir:[99,105,107],save_only_on:[104,105],save_persist:93,saving_period:[104,105],saving_period_by_batch:[104,105,107],scalabl:60,scalar:[6,7,36,69,70],scale:[21,23,53,61,66,67,75,96],scaleop:75,scaleopmak:[60,75],scan:[6,13,40,60],scatter:[6,51],scenario:[49,104],scene:104,schdule:97,schedul:[13,17,23,97],scheme:[12,62,75],scienc:40,scope:[5,18,22,26,31,39,52,111],score:49,scorer:67,scp:100,script:[0,51,75,92,95,96,97,100,118],sdk:119,search:[0,9,64,105,116],second:[4,18,28,30,33,35,48,49,56,57,59,64,66,75,95],secret:97,section:[6,23,30,58,72,74,94,97,109,116],see:[4,6,9,18,20,23,29,30,58,67,72,75,77,93,97,109,110],seed:[105,110],seem:[3,8,20,29,30,67],seen:[62,75],segment:[48,70,77],sel:20,select:[49,97],selected_generation_scor:49,selected_id:49,selected_row:[65,71],selected_rows_desc:65,selected_scor:49,selectedrow:[37,71],selector:99,self:[5,24,25,33,35,40,41,42,44,50,58,70,74,75],self_addr:18,semant:[4,49,63],semaphor:20,semat:4,send:[9,14,18,21,23,38,51,60,66,72,93,94,97,105],send_back_parameter_typ:12,sendbackparameterspars:12,sendbackparametertyp:12,sendparameterrequest:12,sendparameterrespons:12,sens:[53,62,72,109],sent:[4,14,18,21,60,66,71,99],sentenc:[30,48,49,70,116],sentence_input:70,separ:[14,21,32,53,61,62,92,93,105],seper:[52,70],seq_len:70,sequenc:[6,7,18,26,30,34,41,50,56,67,70,72,74,114],sequenti:[7,18,20,116],seri:[3,19],serial:[7,13,44,52,54,60,71],serializ:[60,71],serv:[1,21,29,60,70,92,97,110],server:[0,4,8,12,15,16,21,31,51,60,74,94,95,103,104,121],server_endpoint:93,serverless:9,servic:[92,109,121],sess:[33,35,50],session:[35,50,57,110],set:[0,4,6,9,17,19,33,37,40,43,47,48,49,55,57,58,60,61,64,67,68,70,72,74,75,77,78,81,92,93,95,97,99,104,105,107,108,109,110,116,119,120],set_active_typ:74,set_attr:24,set_drop_r:74,set_float_el:5,set_input:24,set_output:24,set_shap:19,set_siz:74,set_typ:[24,74],setdatatyp:65,setdefault:75,setp:97,setq:0,settup:74,setup:[21,53,63,74,75,121],seven:67,sever:[0,5,12,21,23,33,48,49,51,54,55,58,65,68,70,95,96,97,107],sexstant:121,sgd:[4,9,17,23,52,53,54,65,93,94,111],sgd_optim:[93,111],sgdasync_count:104,shall:[6,8],shape:[5,6,7,19,21,33,36,47,48,56,58,60,65,67,68,75,77,93,111],shapes_:19,shard:[9,10,11,12,13,14,16,21,23,94,97],share:[0,8,19,33,46,54,58,60,62,67,68,70,75,105,110],shared_librari:8,shared_ptr:[43,45,46,64,68,77],shell:[1,97],shoul:5,should:[4,5,6,7,14,17,20,21,24,25,29,31,32,33,37,38,39,43,47,48,49,50,53,54,55,56,59,60,61,62,65,66,67,69,70,71,75,76,78,87,93,95,97,116,118],should_be_fals:4,should_be_tru:4,show:[0,3,6,7,9,19,20,28,30,36,40,44,48,51,53,56,69,70,77,94,97,99,105],show_check_sparse_distribution_log:[104,105],show_layer_stat:[104,105],show_parameter_stats_period:[99,104,105,107],shown:[4,21,25,51,52,55,67,74,77,97,110,116],shrink:74,shrunk:24,shuffl:[19,21,93],shuffleread:19,sid:97,side:[21,25,40,54,77,94],sig:97,sigint:95,sigmod:66,sigmod_op:66,sigmod_output:66,sigmoid:[7,66,70,74],sign:[27,44,97],signal:95,signatur:97,signific:[67,110],silent:92,similar:[7,18,20,21,23,26,30,39,49,53,55,59,60,62,67,68,70,75,97,109,121],similarli:[30,40,75],simpl:[18,23,29,31,34,35,40,48,53,56,62,64,66,67,70,93,105,110],simple_attent:116,simple_gru:116,simple_rnn:116,simpler:54,simplest:97,simpli:[1,4,14,21,87,110,116],simplifi:[4,49,58,66,67,74,99],simul:[30,119],simultan:97,sinc:[9,13,15,16,20,21,22,23,30,37,40,43,47,53,58,59,61,62,70,77,93,97,110,119,121],sincer:72,singl:[6,9,19,21,23,25,29,38,51,52,60,64,67,74,87,94,99,109],singleton:[18,22],sit:21,site:[8,97,109],situat:[6,39,57],size:[1,9,11,12,14,20,21,29,33,40,44,49,52,53,58,59,65,66,67,68,70,74,75,77,87,93,105,111,116,118,119,120],size_in_byt:43,size_t:[12,19,68,70,74],sizeof:7,skip:[6,59,72,95,97],slice:18,slide:9,slight:30,slightli:33,slow:110,slowli:[0,109],small:[5,18,31,33,42,49,72,74,105],small_messag:[104,105],smaller:[5,9,29,49,72],smart:64,snap:99,snapdragon:29,snapshot:[10,16,97],snippet:[20,32,50,74,97,110,116],sock:17,sock_recv_buf_s:[104,105],sock_send_buf_s:[104,105],socket:105,softmax:[4,7,21,23,30,35,36,49,52,56,74,116],softmax_grad:52,softmaxoutput:35,softwar:[29,55,110,121],solid:33,solut:[51,121],solv:[4,6,19,40,60],some:[0,4,6,7,8,12,13,14,16,17,19,20,21,23,24,29,31,32,33,34,38,39,40,43,47,48,49,50,56,57,58,59,60,61,64,68,70,72,74,75,76,77,92,97,104,105,107,110,118,119,120,121],some_c_api_funct:46,some_inst:46,some_op:[37,48,70],some_python_class:45,somecppclass:45,somegotyp:45,someth:[0,6,12,58,72,109],sometim:[0,55,59,110],somewhat:14,somewher:64,soon:9,sophist:74,sort:[70,97,105,109],sort_by_length:70,sortagrad:67,sourc:[5,8,28,30,33,42,44,46,49,59,60,96,97,99,109,116,119],source_dict_dim:[49,116],source_dict_s:49,source_language_word:[49,116],space:[0,23,29,58,62,67,110,116],span:55,spars:[12,20,74,77,92,97,105],sparse_remot:12,sparse_upd:12,sparseparam:74,sparseprefetchrowcpumatrix:74,speak:116,spec:[97,99],specfii:105,special:[6,14,21,29,31,37,47,49,50,75],specialvartypeinfer:37,specif:[6,8,9,19,21,24,28,31,49,60,64,68,75,93,107,118],specifi:[1,4,5,12,13,14,17,18,20,21,22,24,25,26,28,33,44,55,58,64,66,70,72,74,77,78,97,105,109,116,118,119],spectrogram:67,speech:67,speed:[0,29,44,51,53,121],speedup:55,sphinx:[45,78],split:[16,18,19,22,30,36,49,60,70,92,94,97,107],split_count:[92,97],spread:6,squar:35,square_error_cost:[93,111],srand:105,src:[8,43,92],src_backward:116,src_embed:[49,116],src_forward:116,src_primitive_desc:43,src_word_id:[49,116],src_word_vec:49,ssh:[97,99,100,120],ssh_server:95,sstabl:4,stabil:[5,40,75],stabl:[63,97],stack:[26,60,70,97],stage:[8,15,22,33,40,43,67,71,95,118],stale:9,stamp:110,standalon:118,standard:[0,3,20,30,60,62,67,109],stanford:[5,99],star:8,start:[0,1,3,6,8,9,12,13,14,16,17,20,21,22,49,51,54,55,95,100,105,109,110,116,117],start_mpi_train:100,start_op_idx:6,start_pass:[104,105],start_program:52,start_pserv:105,startup:[9,17,30,97],stat:[105,110],state:[7,9,25,26,48,49,55,64,67,70,76,99,105,116],statem:40,statement:[20,30,34,40,74,97],static_cast:[43,77],staticinput:116,statist:[25,55,105],statset:110,statu:[17,49,97,99,110],status:99,std:[8,12,19,35,37,38,43,45,46,55,57,60,61,64,66,68,74,75,77,105],stdbuf:92,stderr:95,stdout:95,step:[0,1,5,7,9,14,20,21,23,25,30,33,34,41,49,52,53,54,58,60,66,67,70,72,74,87,94,97,99,100,109,110,116,118,120,121],step_gradi:6,step_id:70,step_input:70,step_net:7,step_output:70,step_scop:[60,71],stepnet:[7,48,60,64],still:[3,6,13,16,21,30,40,61,77],stirng:58,stmt1482205552000:97,stmt1482205746000:97,stochast:[9,13,16,53,94],stop:[0,58,95,99,105],stop_gradi:58,storag:[27,29,92,97,99],store:[5,7,8,12,26,35,37,44,47,49,54,56,58,60,61,62,64,70,74,75,77,78,92,94,97,99,100,105,119,120],str:[6,17,70,107],straight:[56,59,65],straightforward:43,strategi:[9,58,105],stream:[21,43,55,68,76],stream_:68,strict:[59,94],stride:[43,47,67],string:[6,7,13,28,35,38,44,55,56,57,58,60,61,64,65,66,71,74,75,97,105],strip:109,strongli:103,struct:[13,14,27,29,37,38,39,46,47,55,61,66,76],structur:[6,7,13,30,33,44,49,56,58,60,65,95,97],sts:97,stuff:72,style:[0,60,66],sub:[4,6,16,18,23,33,40,48,51,54,58,74,116,118],sub_block:6,subclass:58,subcommand:28,subgraph:[23,33],submiss:21,submit:[43,60,78,96,97,104,105],subnet0:97,subnet:[4,97],subobjectpath:99,subsequ:51,subset:74,subtract:5,succ:40,succeed:[13,99],success:[14,97,99],successfulcr:99,successfulli:75,successor:105,sucess:40,sucessor:40,sudo:[0,97],suffer:5,suffici:105,suffix:[3,17,92],suggest:[8,72,110],suit:121,suitabl:[65,68,105],sum:[6,7,10,22,37,58,74,116],sum_op:6,summar:[33,55],summari:55,sumopgradmak:61,supercomput:40,suppli:65,support:[0,1,3,5,7,9,16,17,18,20,21,23,30,32,33,39,40,43,44,47,49,53,54,55,57,59,60,61,62,65,67,71,74,75,77,78,87,92,94,96,97,105,110,114,116,118,119,120,121],support_inplac:40,suppos:[8,18,32,65,74],suppress:28,sure:[0,74,93,97,109],svs:66,swagger:27,swig:[0,15,45,46,118,119],switchop:7,sychron:51,symbol:[3,7,35,46],symbols_ready_:7,symbolt:[7,60],symlink:72,sync:[9,53,62,105],sync_with_cpp:109,syncflag:74,synchron:[9,13,20,43,51,55,94,97,105],syntax:[18,26,30,49,59],sysroot:118,system:[0,1,3,7,8,9,14,16,20,21,23,27,32,33,40,42,67,75,78,92,96,99,109,118],tab:3,tabl:[7,18,30,37,44,65,71,119],tablelookup:65,tablelookupgrad:65,tablelookupop:65,tag:[1,63,103,116],tail:49,take:[0,4,6,7,8,9,16,18,19,20,21,24,26,29,31,33,34,36,37,39,40,43,47,53,56,57,58,59,60,61,68,70,72,74,75,76,92,93,97,99,103,109,110,116],taken:[24,35,40,47,70],talk:[14,31,120],tangl:109,tanh:[33,49,74,116],tar:97,tarbal:97,target:[0,6,7,8,24,26,33,35,50,57,60,75,116,118,119,120],target_block:[6,24],target_dict_dim:116,target_dict_s:49,target_language_word:116,target_link_librari:8,target_word:49,task13:67,task14:67,task:[21,44,49,55,66,93,107,116],task_queu:13,taskentri:13,taskqueu:13,tbd:[15,43,67,79,80,82,83,84,85,88,90,91,98,112,113,115],tcp:[97,105],tear:110,technic:[6,9,93],techniqu:[40,74,109,116],technolog:[0,30],tee:99,tell:[1,9,13,14,49,66,110,118],templat:[32,43,66,68,75,76,77,99,121],tempor:67,temporari:[6,17,26,40,53,58],tempori:40,ten:0,tensor:[5,8,18,20,22,23,29,30,31,33,35,37,38,43,44,47,48,49,52,65,70,71,75,111],tensor_arrai:18,tensor_array_read:70,tensor_array_s:70,tensor_array_stack:70,tensor_array_unstack:70,tensor_array_writ:70,tensor_data:44,tensor_in:39,tensor_s:5,tensor_test:8,tensor_to_check:5,tensorarrai:22,tensorarraydesc:70,tensordesc:[44,65],tensorflow:[7,18,20,21,23,30,33,36,62,70,77],term:[9,61,62,67],termin:99,terminolog:40,tessorarrai:70,test1:11,test:[4,5,8,35,46,53,59,63,77,81,87,92,93,100,104,110,111],test_:75,test_all_data_in_one_period:99,test_check_grad_ingore_i:75,test_check_grad_ingore_x:75,test_check_grad_norm:75,test_check_output:75,test_data_dir:92,test_fcgrad:74,test_gpuprofil:110,test_layergrad:74,test_mkldnn:42,test_mklpack:41,test_mul_op:75,test_norm:75,test_pass:[104,105,107],test_period:[104,105,107],test_recurrent_op:72,test_sum_op:0,test_wait:[104,105],testa:4,testb:4,testbilinearfwdbwd:110,testcas:75,testconfig:74,testfcgrad:74,testfclay:74,testlayergrad:74,testmodel_list:104,testmulop:75,testq:4,testsave_dir:104,testutil:74,text1:28,text:[4,44,48,55,67,97],tflop:110,tftp:121,tgz:3,than:[0,6,9,17,18,19,24,30,31,32,33,58,60,62,69,70,74,92,93,97,116,118,121],the_step:30,theano:30,thei:[0,4,6,8,9,14,16,18,19,20,23,24,28,30,33,34,38,40,49,50,55,58,60,66,70,72,74,75,77,93,94,97,104,110,116],them:[0,4,5,6,8,9,12,17,19,20,23,24,30,31,32,37,38,39,40,49,58,59,60,61,64,65,66,70,71,72,75,78,93,97,104,105,110],themselv:[6,8],theori:[30,110],therefor:[6,40,53],therein:7,theta:33,theta_d:33,theta_g:33,thi:[0,1,3,4,5,6,7,8,9,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,29,30,31,32,33,34,35,38,39,40,43,47,48,49,50,51,52,53,54,55,56,58,59,60,61,62,65,66,67,68,70,72,74,75,76,77,78,87,92,93,94,97,99,103,105,107,109,110,111,116,118,119,120,121],thin:37,thing:[21,33,60,68,110],think:[4,8,93],third:[9,35,75,109,110,118,119,120],third_parti:[42,118,119,120],those:[7,8,9,32,34,35,36,56,118],though:[70,121],thought:[8,110],thread:[18,20,22,52,55,74,92,105,107,109,110],thread_count:22,thread_id:55,thread_id_:55,thread_local_rand_use_global_se:[104,105],thread_pool:22,threadid:107,threadloc:110,threadpool:18,three:[5,6,9,20,25,29,30,31,34,43,49,50,54,55,56,59,67,68,105,118],threshold:[9,13,24,72,105],through:[6,8,9,13,15,25,40,50,53,74,75,78,92,110,111,116,119],throughout:26,throughput:[52,92,110],thrust:60,thu:[16,25,35,40,67,74,97],tier:99,time:[0,4,5,8,9,13,16,19,20,21,23,24,30,32,37,40,41,47,48,49,51,55,58,59,60,61,65,66,67,70,71,77,99,105,107,109,110,116,121],timelin:[55,60,110],timeo:97,timeout:[9,13],timestamp:10,timestep:64,tip:[118,119],titan:40,tls:27,tmp:58,todo:[7,9,13,16,49,66,67],togeth:[6,70,93,116],token:[4,67,116],toler:[0,5,75],too:[5,18,20,24,39,43,70],took:121,tool:[0,3,55,93,96,97,109,116,118,120],toolchain:[109,118,119],toolkit:67,top:[48,49,67,75],top_k:49,top_level_rnn:48,topic:43,topk_generated_scor:49,topk_id:49,topk_scor:49,toplevel:0,topolog:[4,9,21,35,40,44,54],topoloi:35,torch:[7,30],total:[9,23,25,51,55,59,92,96,99,109,110,121],total_pass:59,tottim:109,toward:30,trace:[7,31,33],track:[9,13,35,58],tradit:[7,29,67],traffic:21,train:[6,7,11,13,14,16,18,19,24,25,26,30,31,33,34,40,41,44,51,53,54,55,56,57,58,60,62,65,67,68,71,74,81,96,100,101,102,104,108,110,116,119],train_config_dir:97,train_data:92,train_data_dir:92,train_id:97,train_list:92,train_loop:30,train_read:[21,93],trainabl:[44,58],traindot_period:104,trainer:[4,10,11,12,13,15,21,23,31,41,42,53,54,60,74,93,94,95,105,107],trainer_config:[97,99],trainer_config_help:74,trainer_count:[87,92,97,99,104,105,107],trainer_cpu:17,trainer_cr:17,trainer_gpu:17,trainer_id:[92,97,105],trainer_intern:12,trainer_mem:17,trainer_packag:17,trainer_prog:21,trainerid:16,training_rol:93,trainingjob:21,trainingtest_period:104,trainonebatch:12,tran:[43,74,105],trans_var:39,transact:[9,13],transcript:67,transfer:[40,55],transform:[60,67,74,77,116],translat:40,translation_id:49,translation_scor:49,transpar:[49,95],transpil:[18,93],transport:105,transpos:74,travers:[6,34,40],travi:72,treat:[7,14,40],treatment:[14,29],tree:[7,18,26,30,58,105,111,120],trg_dic_siz:49,trg_embed:[49,116],trick:49,tricki:45,trigger:[16,19,54],trivial:[49,70],true_block:[7,36,56],true_imag:59,true_label:59,true_neg:25,true_posit:25,true_read:59,tune:[67,108,109],tuninglog_barrier_abstract:104,tupl:[6,58,59],turn:[1,58,59],tutori:[0,1,74,75,97,100,101,102,109,110,114,116,119],twice:[23,33,93],twine:63,two:[0,4,6,14,15,16,17,18,19,20,21,25,28,29,30,31,33,34,37,39,40,44,47,49,53,55,56,59,60,61,62,64,65,66,67,70,71,75,77,95,97,107,110,116,118,120],txt:[8,17,28,41,42,74,78,92,97,100],type:[4,6,7,9,12,13,16,17,19,21,27,28,29,31,37,38,39,43,44,45,46,48,49,56,57,58,59,60,61,62,65,66,67,68,71,74,76,77,87,92,94,97,99,103,105,107,116,119],type_nam:66,typedef:[14,29,45,46,47,68,76],typeerror:24,typeid:66,typenam:[32,66,68,75,76,77],typic:[21,110,119],ubuntu:[3,63,87,109],ubyt:59,uci_h:[87,93],uid:99,uint16_t:29,uint32:[27,44],uint32_t:55,uint64:[44,45],uint64_t:45,unawar:14,unbalanc:105,unbias:5,unblock:20,unbound:[40,116],unbuff:20,unclear:16,uncreat:6,under:[0,1,8,13,23,39,51,77,78,92,95,96,97],underli:[19,49],understand:[30,58,67,109,110,121],understand_senti:116,undeterminist:110,uni:67,unidirect:67,unifi:[19,26,35,65,72],uniform:[11,33,58,59,105],uniform_random:58,uniniti:6,uninstal:0,uniqu:[4,7,9,16,17,43,47,58,64,75,93,97,103,105],unique_nam:58,unique_name_gener:58,unique_ptr:[61,64,68,74],unit:[0,8,53,55,62,68,77,81,116],unittest:[46,72,75],unittestcheckgrad_ep:104,unix:20,unk:[65,71],unlik:[49,75],unnecessari:[6,67,72],unordered_map:64,unpack:70,unrol:48,unseen:62,unsign:[14,29],unstack:70,unstack_from:70,unsupervis:33,unsupport:75,until:[9,14,20,22,23,30,40,64,93,97],unzip:118,updat:[3,6,9,13,14,21,27,29,33,48,49,50,51,53,54,64,67,70,74,94,105,107,109],update_memori:7,update_op:50,updatecallback:74,updatestack:97,upgrad:[0,3,51],upload:[9,17,20,27,63,94],upon:9,upstream:72,uri:97,url:72,usag:[29,36,40,54,58,69,75,110,119],use:[0,1,3,4,5,7,8,9,15,19,20,21,22,23,26,29,33,35,37,38,39,40,43,47,49,50,51,52,54,55,58,64,65,66,67,70,72,74,75,76,78,87,92,94,97,99,105,107,109,110,116,118,119,120],use_cpu:38,use_cudnn:38,use_eigen_bla:118,use_eigen_for_bla:[118,119],use_gpu:[52,87,92,99,104,105,107],use_mkl_pack:41,use_mkldnn:[38,42],use_old_updat:[12,104,105],use_sparse_remote_updat:12,used:[0,3,4,5,7,8,9,15,16,19,20,21,24,26,29,30,33,35,39,40,48,49,52,53,54,55,58,59,60,62,64,66,68,70,74,75,77,97,104,105,107,109,110,116,118,119,120],useful:[5,29,39,40,58,64,74,107,116,118],usegpu:74,user:[1,4,5,6,7,8,11,13,16,17,18,21,22,23,24,25,26,28,32,33,34,35,37,38,39,43,47,49,50,51,53,55,58,59,60,61,62,64,66,68,70,72,76,78,92,97,104,105,109,118,121],user_nam:11,usercert:11,userkei:11,usernam:11,uses:[0,3,5,9,16,18,20,21,29,39,40,47,48,49,54,55,68,71,72,74,77,78,94,97,105,116,118],using:[0,1,2,4,5,6,7,8,9,13,14,16,17,20,21,26,28,29,30,32,33,35,37,40,48,50,53,56,58,59,61,62,64,66,67,68,72,74,75,76,77,78,87,92,97,99,100,103,105,107,110,116,118,120],usr:[0,1,92,97,105],usual:[6,17,40,47,55,56,62,68,72,75,97,105,107,109,110],util:[21,41,42,51,74,75,76,110,116,121],uuid:[10,16],v7a:118,v8a:118,val:6,valid:[59,60,64,75,97,119],valu:[5,6,7,9,18,20,24,25,35,36,40,42,44,48,49,50,53,54,56,60,64,65,66,69,70,74,75,76,93,97,105,107,116,118,119],value1:105,value2:105,value_:65,valueerror:35,values_:70,vanilla:[52,116],var_nam:[6,39],var_recurs:24,vardesc:[7,34,56,58,60,65,71],vardescbuild:7,vari:[97,110],variabl:[4,5,7,18,19,20,21,23,24,25,26,31,33,34,35,36,37,39,47,48,49,50,52,53,56,57,61,62,65,66,67,70,74,75,76,92,96,97,99,109,111,118,119],variablenamemap:75,varialbl:33,variant:[37,47,68,70,76],varibal:6,varibl:35,varienc:70,varient:70,variou:[7,20,29,40,62,118],varproto:66,vars_:[7,64],vartyp:65,vartypeinfer:37,vec2seq:67,veclib:119,vector:[4,7,12,14,19,35,36,43,48,49,55,58,60,61,65,67,69,70,74,77,116],vectorenable_parallel_vector:104,vendor:8,verbos:[28,72],veri:[8,13,18,23,26,30,32,33,40,43,49,54,59,62,64,67,68,70,95,109,110,116],verifi:[7,74,119],version:[0,1,6,8,17,21,24,28,31,33,35,36,44,49,63,67,74,87,93,97,99,103,104,105,109,110,118,119,120],versu:4,via:[2,6,9,47,72,93,97,110,119,121],view:[44,47],vim:1,viriabl:92,virtual:[0,19,24,37,38,61,68,76],virtualenv:0,visibl:[16,64],visit:6,visual:[49,110],vlog:[12,72],vocabulari:67,voila:87,volum:[78,99],volumemount:[97,99],volumn:97,w1_grad:52,w2_grad:52,wai:[0,4,6,14,16,20,26,30,38,40,49,53,58,59,62,70,72,74,107,116],wait:[9,14,20,22,76,92,93,94,105],walk:119,wangkuiyi:8,want:[0,1,4,17,18,20,25,33,38,39,47,53,55,57,59,62,64,68,69,70,72,74,78,92,105,107,109,118,120],warn:28,warp:110,warp_ctc:67,wast:51,watch:9,wbia:97,web:[78,109],websit:78,weight:[41,44,62,74,105,107,116],weightlist:74,weights_:74,weights_primitive_desc:43,weights_t:74,welcom:[8,67,72],well:[6,17,20,21,23,30,32,33,62,65,67,74,93,97,105],wer:67,were:[8,20,30],west:97,wget:118,wgt:43,what:[0,8,19,30,33,39,49,58,66,75,109,121],whatev:[0,92],wheel:3,when:[0,2,6,7,8,9,12,13,14,17,18,21,23,24,25,26,28,29,30,31,35,49,51,53,54,55,56,58,60,68,70,72,74,75,77,78,92,94,96,97,99,105,107,109,110,116,118,119,121],whenev:[58,67,72],where:[4,6,7,9,16,18,21,30,31,34,47,48,49,53,56,60,62,68,70,74,75,105,107,109,110,111,116],wherea:[7,13,32,36,68,69,71],whether:[0,1,5,6,7,19,26,55,59,65,70,71,74,75,105,119],which:[0,3,4,5,6,7,8,9,11,13,14,16,17,18,19,20,21,22,24,26,29,30,31,32,33,35,37,39,40,43,44,47,48,49,50,51,54,56,57,58,59,60,61,64,65,66,69,70,71,72,74,75,76,77,92,93,94,95,97,105,107,109,110,116,118,119,121],while_grad:40,while_loop:[49,70],while_op:6,whileloop:70,whileop:7,white:67,whl:0,who:[6,32,34,51,58,72],whoever:14,whole:[6,19,33,36,40,45,46,48,51,57,66,67,72,94,97,99,121],wholli:19,whose:[5,6,9,16,24,48,60,61,66,70,116],why:[0,5,46],wide:[3,8,24,33,95,100],width:[12,45,59,74,75],wiki:8,window:[0,1,53,67,118],wirt:35,wise:[23,60,67,77],wish:[0,3,78,92,93],with_avx:[0,1,103,118,119],with_bia:66,with_c_api:[0,118,119,120],with_distribut:93,with_doc:0,with_doubl:[0,74,103],with_dso:0,with_golang:[0,118],with_gpu:[0,103,118,119],with_mkl:[0,41,42,118],with_mkldnn:42,with_mklml:42,with_profil:110,with_python:[0,103,118,119],with_rdma:[103,118,119],with_style_check:[0,72],with_swig_pi:[0,118,119],with_test:[0,75],with_tim:[103,110],within:[13,21,30,67,119],without:[6,9,14,19,20,55,58,59,60,67,75,92,100,109],wloop:70,wmt14:116,won:[94,110],word2vec:[17,92],word:[6,23,34,37,40,48,49,60,66,67,70,76,92,107,116],word_dict:[92,100],word_vector_dim:[49,116],wordcount:67,work:[0,1,4,7,8,9,21,26,29,30,38,50,53,55,58,72,74,78,93,94,97,99,105,109,110,116,121],worker:[23,71,97],workercount:97,workflow:[60,89,97],workspac:[72,92,95,105],world:92,worri:5,worth:111,would:[0,1,7,8,9,16,20,21,22,23,30,32,33,34,43,50,53,54,58,59,65,67,70,72,93,97,109,118,121],wouldn:[30,34],wrap:[19,30,32,33,51,121],wrapper:[8,19,20,32,51,53,61,70,110],write:[4,9,16,18,19,20,21,23,29,30,31,32,35,37,43,50,52,53,58,59,60,61,68,70,92,96,97],write_lock:10,write_output:52,write_to_arrai:40,writer:[4,58],written:[0,1,6,7,18,23,26,33,44,53,60,61,65,75,77,95,109],wrong:59,wrote:35,wsize:97,x64:[118,120],x86:119,x86_64:[118,119],x_neg:5,x_po:5,xarg:[1,74,100],xcode:119,xcodebuild:119,xeon:76,xgbe0:[92,105],xgbe1:[92,105],xpu:30,xrang:[5,30,33,55,59,74,87],xx_layer:38,xxx:[4,70],xxxx:10,xxxxxxxxx:97,xxxxxxxxxx:97,xxxxxxxxxxxxx:97,xxxxxxxxxxxxxxxxxxx:97,y_dim:33,y_neg:5,y_po:5,y_predict:[87,93,111],yaml:[8,95,97,100,121],yancey1989:17,yapf:72,year:30,yep:[55,109],yet:[30,67,121],yield:[4,11,19,59],you:[0,1,2,3,5,17,21,29,64,72,74,75,76,78,87,92,93,95,97,100,103,105,107,109,110,116,118,119,120,121],your:[0,2,3,4,8,12,17,28,60,72,74,78,92,93,95,97,103,107,110,118,119,120,121],your_access_key_id:97,your_secrete_access_kei:97,your_source_root:46,yourself:0,yuang:30,yuyang:109,z_dim:33,z_size:33,zaist:0,zero:[5,6,9,20,33,49,54,58,65,74,97,105],zip:[58,118],zone:97,zxvf:97},titles:["Build from Sources","Run in Docker Containers","Install and Build","Install using pip","PaddlePaddle Design Doc","Auto Gradient Check Design","Backward Building","Design Doc: Block and Scope","Required CMake Function","Design Doc: Distributed Training","\u6a21\u578b\u53c2\u6570\u68c0\u67e5\u70b9\uff08Checkpointing\uff09","\u8bad\u7ec3\u6570\u636e\u7684\u5b58\u50a8\u548c\u5206\u53d1","Alalysis of large model distributed training in Paddle","Design Doc: Master Server","Design Doc: The Client Library of Parameter Server","Design Doc: Remote Parameter Updater for Cluster Train","Design Doc: Save Model","Submit a Distributed Training Job","Design Doc: Concurrent Programming with Fluid","C++ Data Feeding","Design Doc: CSP in PaddlePaddle Fluid","Design Doc: Distributed Training Architecture","Design Doc: Execute the Program with Multi CPU","Design Doc: Parameter Server","Error Clip","Evaluator Design","Executor Design Doc","FileManager\u8bbe\u8ba1\u6587\u6863","PFSClient","Design Doc: float16","Design Doc: PaddlePaddle Fluid","PaddlePaddle Fluid: Towards a Compiled Programming Language","Design Doc: Functions, Operators, and Layers","Design for GAN","Design Doc: Computations as a Graph","Survey on Graph","The IfElse Operator","Design Doc: InferVarType","Problem","Background","Memory Optimization","Intel\u00ae MKL Packed on PaddlePaddle: Design Doc","Intel\u00ae MKL-DNN on PaddlePaddle: Design Doc","Design Doc: Add MKLDNN Kernel in Fluid Operator","Design Doc: Model Format","Paddle\u591a\u8bed\u8a00\u63a5\u53e3\u5b9e\u73b0","C-API \u6a21\u578b\u63a8\u65ad\u5b9e\u73b0\u6587\u6863","Design Doc: The Keys of Operator Kernel Type","RNNOp design","Design: Sequence Decoder Generating LoDTensors","Optimizer Design","Design Doc: NCCL support in Paddle Fluid","Design Doc: Parallel_Do in PaddlePaddle","Averaging Parameter in PaddlePaddle","Design Doc: The C++ Class Parameters","Introduction","Design Doc: PaddlePaddle Programs","Prune","Design Doc: Python API","Python Data Reader Design Doc","Design Doc: Refactorization Overview","Design Doc: Gradient Operators Registration","Regularization in PaddlePaddle","PaddlePaddle\u53d1\u884c\u89c4\u8303","Design of Scope in Paddle","Design Doc: Selected Rows","Interaction between C++ and Python","DeepSpeech2 on PaddlePaddle: Design Doc","Design Doc: Supporting new Device/Library","Design Doc: Switch","Design for TensorArray","Background","Contribute Code","Development","Write New Layers","How to write a new operator","Add Kernels for a New Device","How to use Eigen in Paddle","Contribute Documentation","Install, Build and Unit test","Cluster Training and Prediction","FAQ","Local Training and Prediction","Model Configuration","Parameter Setting","Basic Concept","GET STARTED","Quick Start","Install and Build","C-API Prediction Library","Input/Output Data Organization","C-API Workflow","Command-line arguments","Fluid Distributed Training","Distributed Training","Fabric","Use different clusters","Kubernetes on AWS","Kubernetes Distributed","Kubernetes","OpenMPI","<no title>","<no title>","Preparations","Argument Outline","Detail Description","Set Command-line Parameters","Use Case","HOW TO","Profiling the Python Code","Tune GPU Performance","PaddlePaddle Fluid Source Code Overview","Layers supporting hierarchical sequence as input","API comparision between RNN and hierarchical RNN","RNN Models","Recurrent Group Tutorial","RNN Configuration","PaddlePaddle Documentation","Build PaddlePaddle for Android","Build PaddlePaddle for iOS","Build PaddlePaddle for Raspberry Pi","Cluster bootstrapping tool survey"],titleterms:{"\u4e0a\u4f20\u8bad\u7ec3\u6587\u4ef6":11,"\u4e0d\u4f7f\u7528":45,"\u4e0d\u4f7f\u7528swig\u8fd9\u79cd\u4ee3\u7801\u751f\u6210\u5668":45,"\u4e0d\u5bfc\u51fapaddle\u5185\u90e8\u7684\u7ed3\u6784\u4f53":45,"\u4e0d\u5f15\u7528\u5176\u4ed6\u52a8\u6001\u5e93":45,"\u4ec5\u4ec5\u4f7f\u7528void":45,"\u4ece\u5feb\u7167\u6062\u590d":10,"\u4f7f\u7528\u52a8\u6001\u5e93\u6765\u5206\u53d1paddl":45,"\u4f7f\u7528\u8f6c\u6362\u5e93":11,"\u5177\u4f53\u67d0\u79cd\u7c7b\u578b\u7684\u5934\u6587\u4ef6":46,"\u5177\u4f53\u67d0\u79cd\u7c7b\u578b\u7684\u5b9e\u73b0\u6587\u4ef6":46,"\u5206\u5757\u6587\u4ef6\u4f20\u8f93":27,"\u5206\u652f\u89c4\u8303":63,"\u52a0\u901f\u6267\u884c":10,"\u52a8\u6001\u5e93\u4e2d\u4e0d\u5d4c\u5165\u4efb\u4f55\u5176\u4ed6\u8bed\u8a00\u7684\u89e3\u91ca\u5668":45,"\u52a8\u6001\u6269\u5bb9":10,"\u539f\u56e0":45,"\u539f\u56e0\u5217\u8868":45,"\u53c2\u8003\u6587\u6863":27,"\u53d1\u5e03docker\u955c\u50cf":63,"\u53d1\u5e03wheel\u5305\u5230pypi":63,"\u540d\u8bcd\u89e3\u91ca":27,"\u57fa\u672c\u8981\u6c42":45,"\u5b9e\u73b0":45,"\u5b9e\u73b0\u65b9\u5f0f":46,"\u5bfc\u51fac":45,"\u5feb\u7167\u4fdd\u5b58\u7684\u8bbe\u8ba1\u5982\u4e0b":10,"\u6307\u9488\u4f5c\u4e3a\u7c7b\u578b\u7684\u53e5\u67c4":45,"\u63a8\u6d4b\u6267\u884c":10,"\u652f\u6301\u7528\u6237\u81ea\u5b9a\u4e49\u7684\u6570\u636e\u9884\u5904\u7406job":11,"\u6587\u4ef6\u4f20\u8f93\u4f18\u5316":27,"\u6587\u4ef6\u8bbf\u95ee\u65b9\u5f0f":11,"\u6587\u4ef6\u8bbf\u95ee\u7684\u6743\u9650":11,"\u6587\u4ef6\u9884\u5904\u7406":11,"\u66b4\u9732\u63a5\u53e3\u539f\u5219":46,"\u672f\u8bed":10,"\u67b6\u6784\u56fe":27,"\u6846\u67b6\u751f\u6210":27,"\u6982\u5ff5\u89e3\u91ca":11,"\u6a21\u5757":27,"\u6a21\u578b\u53c2\u6570\u68c0\u67e5\u70b9":10,"\u6a21\u578b\u63a8\u65ad\u5b9e\u73b0\u6587\u6863":46,"\u6d41\u7a0b\u4ecb\u7ecd":11,"\u751f\u6210sparse\u6587\u4ef6":27,"\u7528\u6237\u4f7f\u7528\u6d41\u7a0b":27,"\u76ee\u5f55\u7ed3\u6784":46,"\u76ee\u6807":27,"\u793a\u4f8b\u7a0b\u5e8f":11,"\u7b26\u53f7":45,"\u7c7b":45,"\u7f16\u8bd1\u9009\u9879":46,"\u7f29\u5bb9":10,"\u800c\u662f\u624b\u5199\u591a\u8bed\u8a00\u7ed1\u5b9a":45,"\u80cc\u666f":45,"\u8986\u76d6\u4e0d\u4e00\u81f4\u7684\u90e8\u5206":27,"\u8bad\u7ec3\u6570\u636e\u5b58\u50a8":11,"\u8bad\u7ec3\u6570\u636e\u7684\u5b58\u50a8\u548c\u5206\u53d1":11,"\u8f6c\u6362\u5e93":11,"\u8fd9\u4e2a\u52a8\u6001\u5e93\u4f7f\u7528c99\u6807\u51c6\u7684\u5934\u6587\u4ef6\u5bfc\u51fa\u4e00\u4e9b\u51fd\u6570":45,"\u8fdb\u884c\u8bad\u7ec3":11,"abstract":[21,22,23,51,121],"book\u4e2d\u6240\u6709\u7ae0\u8282":63,"case":[6,107],"class":[33,54,58,74],"filemanager\u8bbe\u8ba1\u6587\u6863":27,"final":38,"function":[8,32,33,58],"new":[68,74,75,76],"paddle\u52a8\u6001\u5e93\u4e2d":45,"paddle\u591a\u8bed\u8a00\u63a5\u53e3\u5b9e\u73b0":45,"paddlepaddle\u53d1\u884c\u89c4\u8303":63,"paddlepaddle\u56de\u5f52\u6d4b\u8bd5\u5217\u8868":63,"return":[58,59],"switch":[43,68,69],"tensor\u5230eigentensor\u7684\u8f6c\u6362":77,AWS:97,DNS:97,E2E:93,EFS:97,For:[8,99],KMS:97,The:[7,14,18,26,30,33,34,36,37,47,50,54,60,61,69,120],Use:[7,56,78,87,96,99,107],Using:[8,14,118],With:17,about:33,absolut:49,access:97,account:97,action:[41,42],activ:42,actor:20,add:[40,43,76,97],address:97,advanc:68,alalysi:12,algorithm:[5,9,21,48,57],all:[64,70],analog:18,analysi:[21,40],android:118,api:[21,41,42,46,50,53,58,62,66,89,91,113],appendix:[0,121],approach:110,arbitrari:30,architectur:[21,55,116],argument:[28,59,92,104,107,118,120],arrai:5,ask:0,asset:97,associ:[64,97],assumpt:121,async:[92,105],attent:116,attribut:[40,62],auto:5,averag:53,aws:97,background:[5,23,39,41,68,69,70,71,75,76],backward:[6,30,34,60,75],base:[17,49],basic:[40,68,85,121],batch:59,batch_siz:59,beam:[49,67],benchmark:[41,42],benefit:[23,60],between:[4,20,58,60,66,68,113],binari:7,bind:75,bla:0,block:[7,31,33,34,56,58,60],blockdesc:56,book:1,bool:0,bootstrap:121,bottleneck:109,bring:121,bucket:97,build:[0,2,6,33,60,78,79,88,99,118,119,120],built:110,can:64,capi:46,capi_priv:46,challeng:[6,23,57],chang:49,channel:20,check:[5,74,95],checkpoint:[9,10,16],choic:38,choos:[8,97],client:14,clip:24,close:5,cloudform:97,cluster:[15,80,93,95,96,97,100,107,121],cmake:[8,41,42,120],code:[17,31,58,72,109,111],command:[92,106,107],commit:99,common:105,commun:105,compar:121,comparis:[58,113],compat:30,compil:[0,7,29,31,56,60,75,111,118,119,120],complet:30,compos:59,comput:[7,34,43,60,62,77],con:121,concept:[58,60,85,97],concern:42,conclus:[16,35,121],concurr:[18,20],condit:33,config:107,configur:[83,97,116,119],construct:34,contain:[1,99],content:[41,42,46,67,97,110],context:76,contribut:[72,78],control:[40,60],contruct:40,convert:16,convolut:67,copi:52,core:[5,58,97],corner:6,cpu:[22,107],creat:[6,20,59,60,64,97,99],createreaderop:19,creation:[13,53,62],creator:59,credenti:97,cross:[118,119,120],csp:20,ctc:67,cuda:[0,29],cudnn:0,current:[29,61],custom:59,data:[9,19,21,39,59,90,97,99],dataflow:40,dataprovid:105,dataset:[9,13,92],datatyp:47,decod:49,decor:59,decoratedread:19,deep:[7,30],deepspeech2:67,defin:[75,97],definit:71,delet:97,demo:[33,93,97],dens:16,dep:3,depend:[0,3,33,67],deploi:17,deriv:74,describ:[30,50],descript:[28,60,105],design:[4,5,7,9,13,14,15,16,18,20,21,22,23,25,26,29,30,32,33,34,37,41,42,43,44,47,48,49,50,51,52,54,56,58,59,60,61,64,65,67,68,69,70],destroi:[64,97],detail:[12,67,105],develop:[60,73],devic:[52,68,76,107],devicecontext:68,dictionari:59,differ:[52,60,68,96,107],directori:97,discrimin:33,discuss:[23,33],dispatch:[9,13],distribut:[4,9,12,17,21,23,93,94,97,98,105],dnn:42,doc:[4,7,9,13,14,15,16,18,20,21,22,23,26,29,30,32,34,37,41,42,43,44,47,51,52,54,56,58,59,60,61,65,67,68,69],docker:[1,17,99,118],document:[78,117],doe:59,down:97,download:[97,99],dure:[49,59],dylib:46,dynam:[9,70],dynet:35,each:3,ec2:97,eigen:77,elast:97,elect:16,els:7,engin:33,enough:5,entri:59,environ:[17,118],equat:74,error:24,evalu:25,event:[4,55],evolut:30,examin:109,exampl:[4,8,18,20,36,46],execut:[7,22,30,56,60],executor:26,explan:5,extern:97,fabric:95,faq:[2,3,81],fault:9,feed:19,file:[7,97,99,109],fileread:19,find:97,float16:29,flow:40,fluid:[18,20,30,31,43,51,93,111],format:[7,9,44],forward:[34,52,75],frame:7,framework:[5,76,77],frequent:0,from:[0,2,4,16,66],functor:68,futur:[30,67],gan:33,gate:116,gener:[31,33,49,109,116,121],get:[86,93,99],give:59,global:[56,58],gpu:[1,105,107,110],grad_op:6,gradient:[5,6,14,42,61,74],graph:[34,35,40,60,62],group:[97,115],gru:105,hand:110,handler:[4,45],happen:16,hardwar:29,have:93,helper:58,hierarch:[112,113],hierarchi:7,high:[50,53,62,66],how:[0,5,12,53,59,60,68,75,77,78,108,110],iOS:119,iam:97,identifi:109,ifels:36,ifelseop:7,imag:[1,17,99,118],implement:[5,6,8,12,22,24,25,29,44,48,51,53,58,59,60,61,62,74,75,76,77],imporv:52,infer:118,infershap:[56,65],infervartyp:37,ingredi:4,ingress:27,initi:[14,33,97,107],input:[52,90,112],insid:64,inspect:97,instal:[2,3,79,87,88,93,97,118,119,120,121],instanc:97,instead:59,integr:[68,97],intel:[41,42],interact:66,interfac:[5,9,14,15,26,50,59,64],intermedi:60,introduc:[49,70,93],introduct:[55,62,93],isn:59,issu:29,job:[9,17,95,97,99,100],kei:[41,47,97],kernel:[43,47,60,76],kill:95,kube:97,kubectl:97,kubernet:[17,97,98,99],languag:[7,31],larg:12,launch:[1,95,100],layer:[4,32,41,42,58,74,107,112],layout:47,learn:[7,30],leval:66,level:[50,53,62,66],libpaddle_capi_shar:46,libpaddle_capi_whol:46,librari:[14,29,47,60,68,89,118],limit:21,line:[92,106],linux:[95,118],list:[10,59],live:40,load:20,local:[21,64,82,97,107],lod:49,lodtensor:[48,49,70],lodtensordesc:71,log:72,logic:13,look:109,low:[53,62,66],lstm:105,machin:49,macro:60,main:33,make:40,manag:8,map:[59,60],master:[9,13,17,18],math:68,mathemat:5,matrix:[42,105],member:33,memori:[40,48,68],messag:66,method:49,might:33,migrat:60,mileston:60,mini:59,minibatch:20,mix:107,mkl:[41,42],mkldnn:43,mkldnn_helper:43,mkldnndevicecontext:43,model:[4,12,14,16,20,30,33,44,49,83,95,107,114,116],modifi:99,modul:[60,68,77],more:33,motiv:[6,20,26,44,51,57],multi:[22,31],multipl:59,mxnet:35,name:[64,97],nativ:31,nccl:51,necess:58,necessari:60,need:[59,110],nest:48,network:[60,107,116],neural:116,nlp:105,non:93,norm:62,note:5,numer:5,numpi:5,nvprof:110,nvvp:110,object:9,offset:49,onli:[59,64],onto:52,op_mak:60,openmpi:100,oper:[19,32,36,40,43,47,53,56,58,60,61,65,70,75],opinfomap:60,opkernel:[60,68,75,76],opproto:66,ops:62,optim:[9,14,34,40,50,58],option:[0,28],opwithkernel:60,order:28,org:78,organ:90,origin:60,orthogon:64,other:42,outlin:104,output:[90,95,97],overview:[16,24,26,41,42,52,60,64,67,111],pack:[41,49],packag:[3,8],paddl:[12,51,59,64,77],paddlejob:17,paddlepaddl:[0,1,3,4,7,20,30,31,41,42,52,53,56,62,63,67,78,93,97,99,111,117,118,119,120],pair:97,paradigm:30,parallel_do:52,parallel_nn:107,paramet:[4,9,14,15,17,20,23,42,52,53,54,58,62,84,92,93,97,105,106],parameteraverageoptim:53,parent:64,part:34,partit:14,pass:[0,107],path:[16,28],penalti:62,perform:[52,53,105,109,110],persist:13,pfsclient:[27,28],pfsserver:27,pip:3,place:[40,47,68,76],placement:21,point:[41,97],polici:40,pose:[37,61],potenti:38,predict:[80,82,89],prefetch:59,prepar:[92,93,95,97,100,103,119],principl:43,privat:97,pro:121,problem:[25,37,38,39,40,47,50,61],procedur:121,process:[9,14,17,50,60],profil:[109,110],program:[1,7,18,20,22,30,31,56,58,92,93],programdesc:[31,56],project:8,propos:[37,61,62],protobuf:65,protomak:75,provid:59,prune:57,pserver:16,pull:1,python:[5,17,21,41,42,48,50,53,58,59,62,66,71,74,75,109],qualiti:60,question:0,queue:[9,13],quick:87,randomnumb:105,raspberri:120,reader:[4,19,59],readerbas:19,readerhold:19,readi:93,readop:19,realiz:60,recoveri:9,recurr:[115,116],recv:20,refactor:60,refer:[5,21,23,40,41,42,67,110],region:97,regist:[37,60,66,75,76],registr:[60,61],registri:60,regular:[14,62],rel:49,relat:[19,60,70],remark:75,remot:15,remoteexecutor:21,render:97,represent:[7,60],requir:[0,8,33],result:[95,99],retri:13,reus:58,review:72,rnn:[48,70,105,113,114,116],rnnop:[7,48,60],route53:97,row:[65,67],rpc:20,run:[0,1,26,75,99,111],runtim:[3,17],save:16,scale:9,scope:[7,48,60,64],script:[93,99],search:[49,67],secur:97,select:[14,20,65],selectedrow:65,semant:69,send:20,separ:60,sequenc:[49,112,116],server:[9,13,14,17,20,23,92,93,97,105],servic:97,set:[84,106],setup:[97,118],sextant:121,sgd:[92,105],shape:49,share:[4,6,40,64],should:64,shuffl:59,simpl:[49,116],singl:59,slice:93,solut:[37,38,39,40,41,47,57,61],sourc:[0,2,111],spars:[14,15,16,65,107],specifi:107,split:52,stack:7,standard:72,start:[4,86,87,92,97,99],startup:99,statement:25,step:[2,48],storag:62,store:9,strategi:40,style:72,subcommond:28,submit:17,suffici:59,suitabl:8,sulut:43,summar:[4,18],summari:44,support:[29,51,68,70,112],survei:[29,35,62,121],synopsi:28,syntax:20,system:[30,97],tabl:[46,67],task:[9,13,67],tear:97,tecton:121,templat:97,tensor:[60,68,77],tensorarrai:[49,70],tensordesc:71,tensorflow:35,test:[0,41,42,43,72,74,75,79,105,107],theori:5,thi:64,think:33,three:70,time:111,timelin:16,timer:110,tip:110,todo:[10,11,22],togeth:64,toler:9,tool:[8,78,110,121],toolchain:120,topic:68,toward:31,train:[1,4,9,12,15,17,21,50,59,80,82,92,93,94,95,97,99,105,107],trainer:[9,14,16,17,20,92,97],transform:39,translat:49,transpil:[21,22,23,31,40,51],tune:[105,110],ture:30,tutori:115,two:5,type:[0,20,47,75],uniform:70,unit:[41,42,43,72,74,75,79,105],unpack:49,updat:[4,15,16,78,92,93,97],usag:[6,24,48,49,59,77],use:[12,59,77],user:9,using:3,valu:58,variabl:[6,40,58,60,64,71],vartyp:71,vector:105,verifi:97,version:[3,18,29],volum:97,vpc:97,what:[12,16,110],when:[16,64],whl:3,why:[29,30,53,59,60,70,110],work:67,worker:18,workflow:[72,91],wrapper:74,write:[72,74,75,76,78],www:78,yaml:99,your:[1,76]}}) \ No newline at end of file +Search.setIndex({docnames:["build_and_install/build_from_source_en","build_and_install/docker_install_en","build_and_install/index_en","build_and_install/pip_install_en","dev/contribute_to_paddle_en","dev/index_en","dev/new_layer_en","dev/write_docs_en","faq/build_and_install/index_en","faq/cluster/index_en","faq/index_en","faq/local/index_en","faq/model/index_en","faq/parameter/index_en","getstarted/concepts/use_concepts_en","getstarted/index_en","getstarted/quickstart_en","howto/capi/compile_paddle_lib_en","howto/capi/index_en","howto/capi/organization_of_the_inputs_en","howto/capi/workflow_of_capi_en","howto/cluster/cmd_argument_en","howto/cluster/index_en","howto/cluster/multi_cluster/fabric_en","howto/cluster/multi_cluster/index_en","howto/cluster/multi_cluster/k8s_aws_en","howto/cluster/multi_cluster/k8s_distributed_en","howto/cluster/multi_cluster/k8s_en","howto/cluster/multi_cluster/openmpi_en","howto/cluster/multi_cluster/src/k8s_data/README","howto/cluster/multi_cluster/src/k8s_train/README","howto/cluster/preparations_en","howto/cmd_parameter/arguments_en","howto/cmd_parameter/detail_introduction_en","howto/cmd_parameter/index_en","howto/cmd_parameter/use_case_en","howto/index_en","howto/optimization/gpu_profiling_en","howto/rnn/hierarchical_layer_en","howto/rnn/hrnn_rnn_api_compare_en","howto/rnn/index_en","howto/rnn/recurrent_group_en","howto/rnn/rnn_config_en","index_en"],envversion:50,filenames:["build_and_install/build_from_source_en.rst","build_and_install/docker_install_en.rst","build_and_install/index_en.rst","build_and_install/pip_install_en.rst","dev/contribute_to_paddle_en.md","dev/index_en.rst","dev/new_layer_en.rst","dev/write_docs_en.rst","faq/build_and_install/index_en.rst","faq/cluster/index_en.rst","faq/index_en.rst","faq/local/index_en.rst","faq/model/index_en.rst","faq/parameter/index_en.rst","getstarted/concepts/use_concepts_en.rst","getstarted/index_en.rst","getstarted/quickstart_en.rst","howto/capi/compile_paddle_lib_en.md","howto/capi/index_en.rst","howto/capi/organization_of_the_inputs_en.md","howto/capi/workflow_of_capi_en.md","howto/cluster/cmd_argument_en.md","howto/cluster/index_en.rst","howto/cluster/multi_cluster/fabric_en.md","howto/cluster/multi_cluster/index_en.rst","howto/cluster/multi_cluster/k8s_aws_en.md","howto/cluster/multi_cluster/k8s_distributed_en.md","howto/cluster/multi_cluster/k8s_en.md","howto/cluster/multi_cluster/openmpi_en.md","howto/cluster/multi_cluster/src/k8s_data/README.md","howto/cluster/multi_cluster/src/k8s_train/README.md","howto/cluster/preparations_en.md","howto/cmd_parameter/arguments_en.md","howto/cmd_parameter/detail_introduction_en.md","howto/cmd_parameter/index_en.rst","howto/cmd_parameter/use_case_en.md","howto/index_en.rst","howto/optimization/gpu_profiling_en.rst","howto/rnn/hierarchical_layer_en.rst","howto/rnn/hrnn_rnn_api_compare_en.rst","howto/rnn/index_en.rst","howto/rnn/recurrent_group_en.md","howto/rnn/rnn_config_en.rst","index_en.rst"],objects:{},objnames:{},objtypes:{},terms:{"00m":37,"03m":37,"0424m":37,"055ee37d":25,"0630u":37,"06u":37,"0810u":37,"0957m":37,"0_cudnn5":0,"0_cudnn5_avx_mkl":[1,3],"0_cudnn7_avx_mkl":3,"0rc":31,"100gb":37,"100gi":25,"10m":37,"1150u":37,"11e6":27,"124n":37,"13m":27,"1490u":37,"1550u":37,"16u":37,"173n":37,"1770u":37,"18ad":25,"18e457ce3d362ff5f3febf8e7f85ffec852f70f3b629add10aed84f930a68750":27,"197u":37,"1gb":37,"210u":37,"215n":37,"228u":37,"2520u":37,"2680u":37,"279n":37,"27m":37,"285m":37,"2863m":37,"28m":37,"2977m":37,"2cbf7385":25,"302n":37,"30u":37,"328n":37,"32u":37,"331n":37,"3320u":37,"365e":25,"36u":37,"3710m":37,"3768m":37,"387u":37,"38u":37,"3920u":37,"39u":37,"4035m":37,"4090u":37,"4096mb":33,"4279m":37,"43u":37,"448a5b355b84":27,"4560u":37,"4563m":37,"45u":37,"4650u":37,"4726m":37,"473m":27,"4gb":33,"50bd":25,"50gi":25,"514u":37,"525n":37,"526u":37,"536u":37,"5460u":37,"5470u":37,"54u":37,"5690m":37,"573u":37,"578n":37,"5798m":37,"586u":37,"58s":27,"5969m":37,"5_cudnn5_avx_mkl":3,"5_cudnn5_avx_openbla":[3,16],"6080u":37,"6140u":37,"6305m":37,"639u":37,"655u":37,"6780u":37,"6810u":37,"682u":37,"6970u":37,"6ce9":25,"704u":37,"7090u":37,"72u":37,"73u":37,"75u":37,"760u":37,"767u":37,"783n":37,"784u":37,"78m":37,"7kb":27,"8250u":37,"8300u":37,"830n":37,"849m":37,"861u":37,"8661m":37,"892m":37,"901n":37,"90u":37,"918u":37,"9247m":37,"924n":37,"9261m":37,"9330m":37,"94u":37,"9530m":37,"983m":37,"988u":37,"997u":37,"99u":37,"9f18":27,"abstract":[6,33],"case":[6,25,34,37,42],"class":32,"const":6,"default":[0,1,3,4,21,23,25,27,33,35],"export":[1,7,21],"final":6,"float":[6,35,37],"function":[6,21,33,37,42],"import":[3,16,21,25,37,42],"int":[6,21,35],"long":37,"new":[0,4,5,16,25,27],"null":[6,33],"public":[6,21,25,27],"return":[6,25,42],"static":25,"super":6,"switch":25,"throw":25,"true":[6,21,25,33,35,42],"try":[0,1,3,37],"var":7,"void":6,"while":[33,42],AGE:[25,27],AWS:[24,29,30],And:[25,35,42],But:[3,4,22],For:[0,1,4,6,16,21,32,33,35,37,42],IDE:0,IPs:21,Into:25,Its:[25,42],Not:[0,3],One:[6,33,42],PRs:7,QoS:27,TLS:25,That:[1,33,35],The:[0,1,3,4,6,7,22,23,24,25,27,31,33,35,37,42],Then:[1,3,6,22,25,27,28,37,42],There:[25,37],These:[0,24,35],Use:[0,6,21,22,25,33,34,37],Using:[0,27],VMs:0,VPS:25,Yes:[0,1],___fc_layer_0__:25,__init__:6,__rnn_step__:42,_source_language_embed:42,_target_language_embed:42,aaaaaaaaaaaaa:25,about:[1,3,16,25,32,33,37],abov:[0,1,2,4,16,25,27,37],absolut:1,acceler:[1,35],access:[3,21,42],accessmod:25,accord:[21,32,33,35],accordingli:6,account:4,accuraci:6,achiev:37,ack:33,act:[16,42],action:25,activ:[6,7,16,33,42],adagrad:21,add:[0,4,6,35,37],add_input:6,add_test:6,add_unittest_without_exec:6,addbia:6,added:[4,6],adding:4,address:[1,23,28,31,33,37],addrow:6,administr:0,advanc:[33,37,42],advantag:31,advic:37,after:[0,1,4,6,23,25,27,31,33,35,42],again:37,against:25,aggreg:25,agre:4,agreement:4,aid:37,alexnet_pass1:35,alexnet_pass2:35,algorithm:42,all:[0,1,6,21,22,23,25,27,32,33,35,37,42],alloc:[6,35],allow:[4,6,25,33,37],allow_only_one_model_on_one_gpu:[32,33,35],almost:[0,23],alreadi:[1,23,25,33,37],alreali:32,also:[0,1,3,6,7,22,27,31,37,42],alwai:[25,33],amazon:[25,27],amazonaw:25,amazonec2fullaccess:25,amazonelasticfilesystemfullaccess:25,amazonroute53domainsfullaccess:25,amazonroute53fullaccess:25,amazons3fullaccess:25,amazonvpcfullaccess:25,amd64:25,amend:4,among:25,amount:37,analysi:37,andd:25,ani:[0,25,28,37],annoi:23,anoth:[0,25,33],ans:25,answer:[4,25],anyth:25,api:[0,3,6,21,24,25,36,37,40],api_trainer_config_helpers_lay:42,apiserv:25,apivers:[25,27],append:[4,6,21,42],appleyard:37,appli:[6,42],applic:[4,24,25,27,37],appreci:4,apt:1,architectur:[0,22],arg:32,argument:[0,4,6,22,33,34,42],arn:25,around:25,articl:[0,27],artifact:[3,25],assign:[21,25,31,33],assum:[1,35,42],async:32,async_count:33,async_lagged_grad_discard_ratio:[21,33],async_lagged_ratio_default:[32,33],async_lagged_ratio_min:[32,33],asynchron:[22,33],attr:42,attribut:6,auc:32,aucvalidationlay:33,authent:25,author:25,auto:[0,4,6,37],autom:[24,25],automat:[0,4,6,23,25,32,33,42],avail:[3,25],averag:33,average_test_period:[32,33],avg:37,avoid:[0,37],avx2:0,avx:[0,1],await:27,awar:25,awk:28,aws_account_id:25,awsaccountid:25,awskeymanagementservicepowerus:25,b363:27,b8561f5c79193550d64fa47418a9e67ebdd71546186e840f88de5026b8097465:27,ba5f:25,back:1,background:21,backward:[6,33,35,42],backward_first:42,backwardactiv:6,baidu:27,balanc:[25,33],bare:27,barrier:[22,33],barrierstatset:37,base:[6,25,33,37,42],basematrix:6,bash:[0,1,25,27,31],basic:[6,15],batch:[4,6,25,27,33],batchsiz:6,beam:[33,42],beam_gen:42,beam_search:42,beam_siz:[32,33,35,42],becaus:[0,6,25,35,42],becom:37,been:4,befor:[0,1,4,25],begin:[6,21],beginn:42,behavior:37,below:[0,3,6,21,22,25,31,37,42],besid:3,best:[0,1,33],besteffort:27,better:25,between:[1,25,40],bia:[6,42],bias:6,bias_attr:42,biases_:6,biasparameter_:6,biassiz:6,bidi:27,bidirect:42,big:37,bilinearfwdbwd:37,bin:[0,1,21,25,27,31],binari:[0,2,3,25,37],bla:1,blank:25,blob:0,block:[6,33,37],book:[7,42],bool:[6,33,35],boot:42,boot_lay:42,bos_id:42,both:[6,7,22,25,37,42],bottleneck:37,box:37,branch:[3,4,7],breadth:33,briefli:37,broken:4,browser:[1,7,25],bsd:0,bucket_nam:25,buddy_alloc:4,buffer:33,bug:[4,25],build:[1,3,4,10,16,18,25,29,30,31,33,43],builder:4,built:[0,3],bunch:[31,37],button:[4,7,25],c703c041:4,c99e:25,cach:0,cacul:21,calcul:[1,6,22,33,35,37,42],call:[0,6,16,25,31,33,37,42],callback:6,caller:25,can:[0,1,2,3,4,6,7,16,21,22,23,24,25,27,28,31,32,33,35,37,42],cannot:6,capac:25,capi:0,captur:23,card:31,care:[1,32,33],carefulli:33,cat:[1,28],categoryfil:27,caus:3,caution:[25,27],cento:[0,3,16],ceph:27,certain:32,certif:25,cfg:27,chain:6,chanc:6,chang:[0,4,6,21,25,33,37,42],channel:37,characterist:35,check:[0,3,4,7,25,31,33,35],check_eq:6,check_l:6,check_sparse_distribution_batch:[32,33],check_sparse_distribution_in_pserv:[32,33],check_sparse_distribution_ratio:[32,33],check_sparse_distribution_unbalance_degre:[32,33],check_styl:4,checkgrad:33,checkgrad_ep:33,checkout:4,china:1,chines:7,chmod:25,choic:1,choos:[0,1,2,33],claim:25,claimnam:25,clang:4,classif:35,claster:25,clean:[0,4],cli:25,click:[3,4,7,25,37],clip:33,clone:[0,4,7],close:4,cludform:25,cluster:[10,21,22,27,31,32,33],cluster_test_fil:21,cluster_train:23,cluster_train_fil:21,cluster_train_v2:[23,24,28],cm469:25,cmake:[0,4,6,7,37],cmakelist:6,cmd:27,cname:25,cnn:27,code:[0,1,3,5,6,7,16,21,25,27,37,42],codebas:4,collectbia:6,column:6,com:[0,1,4,7,25,27],comma:33,command:[0,1,3,4,6,7,16,22,23,25,27,28,29,30,31,36,37],commandlin:37,comment:4,commit:[4,21],common:[6,32,42],commonli:[35,37,42],commun:[4,6,21,25],compar:[0,6],comparis:40,compil:[6,7,31],complet:[2,6,25,27],complex:[37,42],compon:6,compromis:0,comput:[0,1,4,6,24,25,31,35,37,42],computation:42,concat:42,concept:[15,42],concurr:22,concurrentremoteparameterupdat:33,condit:[27,42],conduct:37,conf:23,conf_paddle_gradient_num:25,conf_paddle_n:25,conf_paddle_port:25,conf_paddle_ports_num:25,conf_paddle_ports_num_spars:25,config:[6,25,27,32,33],config_:33,config_arg:[32,33,35],config_lay:6,config_pars:6,configur:[0,4,6,10,16,21,33,37,40],conflict:4,congest:33,connect:[6,21,25,27,31],consid:[0,35,37],consol:[25,37],consolid:7,constant:6,construct:42,constructor:6,contain:[0,2,3,21,25,28,31,42],container:24,containerport:25,content:[7,27],content_dir:7,context:42,contin:25,continu:[22,33],contribut:5,contributor:4,control:[21,25,27,33],convent:4,converg:23,cool:4,copi:[0,4,21,25,28],core:[0,33],coreo:25,correct:[6,25],correctli:6,correspond:6,cost:33,could:[0,23,25,37],count:[21,27,33,35,37],cours:0,cp27:3,cp27m:3,cp27mu:3,cpp:[6,37],cpu:[0,1,27,33,37],cpu_avx_mkl:[1,3],cpu_avx_openbla:[3,16],cpu_noavx_openbla:3,cpuinfo:1,crash:[23,33,37],creat:[1,4,6,7,16,21,28,33],create_bias_paramet:6,create_input_paramet:6,createstack:25,creation:25,creationd:25,crlf:4,csc:6,csr:6,ctest:0,ctrl:[0,23],cuda7:[3,16],cuda8:[0,1,3],cuda:[1,3,31,33,37],cuda_dir:[32,33],cuda_so:1,cudaconfigurecal:37,cudadevicegetattribut:37,cudaeventcr:37,cudaeventcreatewithflag:37,cudafre:37,cudagetdevic:37,cudagetdevicecount:37,cudagetdeviceproperti:37,cudagetlasterror:37,cudahostalloc:37,cudalaunch:37,cudamalloc:37,cudamemcpi:37,cudaprofilerstart:37,cudaprofilerstop:37,cudaruntimegetvers:37,cudasetdevic:37,cudasetupargu:37,cudastreamcr:37,cudastreamcreatewithflag:37,cudastreamsynchron:37,cudeviceget:37,cudevicegetattribut:37,cudevicegetcount:37,cudevicegetnam:37,cudevicetotalmem:37,cudnn:33,cudnn_conv_workspace_limit_in_mb:[32,33],cudnn_dir:[32,33],cudnnv5:0,cudrivergetvers:37,cuinit:37,curl:25,current:[0,1,3,6,7,21,23,25,33,42],current_word:42,custom:[6,25],cxxabi_1:3,d3e0:25,daili:4,dangl:0,darwin:25,data:[6,16,18,21,22,28,29,32,33,35,37,42],data_typ:[16,42],dataset:[16,22,33,42],date:21,dcuda_arch_nam:0,dcudnn_root:0,debug:[1,4],decod:42,decoder_boot:42,decoder_group_nam:42,decoder_input:42,decoder_mem:42,decoder_s:42,decoder_st:42,decor:6,decrypt:25,deep:[1,37],deeper:1,def:[6,42],defalut:[33,35],default_devic:35,default_valu:35,defin:[6,21,23,33,42],definit:1,delai:33,delet:4,deletestack:25,demo:[23,27,29],demolish:27,demonstr:42,denot:35,dens:[6,25],dense_vector:16,depend:[1,21,22,35],deploi:[23,35],deploy:[23,24,25],descent:22,describ:[6,25,27],describestack:25,describestackev:25,describestackresourc:25,descript:[0,3,4,21,25,34],desir:[25,27],destructor:6,detail:[0,6,7,16,23,25,27,34,35,37,42],detect:[0,4],determin:6,dev:[0,1],develop:[0,1,3,4,7,21,32,33,43],deverlop:33,devic:[1,21,33],deviceid:35,devid:33,devtools2:0,diagnos:23,diagram:22,dict:[21,28],dictionari:35,did:1,differ:[1,6,21,22,23,25,27,33,42],difficult:0,dig:[1,25,37],digit:21,dim:6,dimens:[6,35],dimension:[6,42],directli:[0,2,23,27],directori:[0,1,7,21,23,27,28,33,37],discard:[21,33],discoveri:25,discrep:37,disk:[0,27],dispatch:[23,24,33],displai:4,dist:0,distinguish:23,distribut:[3,21,23,27,29,30,36],distribute_test:[32,33],distributedli:6,divid:32,diy_beam_search_prob_so:[32,33],django:7,dnn:0,dns:25,doc:[0,7,21],doc_cn:7,docker:[0,2,4,7,25,29,30,31],docker_clust:[23,28],dockerhub:1,document:[0,4,5,31,35],doe:[0,3,6,37],doesn:[0,1,4,27,37],doing:37,domain:25,don:[0,1,4,7,25],done:[4,25,37],dot:33,dot_period:[33,35],doubl:[0,33],down:37,download:[0,1,3,21,22],driver:[1,31],dropout:6,drwxr:27,dtoh:37,durat:37,dure:[6,25,32,33],dwith_gpu:0,dwith_profil:37,dwith_test:0,dwith_tim:37,dynam:[0,33,37],dynamic_cast:6,each:[6,21,22,23,25,31,33,35,42],earli:4,easi:[4,6,23],easier:[0,4,6],echo:1,edit:[0,1,25],editor:0,edu:[25,27],eeoi3ezpr86c:25,effect:[0,25,33],effici:[0,6,42],efs:25,efs_dns_nam:25,efsvol:25,either:[2,37],elb:25,elbapis:25,electron:27,els:[0,1,6],emac:0,email:4,emb:27,embed:[21,42],embedding_nam:42,embedding_s:42,emphas:37,emplace_back:6,emploi:42,enabl:[4,21,25,33,37],enable_grad_shar:[32,33],enable_parallel_vector:33,enc_proj:42,enc_vec:42,encod:42,encoded_proj:42,encoded_sequ:42,encoded_vector:42,encoder_s:42,encrypt:25,encrypt_decrypt:25,end:[3,4,33,42],endpoint:25,engin:37,english:7,enjoi:1,enough:0,ensur:[0,1,3,6],entri:[0,4,6,25],env:[7,25],environ:[0,3,4,21,24,25,27,32,33,37],environmenterror:21,eos_id:42,equal:33,equip:42,error:[6,23,25,33],especi:0,eta:27,etc:[0,24,25,32,35],eth0:[21,25],evalu:37,even:[0,4,33,37],evenli:25,event:27,everi:[4,6,21,22,28,31,33,42],everyon:4,everywher:0,exactli:25,exampl:[0,4,6,21,24,25,27,32,33,35,37,42],except:35,exec:33,execut:[6,25,37],exist:[0,3,6,25,33],exit:[27,33],expand:[1,6],expect:37,experi:35,experienc:4,explain:[4,22],explicit:6,expos:25,express:25,extraattr:35,extract:25,extrem:37,f120da72:27,f7e3:25,fa0wx:27,fabric:24,fail:[27,33,35],fals:[6,16,21,27,33,35,42],faq:43,fast:37,faster:[1,37,42],fastli:4,fault:0,favorit:0,fbd1f2bb71f4:27,fc1:[6,35],fc2:35,fc3:35,fc4:35,fc8a365:25,fc8a:25,fc_layer:[6,35],fclayer:6,featur:[4,33],feel:4,fetch:[6,42],few:0,field:[25,37],figur:[6,37,42],file:[0,1,3,4,6,16,21,23,28,33,42],filesystem:25,fill:25,find:[0,3,28,37],fingerprint:25,finish:[0,21,22,23,25,27],finit:6,finnal:1,first:[0,4,6,25,33,35,37,42],first_seq:42,firstseen:27,five:37,fix:4,flag:[4,7,33],flexibl:42,flist:21,fnt03:25,focu:37,folder:25,follow:[0,1,3,4,6,7,16,25,27,28,29,30,35,37,42],fork:4,form:[3,37],format:[4,6,16,21,25,33],forward:[6,35,42],forwardactiv:6,found:[24,42],framework:[4,6,24],free:4,frequenc:37,frequent:23,from:[1,3,4,6,21,22,24,25,27,33,35,37,42],fulfil:37,full:[6,42],full_matrix_project:42,fulli:[6,37],fullyconnectedlay:6,gap:33,gather:6,gcc:0,gcc_3:3,gener:[0,4,25,28,33,35,37],generatedinput:42,get:[0,1,3,4,6,21,23,25,28,37,42,43],get_config_arg:35,get_data:27,get_input_lay:6,get_support:3,getbatchs:6,getenv:21,getinput:6,getinputgrad:6,getinputvalu:6,getoutputgrad:6,getoutputvalu:6,getparameterptr:6,getsiz:6,gettempl:25,gettranspos:6,getw:6,getweight:6,getwgrad:6,git:[0,4,7],github:[0,4,7],give:[0,4,6,25,37],given:[6,33],glibc:3,glibc_2:3,glibcxx_3:3,global:[0,25,33,37],globalstat:37,globalstatinfo:37,glog:4,glog_v:4,glog_vmodul:4,goal:37,going:31,good:37,googl:[4,24],googleapi:25,gpg2:25,gpg:25,gpu:[0,3,16,21,31,36],gpu_id:[33,35],gpugpu_id:32,grad:33,grad_share_block_num:[32,33],gradient:[21,22,33],gradual:37,grant:25,greater:21,grep:[1,28],groudtruth:42,group:40,group_input1:42,group_input2:42,group_input:42,grow:4,gru:42,gru_decod:42,gru_decoder_with_attent:42,gru_step:42,grumemori:42,gserver:6,gsizex:37,guarante:6,guest:[0,3],gui:37,guid:[4,6,25,27,37,42],gzip:27,half:25,hand:22,hard:[0,25],hardwar:[0,37],has:[0,4,6,25,27,37,42],have:[0,1,4,6,21,25,33,35,37,42],haven:0,head:[4,21,28],header:6,headip:28,heard:0,heavi:23,height:6,help:[0,4,23],helper:6,here:[0,1,3,4,7,21,23,25,27,32,35,42],heurist:33,hidden:[25,42],hierarch:[40,42],high:[6,24],higher:4,highli:[35,42],hl_get_sync_flag:6,hold:25,home:[1,25,27,28],host:[25,27],hostfil:28,hostnam:25,hostpath:27,hostport:25,hour:0,hourli:4,hous:16,how:[22,25,27,33,42,43],howev:[25,32,33,42],howto:21,htod:37,http:[0,1,4,7,25,27],hyper:6,i1117:37,iamfullaccess:25,iamusersshkei:25,id_rsa:28,ident:25,identifi:6,ids:6,idx:6,ignor:33,illustr:[6,37,42],imag:[0,4,25,29,30,35],imagepullpolici:25,imgsiz:37,imgsizei:37,imgsizex:37,imikolov:21,immedi:[0,25],implement:42,improv:[25,37],inbound:25,includ:[0,3,6,24,25,27,33,37,42],increas:[22,33],increment:33,incupd:6,index:25,indic:[23,25],individu:25,infer:16,info:[6,23],inform:[4,6,25,33,37],infrastructur:25,ingor:33,init:[6,16,21,25,35],init_model_path:[32,33,35],initi:[6,16,33,42],inlin:25,inner:6,input:[4,6,16,18,28,35,40,42],input_data:6,input_data_target:6,input_hassub_sequence_data:6,input_index:6,input_label:6,input_lay:6,input_sequence_data:6,input_sequence_label:6,input_sparse_float_value_data:6,input_sparse_non_value_data:6,input_t:6,inputdef:6,inputlayers_:6,insert:4,insid:[0,1,25],instal:[0,1,4,7,10,18,27,31,43],instanc:[6,33,37,42],instance_ip:25,instead:[0,4],instruct:[1,37],int32:33,integ:6,integer_value_sequ:42,integr:0,intend:0,interact:[1,25],interest:37,interfac:[0,25],intermedi:0,intern:[22,23,25],interpret:[0,37],introduc:[21,22,24,27],introductori:0,invok:[4,25,37],ips:25,ipt:42,is_async:21,is_seq:42,isn:37,isspars:6,issu:[0,1,3,4,37],item:16,its:[3,6,22,25,33,37],jeremi:37,job:[1,21,22,24,32,33,35],job_dispatch_packag:23,job_nam:25,job_namespac:25,job_path:25,job_workspac:23,jobpath:25,jobport0:25,jobport1:25,jobport2:25,jobport3:25,journei:1,json:[25,27],jupyt:1,just:[3,4,23,25,35],jx4xr:25,k8s_data:25,k8s_train:25,kebilinearinterpbw:37,kebilinearinterpfw:37,keep:[0,4],kei:[0,4,37],kernel:37,key1:33,key2:33,key_pair_nam:25,keyid:25,keymetadata:25,keypair:25,keyserv:25,keystat:25,keyusag:25,kill:25,kind:[1,25,27],kms:25,know:[4,6,21,25,37],kubeconfig:25,kubectl:[23,27,28],kuberent:25,kubernet:[24,29,30],l2regular:21,label:27,lag:33,lan:31,languag:35,larg:4,last:[0,33,42],lastseen:27,latenc:[23,25],later:[0,3,25],latest:[0,1,3,7,27],launch:[25,33],layer:[5,16,32,33,40,42],layer_0:6,layer_attr:[35,42],layer_num:35,layerbas:6,layerconfig:6,layergradutil:6,layermap:6,lead:37,learn:[0,1,6,7,37,42],learning_r:21,least:3,leav:25,legaci:1,len:[6,16],length:[27,33,42],let02:27,let:25,level:[4,23,33],lib64:[1,33],lib:[0,1,21],libc:3,libcuda:1,libgcc_:3,libnvidia:1,libpython2:0,librari:[0,3,21,31,33,36],libstdc:3,licens:4,lifetim:3,like:[0,3,4,21,24,25,32,35,37,42],limit:[33,37],line:[0,4,22,23,25,35,36,37],linear:16,link:[3,25],linux:[0,1,3,4,25,31],linux_x86_64:3,list:[0,6,16,21,25,33,35,42],listdir:21,listen:[21,33],littl:33,load:[0,25,33],load_missing_parameter_strategi:[32,33,35],loadsave_parameters_in_pserv:[32,33],local:[0,1,4,10,23,27,32,33],localhost:[1,7],locat:[6,21,42],log:[3,6,21,23,25,27,28,33],log_barrier_abstract:33,log_barrier_lowest_nod:[32,33],log_barrier_show_log:[32,33],log_clip:[32,33],log_error_clip:[32,33],log_period:[27,33,35],log_period_serv:[32,33],login:[3,28],look:[21,25,27,32],loss:6,lot:[21,32],lower:[4,23],lowest:33,lstm:[27,42],lstmemori:42,mac:[0,4],machin:[0,3,6,25,27,28,32,33,35],machine_transl:42,maco:[0,3,16],made:42,mai:[0,1,7,21,25,37],main:[3,22,25],mainli:33,mainlin:3,maintain:25,make:[0,4,6,21,22,25,37],malloc:6,manag:[3,7,24],mani:[0,33],manipul:23,manual:23,manylinux1:3,manylinux1_x86_64:3,map:33,mapreduc:21,mark:42,master:33,match:[3,37],math:[4,6,37],matric:[6,42],matrix:[6,32,35],matrixptr:6,matur:24,max:[33,35,37],max_length:42,maximum:[33,37,42],mean:[0,1,25,33,35,37,42],measur:37,mechan:[25,42],memcpi:37,memori:[0,4,6,27,33,35,37,42],memory_threshold_on_load_data:33,mention:0,merg:[4,7,33],messag:[4,27,33],metadata:[25,27],method:[0,1,3,6,7,33,35,37],might:[0,4,6,25],mileag:37,million:35,min:[25,35,37],minim:33,minimun:33,minut:[0,1,25],mirror:1,miss:33,mit:25,mix:42,mkdir:[7,25,28],mkl:[0,1],mobil:7,mod:21,mode:[4,33],model:[4,6,7,10,16,22,25,33,36],model_list:[33,35],model_path:35,modif:2,modifi:[6,21,23,25,42],mon:27,more:[0,1,6,7,16,21,22,27,35,37,42],most:[3,6,32,37,42],mount:[0,1,21,25,27],mountpath:[25,27],move:[1,25,37],movement:37,mpi:28,mpirun:28,much:37,mul:6,multi:[6,23,32,33],multipl:[6,21,22,25,33,35,42],multipli:6,must:[0,6,21,25,33,35,42],my_cluster_nam:25,my_external_dns_nam:25,my_lib:21,mypaddl:27,name:[1,3,6,16,21,27,29,30,33,35,37,42],namespac:[6,27],nativ:4,natur:35,navig:7,necessari:[6,28],necessarili:6,need:[0,1,2,3,6,7,16,21,25,27,31,32,33,35,42],net:0,network:[6,16,21,22,33,37],network_config:35,networkadministr:25,neural:[16,22,33,37],neuron:6,never:[25,27],next:[6,25,27,33,37,42],nfs4:25,nfs:25,nfsver:25,nic:[21,32,33],nnz:6,node1ip:28,node2ip:28,node3ip:28,node:[6,21,23,24,25,27,28,31,33],node_0:25,node_1:25,node_2:25,node_id:21,nodefil:23,nohup:21,nois:22,non:[6,25,33],none:42,nonlinear:6,nor:0,normal:[6,27,31,33,42],note:[0,1,7,21,25,33,35,37],notebook:1,noth:[0,33],notic:[4,6,42],notif:4,now:[25,33],nproc:0,nullptr:6,num:[21,33],num_gradient_serv:[21,32,33],num_input:4,num_pass:[27,32,33,35],number:[0,6,21,24,25,33],numdevices_:35,numlogicaldevices_:35,numpi:0,numsampl:37,nvidia:[1,33,37],object:37,observ:[6,37],oct:27,off:[0,1,31],offici:[4,7,25],often:[4,21],ograd:6,old:33,omit:0,ompi_comm_world_rank:21,onc:[4,6,7,25],one:[0,1,4,6,23,25,27,28,33,35],ones:4,onli:[0,2,3,6,7,25,27,32,33,35,37,42],onto:[25,28],open:[4,24,25],openbla:[0,1],openmpi:24,oper:[4,6,25,33,37,42],opt:0,optim:[6,21,22,37],option:[6,21,23,35],order:[0,6,22,25,27,33],oregon:25,organ:18,origin:4,other:[0,4,22,25,27,35,42],otherwis:[4,23,35,42],our:[0,3,4,6,25,27,42],out:[16,25,27,28,33,37,42],out_dir:25,out_mem:42,outlin:34,output:[0,4,6,18,21,27,33,35,37,42],output_:6,output_lay:16,output_mem:42,outv:6,over:[4,6,37],overal:4,overhead:37,overlap:6,overrid:6,overwhelm:4,overwrit:21,own:[0,21,23,25],owner:[0,4],packag:[0,1,4,25],paddl:[0,1,3,4,6,7,16,21,23,25,27,28,31,33,35,37,42],paddle_init_num_gradient_serv:21,paddle_init_port:21,paddle_init_ports_num:21,paddle_init_ports_num_for_spars:21,paddle_init_pserv:21,paddle_init_trainer_count:21,paddle_init_trainer_id:21,paddle_init_use_gpu:21,paddle_manylinux_devel:0,paddle_output:27,paddle_pserver2:23,paddle_train:23,paddlepaddl:[2,4,6,16,21,22,23,24,28,29,30,31,37,42],paddlepaddle_gpu:3,paddlepaddlebook:1,paddlepaddlehub:1,page:[4,25],parallel:[0,21,22,24,25,27,33,35,37],parallel_nn:[32,33],param_attr:42,paramattr:42,paramet:[0,4,6,10,16,22,23,35,36],parameter_block_s:[32,33],parameter_block_size_for_spars:[32,33],parametermap:6,parameters_:6,paramt:[21,25],paraspars:6,parent:6,pars:[0,25,35],part:[6,21,22,37,42],parti:37,particular:37,partit:[22,25],pass:[4,6,21,23,25,27,33,37],passtyp:6,password:28,past:[1,16,25],path:[0,1,21,25,27,33,35],path_to_paddlepaddle_working_directori:7,pattern:25,pem:25,peopl:0,pep425tag:3,pep8:4,per:33,perfom:[33,35],perform:[0,6,24,32,36,42],period:33,permiss:25,persist:25,persistentvolum:25,persistentvolumeclaim:25,perspect:37,perturb:6,pgp:25,pick:25,pickl:[21,28],pil:21,ping:4,pip:[0,2,4,7,16],place:[6,37],plan:6,platform:[3,4,21,24,25],pleas:[0,1,3,4,6,7,25,31,42],pnpairvalidationlay:33,pnpairvalidationpredict_fil:32,pod:[25,27],pod_nam:25,point:[0,4,37],polici:25,pool3:6,port:[21,25,27,32,33],port_num:32,portal:7,ports_num:[21,33],ports_num_for_spars:[21,32,33,35],possibl:37,post:0,potenti:37,ppo_workspac:7,practic:[6,42],pre:[0,4,25,27],precis:0,predetermin:33,predict:[10,16,33,36,42],predict_fil:33,predict_output_dir:[32,33],prefetch:6,prefix:25,pregrad:6,prepar:[22,29,42],preprocess:27,prev_batch_st:[32,33],preview:7,previou:[6,25,33],previous:27,price:16,primer:4,print:[3,16,28,33],printallstatu:37,printstatu:37,privat:4,privileg:[0,25],prob:16,probabl:[1,4,42],problem:[0,3],proc:1,proce:[1,25],process:[0,4,23,24,25,27,33,35,42],processor:37,product:[6,25,27],productgraph:27,proflier:37,program:[23,33,37],progress:33,project:[4,6,42],propag:[33,35],proper:31,properli:0,properti:33,protect:6,protocol:33,provi:21,provid:[1,16,21,23,24,25,37],providermemory_threshold_on_load_data:32,provis:25,pserver:[21,25,32,33],pserver_num_thread:[32,33],pserverstart_pserv:32,psize:6,pub:28,pull:4,purpos:37,push:4,push_back:6,put:[6,27],pvc:25,pwd:[0,1,7],pypi:3,python3:3,python:[0,1,3,4,7,16,21,28,42],queri:25,question:25,quick:[15,33],quick_start:[25,27,29],quick_start_data:27,quickstart:27,quit:37,rais:21,ran:37,rand:[33,35,37],random:[22,33],randomnumberse:32,rang:[4,33,35],rank:25,rate:6,rather:25,ratio:33,rdma:33,rdma_tcp:[32,33],reach:37,read:[0,1,7,22,25,31,42],reader:21,readi:[25,27],readwritemani:25,real:21,reason:[4,27],reciev:33,recommend:[0,1,2,4,6,7,23,31,33,42],recompil:37,record:25,recurr:40,recurrent_group:42,recurrentlay:33,recv:25,reduc:[1,4,23,33,35],refer:[0,1,6,27,42],reformat:4,region:37,regist:[6,37],register_gpu_profil:37,register_lay:6,register_timer_info:37,registri:27,regular:[6,21,25],reinstal:0,relat:[4,27],releas:25,relu:6,rememb:4,remot:[4,6,25,33,35],remoteparameterupdat:33,remov:[4,33],removing_docker_contain:0,renam:3,repli:4,repo:[4,7],report:37,repositori:7,repres:[6,25,42],reproduc:0,request:[4,25,27],requir:[3,4,6,7,21,25,27],reserveoutput:6,resid:0,resolv:[4,27],resourc:25,respect:[6,33,42],respons:[25,27],restart:[25,27],restartpolici:[25,27],restrict:33,result:[25,33,37],retran:25,retriev:[6,27],retriv:21,reus:6,rev:0,revers:42,review:27,reviews_electronics_5:27,right:4,rkt:0,rnn:[32,36],rnn_bias_attr:42,rnn_layer_attr:42,rnn_out:42,rnn_use_batch:[32,33],role:25,root:[0,25,27],row:6,rsize:25,rule:[6,25],run:[2,3,4,6,7,16,21,22,23,24,25,28,29,30,31,33,37],run_test:0,runinitfunct:37,runserv:7,runtim:[1,23],s_recurrent_group:42,sai:[33,35],sake:6,same:[0,23,25,35,42],sampl:[1,21,23,33,35],satisfi:[3,25],save:[0,21,25,27,33,35],save_dir:[27,33,35],save_only_on:[32,33],saving_period:[32,33],saving_period_by_batch:[32,33,35],scale:24,scenario:32,scene:32,schdule:25,schedul:25,scp:28,script:[0,21,23,24,25,28],search:[0,33,42],second:23,secret:25,section:[4,6,22,25,42],see:[4,25,37],seed:[33,37],seem:3,select:25,selector:27,self:6,send:[4,22,25,33],sens:4,sent:27,sentenc:42,separ:[21,33],sequenc:[4,6,40],sequenti:42,seri:3,serv:[1,21,25,37],server:[0,6,22,23,31,32],servic:21,session:37,set:[0,4,6,7,10,21,23,25,27,32,33,35,36,37,42],set_active_typ:6,set_drop_r:6,set_siz:6,set_typ:6,setp:25,setq:0,settup:6,setup:6,sever:[0,23,24,25,35],sgd:22,sgdasync_count:32,shard:[22,25],share:[0,33,37],shell:[1,25],should:[7,16,23,25,42],show:[0,3,22,25,27,33],show_check_sparse_distribution_log:[32,33],show_layer_stat:[32,33],show_parameter_stats_period:[27,32,33,35],shown:[6,25,37,42],shrink:6,sid:25,side:22,sig:25,sigint:23,sigmoid:6,sign:25,signal:23,signatur:25,signific:37,silent:21,similar:25,simpl:[33,37],simple_attent:42,simple_gru:42,simple_rnn:42,simplest:25,simpli:[1,16,37,42],simplifi:[6,27],simultan:25,sinc:[25,37],sincer:4,singl:[6,16,22,27],site:25,size:[1,6,16,33,42],size_t:6,skip:[4,23,25],slow:37,slowli:0,small:[4,6,33],small_messag:[32,33],smaller:4,snap:27,snapshot:25,snippet:[6,25,37,42],sock_recv_buf_s:[32,33],sock_send_buf_s:[32,33],socket:33,softmax:[6,42],softwar:37,some:[0,4,6,21,25,32,33,35,37],someth:[0,4],sometim:[0,37],sophist:6,sort:[25,33],sourc:[24,25,27,42],source_dict_dim:42,source_language_word:42,space:[0,37,42],spars:[6,21,25,33],sparseparam:6,sparseprefetchrowcpumatrix:6,speak:42,spec:[25,27],specfii:33,specif:35,specifi:[1,4,6,7,25,33,42],speed:0,sphinx:7,split:[21,22,25,35],split_count:[21,25],srand:33,src:21,src_backward:42,src_embed:42,src_forward:42,src_word_id:42,ssh:[25,27,28],ssh_server:23,stabl:25,stack:25,stage:23,stamp:37,standard:[0,3],stanford:27,start:[0,1,3,23,28,33,37,42,43],start_mpi_train:28,start_pass:[32,33],start_pserv:33,startup:25,stat:[33,37],state:[27,33,42],statement:[6,25],staticinput:42,statist:33,statset:37,statu:[25,27,37],status:27,std:[6,33],stdbuf:21,stderr:23,stdout:23,step:[0,1,4,6,16,22,25,27,28,37,42],still:3,stmt1482205552000:25,stmt1482205746000:25,stochast:22,stop:[0,23,27,33],storag:[21,25,27],store:[6,7,21,22,25,27,28,33],str:35,strategi:33,strict:22,string:[6,25,33],strongli:31,structur:[23,25],sts:25,stuff:4,style:0,sub:[6,42],submit:[7,24,25,32,33],subnet0:25,subnet:25,subobjectpath:27,subset:6,succeed:27,success:[25,27],successfulcr:27,successor:33,sudo:[0,25],suffici:33,suffix:[3,21],suggest:[4,37],suitabl:33,sum:[6,42],support:[0,1,3,6,7,16,21,22,24,25,33,37,40,42],suppos:6,sure:[0,6,25],swig:0,symbol:3,symlink:4,sync:33,syncflag:6,synchron:[22,25,33],system:[0,1,3,7,21,24,27],tab:3,tag:[1,31,42],take:[0,4,6,21,25,27,31,37,42],tanh:[6,42],tar:25,tarbal:25,target:[0,42],target_dict_dim:42,target_language_word:42,task:[35,42],tbd:[8,9,11,12,13,14,17,19,20,26,38,39,41],tcp:[25,33],tear:37,techniqu:[6,42],technolog:0,tee:27,tell:[1,37],templat:27,ten:0,termin:27,test:[10,16,21,28,32,37],test_all_data_in_one_period:27,test_data_dir:21,test_fcgrad:6,test_gpuprofil:37,test_layergrad:6,test_pass:[32,33,35],test_period:[32,33,35],test_recurrent_op:4,test_sum_op:0,test_wait:[32,33],testbilinearfwdbwd:37,testconfig:6,testfcgrad:6,testfclay:6,testlayergrad:6,testmodel_list:32,testsave_dir:32,testutil:6,text:25,tflop:37,tgz:3,than:[0,6,21,25,42],thei:[0,4,6,22,25,32,37,42],them:[0,4,7,25,32,33,37],theori:37,thi:[0,1,3,4,6,7,16,21,22,25,27,31,33,35,37,42],thing:37,third:37,thought:37,thread:[6,21,33,35,37],thread_local_rand_use_global_se:[32,33],threadid:35,threadloc:37,three:33,threshold:[4,33],through:[6,7,21,37,42],throughput:[21,37],thu:[6,25],tier:27,time:[0,27,33,35,37,42],timelin:37,timeo:25,togeth:42,token:42,toler:0,tool:[0,3,24,25,42],toplevel:0,total:[21,24,27,37],train:[6,10,24,28,29,30,32,36,37,42],train_config_dir:25,train_data:21,train_data_dir:21,train_id:25,train_list:21,traindot_period:32,trainer:[6,22,23,33,35],trainer_config:[25,27],trainer_config_help:6,trainer_count:[16,21,25,27,32,33,35],trainer_id:[21,25,33],trainingtest_period:32,tran:[6,33],transform:[6,42],transpar:23,transport:33,transpos:6,travi:4,tree:33,trg_embed:42,tune:36,tuninglog_barrier_abstract:32,turn:1,tutori:[0,1,6,25,28,29,30,37,40,42],two:[0,23,25,35,37,42],txt:[6,7,21,25,28],type:[6,16,21,22,25,27,31,33,35,42],typic:37,ubuntu:[3,16],uci_h:16,uid:27,unbalanc:33,unbound:42,under:[0,1,7,21,23,24,25],understand:37,understand_senti:42,undeterminist:37,unifi:4,uniform:33,uninstal:0,uniqu:[25,31,33],unique_ptr:6,unit:[0,10,42],unittest:4,unittestcheckgrad_ep:32,unnecessari:4,until:25,updat:[3,6,22,33,35],updatecallback:6,updatestack:25,upgrad:[0,3],upload:22,upstream:4,uri:25,url:4,usag:37,use:[0,1,3,4,6,7,16,21,22,25,27,33,35,37,42],use_gpu:[16,21,27,32,33,35],use_old_updat:[32,33],used:[0,3,6,25,32,33,35,37,42],useful:[6,35,42],usegpu:6,user:[1,4,7,21,25,32,33],uses:[0,3,4,6,7,22,25,33,42],using:[0,1,2,4,6,7,16,21,25,27,28,31,33,35,37,42],usr:[0,1,21,25,33],usual:[4,25,33,35,37],util:[6,37,42],valid:25,valu:[6,25,33,35,42],value1:33,value2:33,vanilla:42,vari:[25,37],variabl:[6,21,24,25,27],vector:[6,42],vectorenable_parallel_vector:32,verbos:4,veri:[23,37,42],verifi:6,version:[0,1,6,16,25,27,31,32,33,37],via:[2,4,25,37],vim:1,viriabl:21,virtual:0,virtualenv:0,visual:37,vlog:4,voila:16,volum:[7,27],volumemount:[25,27],volumn:25,wai:[0,4,6,35,42],wait:[21,22,33],want:[0,1,4,6,7,21,33,35],warp:37,wbia:25,web:7,websit:7,weight:[6,33,35,42],weightlist:6,weights_:6,weights_t:6,welcom:4,well:[6,25,33],west:25,what:0,whatev:[0,21],wheel:3,when:[0,2,4,6,7,21,22,24,25,27,33,35,37,42],whenev:4,where:[6,33,35,37,42],whether:[0,1,6,33],which:[0,3,4,6,21,22,23,25,33,35,37,42],whl:0,who:4,whole:[4,22,25,27],whose:42,why:0,wide:[3,23,28],width:6,window:[0,1],wish:[0,3,7,21],with_avx:[0,1,31],with_c_api:0,with_doc:0,with_doubl:[0,6,31],with_dso:0,with_golang:0,with_gpu:[0,31],with_mkl:0,with_profil:37,with_python:[0,31],with_rdma:31,with_style_check:[0,4],with_swig_pi:0,with_test:0,with_tim:[31,37],without:[21,28],wmt14:42,won:[22,37],word2vec:21,word:[21,35,42],word_dict:[21,28],word_vector_dim:42,work:[0,1,4,6,7,22,25,27,33,37,42],worker:25,workercount:25,workflow:[18,25],workspac:[4,21,23,33],world:21,would:[0,1,4,25],wrapper:37,write:[5,21,24,25],written:[0,1,23],wsize:25,xarg:[1,6,28],xgbe0:[21,33],xgbe1:[21,33],xrang:[6,16],xxxxxxxxx:25,xxxxxxxxxx:25,xxxxxxxxxxxxx:25,xxxxxxxxxxxxxxxxxxx:25,y_predict:16,yaml:[23,25,28],yapf:4,you:[0,1,2,3,4,6,7,16,21,23,25,28,31,33,35,37,42],your:[0,2,3,4,6,7,21,23,25,31,35,37],your_access_key_id:25,your_secrete_access_kei:25,yourself:0,zaist:0,zero:[6,25,33],zone:25,zxvf:25},titles:["Build from Sources","Run in Docker Containers","Install and Build","Install using pip","Contribute Code","Development","Write New Layers","Contribute Documentation","Install, Build and Unit test","Cluster Training and Prediction","FAQ","Local Training and Prediction","Model Configuration","Parameter Setting","Basic Concept","GET STARTED","Quick Start","Install and Build","C-API Prediction Library","Input/Output Data Organization","C-API Workflow","Command-line arguments","Distributed Training","Fabric","Use different clusters","Kubernetes on AWS","Kubernetes Distributed","Kubernetes","OpenMPI","<no title>","<no title>","Preparations","Argument Outline","Detail Description","Set Command-line Parameters","Use Case","HOW TO","Tune GPU Performance","Layers supporting hierarchical sequence as input","API comparision between RNN and hierarchical RNN","RNN Models","Recurrent Group Tutorial","RNN Configuration","PaddlePaddle Documentation"],titleterms:{"case":35,"class":6,"new":6,AWS:25,DNS:25,EFS:25,For:27,KMS:25,Use:[7,16,24,27,35],access:25,account:25,add:25,address:25,api:[18,20,39],appendix:0,approach:37,architectur:42,argument:[21,32,35],ask:0,asset:25,associ:25,async:[21,33],attent:42,aws:25,basic:14,between:39,bla:0,book:1,bool:0,bucket:25,build:[0,2,7,8,17,27],built:37,check:[6,23],choos:25,cloudform:25,cluster:[9,23,24,25,28,35],code:4,command:[21,34,35],commit:27,common:33,commun:33,comparis:39,compil:0,concept:[14,25],config:35,configur:[12,25,42],contain:[1,27],content:[25,37],contribut:[4,7],core:25,cpu:35,creat:[25,27],credenti:25,cuda:0,cudnn:0,data:[19,25,27],dataprovid:33,dataset:21,defin:25,delet:25,demo:25,dep:3,depend:[0,3],deriv:6,descript:33,destroi:25,detail:33,develop:5,devic:35,differ:[24,35],directori:25,distribut:[22,25,26,33],docker:[1,27],document:[7,43],down:25,download:[25,27],each:3,ec2:25,elast:25,equat:6,extern:25,fabric:23,faq:[2,3,10],file:[25,27],find:25,frequent:0,from:[0,2],gate:42,gener:42,get:[15,27],gpu:[1,33,35,37],gradient:6,group:[25,41],gru:33,hand:37,hierarch:[38,39],how:[0,7,36,37],iam:25,imag:[1,27],implement:6,initi:[25,35],input:[19,38],inspect:25,instal:[2,3,8,16,17,25],instanc:25,integr:25,job:[23,25,27,28],kei:25,kill:23,kube:25,kubectl:25,kubernet:[25,26,27],launch:[1,23,28],layer:[6,35,38],librari:18,line:[21,34],linux:23,local:[11,25,35],log:4,lstm:33,matrix:33,mix:35,model:[12,23,35,40,42],modifi:27,name:25,need:37,network:[35,42],neural:42,nlp:33,nvprof:37,nvvp:37,openmpi:28,option:0,org:7,organ:19,outlin:32,output:[19,23,25],packag:3,paddlepaddl:[0,1,3,7,25,27,43],pair:25,parallel_nn:35,paramet:[13,21,25,33,34],pass:[0,35],perform:[33,37],pip:3,point:25,predict:[9,11,18],prepar:[21,23,25,28,31],privat:25,profil:37,program:[1,21],pull:1,python:6,question:0,quick:16,randomnumb:33,recurr:[41,42],refer:37,region:25,render:25,requir:0,result:[23,27],review:4,rnn:[33,39,40,42],route53:25,run:[0,1,27],runtim:3,script:27,secur:25,sequenc:[38,42],server:[21,25,33],servic:25,set:[13,34],setup:25,sgd:[21,33],simpl:42,sourc:[0,2],spars:35,specifi:35,standard:4,start:[15,16,21,25,27],startup:27,step:2,style:4,support:38,system:25,tear:25,templat:25,test:[0,4,6,8,33,35],timer:37,tip:37,tool:[7,37],train:[1,9,11,21,22,23,25,27,33,35],trainer:[21,25],tune:[33,37],tutori:41,type:0,unit:[4,6,8,33],updat:[7,21,25],using:3,vector:33,verifi:25,version:3,volum:25,vpc:25,what:37,whl:3,why:37,workflow:[4,20],wrapper:6,write:[4,6,7],www:7,yaml:27,your:1}}) \ No newline at end of file diff --git a/develop/doc/survey/cluster_bootstrapping_tools.html b/develop/doc/survey/cluster_bootstrapping_tools.html deleted file mode 100644 index eb4667e4a0e..00000000000 --- a/develop/doc/survey/cluster_bootstrapping_tools.html +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - Cluster bootstrapping tool survey — PaddlePaddle documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                - - - - -
                                - - - - - - -
                                -
                                - - - - - - -
                                - -
                                -
                                -
                                -
                                - -
                                -

                                Cluster bootstrapping tool survey

                                -
                                -

                                Abstract

                                -

                                In order to bring up a cluster from bare metal machine to a fully functional kubernetes cluster for Paddlepaddle to run, we need to utilize some tools. Here we are going to compare Sextant and Tectonic installer

                                -
                                -
                                -

                                Basic assumptions

                                -

                                Here are some basic assumptions before we move on to details

                                -
                                  -
                                1. You are an administrator of a bare metal machine cluster, which means:
                                2. -
                                -
                                  -
                                • you have full control to each of the machines.
                                • -
                                • you have full control to the network which machines are connected to.
                                • -
                                -
                                  -
                                1. Machines can be booted from network with PEX or iPXE
                                2. -
                                3. You understand the general procedure to bring up a cluster
                                4. -
                                -

                                if your cluster is able to mark above items with checkmarks, then keep reading.

                                -
                                -
                                -

                                Comparing Sextant and Tectonic installer

                                -
                                -

                                Sextant

                                -

                                Sextant is an end2end solution to bring up a bare metal cluster to a fully functional k8s cluster, it integrates DHCP, name service, PEX, cloud-config-service, docker registry services altogether.

                                -
                                -

                                Pros

                                -
                                  -
                                1. End2End: basically all admin need to do is to config the cluster.yaml and power on the cluster.
                                2. -
                                3. Offline cluster configuration: Sextant has 2 phases during working with it, config time and deploy time. when admin is configuring, it requires admin’s machine has internet connectivity, which will download some images, etc. But in deploy time, it’s completely OK to go offline since all dependencies are ready during config time.
                                4. -
                                5. docker registry integrated.
                                6. -
                                7. GPU machine took care of.
                                8. -
                                -
                                -
                                -
                                -

                                Cons

                                -
                                  -
                                1. k8s API server is not deployed with high availability in considering by default.
                                2. -
                                3. No grouping support.
                                4. -
                                5. No API interface, a one-off service.
                                6. -
                                -
                                -
                                -

                                Tectonic installer

                                -

                                First of all, Tectonic is not free, it requires coreos.com account as a step of installation, and free user can only create less than 10 nodes.

                                -

                                Tectonic is a suite of software which wraps around k8s and providing more utility regarding dev ops, ie, -Tectonic installer as it’s named, it installs Tectonic to a bare metal cluster which means it’s not totally an equivalent of Sextant. At the “booting a cluster” part, it mostly utilizes Matchbox, which is a general cluster bootstrapper.

                                -

                                Matchbox’s Approach is similar to Sexstant.

                                -
                                -
                                -

                                Pros

                                -
                                  -
                                1. supports grouping machines.
                                2. -
                                3. supports running provisioning service in rtk. (not a big deal though).
                                4. -
                                5. supports http/gRPC API interface.
                                6. -
                                7. supports multi-template.
                                8. -
                                -
                                -
                                -

                                Cons

                                -
                                  -
                                1. Not an e2e solution to bring up a cluster, need a lot of extra work and other software.
                                2. -
                                3. Not fully supporting centOS deployment yet.
                                4. -
                                -
                                -
                                -
                                -

                                Conclusion

                                -

                                Sextant is a better solution overall for paddle cloud deploying to a bare metal cluster. It would be great if Sextant can also 1) deploy k8s api server with high availability by default; 2) not designed as a one-off service.

                                -
                                -
                                -

                                Appendix: General procedure to bring up a cluster

                                -

                                It’s physically impossible for a cluster admin to manually install OS and applications into cluster nodes one by one, here is what an admin would do in cloud industry:

                                -
                                  -
                                1. setup a bootstrap machine with static IP in the cluster, which has following services:
                                2. -
                                -
                                  -
                                • DHCP: assigns ip address for rest of the nodes.
                                • -
                                • name service: to map node name to a IP
                                • -
                                • PXE related services: the booting related info will be delivered to newly booted machines as their IP is assigned via DHCP service, PXE service will provide further booting and installing info and image with TFTP and http protocol.
                                • -
                                • cluster config service: this is for providing cluster node with OS config via http
                                • -
                                • optional docker registry: a built-in docker registry makes the whole cluster independent from connecting internet, and speeds up software distribution.
                                • -
                                -
                                  -
                                1. New node powers on, it will
                                2. -
                                -
                                  -
                                • broadcast the request for an IP address
                                • -
                                • DHCP server assigns the IP address, and deliver the PXE booting related info to the node.
                                • -
                                • cluster node will request config files with booting info delivered with DHCP via the TFTP service, and in most of the cases, the config file will point to a http service for the booting image.
                                • -
                                • Since PXE is configured with initrd, it will utilize the cloud config service and do further installations like coreOS or K8s installations.
                                • -
                                • then restart the node.
                                • -
                                -

                                For further understanding, following 2 links from Matchbox are some good readings:

                                - -
                                -
                                - - -
                                -
                                -
                                - - -
                                - -
                                -

                                - © Copyright 2016, PaddlePaddle developers. - -

                                -
                                - Built with Sphinx using a theme provided by Read the Docs. - -
                                - -
                                -
                                - -
                                - -
                                - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/.buildinfo b/develop/doc_cn/.buildinfo index eb2dc0daa16..3fa5d35c228 100644 --- a/develop/doc_cn/.buildinfo +++ b/develop/doc_cn/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 85c8b7c86b39554b9baa0019a9b6f16a +config: 83a63eb718f9df9e43a17cb922d8d728 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/develop/doc_cn/_images/control_flow_graph.png b/develop/doc_cn/_images/control_flow_graph.png deleted file mode 100644 index 3579998e58d07abc50bd3332128d4733a391cb3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85311 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

                                2lgXYv@-%QDC?iiVxEc}XZsaKW-@ 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 NxpwDj)fIcp{{g{6PO$(0 diff --git a/develop/doc_cn/_images/deep_learning.png b/develop/doc_cn/_images/deep_learning.png deleted file mode 100644 index 026becc4d94e01e407dacb2a5314a0e5723334ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40605 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�*v>KdtmW{i2{ic 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�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 aV$2ip-0sZfdzJxzh{N88D!&Z*{{I2&Ho|WJ diff --git a/develop/doc_cn/_images/graph_construction_example_all.png b/develop/doc_cn/_images/graph_construction_example_all.png deleted file mode 100644 index 261611a5721f9aa97874f7e6d897fe48cf667db2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57513 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 diff --git a/develop/doc_cn/_images/graph_construction_example_forward_backward.png b/develop/doc_cn/_images/graph_construction_example_forward_backward.png deleted file mode 100644 index 4c69687f4a6a181138f3df72ce5e8aa48487b5be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50107 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 diff --git a/develop/doc_cn/_images/graph_construction_example_forward_only.png b/develop/doc_cn/_images/graph_construction_example_forward_only.png deleted file mode 100644 index e668c16e0cac73acb4e5dc2b1827557ae77126b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30790 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 diff --git a/develop/doc_cn/_images/pprof_1.png b/develop/doc_cn/_images/pprof_1.png deleted file mode 100644 index 8e9edbf377672d0ef40f2fc7bd39e746923550cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 352710 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 f5jO zzQ4W+S#)+pL)wdCh^koBxWYYDef~%YXa)tQK^dFqO})8M=k=S_B&8?And^FpI7ydN z!RmIvf|+%{ZZ{eVpDcAxHmt)Q*|~{>Q6v!O?HfS6Ker7ORm)N-Gvy=<#CC4;*$RSJ zJVWl=3nBcjkY@roOE+c%AVFh&VDAZH#IgBvv8)PXHo4le*qtUgpIq!!fzr1?W*|Iz zwOvjaaI=w7)QQ6(vJebMWd4DvvpXlA_i(n1e~Gs6I2ny*f|%R^p&^1?Ew7}6TwGcT z_qld0e5{@HuWq>h<#ahXC2C=Yg$0T-MQr9OD%0%8rzSvR))9aa6B~O96NZr_>~-`L ze{5i3rHHt=WI8mhS2GtVo{XmIgxK{&iVYGr{( zWEK<$^Fn(U9WXBJB|J>wZscV`jD&d{Y1>|5PtMkh``-5(1tSM$R{IZ1Vmv5l!TH)! zHLJGHIR%Q4DTV{+<^3@!=|4g_o)(CCHW|IFV+xv=%2Bt6OyIutGHI~`3r#@~lN zaPLc*ar}4v@j7*@W&dyNZ)UK4$si0dm+Eu`4h|k9Gup1FZR|e7KrFUL32B`6W_H2w z+lxAwqHo_9$Vf?Ne=ZCt;i00^j>>6pxeW3gZ=C^o6Z{c?y*;t#Na8Lr!^-iIx(RPunVFZL{IXV^N4*qYh>eTq@D!T6Ns{@;+RtWVrc4fhN6?jwRq_L)X&DUVqrBo+Z- zDt^G!1Ea12q`4md4XeB&GBC9Jx&t06N_&Wh`+W$s!2!?ionJ{B>2bzI^G7q0(Fmn( zhsuH4hyO?>-G9BRRnV{cHdb=`U?OdX{8Ai#hbb~PDkNBe1~qyvp8=#?SrV^o_EtIG zZkp;IJ2^A;#Kp=&Dx8Ew@oP_}RTaHZGQL29C82+x+6&d(5OL6(!iY?+RRm*PUxFN0 zUc6pN_EHDW%7axKUguP9Va`{ZcZ6J7R~H-_iNMWQ#FoZbX9?Lf$DQP?T;kUjZMtOD zcH22wr1a+K+Xv(G09U_IvOw7q$nVFQRc%Uy`=$^*P6+s4ckziWpa%iSD}LL?Xf@J* zYTQ|7ULgt_T0~9ENPxLhp&%Bpg#y@@J#%rgZ2(*3%Y^UH{Vp0wc4ifE}re>KT~o{j=}>9wV_I zz`{KPe}cPOZ>t0uA59HE0aLCln_^|$fI&rDm8`z}c6s(}_yum}834%_@LthU*f^+) z)8AIWM;wGu6MQsmw&vGC58SPiIBeOXe2r(JG@b=sGF2_hRE8%Ed>=f#1=rCLSJu-b zlm22;8|j- zBhiUiW0O}<=!-W4DK3{3`K&MXwl#Xg?**N89(!a6KcEDG;MKu521did{cMHF=iF2a z1A;0VhSif)L@HH$qa2bgsZ=mtK0bI>*5Ai>)6;WeS{)iF$BusC4YR$0!TOFjy&8#) z01FftxQ45@4S80EOj08*2&h?m39$=wU&d-N(Q8VGT?z|T#;Dk+h{ocGAB83)4qs>Sf#Sg8`Lsfv3VtGEVVOZ@Rw?9VVlrR>MwUoSIPK{l2gELOY}z`9 z`Q-0+tD&UqzsleQgN{vMW)KjE)V4q=7g9ckcYW(jlHJ#oobl z-$m%aq2MxWg!Bzrkyk@hCnO=juG&JQGn<&$a;P2)u}{zt86ySO=iBze0=v!!yrzf* zv|^k#<%Bn+;%VehmpmDor9dSp+Uj0=L=y%^AVxKc1V&0Aq8hIoM1lCJMA#+USlAqrQy!S&)#HvoHPg6s@rS`s(*}X!=yXS#_Y2qcp0iXGP zN*&vy*o;+mWj+7MXK}ex9!U=#{e98N#~Z95*dm-Ax(S1FSe+OoHfBxRb;&!>{RFr1 zF<6Ksnx0`L7W$Gv#_&EuUfs47DYAH=Iq$=Za$Rp(DTCh9Ugu5F<~>@hRzS=x#|$wpS-QOh9t`hIS)4-}!F%3#(xa)y zlBWhMFEt7y~fEr}r8GKj+qHET>S%0D4>n=6A#88;o%T!y8)I zLrrVM93Id;o@T{*r`(lV(7Cy272An(k9xl`tiAHutX*ZKYcPB9z|zg|zEaKRHsSaR_e}Mr14*B< zc1!R>eK~syjjVazVGPykBXN|3PHf<#gFGYx8HNi7J}0q!AL*lheF+igP7{`04o>U?r%IJGTWn+52cgHoWb9=f7w{f1x6?Rz0^!Ak^Y- z9}QxOWd`reip0)*Kk{R6{9(`+AblPU)CY#7>yxeO^Fl~P3AJ@?o>qyL9S|8{?E@peNB=dR*{Efyfe zS1Bg+7r`P>#ti@a4;$xel#gl{B;+m{`0@gsliuFiI+c7vbM&vYi|)|>3G1suJEhri zri$P0CQt-jsea1?7T!xJr}5}ZfdyVqx#3GR4*~xNZ6_hnU_+1}-FKe8xFFv(y7o^^ zX^`OYc`sOvm)#bbgmQ4!6!$6qV^?8jQ3CCZSy-}fInToW&zTwDirLyp&H%p;kv_y% zSYtI_!A>7#CI_dWFdUPgsu81X<|!%JZe1dsBHXhMi0fJ^Ir1afMl5SgXV8YEvGQ&J zCi~G)KA_N;B1uBu_2IO}3N`p*j`Q&8xjQ(7Z!;+FSL3&*TOL~4NoH_k^Gk~)d@IQ8 zuPtTOM~;>255c6=ie3o+e{JB89WKHT)T;O8=zU62qVn)r6*}QS;B&3?cE?79Dd z>VdhB6g-q;ZOvD)$-bE$8k&L+N7@32;|@+eCRW$ipfU#`6$|gdiIW=Vi+xue3S3ku zxvq!YY1-cbpEmN0v(CK?)I7)(tffk5(!^#<`ZMLh>QpaQy0NaEyi-MF;<_tdEtSf=5!|Ifm~JFroqJ=Wno!&S9{f zZ3cu)NG`u0zo*(YE%Lv}u5P?LUvc99 zj9M=xYFb!l=Jy=_YEI&XWZ3S7havos({OKd=B_+n{|H`iO;y)n0Cf|KVEeI6$w+MT z{(6{hY_S~c4`?K@JJxEwB}{QfRTOU2Z)FxhVE96EW$NI8vYC!(mOVj`&YKRyiC~I8 zLfTSK8i&{Kp7QQ=9z7B`j=JC!MBZnis5n!vO+lEAZac7%0rQWl<8^=}Ot=Lr5KnMj zt-wYkYy>X1B)xS=pvY&!!V(=w5R3>p24JPs{etPb85t8fGt>)RoWyLs!d_8?t`_XKPXiVjW;IFZ&l;7twy02`wOrS5|mS4&ediCI;47#=#p;uel^_);r;J;u1SaB5+ZaA zxUDPVY9R_GZ=*V2~*OI$a+4KV*A1EI% z;`+h7`!F*g0S^rShU^FkXK5zy*fT`P#wM#>*!3T7e}|Ul7UJMkt8*bHh4rl_>hBRT z^!W1SDa?IY=U5E}a4gwKUn|8NkWC~!ySLlqZ7WT1o>9BQ72W4`ke=UvDhTG;ZHI4% zZa%*+rlWraGXm1}8gvooe!wUPs%dGO>6wbin>unbyGZ^JO+dM4@TlZNFDlLVKzkGP z(S$q`M2{0YJ{>2gHqSTmsnMYYYu1QDUfZL=9grvn!qxYqSz&~Qs8W0d2)Q5Bqz5ee z90&-NHJJ&Ah> z_-2!MTVAED%EcKo(skZkk4 zCzxC68L#Y)Y-Uz(eS2tW4Z+3e3HRa6kCQt6OZ@%*j~^yC7*O38BwYTd-iOb+Yqn^$ zXy?y7#5Vj83xTADfrv9dANiup0YLR(Bbu~c#*c5zCsQ%ZBTDu(!quz(9oA(8-qGZ1pQ zKRrsxm`mWgp=r(;@qyNFd+Mu>6_c`S1_uSL+2`6C(@FtmS$7;Awyp{z`C0m;=TR#0 z8a=W~5$}%4K2_ggj545+@J#s)aO%|yY-^W_6|kw7LQ(q{O%^TGx=`O*E2QNKlaP(8NjKf zwipdURKNSl18zb~zq}f)d+4P!0uk%`VOKJ{#HHuGRBOTsM3K{ue^pUf@$?z$e~{e2 z-oEymHnhF_op=L(fYfyUJSRs$aE`UsyNuIjrGDV`_c48kXK$R2CAZ%kIf9#XkKIU0L)jzy_ByL_&v<*VR z#eig(VUvnYLS{W~9J=%9Wuhh`qDN^JLqf2M7~EF`1Y<~)3OIorZ1c`%WYCRW|2s#P zx+BNr*)>nZwFBwBEu!P*lwGRAj1?#Z9ei##cs_Y%$mB&eGQ&+egX)bhmc_np@l0C+ zL!OTrh@Bu9FtWlxN=ID_cke%5t&G@tdQNOW-_k29MRQ(>9&DL zOc5RWvKuGeJn_ein?J?-lSPD*R>(CT&{vsYf9I&S+k&+z!+9z9*SU%us2Xv2zl^X; z9I9@Y>?;NkFWGzjP=A+V=HgyuSBRNE0}Zg-AsBl%maNFHDV||w$%(FGDR-q38ft|{ z`kVDh)oWj{v^}REkX7K*N1LLK`L4(4a&?5vmTbY;75Rlw!__DRS0*7&VqaXJe`{Vn zw64CmuuT66bz5ld!Mk<-QLN_yPQ70E)_4^t69WQhQ7U8aPi(5d)ED1<5ewdT90eEfoX)iKOk(M zCQk^-#PCD1X~g{v1&m`2{=Y*pLV7{-5iEepZ6us5%>#kIOAZAzH3G)hFrQ`tE&1;K zp3dvol-X*neWj_u=+{ungeS~}akl&&obKMbq)tREmk7Zw)dz^^N>&EI0SODiN?Sg{!q(sO*I^#jA za*x;(8``zK=8xgU?jN)BSW& zeJqhF31Jd%>NiuoB+z~SfoF-58)c|;``z|4&qv$6GO~J zzHz#MaQB3`mHEfk_6_sdZkc4tdBj8@_&~gT(H64q&8`sZi_qx5?kpHd8YYRg-0EzB zN-liUgec^(<&B#y3^trxX<^0f(?{6OmSFp2OHp#c%FI6R%~AvD{AM3{fxo!?q>hA6 zvBtEAT_w=q{TWx9fQVIv;ll6rmf+;=#AGyX7v1F1XaP z#1=STT@rylsLZj8Yx}TV=J#&G?eyZYmtFwqd&yh(!;~pq{9E=2+Uv`Ij=w)GCKP7_ z+HZEDIbm1- z!pO>y9+9tK@;0+TT&3@keYQw7rap9E!u(r3Y9-}um_%X5i+`%b605V-tHy9rtyAXNQw~@;v3*QzB*JA${D>Cp9Oa~q6+w|S} zY7-DB-S5q~(? zo$EEg9M*<#h{MsL*)QKd)rQKKzgOD(LdXw%rcW}zD*4rO&T-Tod7JaLsstH?3?sJZ z%`IWT+>wr{r0by_%FQz-dy6csB0mGP*-|BD&nSIff7c&NEml|J)_7y|1#97)&`(2- zt2e9Fh1`>?z6fr;08rmO9&pxn7Km)YGTR%+-8spXu=fV6eVyH$OYF|p`VSmrh8Azz z=+e^Zh_(+Z=Mo+sHxx``yTNUaJySof3{M{oN4azwR2a_st5MNdu4J0?sagQC6i3}E z$f>h=Z{=*FiF0Tgy-I8xSbxi9t3_=#xi>UvL3F|oaj{9Ob;vAN;s3q8+kNrg(fo_k zJ;U?6?8TX-rTYF%FHcX2mu@ml%3BPx(;hSHy_hSvi-l%eYvN4(?l-27<|)8eb**Nd zZK=exT?34;>fTp-&QS6dYqciVw_*1l@S6cWO}4At?L4RO{qb!7ix4@z0-u?{B)9I}@u^o~6@_p;v7^EbF^a={Yr*Ru~CWX0y0+H~_dmdkCb;cOPgTcy|6uG88V zp9L_^`m-Dj?Z_EJesDRa>X(VKR7~><&Zev%h znztl9{3HK1)szuE0t`UKtEl<=SiVT5qK9HwVQxxH^!B@nbCFX^t0ZUPE- z0F<%-MC_>S;np%Ow&=0Zp1J-8!xQZC2z!-T1@$`woO^wThz+0FuqZ)-Ay??o*nqpD z>ffU&lhsDnve``U*X04V^bqYN`mAS)dNJI2%RbjNbqIBTUvU%jn%wc1%cbWuZZXGp z^~t4oCd5{SJKo|01_iI?ddT35zXAiueIndi$l>|*`6 z2LdJnhxP+12<>dp#~+R-0~J$Q6_6p`B_T&sXs*RdRMb_db^8a^`*!#6rWCie7pEzhZqBCIxza~R-)&{L+>5=4df=i};YB*F@_v>yJ z8~5XD1S~+AN%i4>&e;; zP}l*TP)g`4LtP}9|ETSvx9|ii1mKJh(ABpIsqS)Vy zi6o9O(w1OS%!p}TTP6{lv(I117hKD=Y%%%8Lqi2!3v03rHZ&v=4KzvToeW9&@WR&m z)}J>F{EqdC7OV!qc$ZOhxgafIAd=ujHd$a-BO?8E9d?Z=01DOXGqobf^Vod0e=tHB zUs*Q6?Mst%8!~I9&YlPvC1@3E88g<@PS{VNnE_!ufW{l59vMV9gx+0KYH< zcpVZ-fse_YEUn=M?|Ab|xXX%ER?%!HOG~z-Si!=Jbsb6|f`+teVWbd(rH|aAmHzxh z-gLBKjSj&{ZKsxU7ST2iA3qT;Fg_8h)IICqcquU1dE1$qtES4qcJL`Ku>+P`&E+iF z`u4a8N^jjJn&CXc`ro!Ayd__{{{E&OegDv{-QZed4V(yiW3qL<&N(m7A20Xgn-P{W zXK}P>D0Y?atJ*J{Q=O{s?nZ)Q@G)lENVLreR1_WjD#tR=ZMic~CAl|9{Y@Vhp0a`u zv*QmZHX=bLCG2ic*0n^ug}PUaP5U&tn{qf^Y*E2Orz!nGni|OEeC9yUmYsEtBkH*B z`5>vtiI%n0i7@rGI$ zs7^Tlt8%$n5p*vBM_tcn!!W3nuJ14ylDQoiwyTV379}j5p`|o-l7%&dKUZ4k53w%f zcF@}d-ICGav*2VHNe`HRM63vUrAH~olWLb~vna*x@ffW)@qY~u?=J#%5zcyZUfD3p zh?ByQP}69^;qBwvRboDAcWPZTv+;mhtWp$dZ@@>(Vz^IcdbNHK=81H&P&rLx&aaI; zC2-1>gI3JdAEz8&Js`8vFv#|J8QM6P>`zgY5LO)9tR9$tu z7Ojs*s37e`yls24k;^G8I2IY94+3CS{ex-z=O`5__FbM2uP=O*4mr1xJ;Z7`RsDr& zL<49OhF&T!C^aZ$0;$u1UE%AS7Q#0_s)LdSH8Oy*Jl10t>rtkYvx^|I1YMgf!)k9I zR;MG6kbq&14XZ}ZqHWiM6$_#jc zDonxxm^mwEnkr4=lV#VpN|HH}N-S2wmLexy&3&)ba#x{UucheY^%=8E9Z{hS>+5pF zSrrNG=EZ1TMZ&_c_erFXW{t&EqG*6qE2Mtq0q@eqxi|U3Z01^n`Q}% zKVfU4P&&qv9QUZo9B7Lvq_g0$H6pHfzlu+nojhr2R^arFZWk_@MZc=^vz{an?ID{d za=U@nkp(5VwluPS`|?i%4KYDMUgrIWj@mCO1mrx@*m+z^-3GnsGRqybTe65Vu4u&F z;&p;6mpOy7XQC3bM6`o7NkbMuO4e@Bf=)JMhGBz2NP;ezln>*)IH^v`s^Eph#XpLE zTMFGi%+6bG{0>LPM64Y4=fS5Tv%wa@%VOc@%0&NZ`v0q{0_dG`eonRt$HQ=bBkv7- z+3|e19QN7Yy_6Lfn;uQx#+oRV329`Y*yn_6fLhOKNbUXM1=UoCqT+UqKy4_&U|Xp@ zo^~J?D85*VWG1KV`C&Ha|Jhs@ae~(DBDaE#?H$^u%{91h>Mlu1M{zs{>B2cIdpsge z-86J)8Y3c4;{j9zoEG(hLe12buDR!>L(#mZyH~zE3ce z1a$`Ot1ERIYI=LuC$t$PpAE2BxOn_bnV?QA^{;5MJwV94n^h0)BZt|WP!g|z;>7tBGJ92t?F_a;_4J~#uVH1I%h>&P za4b;OqgRnEptj$;y<9^vo$P2;G}vytz63jK(v39S{}~?e{$P)`d#j^(?^HYNyfrb} zud+s;r2Xw6_Xp^sc7iL##>pCmrPcwnXk@ga>f?w6Sq)RU3hR|ZF&`1G_8 zo5fI8Xy+Sz)Ze(#Vf;prlbW(~B&2VK*znAgISw6aD?}e8njEJ+3neS;y2BOdP4!@QLpU(ZV+i>amGDu zzUK``RUoNYZs+U>C&y<51lb@b^>5d(|Iq%Xnk%JZDy%j2XY2IOkX&D{u!y;S zB}!-Ge|}!C44AFV#EW>z9{s@?+B%yQu@r&!)1hR1WuTYN_csJ~O9vcT{1TY+j?T_w zm189h$n&oz1pHBOh&SFV;+ZDn0hUC(=ewP0=C~#4K)8xdizV3PWJb?p(H2fl`8lRO zL$Uw^ltn^anJZQ|ufT40bzv3UMCp56JoAlQ+a$YOYxY_xx$Bp+fW-$1x?HQckKRd; z>XE_jdv9wR@}<#ZoBC(XXib{aHA! zY}zx4GTC#p_@V_&5whNY(9O=i$+rQ{hTk00{RNb*$CtaA3{qW(Ru=c`vVs2CoD&l} zR-@t(3jwaiojdEw2Rf5J4f~v&{erV`8~x$o-*W)8k|Pw+0(j*+-9fCJK^d*M=*B4x zyaLY-Z{}4HFM`y-T09p9EK#;8YFyi*jvp>Zf6*8JLLX8e=`IZ zw^JxU4d95mXHs zHXr{l&>ZALvodEKKJgh%Sn=29zzsUl9nOz_WiTnf`VF<9dou5udt5}DtNu`uG@0Ot z!GY_JR{zr2=%_?0YnIv05ZIzJO7*{z0>2Mx#iRwaHnJ}mMWMXEWBC4(_DG>;QUGj7 zQfz6BDg1KC`ljabq{g27j^AcGS-1vdg%7m>NE}I^lJnwt(jsu&h8JJl1>%et+>;3Z zPB>3tPQLF)hjizmB2^b&noOgl6l@wP`h8I|^h18dH|uLSXZebIs>oUUxiAcQ>&FAy z8afHw9M=5M3{JpUO}7jc1d*1X_Q>OHGFU|&qtnBPpR?4aDsY&EcCx<4wR{ngP!3Kp z5}vID`5h|%JQ0y%FBA`8{F$h|J!Zv?aQa?ZX6CvZu#3_iY<$pda%tcdN8tBWBG-Cw z1JU0u&N?vDM2OSfuiv7Un4uk@j~#2nXuUorRi^3w%PlDORgT9HuNjXCIntd)I_11R zjP#yn%neEUrZNEf=^(q}3#^t~knMp5IRws$DL?+0R~TXH7ki!}n>+Lg_`Dom281os z7VeWk8mro$SYx*Y8#SX>E0{S|{9@7kBuQbJ&zJz+&!}9EO*~dTDXGBL;TL zQe4US32Hi9imS14Y3vgl{P6SJ^<%O*RTWF!PA7uI_LEs87_OGgR3XM=va!i>04sFQ z6#Y+v=ai!BAsrR3gjO^1!ftb9xQ)=@FiZZVX8h$pUd(H_p*Kfd)>D(%cnXJ0F(I>( zJ8Z5b?q<=H^^=Fg)wob=ga!ZHet1TOi}W3qE7nqLl7+9q`)0pje| zltjA$HM+?@JoMV>UUrg*%JD(dJF_g5TSgK>JHzlARYQcdljk^@g^QS>` zg;c99;5HlQmXO03QXxvnN0XtjoZ;Nr_~f<4dlEnXQtlMoT(=ZKU7Ia%pi9BVWbpfE zh(Q$a8+VA35F1c%4u;-D;SV$MSNU>$e6H9E?GeH&Ms#ZP0!gV4KT}TN-+vxD4On)` zeR+kT@sQlMT-xhDDYDmNuf%dvh`jbNk` z#Qr(D9NFzsFezCN8P>biz zQ~&NK7SB({#TRsE7mX5yrrwll7uPi?yP-mZCUsdZ$R>Q#HIwmC_%Mm-A8AieD)sVY z!eU&_^_w@oKJ)lWa&+;ztMQx$VMy=M`}L{1MJ`t5BP(m!5x@M&CFp((IZGH$Mv4U{ zk3FV%k$SRZf6h{(X9DTH=%*ks{3jfoI&5vM{$y@W{s2s%{}Rv-VH10gYW1x8yqjJ- zb8}J7R@PpUMMk984Fc-$-H^58ThKpKTk0@Kenj6mdOD-&ap@6;TUpZ!{t0rDpfBfd zWcZ8KkGV&1hF&aNHfK42gFB*F>8UsoI<7N00O_=3KrqOC$23dAB zVQANm8QCjXu@4#tgsl83BfaH?N!gOeR`aBzz~@^ zc#|bHch-jqV&`U>HpJUS1(6;8RvaN8LONxDu7C7&pb zmIm!Zs^1)ca1fP-&5A=75JEB1)0AVcvEiL0`PQ9(iO1E#lp=+vqaEPI;j!-|X>AlhCj4oo0!-(MksU zlr|g%6J8bZvKOAYt%=<+S*>_<+vWm5RS2TFH{9rsVUgC>=c9XY^v<)LAWsx;&Tf(P zCSvd8^Cn2?ccI6o`Ak-~`rYu-BYRm6Q2qYv@4l*h$)yGq9D4hr=1X21Ig@1%MxBJ_ zGpVbL)EYDYZ^@yD!IYjxjpQaYA!j!g>%nm6K4X8fLu-t#6qjop1?X7UCw-?lY|C*B1E|m& z)*4!4SNYJSr7+$2uwaRHBf0S}jUvR|7n<+;_GHemL#23s+dXx_&qVAp!paCsy7ZK@ zus%w!7r_JOw;0v@PI1{^LFD0d2OBXm9&-X{9AM?;h%mXc#)jAN-@^)mSq(E)apI;_ z$S_Bf4I~ate?pRf*2k&!>n^X90sYQf4-9^Z`J*5B3$C&wnlZD0VF)V3Bnn`y(0@uv zS^C9Cz62tWTXMYE+rj+A?a$pGf=xI0pJ1{U08?lD06!7W#`BS1WC=yu-*F08?xB)< zauZ@a-`iga$D)aq74?@eOa|1B%oXTI4vwDrO0StWo0YF-C+1zM~*iqdqvAUD2uKD&5I%ul=Yc8EBOx#{k|ZgI>TRy zW7y5l36p(UF-svd1W*tc?(3mk6bq z+a0zY1vYPcxJCPH5L&({IIo?8`G!XHjuNlijhOBx_v@Vpr5YcF%wdZK$3dgqs1Buz z6zI9G+VC+rPrru&{T==nkQ$n_U8#T=iM zL?bV#jrxi5YESzT;tgfvpZ1h&q1tf&PHFbXLAd+Wo6!XZbM2XELazoo6YLMRZErGJ zBNy@!NC`4|)ckq>5B+!0&fIDV(Hpmm)!fZ?;Mo1)P;h*8lLI=UJ!DGcd9zj(*)vCp zLG|cX70K%5(N|;$4I`LW3bE!0*w`dyUh!5|hYS}w&l#|?-4-de$(U5by3uJ18u=~2 zs3}TpS)wYZ%p-Z42}Yx$VD0^t{0}pz&B~9-8xo(O5Jt;B6;=7~NOrG!<|j%yF4xY$ z6J|HYSGh^23bCo#upjMX#N4Keg~{vuu-Sdrg@U&1?A-OLhyqzbni5#F_dnLwAb9*_ zeQGlCO3Hv`0~CB@`xdj+TCOKd19``&)kcHD#nsj^Ew%l80!j)ZEL}F?5VRYSd~HsE zsL;?sK_)1OKnYS6GNjs1_b>)1Oj_)vL^MYNSknX5{>m}qLiESs+7(0*h@6)+5DUd} z-JS3{@_<}W&VH=ioiCY4jgyHJA2V5yKVOD7rt)P!-!Te_N;=IMNSRj+UkuAqPI!#e zYR{&6pOe?+OsGLerjO~@+AqY&tUYuRrpoLfdl4U~N>q@Gp+o8og1e~Dz~dz=vbBw< zgK)GAIaRp$w6rr-BbHCrhhex5=?txA3htC@vgAQf^(WY^@Q zVCK0_@GKwz$HRxin8~i|x*0tYg5miUDnO-9jM92o-kGY@Qt>7+Wif+}RT|FOoSY|i zk7n)h+@++ig5IfDWlK63R{A;xo_|FQ+_^QT8e`r_og3G!sL2h~De@qB+{nYt*av!O zhqm(7=F#9;t~suP^ZX9eBB`9zqXx>xJ)=D@zS!gSwX)+ZM6;}&#pe~WN~iB8&f>eP z-*(^VslSB7yRc$3{NX^W_rL%w#l)kMm%#0>^*5jo(J*h+z@yM9^*BdHql(zd6kH${ zN#Juyeomf7yqVP@sKxJ3e{bG7q#@REuDqXf!oZGJ;1vx93<{2PPq6FUby{t6!c-6`HK3O(K|BSC%EjACMtBZ|^|Sm?J~ug{*W&xUkCV|YEy{kC^M4}S7MS#7 zmU1&r(k}jxV*Btw2m`p2-73;vcw}9r;H( zGk$FfV+E$zSOAW0RD+yNUIFyBg^~7p^^&p99_p~z%^4T{L+S~wVB!OUcR`#yf=XZb zcC1=*XV&wFmBKT^$JA#9KZDN@yi~K9w?ikA!t#J(T*A=QB?K4QPTQx_K;*2jh^yo-$>~h>H1UZ* z19V28!&a~p09LDp{0();5z=D!9u)B%Uq!Bjs5exNR4vK8nM?Vigq}m|l_nxqm80XH zB+XVm4WmYAou2S-E$<__qx^;-Hl0@qg&;MVycafG8~rMqmJmUnw3w8z|0klGvs0lp z#Xgqs$6xT6$o3LR;>@0Z_I%w5eM5yKY(d`awa>rfu3z5ed=;Q27qRlg$S-MvWZfm> zXer(YNr&(nP}1XfJ+#3m7%}4a#-Ai*`J=vgNQ2vd!BBNORExi6L7+v1)e_zMOXL7e zfsfSs#+p{BJGmx=Qt=eZ;+rGfCk-+mYV2g#EK__96(vqsE=8l}Uy;fBRN)Lf9VM`ZoUB;A_Qek$U#-RLI26SOS|0(Ko%qTuwx?0om$ln*pUwvG#xF8wFPBM+3&fMw=bgV=7_-We zXZo0w&x+e0;vxgmQ90?OZrK00c*zh0JTkBvYlv-68y{{|kPVKirT6D}5LLNSO(U>B z_*wDgr|M|uY9)0(9PSUMC2#KNYIMxf%V(oBGVHSo)0|_*2Wk#wn@}PmDTQ9`e3JU2 zce`SovW7!i;22)^3Cq@IR*@t=Y35u44pmI$k-zDPjMKN)T-tMF%d!lvw>mzX@8X#m zLtz!)5etVrt2odyosjvP$ZYKU!BXG?)9)#_jwb?LWPQ1#UnT6U;IAwGYVQQM(8x2O z=`-J*WeoZZ(;*mCqkhq@&FP!Z-P%?4Lb{bv?B{2*G znQI)o^0A@;(ciQJ&AED{u2JH#(>jEd+#*jK&Kc^zjv&uX$W8dMe6V3 z_Um`+Exv6+)L*IMY6d}_HVK_EeDW|CH=8I<(W!19S(6to{0Pc0P) z<3VdGL+O9a-YNr|$0nV)-LtImH0GRUrDDEECegO5p6CU1vnm?-d9u*SM8Vqr#?0!k zwKH`I-Pksd9iW@K)+OG#QJmdAY09mc__GZf^u0Lhn<<-yw=NILt95VBy1tMbsEh(f z9J>V01$e4A6Tc-*m)TS+2^Vs$kE#&TPilNdJEr$&rlq!NuFcE9uw`A>v0hwI13S1dd^`g?`O zP+48FSy+apog3>5`%KXY^~RFab{o|w{#ky0w>2ll+#E*FPc@hEz;l|$O}`9#J7P4; z_A)jbK&o~MMN%$QEmHiy0n#%&^fl)!2lsk$a$ghYEz2{?q#1yY2ZFnryWPo|FmiX+ z&YPeUH}w1YCP`@33z^58qQB2b&76{4wjj=5_a!Qox#8sP#H6pwt0~?m2A#+tfA%4G z5213t!|KK;PcjnEYj2-Ds++JE_Y$;xlBByfDj{_j?ECfiPa0%r9WzZ;+(O5%HLtd7 z2lFUojesm^zK6!0#O|A6nnC|u%icshXhb^9q3u+3qYdwA1v3F5BEi-ZRmNDwnmrhy zx0n5HiOW}bX3;-nxdya7asK_wXTuzqtuV_so9i4_Bi(@eVTKSTA3O*#Aug8&5TiXa#9sU(bl5llaNRI_~TiwZSYjmzW2x zO!+AKhvOSFvVk{(0oyyee7+w>f2enEb4Tz}cfMoark3QiGoV*U2aVAyHd!TJ2reSl zxMtu@NXnf}YWvbp=Y9J#%{vFY*1mERIYQBekK#Snh?nTEu~W;C(yo$%*FA}_b1sB7 zk$1S`JWqz4tJRyo1YsK_kx>w5c9-e*8JxEL(1+=}arQS~B-C1pmZM+K>(%qv||Z0xk$ zlTfJaLJhCFZU74>r;yJ#u4R3JO>0osPo|Jbqzv{=L4}&;$N5DEFc(v>E|u{$tj$%@ zuvh^))7#;OWk~1rvGZHUnYXn;p?3A(c9J6{Ruu8zPUoJdMhiX7)vtaJYVs)qCm(meZIQ9;>ftKICIa?}3NQaEMiTCUsN- zDKhCNJM&kfHv9U7w<88Nf=|%ceeP78M{otOZwNOl=afu`w1=ExZH2BX7diaz2y5Qc zuEH;tugR?5V#>kx)m^By-(S~T9@q3YNi~fx>Gdnbi&}<5m?e? zyvDsLtLoZq*?zu!!20=mUUccqVt28lUW|Ns-S|6wqtqgJ$L?#$$Kc99qxI5Emv5+` zyYtB*MvZ=JR8EyYg|p5qw{&XsTU>8FU@rG6K~O-P+_t-c~rr$IzOVS>v?=1krS^Ta%jjpC;fIePzIK_X$u!A zJ14QcxcDdCMk`kfM9W6WW$u}zp@%7S?BgxT@`c6!tVX4(qTzmhLy9RxfM`*Pk266YncAZVIMuiDAEt9w4}i1ip0#;i|7GLJ|0KM&2TKVRh8zH zY2|JdM_1xj@d446RX*k&FuWG@A3o?xe5{PeKpKB9sjHmiA11g^i2gf-Wu|V%h(EdD zG}=m&Ber`StEu9GP;w8yi*>xL5R>As`8zEXFfrslhIhT`S1*M#D%Cp{WK^nF;(*8^r5Ptkl zEb8O~((C@DgKX&;l({eLjxbG^Du^V(vXPu#pIwTZZw@V(aJ8Jn6dSZ6#t-#DcOX!K zeviMs8ii2w%`!=Yhd>%H8vE+_ zOG%f6Pe=T!0MwK}&yPnYSa|W66F;6Lg+5G-=R)hQ{C+e!rcAc$Yj@b+rF1!>ZB6Cz zs%DIiF(}h)S1nt+91aQJ@GAJH_1Ql*^EgSR{Yx^Y5NOGBG?B>sZ|XE&Gz}?R$V`#e z>Dp;}#I%7cuq;o(pC_qq&*NW6ms0W?HXYvLqWk)gmXN`tLce2=Q_-gu1QxX~%q=tr zx$UF%eZRU!e}*#NBmO|>OU2h(EoV=?s0GY?qoAx@QXoT%jTqMa>?XLtl2o)$;K)1b zc+|fwIUIOMU20B&_l&uyW+j7jU|IV1{{gT-PrvdEN2-9p;(to#A?3dgWS;W(=5uca zrREfL91_hO?HTy6d@<1I^ferz-7YT`NNPX0;abJ~zO}7Ct{5w(dU`GEYb<VX4+qI@U={JADwMF`Jr zUA6w_4aI0exnCc~ZMK#v|h zTC7s|&T&=lS>}MuftJJpSuxy_?xu%~rIcZaau4UwJJ<)$jQXvIP}LI2;D^Wbja7tU z%5KB(VQzAj!QLpRSCxwLNu4;*p`+wdS*N<9()j~PSd?%QopBz6VisYvzw75+RW!Df zUt`sxx9~L{!=hF5F{pjz^)q``A;A`b`J+2m7B=LOsvp8%aP`!!iM;sxf8dqf-LY*! zHK7}=+iME)9HAAh$3Me@4@wY2uiQF89q6dQBjvNJIHP<{*p4InSSeJ83lTKD zdzA)GVWX|!0CLI-;agxwuuHzdI^nN^@y?$psOU{i*+I#`bVLmCLW1vF_?FCs@tBQ5 zC>Cdb1?|!=VV}GVc~J@I%Z$w1zM6n;ojPOL4qCP|tg!Hk5dp}goUd-A!8YSYdhIBX zzLj3%(IzSl86J1~Jy;cMLd@EcNSN?v*xwn68C$&=Hun(bW{ku#^;byF>4R`GeRkSW z>>u+mws`#=T8%H#m#l>P)mSLDMj;WguqGWtRNPRQQoq9Sl%@C#I+&)fMNC1W6e{=5 zbJ;xw=PiXz7e<;PP?;vO4#4|cXy*G;|EIZc_*Q%xVugFf^NmUH@u{Z0zHxQ=s?32Z z9Qg4#4G!roe9LhD0N$FD0Qdv#2gM*}G!NXt8Lq>t_5hugICEeR2F*`GM9-7huxbZa zaR*2S1f3tloQTKVVQBVcBAj*S&Rsk+RJV$X;D{UNY%kvbp<}NSTc-)J=KZQeA2l0! zeo39@UQHMc-)L0ovPP&lZ`YHXH5pUqwW?;*nk6dcpRZYZqml+4%Z)nXwL0_sCU~0S za!d85YFOT>7*4*y-h_rFtp#JdpOLysN{Z37+ntL5RA=^5v6`BmO4H~I_+b3Qux^fo zxmO}Ixu>9^;@6h@K9ZTLD?9Bf7A_x8uiwqc?zId)C(6*ri;7~VFEYKG1}!~>-GPWv zknzS2qTLrqnCx#*Y z-FKmW@ntBs&qU%+;V3TdfjPmwz^p4Ur@o6+Zk9}Q=OX6&jRUvBUQcl%IkDaMeX#~3pJ~BebNfAramkxK8dshryAEcxyi9FB*+80rz3g8TUg! zkQ9acdM(0ZZzW+zLRFo7ZFG(${Yhl!!Hg#W2wd>`0VeGth$`}+DKEJz0p6~H3*v_syYLgel*krDB4NEM#x zCKc4|E0B3`Z6!r8Ghd*R{z}5R#%7^qJj>UYY(ZoAY&eH{yTA6!7dUSg!t0?%GUm7) z0$l|D^+i)3rErbDtl3!ndOWtQUV>zk>x1T~nVqtav=d@Uu^O zk3_P$W}E7L9eY=-B~;yWZmqj2D-vx3q0)FYL{NknxR49uYbXa0Pg920=~wJgSa zRtaHId(JmDw0|r{GUhsvFb99iRZ>~n89jS;#-5j6qM=s%Mj7LsMryTM@!*5)JX0xL zN9OqGr{crd(Y%K;)SCnKTqABc&(<>EXKt8`r(T%A`8O7MHzk;1y;mne%mnV%2WN9z zaTZ=2p(f6eNMsrfC%Ee?Cp8`u8FeNx%g9J78JPIO8VSFMrjooNrTo~5LH?CF!1OCw z8Awh}MNZWKI#pO><^CYA+I4qjRT@=4v6+#X<9L2=)~AiRu`{!>kxkk@ae3wi%Dk); zY;b*+t!89r8<}g}(V;ab3)vMX#8W+Pe092-_`D5MVl@k;a5-P}kAxt6(o}l<(ukjX zj-==}VCpqMGOkeuPeu3>p;-PG=7lcd_soQ;NP6mZ6#EaPQkMp}Wf!3A)~@{9sAfiB zv95(O-A+izB&;9fO?i(OBLC726KC##HrS78sVTF$K%88J zy}*D{2n-&B3p5s0cBA6h%Nt&-Z!NuwAbLHoKfKnXzOzmh(!08gFYaw7A%Vqy%JaS4 zE1!zHiv`;ogu3;nPb>m@I8|EIzmW_ zerhU>sBmD)<*XE;IeR9Oj6=Ne8oo|T^O;+b zlVgN(7IT(M()ALUh{xnc3T8DOf;oc%Fwq6QiLGTuB&L2xZzFmGd!->cdq0f!{?J&C zAnUrGPbS z2}Y&r5fd4O2=!J>OcoXlX2h>%4(gp7@zL=#gllfB`pHXcK&>W?2mr^^;ddDRVuM6 z=xV|P73c7p-W5$qfZMJtNKe_x5YpdO<8#e&t7$Jj*?%)0TB$%`sAwww>WVinV<)z3 z-HhaN!;k9y6dQLTF=a1`DG1I^+f}~zv9KSeK)72#%#XFsv$f3k#i@w5OvXp=Z$y4! zEF+fO2y9565es!x1e9*q2WML=Qr4L8=RFqW?~cZd(dCL>H+@;NVlg6-Q8czOLJ3n{ zSWGGKB7Vn|u10vI8gpk6;-H}BJm#JNk5nw^F%G+Ogv8wqSCETF+#La`Q6 zF=5hkZR0cEv3DHP#8@%6`$%j_n8|$&-z%T;{gjGpY-+5$kGb*9spYC2CWdh~pDL=n z?llb2RM_eQ9O0VHnLi-?;6bFPZbs?}YH+;1JhK^RidLjdfY;P+{Lwf!R80qP2 zc786GW6Tp}-+qg1hI&ri{JtdjQ4I`6bY-W)%)ol^_^Ap z<8gFn&h6#`=NSTB?5Sk%AP!LB8@3hL8{_cu9kFOP@b(-WsGO=LVr!M*ov~rgPYD>| z-x>ZRqVS)r?b=lO9&j!2prOm8$Q+P4AakHL4#=UTYvYVuUMCI|pE-rxBRSCY@WT^N zJzb|Za-~M#Kv@xTN-t2YLTgWgX4nK;fja!~iWzdp!d$~zKjs{!C$Z%MElJDl&;JQrtwnljT(F))o3;#*d|zD*A8b;-+JW>uazf`pa!lvHW**igjE?e0 zWaJKfe`OaWdAGBpJN#R`YaTY>RjeOXi05DY7$5%aSqDXy&+x*#3Vi;zXRzTn@4)My zvCvoxv1RHO#2kAPPMJgv@(ZX;F6f5Pf_Ye6N4%E5B?2QN5!SuCLl9D>A3GBN5C`r0 z6;OP41nGPK0oBwMQn#x90Z3oY^98>v7Yx>*rg;@8wOC$~UP-gfioE^%p^X?RJ%h@i z$ygp#e%Z%BFJXgpvV5(M&#w&&d{j~^|)cRw!~U(tt;J{BM9 z9j76)m%wJVK^f%0vu(C0e;n(j>pCo#sxd#bqdJsYLwP>wnV7@=ZOWk%oq@{|q#BfK zN$}zD%KjWBp7*!3=omUTQGQ|18+{!pvRROWC73Nq;C&IPOG6gDhWk1!5m0P0B5w99 z2~l4vTr-C6hmG;+Pwqefqbrtv#}+`2s?E_hJ{g;iUk{$w$s(vT&jZ2 zWP&a(+VM_nhr*B%OHcT)iZJAwuvg1-J?aofnW*$lZ`xm@uVM;a4Qr|+N=2Tfb&wTwg%MW7A;9gS2#P5GX1amqJ8X@YJ!}(p9a_~+3)LEQ!{T?3$TSNrD zj*P@(N3I~o-`R_^LEV3^UA>CSmo5XH>fYvVsQJmPKLD}+M5tvmUP;)D5qp5D8x?5HtNbs2K%A%n+{q*i0W_##jBp ztuwNXdytT&#Zp1buSTw7jOfzY@p=^F=uobO?jUX#46ntf#_ zZp6A}OLL>BofUZ_=kVCkb;4^!RjP1cIDOVXE{JN9$3rF$>%HZaBb()M?R( z+ij*nC`-0)gjSseE8jiW2t2{FU&V{wuOg__vphzta>x_U6d3zjGR9VrW~XQFL0ASF z5G>04Lh+H!gm3#S1u1W6(yKg^+bu}wiwWtIkRoG(?3 zbbe=TEbqk8{Eq*^NZl*o<;Z*Rl`@x+a1^t#V?D|@c%jz zJ03fNT`~TRH7psg%mJALG6x!z1G2|(gR=APL3ZWJW#s(u9rKZ##^b>w(aX>I!EyKS zz+*;Ql8K4y4npJIj-o1IR%%E3Un7xlgq!{R9awy%EmWoZV4_ku<>jX^c-^-!AAApf zQyH3**PlzWQx?L|X-WA^(dviUVPX?ggbmBnfNpK^_ArK$6=<0QCwX5HvX?)F#C$vQ zK6w|3MSyAfa6JFX31lWkp&vb#6H+p%h;Es1uJjCk{q>i+4bFBFNuL4{v?#0u8xN~} z`rFQ6&p~cc-`h^EaE>QXm)iDKDp;DZ0$Uno=Y(}ofcJz z-b0QGjsxLCDA`u_LnIDVcmY}q3lTCkfK)1Am|Dghw|3?z?Tz3O4kHGjgkHY%H2&c4 zRl*l1zxy$QM)XGA@fN{CMewvyqmXh~d<2se*M5XIF`k7^!BARdC9n^PhMswysJ|q5 zA#_|B;&+#bla>ee0vIi7gaqDPNL_1ABzhBshmCjqj~tIcNwHTutCS-CbA3R`yiE0J z=OJxMi|8@jwYP^*<9TG*3XI60=-&DEi)E$~Y%nJ5rjXikReCkWMJ;n*mRj)r&dHcI za=bK8=k@5>^L9|Qz_wNtSjQoVx;mw9IIx@1C?s%Ku0$Z~IMsT^S;EVh zp1vtAUc2U5KyNEsOo->@i5331*@ z2V+d>X$Yg2CTDl|>q7Rk`v;wA;|=F@qQ>nv`Ae% z6ANBng3NMnPi=^S%6^w;sG^^ib#VFeC0u9Jg60Ma1>eUeQ3{hYHaov@N5adoHKAwj zOzr`Ud?KrZLalrIa}(%Y8=UL047VIQHBWxh>uqyhK4J}G@x^Q2Z?GL%wB21 z+o_)QMQ^v;aLknJ$|(;&rU&uC3($x7)tgQgmA~Pkq2>RBZ_8*|sqlib{MnTVq7y;& zeNep#ZRCc9KORFjP4oGt5|IopUc3k|FFH@iaK|_x?t_TN|C0%4y>jg!ACbIkA0*XJgKPFk?r>9P6rFoY0?l@_M^Q*tS1FM~QF9)Aw#h~OtC zA#~A7EPrJ}6{}+pVN-*U(W7@i-2XrwH~7l-c#OS%eez7TzN>8%%QvRuM?Z%4Y%^lc z1_mYtcJ2EY9vl28%%@lI`SWLRhW`(qJjq`hdOkJ>*g6LH44Q-7o};UHJXP!Lj+_=- zn762$O?LZn@H<`ttECja&JQG7EmuU7uAs6EDX$%XddM^7;fuwEGT6Nyg@_nicf8&R zU$6mZ3qM89^UNn&fxrBK3hQNmq_E`sGU+`*Su$39bO4#3eo-OZNk85~6~mHJ*Wra* zoh|Zt!*Sr;nUiSWsXJP=Zqsl`TNoxK^G56Fo$Ca#dO7C`p?J}RjTG{K7pOeZ=%cV_ zsT%3jz6M6o$Y}zFp|2Z3`EVuhSfgnhNQMLhhLy-KSreV!Fqa}X_*__0bW!#xDrxHl6+J@4qPnziO~#B!>4PHdLUqK z;6ZHm^~tJ_6N@UJsH$j{Y%qVv5&9IY#-3c)S~l#8+==M{UJQMvXAqlnC3k0+V_(-#b%DxXz@)aKd3MbmR4*g11zz zy^`dMO;Iij4WFdSzPLt&FU7WblM%x@*+yS@WzR&4E)L6=O@`g-SThuAZH2Kx1@0Dj z(4z;x|Hxw*YUhA3aG_;kWoK;&B1teQ)GbC-y~k z=~ESGK+M9eOox$$=(K1g=ZL5V8Em}-`Rn4ae&;*LnjVT|vl9C42CSGk6A1-c1o0j5 zjr7Ha5o#n-F`OKqQn@a&bEC!GUde^fCO#BK03z40h_2B*zzZQ^A-AQ>Z64!nd@75~ z3?tp6`6z}(e&P1*B@@ENXO7%MtsD?W?p?Z6dTqDw{21#Vz!{eoHCDZw%JAA_{G0?D zlKzA(YiZfN1<8^HHwBAk+UV72?sIA|q?L1J0T!q0tu|;BiUJdt@nM`Z}05A)_QMS%E(}pEj(JMbn4Uzw{PEW z9cG*hM}Q;HE)n30;dXghoinI9^3wVK;J4`9xiiK-{{niuQ79MZAmSoaJ@hE9WFdw; zgaxEYDl%%O5`^7F-@!NQ_kstpWncUzszRgSTe%B!PkJM5={n=4$33Vi6f~oid+3~j zR4ofNZB3g+sn*qzl8xEvu`eDMqlUwlzlhAMBH_*|f_B!)u>bp_!F3xJe#6-DmKIOp| zQAl3H%zIty@uHyAW#44Me#kZE^3~K2K;!_nmI2yU+O>A2po$g@7 z|Iu57Em1TA9Wvo%Bo5W1nv5SjO8v0pwdWDwtoStu^^7? z$ihhT{K5~xlRRsqm0L*>U}&eoBt#p-NNdS$#XnMxx6C2SwTN9EY5MsJ9W>Q4M3Tiw z6>W6xtgFITGRh^HsS+`jAeTIOSdmg*+I;fN5m-?;btq;SjZbt&4;dZyrmus1{R#?2 ztwTwnwFi)imq3g*8FUo3v4p}~`)iM3{mOWHAr@1fH`DWso_lORmKTR1P*HXg@}bYR znBE|k#^JoByWus^myEG2bq$UreKCz&37A9?SEL6p zbpC$BZ{KQk_WQFq-uC$cA<-|HQ(lPqKpKq18B>HDwGsaHkW5>IIEBAS3@fhf`Ad_} zS&zn__XbSrQ7xN9&t)An9`WQwtb}}CEGer*69f+(@=FYgsz%=r^n5q;P+`L|6;`f^ zr$`bS6dU_l^D=y68^`oktm}_I;Ac!y4LBn#M8>nu03BxKDMS1koYSg zm>C$~9px1E9I2)d=1ujqb55RwgWD+U&ENpc-DiwAVyD?7@uYcG+9#8s(vaac$x5>y z_C%x)1=8q4LvyQ;xKzri{Rz@yfi1^IAX2>zs}l0Dki1eO{h3+0xR~ZO;<~my?$)h4 zrFC*Yrv$^kOlx6heH9s39U1kzYq?Z?PB0AY-1!N&83M~M%oW3~ce(lsQF*S=55giF zJM1Z*>!Z1Qcs-Hy{(rEnGC~>k?sc5Vd=ESRZ322t%@VV)FyluY0geDizy%TDieVSL zD6S?F+b}wP>KLjnR3d8BSOg6YaWxTLLLL^z!?xUI%91Caw5@jN_mH?nsGmCyOFw!a zvkLN&cZfW?|M5BA+I18+Y6`G1w~|7#{fRt=*=Cs@Z+)~2+1oyceCbpQh2;(9#~)+E zKPV6JyPu=@eiy8I{Vn9`N8&TgN1xC{%*m~%+{LGmQ&0mHDWFxAHOQyj!-?-r!<49S zy!ysGD82hYd8!Ec#M_|Gbm$P>me}~W|AbRBGmP^^3Okd$AOG<#+iIqA&fEO`2q?_7c$yohAVGn{w$YZUt=B2r2sYtN$OAl+M~ z_?Q4E~nXa_21&vKdi&vZ@z|p;_nR}>|#Dfqzb;Q zMErzjC}&^|GIstA`tYH`hO?d&JZYod$11rw7rr=i2l5K{ATw92IJ54lQ~f|;H@`u4 zp<&}y&D!VvfXs}1^WsKZyo8g>vaT|F@nY<;fX|k19an2r8(Z*~x zZM<%nmx8^<@QkcwNzN`55Z~>Y$ApeL^$*yxm7*CiPaT~K+c)kY{`AbsSb;4@xytkQ z2={|6Cs+E;!btbwVWb~&Nn}`gcs@3+%E8`@)zGb3XUO@h&ZT+AVjy}kKGSTadoTy- z9|E7IDNwLXhCbsdY;(pYXyO+mhMplh=S-$E8`80Q7U!<`( zysaAPnYq~h)()iYN)dkR>fBTW&B{kfW-4Cav<=Iq5q<9fdREC$Y=;*kMO&-L_)t$d zLuC|3asqNUuEK_lY6|mb^!OoVabD64bN*sOAO5$c2;8`)A@3l4i*gH_cn+GlkkVl! zcy6&eYD&VRE3_-hhv z85xT1)Ux?>^OpYsOS32} zb-o^{lMK%oF&_cAsskvNji>yc15kC~zmQ37nc)gEkVEXNq9`ar>-PDl$>*%n&huV_ zbZ;5PE!#@(`Ygm!$Y(Y!RDC!PnT0AyQ&(Yxzv;@+956l=Rg_Pj6<<5=2Ufp#mK?M4 zDv&un8mqFF;5DM(XTUV*C@Qr*UaSub<-0{Y2{FD>1f+OjWBMj!RLL>fXsA?@Q;3vF z)*hWgKmMoVAt3Rm6gdZQ%s7>{B?J+vOmQ%By3rlKm;AzDGtyZ}Z(X$*f)w>f?Dms#W~ z_;4MPmrxY2{C)T|!O%9Z-b?rmnrIoc%I0tUpaBAP$o?W11+*^7qcmHMmGYuoX`^T>GL9a3;PcWb`o{xkY)LWd-m+*9O9g6%MlpFBK_>Ay)(mt;Kq>* z`nDYtjT8GTC-)%hU>O?S!_(bBS=o8>zQ~a+|Aqw%$I}n(B$CpOV0aRxq&b%fe3gas zEtit_qR~EI|vfaObUuY}d z1iMF@jw}R6uU@^a=v=sPP6$8JrHe^P1zf&-37siqhi_kNJPv)IPoC6dek&?xjvvL9 z^fxi=gDs-k);^?M!?dzvOTqG-dB_i4gS4<_hC_a+sBDp8!RDdO9nj$H`gbuf`ClN5 zo#+5+&L?qj!&EFhISOPKjw7Sq#h$cL0@L$*C^t#MNu0QQl0rdWLB`aH*fS~xp$9Y2 zb77VxRHaeGvW$sXhzW!fm(&_0iM_q^Y%aMGuDeSogMf#^edGFziC zy9j$x>2zc^Eos#I!g9ZwWh901_W!Cw@*B?y_i^*++M#16*u;VECv5qzn@BP8YNF+1 zpL(Fb1Lc3OLhSP0EvBWtUJK>1?+`Y8Y~wU^N-W)~$JzxWkU4DuM(o;1UXiS5$uqJP zdRaJaW_uv}^_kG8rXx9;ZGh^KId2ydKAC~4j0HFr{Q;6`lazV#GVdBKDUC~lrvj_{ zB6sQ`tfahr>={#4!W3~b#6%c2&$Wf5ke1CrqCa`@NNCHqgf>qk6O9|L#N+k#7(qOg zl;1BtRe^M$rxE?b&vaf&9y}|cO8fa~O=R~p6}x>6r|kZ1 zq&+>_Z1|gc>yW){F=R_V5tP=Z+V=3t=1FDBVvK*0e)p|dju!5RJnR|t>`fcxk5R51 z+&~dGPBOhNZ3vCWH}nqf%jliYLMM8m{>PciKv+NW2nMFim_dI>VZ)X*Q64fKGCFmI z!oYKSE(fm`4u(fasVep5>1~&()jWslSF}-((9@wmqJO# za;T!0Bhjd|wcED|!R@zi;)$-x!JB#h*qj#G1Xbsrx^VW4@c#D;2y!YTwmyE6jG0+j zN_Q(Y7pw5#!2=8&)I5wTem)J|-8<;--vT30bs?tD%SS?z6q&~q*tsTFm=Ba^$S_)$ zkE>+FR#lvXWfN0rj+}utDe*$&B-=V!br$?)sjz#6oD4F(@DW8HvCM09*gl>-=)XE( zm`gOt^M9~l`TxO2#cZrepa@@)Gsti)K)8hJ!mSiZ1xQvXQ7lcx+GM5xrlQWlt6Tl? z<;qA1ZMIY+f+DM=t~BK1X3y2k*Ji+<6okwG?@>!lRR!g|^h8jIk>8^daFO=flP92j zdojZPy2-9Yx-+|wadRrtqG~XGb{Rg~X1a#;C?Vyn-a8bLewQ#Oc@L65`6FWdO#3hO z$o{whaf{-~W}nu?WDKn(C2&b#JYsx^mA(v1zo2#7tYOHUy%Zz1twq3@J!G^Pi)6Nk zQ(uYVvO0KCNzi|yJiW)Owl=U843(2)wxBUD(j2kx|%I_$xvq@u53de0B0Vk0nU`=6 zPcJ+_{za#c``2H86}%$FlP6Yp^Csm0mG-pae}xpYy?Xbi5N(#_6ARaJ>*h@i@HZ@k zOdSdi9i&jl<4s?M&r3Dc=-#6Tyvd5(RM=wpjvd8t*RI_tbhh<`t~c?vtz&d-mBOqp zXn;R7G={b<2Bk3cVxTeQ z9lPIjC@2PEqE(oiH494?>+z<~0xYPWg)GXomK5(rEewjYD)J;2>=5X}Nyr0u!|G3f z`D0*kpCXT~`7#6rkHnh%pCM6wgRMzhkfu9;ajyeANl{#wvk!VH8KBUnNe+1&dnhI$ zF;YfhI<@45Oddooc>74nM)y_8evy~?g|!}p8?DVCSE&>Y6T>|Kncq({5A3>3_N+5ESo zD22^~exw8Yzj5JOH9@Dr^Ml%kOqvd??7(+3hZowQrMc3^S)iabWu>c$=c9yL38dLJObGm{g4oP zS_s3}~&{C=+Ruq$h zAaeE<>Pq(Qf%@rqcnRU5sXy)UsJ#4ya}krKVf?6Zw4d-dT&2iyTc@r=n!W(z$X0d# zr%b6!N@0p1m-pGn$i*9o(_4>08W@VBxp~lg8P{IBcEKYw4vE9O5f@6S$f!D`6}NxR zlVQw&0Qd41zDawMUS3{YDJy11*B|9gjV~jTiRO-cGZA_DxT4g)aaN7b67m98?xV$z`2_74m7+QzoUF|y@Q)2f1cj?xuqhZCeJ~Q_ zrC7G=xUe}QbT;x8jwNy|ByVMn()3){A~#2dn%bYCTm1#p6z)D=5srX}saW8zrw#RK zNK2l;BH%+)SdG|}X^@%1<>{-@)+RT?nC$$yuC7Ke-&WkDv?BwrvLN6aNgfzXDclOh zH#(u!c(uZC+MLDZ>az$5cVvW%hrf&2d$l?5YcV)NA90179M{&?LZvEq6KNeQrmx&$ z9O_ugVro+Ob~L51c=%2_j!ZNtg`GrRL{>(Mzqa!f775ZSheK)2?~Y30RsqKj6N$7L z3p+dgY^xew%LOFh^CT^{8`G$;eogUgln%|+8@|(;ke$4fw<||rXNqfk`}XTkQFOdo zVPR-{!9?F>fq~H9V-+>XDKo`Tt4CF(7i6?-iinv6-Ob-Wqsl(ORoyUmgzrREqs|Um)*Z7sQ8#A|Nat z3;ga`)@DQ}Zq_y=l44t8Gll_C;9q5s5%c>=4|m&H}Warw_@z$P(A4u6mP_wQlsxEFBe z?p?4@%HqO2Ys<@N=4(@Kld_nFa1xg%$@`&Ow}w{7L&L3=&8*MBfq@OYec8)8IJjXx z@WzFANU*6*Z$3% zb6Tf4fh~Vths?ugtuQD*@HMvY{u?rPe~l7BU#LepJ%@@l_HJ-dSM5(IV0npYnJaED z@LAg&KJ`KlNGz8;lmsK*;|Izy zOy0LM<{ERKN)a~$lymqPdH+%_M1=>cD@sX8KyKMWksy}5(Q_!ruu}iJ5Joz0<0mMm zAG*3&3B?%ZS?o_9>!1*LtPO>u_NazRItD4^++d<23-&-2`=V6}xq}NR_g^A;Ekm7; z^c)TRu@jkDyD6`5 zX@h1u)nOE{kQG9q)B*brnCChy)j=NhDqBPYWy6<==$~R zl%B4aqsVbO90861M}Q;15pXI3TruoacpDOD3S3i;Tk+YeSB*16QRS5@m%)^~;!;N* zw9LEKwiFyXU|S`4+cK|Rarx!fUs$BP28AhuRpq4!R}3dl;i1BLU*Ep)_aA80wo8{T z7(TqA_lBRJKYCDjW^wT##ct1@4JSqR6u9Dk?t08Z3F>rrt;E-nV!qP@Lr!C>6D|Hy zkIXr5Q4UX9aLjohC1QP5{V7bJlS^l6FpEA-TUJ0F<_t@LO5D~Ce|6C=WS_eSE#=FZ zl|$a!HG43JnZJrkan@3Nkh2S~MLmlxCk-o{f*tel;UUUT^UnLU;WiI`i;fz5ctDl+ zISLxy+9Hbluw5cRd3v)hhGFHR7me1>waDFn6UpzSK>O#_C@}5HQtn`tJ_v~~y$JvM z?~V6pJ(QpS3yPb(Z!Ti{mvx8?XZe!E?e$QWdLV6SD%7v8Ly74}V26+P@ZV63FvP#| zGGfTATUYTn%suRf_|cwF{`5UI9`+J)f<(O(q3xB58V=Z$aFGc|z!BU(zU>JTOBND1Yz> zV;k}aPNZWZNWxZ)YF7TcR|+qjP=6FGsQ3aJqnUT(Y`xb8{>TCT93BcLtVj%t47tg}f~@ zXk*Xl8P9mxq1}KPuP`HUpXN^IE0hQs+Hk&UZp05d90EG!ey9|Gz>=wkbqWJOU0sUT z)-_b#G6SN#_2ZFIVVF#m?D$v8H|~#_NfR12ew~))BPst0jqoU$oq>78Bfn_?+M5(Ha>&RT{ZN)C)w!vJttFXthHB1wrnN2m@|C_He?o}yo#Rh zbev~=2QXflB7*}nd4AAA5YVAGdn-0%h1pl17_5vBMa;C<5j`vh$#G06OKE+^F2c@f!-V6Iv2jp@ z#$#rbxA2{XvQCbv!`{kz_(sv%ZCD^Clc#TphZiQlJ`It>;tX^I+D{{K)-*&%#bGjq zhZg$Uj6ph##zaw^A`@OmVqBb%$5?%e6vS^#YV`eS6vSa4EN|+ii|61!$g*yA7;z^P zx_0dvDTetv(8(}!@*Dw<07rl$;2;FJVz>z)^+Mhb>jo_6Ez3nKE-V*rh3aQrMGRE%#D+?qm|AM)V`taAt z{)T9Ob=F*0^;HJ+qn|TcW{ca?B6h-1igf%VH1Etbdd5;WJAA4%b;z0X3g-Ur8G)|q z;MYigX)tsb>!7XHW67f7&}t0E4-v0Chs@1Cn)$oyf!&ZvEaXvB1ETW}Emm!8+e?v{ zJO&=ZewFPxBW0`pjYnrP$swgY!!b;`?1JTnhP;J+xVLa~FU{U%JCLwuHLjjrZ8jz- zNLL`2^5P{Y&qu(fXk^+be;I9UNfxH8+9e8$XTQ$A94aiGb&QM=qESM5tK}>95&wKt z&x<#2{0sd^nX$E4PT}}8IGC!!ORMssQ{_W5Vllp}t3pavDslzcG)NyD3;z{6uriiZ z%{mRTm-{0%&Nx?-Mv}+l_4$z#HQV*0rc6Fe(Jd2rV10K;c25M70{|N6bOAmll+Yl!_GbQ|qxc-&R>EBJcKxRrp|)1Z&sq zLd~Zp?>Y8-jK_%ishGJS37Ml)MMglD0heSf#x>nFeu*vCw5HnmJEU zA^r6okWo1Nl8hNxMn(#HpPPt)Go#0(Z?*e@W8=C98K2g^jLmjmg3GW z)6O{^9nOFwz!BgGa0FZtfp($wW6C(@t!Z2A<+r^=d2E?-R$Q3!_H2d4SB0HpVUd6O zsYKjNIA)6Bd*oefTkPdH@f#383Xh&vP1$#r!^gIS4W-GpO<{R(8-`4#Nv5Q$P0N;j zt-4T&;-j?rMqa|f^3awM>7cz%o+ze!#M%=$Feq5aRqRYiv^D1t>u1PW;^E~9v57$S zsY3XZbtfxcetyEI_T(O@$#OI?l;x$NWozXgq@U>mXT&09m}ogc&ST)s^RvFuXrS6{>?Q$P49X3ZSYjBM;1B@UJXD_TE#5#V5Rx zG?u%9>7SmeFy_EOvCKR9j5qUxwX;NGtJZrqC zMU41iGZCjKk?KHE|Bim`wc2zetRXo3NBk*fUsk$M36M2qp62h=*OLFkxzJ18t zm_f=Jma&=@9jfyuU_q?m?WRbbfGx&QtY)&hVr)F-kAvH$85J(9Tf@4N>X_(ba(nF3V3!(+NA}Dt-D-wCE!K+?Zjp|9O z5KBCLb9fznv~}Y&w(T@&Y}-y6+qP}nHXEZ!8r!yQ=fwU_-+S-(_j%6DJbQk#xz^fJ zWR3>IVuPwO6eR&thaeSV5hGyZ1`EW{AH@lh@zc6Lm4v=8zQ^H%FQm~yi$!d8rJ8l+ zm|p&lv>}0njEpYTG;p3MUo43_^Q*7VEmS0v5oh{Lf)nA%Cz9WIU@pZf^hgh0u74?+ z^cHaXwz_5?2??sws6vT0q|tccSI>0HI`Y^d(qx&?c)(#ys@qUZM#O~@nQ!2ZfE|uW z*ea30MvIE!@|k9g#gvOS@i4P8oD9D)gc1xELag{mU$76lxMoDKaDAUE)84vDcJtoJcVH z(SMD`OT2)oYF<7qJFTJaX4Ori4#4Gli~X**3D~V%E=MSL^0cb9y6whzn$^IszS~Q! z7Mul_^Cj64aT>nfG--ZdZ==?B7Yo79roU01UM|M5ip>MW{Cq z(#M>!usGmVGW(N>$9$fxubUuo`H0lEJP%z57Rq-3xh~GX*GS#or)4|8Xz483-Nc#L zv?e<)el!EwYYF}tsDN$dQXth{#LqMi@FpkHecliLQ5~zeEXTOqaU6_0j z*B-m?BjZ5Xgm{xo)!A$T16cSktYluLMnEAJXM?P19790CKyejCi1-y>l{{-GYbjE+ z))q-gPZv5QL|83e#r@T~&=%_tJ?i9xzZeldXrL~fbJW^@46;-sM;3lV!XO7Aei?-b zoK_GrG=X`*Huf@4qcmTcR~IU!2v@pX$~xm`Nn`o)+~k*&^zkJAo=BmnTLG@Pmr6Wa zOrB6w^1{-hlD`>3&nr?#feUfqBZ?zHtoHr3MCb$mQZbFw`6)Xvkhe%R1J^7h(UW}OkK{Q_5| z{TCFl0WLFLBP3#ovWNa%LOOyScj)AI$_Qminnfgqw$N?QsYYjKypXr}_~=S9@BHa2 z^%F?sFNp|cfjr!({8Kavb{c{gfO|2c5&pgpaeM*K-0B#a;O@Bh&P3dOqPN5nWyT>x zy)mSe-Bh7DV&!8-zv}wZ%b2)8QezO>tVaARumLJH{kb8VE^L9=jH!w(A$b^1O5Pe1 zyFM`VlmFubD&h9;v(Kq+zy7(S_*gC7Mx;Yy!^jQ|rY~A%w#R;hmkG8ggF*^kBTQu# zDFln>sb*Zb4~dDa zs9w1%4{0y#JV@)fdYMO}Fof&$u z7;R}`GZ>%^Z_@~2;5O@aGx^%dxxi91NP7y`4Fed6t^}LEt1m3cW?kY>ld>Ldiy%j{ z#QDS8SDJ38Kt*zu6FBFEmGQW|Gr!uOPpQkK%s~oP;d;9q)bY^%v;!-D9wkYD}1p&57Khaac$_7%$M_e^R0E<(VQJn!~ui$RddMu?CY zxKt%wl-)aQmH)%!n2Pqiw_9-ki)ShNk@2#fglGd7LZn{-*o|6wJ0>4_Khgp)`6Ar* zhHmu2zX0W2uT7QOYZGey5F#kH4sx_iZLuPu+=v#`IS2N)`k|kkaob!wZA=D=>{`rDlfkF&Z*vbi$4G!Hzf15 zKSD>Q*`}6&=Z(w>#S)(LM8^vo9mz2IZRDimw7yswABuv<%GfCXoH4?DDm^xYS$EKE zT#uCs|BsoXV?NH0646=Rx=PU7`su{PQXFh;ewr79B z$=!C5D&QOrda<;s19-?W+bm%2HA>NvhfM>Wi6U6352F7R^LR0j6XunKW8un6QlIsk z!mxI7yWj$1G&dn#K)yd;MGdBBq=Ne}hM=Yq^gn0oTbDLLIp$bgokDn2z5P%ee9njk z&SW-~kc|?z>+>{?jVNmW-U|}#3=TRIZBi-g|EB;SAQ~mk4nslUmC&tH$sp2E@I)a5=1o5fpjDq zF~LX6i4rc(oTTBBLNXtMkoZ!wedsYs+C1>drSIvvMIsJI2+{+nugEm4H6>VV`8{9F znBXjGbR_on=~@WKz&Khw3_8IN(#y70%g9OvL)w3o5Lpk}Wd|OLdas#V) zldmvGn0*%a9Lz6B0mDv4h#U7)lr6<~yP5PTS@q(tul64ip8}*hm zLR}Rpreot}1W_w2^9jp`_t3IZ7%<0Ceh!vUe+erRJV>N*BeArf#<%XG_s z2?b*Dd|l71EpMPhJzQHS-;AY389sa*GVoP}R5kbW&jRJj&CgqU=AVmb`9E)Kzw-Xt zj3j436Adb8w;mEC^1b;Hf4y6&#C-Cuj%&5#y{92kqR5Ga0k0(^awQ~{;(tqrgut2>n7Q&F|6<$$D5uMgugpW)ixogBMF|-K#}16b2aw z@3J4azg`oy!&Z{~lIe9jqaNb=p6K@e%b5?WcpX*hAeuAWI4Q^+thxz1=oFJ*&=`(H zbPND8LI!a>q3#C*#SH;F$%T#E=1ey`Ac_w6w!qaL&OlwKs(Jhl!sQyc`T zN%JDuwDZy=pJYU`lw4Esvy|!Xy`ub>o~JI%7+uzF08rA^ykE>?;-AI z0N4sylu0NJ#eduh?4x2NNq7$-&;(>OgiQAgQV|833hT^#IMg<*FZIP)G9@)33k0e> zd+$ZVsxos-T9W`NdRATK%sVC>BKk{I5Gl+AVNzyZJMY7L63l4+V0B1mwYf%-`+Ml{ zY;bEZkCP|b#yg*1K|5AU73C_a)h!U=5AK%#>OGwJml^$|SXe+qNAB*T zF=+sS78~j##_N534B;uJrFYE*DH^2TZ9{|M8MkcC#x}IrR+`BWyWTlBg*w0}@Yap-|G~ zP`jil=>r8(`Yl{$`A$qbY**tkANIm7;X%f#Ew&i!FILFJ#yw$wAlO5iWCh; z9^!3IPbL>>TvA=Q9CUwfL+(NkzCSaH`xD#Wosm1=o{aU@h555&^0>F`rrhIIsZbTH zitUQChO7t?7{!NdYEG9DDVrzsHC#g^g8g<;Kp#EEM zN-7SW^&ulkgQkrC<7T(XMnZ!b6jpVD;Rl>L?03WE31LqM^utM5f&bwSAV$91C@5hK zLFiG}C%Vg;bs!v*S~h;Ss((xf)Hr^3gc&B{T+1&lDI-=T$c@vebc`pXG`Y@n3BB1k(*_T@?w5DT zBMMGdlEE%X7b$Sokg$mCv$tRW0W+8f#u;*@bF<3zt_oBLNnu8!&k9SHP)^5Ol8=R` zDE?MMB0usC0LUhQk3@;dt|AXCe5srRL(5w0IX}1Q8P6(yW=VOaq2i~#{W+Z*Hp}J` z{X==)#JhZWBIiE(iRgMdrZT_eX?&tdqTk|@@qm0%0LQNw_r^YI;$CF0t;FF71mZdMogUQ z0PYc)aUC*hwP4#5TNP(M%F)kg9GbO07lo2ZaqkZPjmXSd}-*B5O*q2bQ5xS+ly<0wJCI52D{y@&bQV=bL~>s=xqvm9y>tjvm?CNK1wR1~kUbe?uOvxJ7rr|^}uYE{$gm}S#iTx!7 zyo|IFk$H_g6x_kuba~}txJw?mC?N+*uGkD-D00yh0kr<$HJ-=9T7<=1#)A-Rd|>~x zdflhf>lowS&92Cd(13FM^1zNCRGH5xN^Z!bKk?PRr0#CUMlJcgR!4AKU=8nJkPb9~ zn)?R-aCd%g$RgW8-o+_rhtz0Ox3Fg|2L^DmY~a{oamVW4F<7-8N|q$l+eS(20&~IB zs+o^$c8|ou`Vf;FmwtM#K+uhYJbLhJV`go1!m0sYUTpt|$F%wz3^tW`sjnf6RK(EH z=29;A;c6CGxF` zoZ-5O{@>;&sUimC^#%>Em|!+(*TY`vU5Ui%=oAf48tXaS6GF(?SswGv0)jCZE^x=U zv(oY)8UlKH8;ie{@^JyKd@RO(T<8*0zJ&}jaIN4D^(#5VFZ^=!0E07JSNeE8xoZj8lfAsr=la|;QQp<)46u=N# zC-2I)m&E_3B-UT$Dpn3oTX~_09y7v^O{lWsV-8bB^87oNXS?YIJ-ba-Om@3Ntf_t2 zz@mkasC%!r0nmcf z7gPmQdJgGD=6?}#YBoK0q-4p};M%9icN2kw6wrXI>nTT0FI^=qd-opS%EVO|AUe^QDK<|&4{-Z*@1`SjWk^!I%Ut+ zs1U?mpBaum3&x3zQPZMD`WjjloA!;fbD`^rol{lIp`c8*BnQF~RmH540mv>`M1{&Y z72!gXa%q_qjE-vw$RHT8#Rf8}PGn?GFd6?3Ra+Gy3b6GGMH2Xj!=3b50l^->WW%9L zJZ$+2uSmAy9{nA%EB#INiVa8Pc}^Ws6Zfx0lp9gn!RBgo-p8a?i$fMqYx{hzv{kCF zYau~1h2K==A+*Z7c3}ESnwDICjF)bwCwhMv|NM}W{UZgqdZqx|wa@FRLFtdr(f?*z z9H6d9K*}h0eyi7_OM@y6-)m4lQmPd9mRQ#1gVBNP|~eGG6) zt~o6bjPz5-2LAVz2g!iE1c~*P0TH%!rkNHMt zRn?2amgJQYh37tyV;%@1%k4k#l?&xgf}zkt|NJg2HUga)D0gwQD{!LG_`cm;*6;J7 z<9yi*ADh`qM&~RQIvRlp6lj*v22@EqZ|MFB3U-8N`lI&S;ptHp?z>$^;1;XcE}s${ zHp&@apQ9uvXk4HG4WF4$5$c-BeHh5b{NxlqW&N0}O<8~}`X6?h5F5GGHz^ASoca1S zc56}+V4coG4YfXsWOyVDPkg}?Vu$LKC^o2uY1r-ve#m31Yn;7J#WgsJI!x86O*vxh zGa9v?hKF%+jlYsKhknL2i?at(VqEzeH(5gzJ3elohgOu6XTACefLOBv+#x!zLx%z3 zyX@F&hN&}nw0{r;QfBBFEpbiftELb5DrmcjaUs+CHe z4S`Dk7e0X5j+pymS{+Mt>~M`lCNCv!A#PhhB1vi&$NKApYHvGRDrynO+GC&oCjEmg zF^DIhw-MF}5yEirhG~L2vhN7|mV$J&@$#p!r|j@pFp*_D6roC}q2LU)jNW-jjsMme8THP&ZTsh8Bs)4_i$(iG7Gf^GkZ7x>p3i>{yu=OqSU#bCz6d?(Z z7n?1=+=2X!fJgstutnM~HE^V2-75s4{lhom&^))`KLxo#%;JuD4W}R1wSlX>UlET& z!!Dm-?h+ip@q&PuLJ($r;omPRBSG#4Qg>Ni9v+77#h@*=o55n$Vif?E6#{r=l(*N% z5Vgi4c$U1fA}vo*o|wAsssi4~s91_ky3>a^KkPZPT$|Yyb=%!rdh+J-S{i4=SSp{_ zdshg>R=EFnGw~CI{xK1Z7n|%I zs_>9lXGLioni5gkau|5V{?qr$wWk4HHxDfcfsx(mRQ_vB!Jf;F0Q?E|YkB`Z4Vr6_dL0%*`yal`(uhl9$;CF{|9 zR`>A0k42X~TimXJZB*;T5 z+hG9bdD8%7wz*=sHOcdcRFnw{UAC!)VEvGBiwL zQC!Q8<{47kmBhhlS#FaOO#2{~<=xHMu%~w$74&I8N`f~PE>kU?g8N#6?(|u7rn;;7 zTh8L_i|0G~j}P2%7PiIQQE|G$1bausp+WSWqQVD-&O1)D>(0b-GV(62W z`uLskUXiM6Bc&uYw83h*-b zkPtdCJcew}2paO@#c=jA+Vp*eF^!m3#JrBDc<`Cma#)YL_}H%dMTI6X;qRh`>kHy~GUCv_#143E5aviDk6!i-5 z@(){OU&4Lflv*vukT=WXj7Y*<%*IZ3h=sN;fO{j`k)`nERZ_K{2h%POJ6sWI)xopd z-LCthq6`1K+kY?7znyr7(am_{@&_yNH4ss&pmEDA7K1I#sm--?XuKOvmq1?L{UyLG zgd({fO2-NdfQCBs@Irce^?X+H-Q@Q<2xE_uV8l6sS{1(g#y&KFc;2lZ(Sp&5$mvQ# zc&?x&T=2T(k%iVHsIW2K|GSWjHvC85v*;Gb^OiF#vEZ!ryQZ2jlvSO*BM*`*q7NTe zgo?CuRuR{M0W@D0ejHLT3A;19ijfhKhZ}0w%ynO~Jgj|+kYw#UEr!$>Ki;WwkkH0J zR%7JNOAQCwOgh*Q4n`!`2QThg&C4GzL~7f`?Vcd0r`v-h`M;&{+CO3iaEW@@d>7Q{ zT0oAQjXcUeaUetDTrCt0aP@Ut&O9fwqe+gr#+Mo=iXH^YQg0v0wfER6DiK=(k0=5Yx9`^hW>67JlZFFV^qOlD|~qQDln z=uIAOn0{QA!h3(deTpY!Z{DNPN0`Y@S-Ce{&L1dNFZC%y;n@s#C45Zs`M$UVR@cJ)0R_7S*y9eWi6(Z-M_;%v%mzkIDui=kv!a7ZERkpM z?^3%zxjT?AJE7K|sH&Pi(eAebD1>YuPS>{$lXp}DoeVfZiNOSUFOe%7&25`9O2H`DfpUTs3p~9(h4WPO8-i^|;MEQW}w?XW!$ksDcJYA?Y~2H-G)o(KWe)_#UkN{vB8qH)Tz4}P^w0YFSGYs2otr`xq z^=qz=&!|Fv=8)cSK)+Y4DAo%z_5HgfgLqBuI_6Q?mv2eiYw53;P5w3Ny;w)&l35}KL#;aG= zIP4vKe@)VIxKN{DaoZe%}9vmEF6QJtDed`X2YdPl2q4z z%@;Fs5rdd_8jOZ|yH=q*E*7K0^pKI9ZRzy1ee=P&--!!A(!9Mym3$iXY&!yhF%{0V zxbnf%{;2~e^NBfPNVO~VOnA2o~b*zdYw2~JxbLCkDP>&QaTr4shveBUT9>D060 z>q;e7aP0W@@eaCsx$e;ax1NgKZ2C760l_R2k_UaPe-x>Lsw*TWT{aXftkn-6YP*w> zgz48!(SZNc0?6nB$OAjl`5DmKrOq0ZvFHVAc6QORzFire1Y6OUr@JwP zjSzRAF2#Y-XW-XTjMek~2#YmW{&{i$ib9s0>JU#;a997=6p^*oGmZwplL6pyy{-50kWb!-cT zhaZ0aPOooYr!8Titm2F%%1}j&ZVB$sQVv zFt~C|Ib()(HSe@HaBGOisqHTnX-veX(&_ibXS>mQWsl9#dqk=*)Df~SXlwAe-s$_n zwPF{6sV1_+UiTN8{(mdQ85YoY$yF9U8{g)_LYcZP{Lkn+TDo=bcvtZF@vwNqXKHRU zcl7@v;|_Ey7bvZ9mOJUt;-L@T%hiIOup9jq<2wfypz9Jgpzpnw2+<3&>jQLcxre}k zh4!8DuJj;;bS4-1rtqE>m100qgl4=g#sijHm~moG1tXpot>RJ${cj)kZ?E0kp{km|I?i}CEEG4J1~Wt)5)rvnN@;m+`GPZkFrwhA3zEn zyxkqrHpuQ)kg$H(vQ|SH{AuzW;z-OZSTHCn>Q*x3e3F>ga%PtwrY4`390NOuZ2lA6 z)A^|wufIhrN+;{q!(J~A>R@trcCvBOcqf_@v?jQx*Ur_zc!JFNdUouEO8Yx_5v>d( z9x~$u1o=J*uxSw0Gg~Bz#ZHGI9{VmZD`Xo)9i^dbqx)};P>LKs>RpYaqLyO^+yLS+ z)=0&(+5S{#c^*z5AlMt&cds-l%AsX3eqa)*wZ2EYHQ|)~VOCJ85y|wBLZeSGPJ7RL zm+Bh`C+qI3zFxW8aoyJLmfxikQtwd95hqEb)a98%9lCz}X+qOCqQOf6YF)h>?bdG; zIoSTMQnd~K2JF0^401WVi{D?KizlfbYyN8MyV2k?*xYQdA&Trbxw*L&Jz1}GxI4}x zh9Ax31{cy0g=XllS3bReN8@ z#h7>U6mPhx;Zh6r?@=gg+=Jr)t%>x9vVnFxor3`K)ADuHL)b&_a$e7GZgDqOEOe)l zPZ*%hYnKb&%Z$Qfb0W(|aKkX|{q@|JY@Mx(5hvVWz6=&lVsN8jL5gcxH zoa4DRb$Di9zI$T2I4FL{#XPqb<)jY%2{~JJ7zBkF%+o)$_KuhuwsR0+#9VT5qyV74C68f;ZQyg4=k8ph? zBsqd@vgS;2yFESmY`c>gj^HxTb@m_ltur3k>BzjTj~rM4Zmm z{{mK`&d%UmNiBXpKArJzm7RtK?LI{TX5wD>G=!Mq`HbMdr@x}d7gNG^(Ji6jnv{rpP>{70W>X40Ge1fhVI zG?g=kwn<`RJHivlL)%Lr?bNA_A6T*jM+OB~8m(TPx^eSmv9OAi_ zh)>`?#`;+&Jv<@Tr!F_C8o>P|EN(B#z#IcqI-`fwsP(ACP`BxVf12?kb2&_U5SYld zV*InF<}w&%9HtCGh(}6y8}i6VLyB1_}cUdo#g2?XU3(===9K zI#69SrA}S1BAxE(tF4-_Vs6BY^ENl)w24*dzT~ec;0r;I)%Yh zmD$OQQ_snC!)g4ev@|r*qM`T(rLfnmhw@)~0e0J;fekC;a?qyYakqaJXP>Y13B+Pz zE$+PM)998tWEp9PVh$Gx*xogIN0JUZ7tL$(+g?F^3*+ZIy`C_5$}_|n>Epuu0SCx3 z>CbP&q#tCfni-=P$ap& zsg61KuEZ61^kWa_%iyrw!^%f!>)fCd4a-?VmU$cwfsS@>uuEMvJf^0*n;AkGw|&Sb z;m~y*y2~}3l<%FDI~Co+k-G%d=Nh{|jE)_ht-;k#h6{!NLPNs{`}x%r8@Pc<$Mi{Q z(S$${KNJ2N2ywWak@fYX%N-fYZmnk(S~vt5S}EY&|0L3n52A8lniTY>_LI-!i%B3Y zs>*!2Fj;{zlp51Qb1}2G4`1{!^Yh4c3_1ST$L+W=To?O>&DFHqct}A#zPi>oTM|X} z5d!2TulPOk0ZWBe?-vxg9K+lJpIzaXe2wx;$`P#CG+?~+1c(y{JA196&L-~O^#p)r zA%fbi{)WCkoex8M^3hD8G#mP_NZ3FRn7aDm?v<299YQJ|Yw;vy;JVr7a(R?2>EqQ- zss5ZaKaAMYV!-?8o?d3}>cp3cDvYeI{mi(FF)wo`Ja*LNs;FpMxbCwTefxMiUucW}^es14H zR%{4??PMPy4JbuFTpfXZe3%LCuF!fiGLjGjGmMsGQ{Zo$uu*6vz$5Pv^wZhT%1G_j6f@Y=igvW##!IZ7 zGvIU4rK(ZwWhf$)tYR@9w!cAW2eS2;3x{2yZi4+ItHfvklJ zWB9lOmC`+2nFj6S2$EaE(@aTcGIw1;b!B@$JfH3^j0{Tjyl>q&JOJQ7=PW%45=^&s zI)Lxk1?i^P+k*Cf{cCzF3v$rK#ww5y2Wxcfr-2U0sZg} zQc2y*MCCOH88>DEC2VrsYw@~v;l>8fAwj#(8yf`$1zYXT5K3qPANwPn4lHPmC=m}2 z3hKU5&EmRn)Jl^TXM0f zA9&ESi6lFron2imk333slSP>X1(0T7Knt;4=VkbOoe|&Wm^(=@GOQI=U6bGuAA-;k z60L=a7#R}`S@FrQcP*R#{8?394Ji?a1Eaf;Z9@Uyh!U{3hlYgu<1vjpERKYcbfD{B z;wIQL3f;uAyeqm%n*FguNJ=4h^|WXY1qIc=yzJ)Eygs$MlH8d?_8oLeU}rE&thl(C ztH`2q?PAew4rkQ(mj<;lE@*p%iGZ|9tL5WLRb?ePTTV<2#rDM1Z<0_ON2ZU?`8;iI zYB65&ddH<%3q4N^-g7l2QABuneOFi0ipshhdt+nc-HBCDW7EsBmn_j=i>NAF-NFQe z^o(7j+4QUjyHM60%6A8Jj&V5;Hwjhfe)jfAyDZb1@Ci+>1GyRf-CvfT>`yXiqLx4l z-C%%=FkXaa)Ob9CM@Uu}+x$#5we{Cq)Iqp^&|h!1xnHfZ zPub+bQpTm2^i=i7S~Vx0B%TP!RbNSp-FLQNoW!EkN0}!7DOVjGfy9s@wcHOPJa zoDnCndg7aDoPhFvlO1*Hlrvb!FI+LgsZM7TxHTB6 zS4lr}SD=?Gx(d<_9^>#KqKruBf8(blXYjaDU+SJ9Sof_h=t>ctuO+ z>@PIP+3G4t0Ux_36MgVfW?54fh-We|&$vlWnSMlto->+n}ys(9rN&bbbRj zo97``=;tJ31TM}QBQvusV}wh1%xpks%%AwoTs2|Lyx{mc=$~+AlUT2BZwZ-ad`r=+ zppv2g`6i&j>O{d83_@E61>L0{9-EhU(%CP5RvixDniQfvR$<$IDO2mdSNc_W^GE|8 zN@9rQ2aSefi`v_xF!ZLE=}(SmYO^diXak(-p*b)?*g|oZ@|SO-9TL&{+p}SFo9Lih zu>wk8ht0hn@Ce_F{3xUhU{|J5Iw>0y%N40N*4HbsOf`|T8o&d765jw!nCIr1RZ7a& z=KPBrj*!i*e5&1TJ+A~7_Zd6FcW+V46tt8@r!y)BY2#jw%pNUEZi>R5@aev4dWgu# zN~_G%cyCEbic&gs+Ce4jTQMmC^2B5u5-+kQhbl-1`gQiBG1U zXGm%To4%W1>RzB{k2I1fc-$~GJE(G{n zYCvi##=+5%jnt-zE)dHIBB*~3eedjM7`_K*MmVwQY4pRgpyZM6C|t_ZuI9Lrwj5d& zc~BNQ8VBt&Dc&$Lfv~UB1~;myqg{a9OBMm6xTIm?`Y9+%-sHPTv1Jpsv;8i-}axZ{ERi5>B3r| zVn4iSK@D~jL@uxXV%(gAOsmXse}FEv)4l}y4-?%q)Z@VaLA1ZP4+9>(bPX+PD&^Qn zC3kWP$0IE8we|J*A93&?>m~W}i1PQJym#FVo+$)I1Cf z{>{y7mG%eQ&UrRx1&M5!uNU-NgO_=JEYpCI{Y5DQ0uetw!WHHP^a%96Cg~ z+~AIWafcIy8lmOQ)!EoA_AYV!L5eHVSBpOsrM%s0w}_d*HtwTmWc_5l6?p}2Kt%;L zFl7DKl1PvPngtvLotOwHRxdNu$=yO#DiHwd=_rqBH)`~|OYX$}Qk0*T2gZvT;h)da zi1=oQkj>)(W4G1O3p7;El8dFxyvQ^w%S@5jtO$i*4;?rtsJe$GK;rCg3?z>{`A^1B z_CARk;7udykvBRYs!^cc2Qu_}`30_yA53Mo=Zgj?wXfR_U_muS^E*3p(E6!u2?>wQ#(B>T$!O{AwDH<*WL3+-)FvCZ-RB{EUns9g(_BCrVHPKP^ik{jkj7*+SaI zUvcq%0NQ4o`5FY@w@3UDK6{C%c}k->B2Wtp3$$xz^#bkDsVOn*D!E@p(cyCeDgBAy zAU}zb(D9|6=Yqn^Vi2my9x61H)5Vh(bC!KNppdV0dR0qQ4MTrWF1~4C?Fa`y+XbFF{C12)Qy!*yRBgX3=?| zOH4&Gs`Jm}JX@a4fhdohZim6qDjlb3t?8B-E+zeueqTpghw6(PP=gI4Awe;`zz420 z`-o%cN+PADTX-u1^x2Z<%GS;k?n?_IXl1GaTr&1dgcvy~!c5>OF zkE2Chs@eFCF`Lc7A;QY#*pMZV7{v3h9KVa@@hdmTeSG}9lg{KpKtxpAvtL-?0h{+U zF{>OmTA%hK=e=ARK?)QmW#PnRqPiCF&kNZ^vr?Ci++97DEKJ-w#7CtnT7Uz+Ab)SD zkKB^&w?E5n=H`7=AK7#tcIxUJ|!cR4{iv%Vg6aG(+(jC8{Ro{nwl z>KYo2qgqqJV@vb{BON`_dSYWmA#S3|8eO`Lb(VyLbeUyF5bcezzMigt=81Tag(ifv zo++1~G}K^X=3}yZHrkJhy4uKSAMKEQUa6ggx6KReulO|5di3M6(8q_*K}hB)jCu*8 zU=IbjJ3Iq3vyC!7H7)Rj1p0FVGe0)*{(#}mPTsL`%~F{17Ca7Gi?IM`IK)TNWJ9~( zy;(e`?1Sm}tQ_{vxw8ue!koobXG$GmcL0PWwP3Coj(eS-g;x9^H^adD`qWARj>yna7^ zv4Y0Vn-LxM_XhRBl>ClxNMuM#N-9186wQFHg)>hqbl2*!8GHrcQ4&*3GJ!@kEiZ0t zgr}yeNyu)Vv*rh*KDyqz#}a0obrd(8^7%wJqjNO?U{ zxMHmL2d!_D`uNqTQH8{ak(QQ~9paDA#ZYpg&ZQHhO+qP{djT+m=#C96nHhbs&?!ABJ|D5xjz1LoQt@Usg zxVSKL@YwuU%1}|0SOFvQI-%pmRWp75>rrVAyz_oJx1!2vDZg1-utKCv*sri@btuC8 z`aHC|ol)A_A5LrLDdJ_#}<-Vh6H9f=3$8iSC*ph;9` zk%#1B6hLP{#ej#6t(Z&_5O5mTF~M*}a+#BYMg^)A<(Eq?c5t{+O>=YY+su{y-G%h4 z8S*CD4SI=&hAtto{(C?G)m{Z>A)Q*|=t8EYB5X@jQ^J!^J%SLM0ZVZmLW+(iGYt)z zOVeUe^7-$r=ndM7HJzNQSfL3=XBQW8FWBm9MWo#=!B^^EB`JqUWUPR*v&B6W5XqtY z%=s!VS|Q}Hu8VNH*BRfQ{-y*Yy)s)?ByecV=6*KU%-K1*Ff++DJDOi<9!?~prrF*> z7QdO9?te#m0|tECZPiA+b=U4*n481-b6FKz(JsbHBzG*p5~pP83}(8+|2I{d{mHF| zcQU#^?A*6%iBL;z8Vcdf5IG5-&TQ=Q$appUP$@M!;&Y@tBDzadY8Ace9S$)R1qPU? zbUzQZngwX>9?ihkBux7aZ^OzAH6s>D-Zp5z97IkXSmz-}??<+SnFNT|x^wQ^F-8T? z2g=C~zT5uk!oQt9Y+w2@ZeL!=`WlVm@Oem1>onNJ4Sc{D!RYwvqOm(L833j1&(93{ ziGO^h5?$rzFzioJ#s2N<{5q~>-lo7>#nA}gn^n=JlG+MXDg58BG4)5d zcKM!xiYs3SQhq^wje@B?%7`VGT1;FKvK^kvu|yGbax^w0n2T0aw@Dg!`__<5K%Mx9vTYGBVrsj{!_%jX{BL7rz{LGZ)8-seT@m8KphUxIf~4T6U^@5 zb9p_2$HqF$Jw9O3(9m2XM&3yHeEym3E;3ZHm3iMt6BUIA!b(z*XY}zh`0<(Wa=v~S? zbk35ex}J(*c74p&P;N=k7#0>d50COQ`UfP9`uDlQyExfo$&WtEne zo&ql8w3=*P%XMtdE=}cY)>PEDb4$O7&`e3=qg+w#z(JU%16BKEwHO*7Neuyh8JJo} zgH7Nht4S);Ffw{q>mPely18b;ZFevPf#@aBLS?#ePc%#)cD+~Uz1%G0-`p`W)-LvK zM$kGO$gKArj2|Mn8zibo_vl04+^XBJvZ061aFg>gF&HD`;Zah+emZ^lQ&l#!zODs| zVo!~J4hmvJDh4B+C`=bQ`||DOm6P9CLsZbaC1|b~SOf$@!ohCtVjVwBPgMU0sswst zV8VxMA^VQlrJ;Y@N=T{_pjSbLS(qq^%CjTx*G3%+&K>x|&wa_H@WZURZc$JG<7s-( zb*G~G=v|(jn8z}!^6%$&(&V(XIVo0;EJeP==Fnbq9~NjTKSf?EEyk_zI$PZjm$q?9 z1IyaozgO2UAaBmO!o<%5b(%X0cuqs@8uJCTsz%O37G`Gnqp2>bI?qsfHMI`H(%0@? zG_@gzOjg-4Iq?K==N2L))W>wS-YTH3ovi1%mG2DUas1mUcznYEX<2cpZ`?|7^>2|6 zy|{MBEC>C&)BaCd31oW`2uMgs#6momBJH_U!fhIuTH;wWzcslYCI7c4TPkYpO-41G zm?WcjSs58yC4n0}%>Rd41@x(4!VTT2j;qSG-p+p@ z9!OHlf5R}M8taCPWK^R>A9Zm@w;V5xD(^qYJ}6v@wCX)di~li`UtY4G_9ZVnNbcdvq2inoc4?Vq?Qe?G z_%!N+`Ov3!n*5Jd&iFw;MQa^&uERxjome}*?(j3XJ7wn!UdlaL;`LGh!I5{EUD*+x zVt;&MS+|D?-0Yt}|hpK z1CA?bhe=WKi9FB3&}IJVR6*|!3axM;JXT6rSouBlp~*8LkHg4F5O^VRH||iYrKMHp zb|q=bBZnO{LixX&+>73MaOSylHs4}hE#T`vB^feK##`QIRwdfyPq|CvJ6lu$TDSy6HG? z$U6&%iQe?Pv>i+8)I^6j)T{hD!G`Cv3)<>60if`ab zYDHR~X!c!)^i(LR40pNOS0JNDglHI3^`!Im*8-T0?n_-uNqIW4^YL^bDSz8M>A0== z^I(Ek@@rUytQ2Oy3&wszaI>hvxT~9%5{w%tX!}yANLy7mTWuM-^J}OFn$9Z5j}=6x zXQ<*Rfr& zPELDh?eSS+BK*u~0roOb4h+zMl$i6+6@Sp`bP4B0y2$vj={+^?THdHM{{3UTt0lbs>R#vsyFecrpPDsR;5R2>BH1oV?+j9A4x~8 z1dmGo7NT2T!N2u_-D~Ih4pyj z;_4yf>r5{!gjZkKwUMY4$CSMvf9%qxP+c_X(ur<<^V9AYet^SCK(`P1-RLPw*?P~B z`%z_{XnhS@!!795axzerA{RfLv1&B$%^+rqD*k7d{USptxXF>A}GfXJ3wxIgE@ z-Rg;QFaj!eMC&FxaI!F|(7@wxW`+=jbl}O7iL$vHW1iz6pIWX$8DDY7b2$2h)>F|@ zA@8qH;jJk%mdMKS`GSP6{JWyUY0`Zmy-zZ*g|?_d5eQA3^op#1_K=%POZCl4#K9eZ zgcCOHm}BKt0fV;6CtOkMKDzDyLC4y93m*{*Nt^)sS3IWBgThvNCzG#SQ-_;V`eE+0 zs{z@{4p0#19|~$Nm@?COgj`R|^@s-@8&qQ`dx@;ze$x8^1158c=;`fK2t~E&5Qjr* z4H=!g1MjMiknPJ1Reo|d8E$AfP@w1e=pY6;*gQNqdXKg~j@&Srrd1`C)>UGqAsi`e z&if0#BgkUt<*5Nsa28+2p|vTl`WB<0wMRO{1ME7vL_|R0V$Eo_0ng9w9e~TV7CW~< z=4zY7D~eBM?iwfY;ibzc7TummK|`{)#&vH2{SCWNA*iOh1TbxLd+LJM|->eCuA#y(kD zY4TFXh?Go~MAjdGHhoL_|2Ps7!dL}p0SDvk(wt>!m0P{mpT}3SO|Q4E*Y11f#QCq@ z@Q=I8UIT1gz=yLSNsOYG*IiRJUSS_$qD?@>#Moh{8);nHNqDD&bq z`r?P_H)JK6CmB7T&$_uon#^g?zQmoTo}L-8=ZVNH&uK?X$E2|2x41-&;6)4wruq32 zEw*v64rrY1UMqm^B!WIK)Xt}S*V_e%;5Wf=;NA4D1)4_PC8hVdNux|E9zIyOrsuJ; zk=v-Tl3{82XYC~dCe*D_0@7j@OT^s9WH#_>npYCt)Jm_(OPZH3uAl`(>0s3P^P3+t z$~ro%4pLI>l3iBj5}ltha_Fk}Qlo5}FY&q`LQeLkd+2?@mtI$HC7adJAQ@HcXE3U4 z==l<)m%ln1_}DN$C~vSmP)F#97`?=+Zj6tbdZbp2B@k{SL%GM5RWC6uXI6Z5Uw!Yt zKQ);@wZ@rdTf@{^)E*!>xypQ+$Cxwi`Ki=cBTC>#q6nLn`2*-yygWHA!?*Q}R8kUZ zSs_f=uB#*`*K(rqpftb1#g|oHkxM=ej~}Lr>hYRINoi|g!p?|@0POX11LKRCYZw#r z{}6&TlcAVDwR}{f|`_a2XsfD-Q$k_>ovX9@D_%aby}T!s;FJ$Zb2F(Vj4rMtG4Pk zIsYa;&MC|sQc-oa2t4lE0_b0Zu@3*gKRy;N$;8tc%O7tIv&+kHoxLf}U1()&RZDLoR(<{QSDUQ+kBxmS~QmtPJ7Pm#CT`_GB8 zJI(lFb4$_$BwT^~QB>t;K}Gw3jx~89(9wQKlb0LB>|scm0B(W+5N2Xxf;`voaA4BTxre)vN|K?tcj#oj z3GMdg%>b9%XCRwj0gVwA?U7F?-HFDuoTrZMr{KJ(vNo}5VhuLnk$9?6EH`9mU&;h# zCX_>A>roK1Mav}7hIWee7VFSGLsQ)AskpGaI~1#h^Ee~Ld@KH#Oi+u?1Z|y^$grf(Sv0QO@kJX{UK~H8#0Xw@IcQ`El9*Gewa8dGfS%IdUK)&79w?a}0S)?R!@#WfOFeEo=KMQ_d8R_#KH2nN3h+o~3 z*!$}EeyPQ%NCdLCn5GGyyu#ApNo;GetF`G^S<*mA2Q=aY`1*Xm{CuuL6?;Da{twHG zDSTLHE){vZH3>`^Ygq~*q%bko3sY2vM$DwcD=CR;u2p+?Hz{)K#^17n&UZSVxplEW zL(g=9KTULs<&p1TF{`28rd(qF6!mKcAT%DYul?)iIQg z&a8gIE+YAf%BfKy;&H^R8<|zA!fK&LqW67AJlyVj@{0%_Bx%12b2xJS_8+qX#_zRt z38kd5bl|K`ZW-&Ew6rT0w~s?Fo@a>vwr1|sVAi(T>2w96sp^46@#$Qv=i5K}{rSZ) z)sJ$%IfcO+0Fc%pxgCMeAddAL( z>(Bi~ArVTgW$U?0Z%W%ac)iDE3h8gSX`h-Vz&1GaZKwCI4!muxOMiqCzS#xEXdbL= z{KndZA!=(@ff9v>ba#H@a&GDo-i&ZdVedb~Cbn&2D!WR6somvIB-}QK+DzP;w*=Xz z)8@68>8h5`Wn{#<>jon%bE4V7{9Ks{3$i_f{mn*og;JLCGTDm zAJTlE(aZ9D(3yF1rq=oImCqSuG&WbW8nm9q2@~A@q}0Tu+y7nEh+DEldF%U$SUmRa zY+nOaSm?X32^t0? zj#zvo`ewMK-!N+@>N|S${F=nRkD(V-{Ri1#iTQY+5lpHhUKm(9;?m`+?F{*Sx*40Z zNBd}SNaF6~Z_7u0I48M1t)yRgLC(%Hj7;%{J6-wmBQksaiBVAI@d*}-qnuq5J!_+R zmr(~S{K%jN`t<`a#K@cpWjGN6s;gze*pIWy$3p#o2STa|rm z$=PtT9?WrpRVygsl9Hmfw)o}cxxc%*CNp$6iZ3=KEMVX@+vsuejnM#LY0DjQcx0r2 znAce-UXlItw+7-noLNq5e$H9}ug?+c5rLBWndO~ZdpHl2((QRC4RUI$_597hQci-T zT^N8-2N(!2>uLU{OxWl`=zM%avuu%5nrd?}I;%dMEOu=VJkycPaH6q?iR!p{Z1n!YSHR!>K}M!M#eXXq`Q57XmY zy29d9oa63KfW{7})<&dOpj4}MAI9=zb@iunbJt*@7n?j-Z1S`Is^5#?16t#IoFPxh z_3shu-VT-N@$hhQ;|o52w3kx!a%)y@kNaz0eBM^MXsa3qmSWi;&k|59DV@1QZWur1 zPoS`80#R~wORiT>UqU|C6Cc$2M1spdd|31YRK znP#gQZjxG_c=(QUf0`*}RCw2LnYo!g6D8wh!7s9^0;vD~)}L%;L0cu@2Hsb)`@G_5 z?o020)iMB~HDei;#ncQe0?e(@Zk52n*Wjx2)$=DMHbQOZ<%bnOw@P(0 z>Sbfa*fQT7MDRN@HcAmYqPq#TO(ad<@&)?2d16Uxl=~a7Ea`+hhR@{{&MMp$XXmCo*80C3QN+BCn1AsIsem>!~wdUS@pU3B~*T%hc%8#y%ZOqecWUrxJte@5v#d}v$42vvRCz+qC zJ;qYsaE=nq=kJ(qE*c!Qb&u7loGjpCwON5cw4k6M_v?IA@MX{<($djYGJk%13*Ksq zLdA;UqG#p9z6iriixK)qQv?PI&4@WSZr#Vb zOw2v;{dmuXb??}bd_W$@DfHxGZ9xTrUz#O(nb+r*##OY?#N4yH0!(t{0Rq~= zguoY^W2u&1#ZOAB<6Z-?Ciq*!js>%}F!E>nWHU zYEe}apC$2;UqSbjJ_Xz%43NvGT0f387}`7jCWcB!b$xrZS!tVB6H&CG9YefbC%|K{ z)}4Wrs-5Hdx6jq;_C%J=`2klUCU3uZ+l|F0@9~1B{rnh5&TKNrD#{_5{H-snRZ-MS zSmfKiThFE)v;y?oKfK*Ym**1y;|srk2(T7110akk7gL>2xTo<@kSId=0p0DTz zy4$P=J@QbsGcwt9)mz-8oGggs;G8scbiV27@ttq=`0227p9q?r!70L%_4Dbckwwtd zmtzI&>=1QY+YZ+4W$`GTJZ+jEF(v!z9X{nP^HME)HQPdK+|3iz&C`9MSS4elqFnw4 zUM|wd>{2PhJUKTZn>gd6CeBl*CP}}c=!X()`Y&l3dJdnQSU~-_s8}jdMc*r{sS#0D zzHe8~RITDkIjTmOw$>WYA~K2L9^>-Y$N>q#jmN!6X~mn>*}SNJhuGN2xh7Ib$6iiC z?E$WTp8T5Xa@$NAY?fFmC=h7u^o;`84$`cCh8L?p{&#)g6yAgA|;%=DfP%Xf@mB!^dF}`!W6Ppy+QPYB1Np5PQCJjzd z#f4q{P5c*wL$BMrELd@+!7Pquv8a-8n-%K$>3p^@jNR$5a?LpYKlxd21Io(b>TZYb zD`F%8Hm-G83NDq)@}-0p&llBC&GJj>V)`}s{eAp8NeXx$4&Il?mey9VAb7g!ZlA%c zDl>Igcta)e43gkC6b;8!kpC9~K<2FLtzk}5Ko!@?>xb_xYo+uu#hAZXqZ*IhsXsCpJ~IPVs)> zhf2V@G!3iRSk`10aq~62N^VbTZoYMq@ylxaPi8}Z*kM)a^>G>< zcB8S6{=Bw($x6KDYE{wt`r&Vi_Ytsn2+hUCW$H@Ygr^oI1S3XY1-c;|2xI;qjlIU+ zm4jC$E-u|%muiM#MrmxdhmM6!MIJl;LJE5{aVJ8)Z*V8cO-%s8196t3$m&~;8Anvj-Pph?lXQt!PM=udT2U)T5rGa563vJ=M_0GhpPurh=rXo z9vlpn&7Kfmps?k~A9A6@=zlZgRxeZ$>exCD-J{oxXy$_G@ctS@|oCNE{%h+(W+tY_YIg0)j z*$GutdfFBKv@o>f{;Kz?W$rl}o=52`Y$U`JN^YH2nAE3FSi+`fzm>?16kr43<6>c1 zyo1{MJ!s8L=7p*SrBDtBp&RQzh}FCU4fYxM6KEiRZ-4nV0iB?ux{z;I)ID*MMIow$ z=<$_KoWGW+w1{5;7e`{JMfbLpT`mgS2$acGiuEm7$RMm~+wo`y&rz3FbTiK`$iW^tFgEBm#e)2#=kD5I|aOs%2S5=gyCx9HE%@-CQpo5*_jeVu~JVYti}Ith;`pk7RvJR6d}rX8EMAyJZqwQIRonB2ibin z=K6%N>5!3?9_tt$h}N0KNfxQ0L7W$lY?1+iMcFVcene_X$;45F`94q(BTfl>qn<)z z#G!HJ<-?I^qRx#@d;9HRmb_@i#PdC2$2SsvJ!FF=Bz$ZzU_&2(?A&PY>8h0=tFIT0{QJq>e|TW_fR+Z2nO> zg)`894OzdGL;=17!S_TRc?Jr?P}A^$`4-8xraP;0WVfnvXBCv5xNC9;SMj|-YV=#~ z31*H@+2&Yl%sIn*Gx+V$^}URBO6;lsE-x3-a>-hjxW|5z{Rv z4b9NODaf%(pKPJF_T@1dmiC>D!6Z*?$o)@;cA!@eg*@-$^a1xwlvC^TWZRunH@jH& zfYV9bdK3q93h0k{u~iW%Ee*9WD3N%j%V|`R6Ie$kD$vIPkA$?h+F)tsyz|H^BnYf? zN;wiRx`2$1fp61cMd8nZxrXkanaMvIY(b;6aM={6jJGtjhGLPkEj;a$xqY0W!0-Pd z{6seT0z*#~wuD9%LNhG3@H%4RT`f$=$Os!Gn}6zjfK@~%ppOy&9hr9?G5VbsHY=8F z%r7;hqInAUqT=DnweZ9Pozl)PY>n+-kRZZ^*uupd5+0f5@fP9L zvqsV7II-MLOiF(_-hQAyk+C!Y2j>Wt!A+69V&g{yyYx-CTsAvGtj5O1VgwFfa^ax{ z`o+ehI?Z>!D`KFvY zUw6`4&B}YBEz;z^PrO@ro}k%wk)!%DTe@umR&s6DATr zyE}73oXU12|LJX>_U$SQ?m1S;I6j47LBxcqP4*Ss3e@Uv`8E0n( z_Y5*Ig$-83%`-hIz5h8H;qumgV6PpfZ&NPQl|`9xfvGjKKdbPx-fD)dyBTG7-j6=x zOv?p8F)}p~G-z;#9GJR&gP5?L-`qTntS&-IA?zLUz@<};icEM8CaIm}Qi|bZa&dK~ z{2(FY8q%6e>jY+SE@#ap6q1q0o+D&)yM*?SyVG{H1qjX{JU;1XM}K?C;t2%)HUx;+ ziyyythp8U99F^N^1VMg;JAYZc6Lr7YVr8nk3HzCoj*-a+?mv;33{(|HhDOT|mFFiX zs(=BU2cqSLnBJ9@^xOAa*1gd-j-+|8em>XZfBN?3NPi?A_7J#PSb$Y7PeED)d(912 zGejbbNOVjw4Eb$XS-bfpOQ~`E_xgl&#WbHFgw|6uM4fQ}MQNH-&Rok7j?05Kwgs(P z_n^nL_N}Ohiwk;SU|@VgLfH+M)xmYTU`0y@`pN3Bs%|_}jmY-No@7zcWy2)>D1tc) zU)PU+`Sc_u1P(%1bH$m+$0ybTYiCDe(57>_;1AH8N!UM=o-Iv;`e1T4-bkR=0cO4X z0}U()s5|{wcev16LshCi_2R7i*K1%^AdJAeA|oa3NMU-QHS9@&1?(^BIFawy15eM}L3-88!TVlc zAgt2|{JwXD2X1Ada%Eog_#Vs0vLR><{U=UA6b2_Ns|I@Pz5NSz+xoZIu4<~vTKHo4 z8cEf$IP>d>%4^%3Wi2eGPv>ob24qa z$BvFt*y6#3Iibd3wa5lIU;cvntEq>!mWVR(XV1nWQoR_T&)1*HY^u!l*t(ICA29pT zrL!W6Utu5&i6=oMtp3xw+SwWOWmBH|6pw2`3VL+RH&*BBa$#$$bddD&;-X;2X(uw! zJ=Pe9^wrVS3A}T6$A;kH;laYf>g@~q&LiWTpa$lgl>@;#>8kYbzOSAE$7do-zAtr6 z5VTkb`yVHvSUn3g>oYW)of#r@8ueGQ(oN9#ag=*DPA8Y68QIywDvL@aBqXgqz$qPd zFh5aPQ;N`$lxE~uZo+UvE8SV8rwZR7;->8#Xc@M7zyHg76q%g#t;o^@(1#n>%S=Jc zrImHv-UdDD^#sh|4*p;^Mm}^O%w8kLQ6iQ1=CG3ht5PFT*B5c7HUn#-ok$^oK%lv` zb^c0BHR~f-nw|XvVl$Fo&W#N8dN~{rt2);0qQ!2DTv9(4b7E{e zeg;N(co0bG$_5b>*yR{|j_2&PW<^4JRoBukbc%osVhMvYjyp?FR~M1M71|s;FQ$_~ zz6LgzkFohH_0cpzcwo8K zN3Q*UL&g3Qv0v&d9K(-q>vXi{f%yEq+|r8q-8u};|Hi__9?I={BR3Xc)9tbxqBXRQ zipVI<(*1cl@p>a6A<(M=Ltio0Y;*ZES)~pfXMGL$oCT)z7&Vghhx)(&h>HGYw~c%*FwBBZ6o-`PPKBeVMV^>5Hm#p4nJo=&+P z!276tMrXf71TJ!ZPP_wE@A61QYMud(42qqY{R$FzTLa!0tVH?COK1hGBW-<%b^aUg zLA^qzs!b&RZ#YngIz2rNuYO0cVGS=BvNX<9+Zy;>SE^_@&<4VA7q1wOQh1T;sx_X9 z-nSpJQiLAWvK?WTC&_@LHzB0Wrf-6{z~$=~?T?7E3|O7*CC!w-vHbep-qDr2Ewd$N z`M}Ji|0GNLXi)Bj4~LTk*Pm}a>qSL(v`8o^wErgG#!EWy_)AhNa(M+cJ%0rTqb{3f zYm|YkSj6n6rl+QMr!EK_E;o>DQYEa=b-S!fX7GFgyu_nKLVGXRICw+k9RATs#OXpo z2#;qd*!U6G;pPWjbj-xCmTI-t&_P!q@KRNi&qFo50czHQ9%ormE}IL zT@kw%;ed~1Ed-bZu!EQz8KKu@UfO$(aAT#QNb5ogAgU+XK*thh*xEms!8zJeF}gfE z8)z_F92p%YwFEwBQFXv#N_{Nwbj4I=CmFj?2VL#tUFmEARrJC_c#3E=lQOapp0A_ z%`Y_Iq=*4c#4yVM`*XajGH-2hRnqTizls!^=q!jtjXA0}j&01LdE2Mv3HR`aspN_J zEwc$Io5mtAdTeM|6d*!R6_A1dmyb~1;Pb~11hwQ|Tsn4o_Q6!s;>sWt{jn!~%&D(b zXnLLIgExCiA?4V3cq)ddPm0>R;432o_E3gV51a{k2*4BErC@${cWysPumO0ux156c=D)Mo3}U@xI17Sdw5{-|UB?nmz9XdF^wY%SFatv#iL;MjIG<1KxQ= zlgIY1X7|8lfu0@K8}9 zKF_73zEjm{2&}KaLntXFNlES!Mru%lRqCV=o7jfKDOgf^f&NP<$e`bB^mx#}zgviFnkjQr{QB0`(cI#lUWHY~2P~kLsQOlvOZbUm8G&Bh zuO$=k2nb5Mw2ru<;9^5Y+zZWm8E(+7Quz)EA1^2-A(vm6wklg@>rD{k= zSkZhHA7k-hH?(uJ0ls=Fl*x~)hwnNR7w6>J`yfqpGA79)Z zkM7BVm+d}2G`Dwh9=G(uu5_aL?WZV=jE`tR@kS?s8L_E*i=v{OVFs~yfM_KpT{b6C z#^ao9EK;Ox1`uR=&nk|)sb?hoi=e#H2TaBr5)r2>o1(cahg^Dr>gF$8rxczkkF8#` zB-$xYJ6)~eVJ~v9KBEYW%bN}#=7}$!T zq49=7Ku}Xw$Kgf)D@me`7Kzwo&oDD5NAZ**MNerJm5wwu(cQnhQ#49azxmDO@LrlW(pCV;4kxLuvT$V zy{WcP0W!${VIf2B;o%O}*o|{)JI_~J;vDTwN(h@O8p(52RT7DMeDG5@s8#FA%gcL6 zu_k|cRcY7_X{DnX2-VD0aL&xVNlMy_+)X>lGn43Ju*6d4_V;mnrC6BmfC%a%P<_8O zV_15=Z$v?&yxIjDoV6I#3uph33#l28MG)4)29U|+5|WaFETHk$H}>~~cO@nwcQZ0H z6p#`;KHk?G ztW9HBb&qWuB&-tgLkBv_@E2_aoSQ7^6e&7685!i5V`>}P@u(cBfV3%9LS!_wsHe>+ z5gnZzL57^1oT|Z5Z3S^zYU17=i$h5R+Wox-grJWNWKgZh$a=2F?mm~h>H}6=SX`S9 z#toM18^D^px6wgS0otvpC)kfazaO4(vkynGWGw18K=q(8TwXVlUsUwh<@!qotDa6N zmg#|EB0CjmRjDv~!k z%5dNn`>Q(DAEGu%-K}9eAa>(8rLGhNncQH88pm2M4CnkG|BEsQK?3ep-a2VqV zNda9ub-BOy}8H#?5yPY-@_2p{RaP7lWB-m6370?7@{XW#x+^Kdjk+>UICaS?u z{;&Y%T24>Nq+sRS8EDXE^g2sntJmGu-o4j9P^R~&Jq<)(U%^UFdT==zQi9uls}+~t zB95K*YxB^m&~b5y^Ii2wVRu_;1@7vOADdgO}>nsR(XuQ%C*-!_)BZ)x2= z$2|gypO=JoexNfqHDn0!uedmA;zva6>1lGIFj{Mo`zuG4?iHS|Fz=W2JUmtGtkLq~ z%-z2vv|zx0%fQzD2bEhZ( zlqn@SDXbiQ#{HKSS%!8soS)7^DO}P0XJc-z?Like2ZsrVQY_S0HsW5`o#8kFN(L3T zbNeaQ{%`}B6gN9^U4!l-tV7=wd%I0`>J)Q!;Ci^fGYvRu?&~9`ah#T0iH2jcelxS` zXFatjr>P0OR|NvnBTC0+=Ny}V_v#xPHL<1wG{FQ{giT}G{>0$N$pg=r9qQA-*bdmP zJVI(`C~*ffF*!-$yg&6i>54wJcA`wlT~La{d?{Eg~tI?o3pVi+yC} zuJA1+Gi(y`R7m5y!&(U;w}AF>QY@cO>7V;$Jw3%2eU{$NZ;!no}TSPV(0HW z8o%d|;^q>Dk8$-)xtLiQq5S^#qL|b<9T~G}L^EZHIVnNT%{64Nt#Vd@qkYl#27J!6 zQ>@K^y*P=L@Q1B^Ts|KWl%7a)eD9N~U2@qpEsZ@45YpesEPe*Gwmu)AaiD@JgWg=8 zx9f8amRMYlQ$PfJE`8YJHrC#|hP2Nst)jTh&h?EOM#H`qaxHei4@L9Ghm+9(=e$K1 zR;rbajcOtSbwK?h|*LZaa2P2l4B3@N9(FsNn6QR*a1=^|%)%+>qBB8Um~+uU0k2wmmjmFAS#rcf=TXAr;?xX}nVGr8Ob&d&$_jAkL}m`+ zz2Nr*2CJ@)p<#q$TPxAS0&lg59hMLJEYS6J{_Q&B*89ojDZj8W^9t;mhQ)V<@SY3? z&I%8UW%#c?Y8AUbC$ciE;}e?y(a!=T;We4UxgYH_S)G23a7h3L@VP>WThoZ+GcrQf zTKp9MY~|ck#zZd})L$&ZItK*`^+kS>m=fTZTX>ilskcgFZ3%0(S(9bn-$8_ody?4Q z)i&ZMXyqrv!|&#ed1dxkrkmqoT4Wl2GdVRwjA50$KmRP+HnG!-y&H$!z8=9EBrBqf z)bBowI9a(#(!bi~grysRMOB4y+O zy~A3FKg;g3*`QXy0?nJXwY*6xpi@3S#`$qmU0OPh1YAVGY{~X$P@cp4LdSRpzIU?s zPTn4D=_-N%L!1aF3@tY{`ReHL|$ zk8)gNkg+dAxCioUm;Vm{6G800ubSz+9&z!B$Z=wPvF$s2@rD*-lAMD; ze{ZLv3}&S;d*JU*+J|VJ7^*o3ZTGc0O`Bapk>@`ArDs84D+nAql&ermpE%)o!#5q# z)OM367_YlH@g{kC=E1FqD|I(PAT2#}lM-^-T?p{nZGsfNhT(yEPhV1mu=1C^e%afX zk2#EuKU3s#ykAlzhlWK$7oSARVA|iIb1fLOTf#q%yg&K#viSumgPTY}G^-S2g~`A` zKcb@6GCWyoNAf%$fz9aFIkxcb-3cByP*(gU60;+Jc%PP)#H}r_F*0JHn8c(cj*lay zXqd;1%TWS*^E!f!21GIJs5?p85d^#!0Z|NZF!$TYD|Bwod#I!t3bw4Qt9?e}eoK@k zuCapMU5)uO5yzA`j z#DfP9$kJ4YB%&&kXx4RV)(ebLKY+Eg_TF%om_ABv*l}(}MM#XAa z-_wOXL^mBw_q{XH_8mK6GR-N^O7=pLv~>iA2YS)d#c_jM!7;q!cBkOr;WJxrSXxjm z0{mQ(v=)J0iZM4iIZ4JYYo8NqOG}O*;2s1*Lqlm(Iu@<1El5d8b*K;#Q87wfRfQ#% zD7-kfY7}`9OA-XMih$8LiD`xInY?`$l)n6)X&4&7#P}!~NzidWv*9q^^KzWudHUyF z^!MW3@1pzCGLTB~&+F@J6fa^{m~gCCQ4FvAiy0du+Hf);ute9tvZQC8^-~=2=orh- zimt9siaqVw21d-Vla!RAe5NUcm0qtW=B!p2DBf}cF+N07OyZ#6wFc>)Ih!K2H3<0m zIgcUDn*ODXARq{MJ_4c`-e3-yub=66yeY-UC!n#RjyAlvD|AxcG{jgN%q?Yk0#H z_0x*g|8guZrh;Qn8B5A#2Z*7WCUkMTargGEB~Jmi8n3N+ic{|tIBksKF-b%xJq=%f z&!pgU8Zb6AJlNlj-tKnv^|T=>HUZ&85uI`17;RX|>!}SedQ?$^!9X$6yw|hAn#qbK zntVxufF~fp3gPPNr{tLzJu|H{d-w*E2jDL9{!QMKsVIFP zKdQv>)9+c^o$AY($lzm`l-`a`3FHwP9Ti1N;a3_@M@n|?!fI=UNGw-*{3j_tIM zX(_SuM-S1)Gexo15JjW!iB?q6N;2=_f z=URe6@-&738+r((xW*<`h9d~L0RhWz3~mraja~9a{30EV8s&3_O#I>;78Ze_p+Uvs z%o%-1o9aR!>B4`5=l|RPfH_idfE?r_PZnUCSe~hClAIt-Mn)!45>2A9u>l<&?W7>i zBr9~wizz2`FHKrNASNzpO)hUF^^XoAY0onKH^)fQs-^cD0IbMhJnsDbBN=kdQ%=rT z@xkcW2yF=UAl6Cj7skm^qLVg?Vt8SWn6{6N7&c1-y++(l9o5H%4hQpBE>I$$PyFRT-`` z5SSr_E*n5^RWZ!rd3Nqx-bP~uFDrVP+F4Qjl9A_IdM6zn8Jf?deD?C4_wJ={GAIm> zB=28R{PNn16~aE-wrx0M?!(&mtPLAd$;Hl&R*vLTs}nCOo>cxwF(js3-L=vm zF%`kb#is;a7#SdSSQ86GqO?TZ>gl)C&ePc!svcv1HVxyNO}$GALw@<1_a zF~^9HXJ=*=ui;qTuUB7k$oWp+0L+ku_Ac!hpWB5C$G5vz@gEQqn}|b4&suDwx2GM$ z6tbYZ;}va&#!}qiWW_Uh2T^iM@*V`3+TGhccf4nIWu)GW!13ex6sF`p&Yby$!(fPt zi6gJSMx^YK_fm&}x3eK!6da$Mz0-SodXSy%9n2FPrsdf2llbxG_c-_N2X5KVcGXS5b9?8`ZF={x zy#92R9Pa9e6~h4m;@IIX{H0$(Kr0A{VtA98+_rriz3{Uoj_ZDK$HxqcH`syP)0;@= zJ(oM%nlME12i>U{W(&-kr}uH>gyS|n)G&koy4?s&-UGw%0KGVFL+l6tNDX3%3@$`~ z<1g{2t*s3|{O~=}(=*88G}(m`NLRKX5I`OV2al{>06nd|fy4Rl+tQRK${ss@3f)~D zc=fW0;&M)aX{5=#Nf{f{{c-GJjy>k+w3ECX-pshifXmTivA4apSI^N%Mha}K(AD0& zq!{MsWxu|ID5BfZ-`h!E!AZ11N}j>{4+~ASyvBw4xZ^Djrf_5ZDZXUF4DmO-l`O4W>aR66Bap7ymLinK|oyyh+=q?`CzIcjv?bp#W0J+bV574EFQ{6Q^6Yp z?oJ$+B=@K`mGvqA>{HY<)*|jBi7o8z`^=sFvoe@JFJ8RB?b|;q3gXzHfjk*o5u3!PB{kpx{1Pjmg@N^?=6kB4{77lfU(hGL{rS*-AVhzv)v|CwN;qk zpC>0LX(KyATLW{_Xj)raDE^&eW3@U-RB6^p2-G~ijfCWkO=)GF)cuy4WoljiP*fU+ zrR0=(3Ta2S=`i73)KFhvr}7TBJIT3p+FCW-nWuK1T=Mp1W2GgEXEG+_n5%w7?aZ-# z7i0W}ghn7LCSJ*7FJLw7L$K!~$4QkW2si=(_O#^W4t7LG$Zt&>yjG4T=84CTACtFm zwl!5WRc8D49r)mvAEDyb4V=h7EuN*Cnq81V(-eh8kT6Udn^qZ)AmA1RL@~Sx>>t#-a6h5T!7!j1iccj=mrN!J%z$wXx6x zhv65ql1g{0ZA$%(5nwv$c?EGJdV717lm@z962+c*?B9(_JLXz!SO8+fGB9KqL3eLIri|0LfBOc~_c+!I z{_WdYjP!S4I~fgmLyFqH58G(IhX;G{@b+I8JhPWaK07m`D2n&z>72uJaSU5l`YKeg@A(h8vE@)NP z))Z>5y^Hqg5cp4zBILknq+484_u}7wQ-}91ya$Vyt?9^yGHkfl^r8Vd6eC{CiH#H4 zdp0=Od*l8ToO_>Q4p$)W@KMG1P|Ne}O=A-pX>Xcs8LJ@RTm-yhH**UZ@T65W=XuS zdtOB4@cH#5w1%PUiFcPqtyO<9?_!P(2_ zPsuZM2zf+bZAn4g-_eA|N8iIg$bGTlc^e>Lrw`_)jA(1@-(WQMU78_};jt0zZ`2vb zM=(05$DD5vT3*(ZQkXrZR~j5Jg44zcQ3~64D`~QpD1|jStuiPa${Z z-s6|TgpeYOMkT^@wG-~YQO_}ewt?UG=_N=a!kxR!7V&Hv|*_|v-NbJOS}Fr2ON=&)%3pq;m{$f@vOx5C5mTT!)|S(c+IEJoZHf*2uB04e(q96(x9 z8V>&LzroFaa{!N<4YX#R*Zi`u*DtXY09DIQ7lNM6SqXqf#Iar6N7cXV0NtF(s^^iKOBHk9io;o|?Eq)0PT z`wjM=dx@&f{|QMOG;2Y0$udKLjZ6Cadg-A%299h2p5lGvp;q@6a)l;Eg>K~`WkBF-kAQo8YD8%UvBUh$1UwKcb@O%Wq zDZX8NdLG_V+-8m|%->9>&2gNWwvpp4^V`zSoxYwwSQ&v`2y}II(*CH#rMDG4-rV8e zQf1@X*2+@e3lT7qa%hqD!w;c~Qek}Tvo0aNBS`0N9CqRFh8Pc*4@zGLdd4$vedJA z-eTLf(8L;vlD3_|3MJ*zB0M9#G?v&HvoTn}YF=pb?mg~!8-+|-6?w$&F-#jt*}JIt zC9hu&Ju*IOn2+7+Pwj5w=RdSaA5V-ilhwCyELOnQRG z`~l5>gk;U4V$TAcGXb0qNV+Mt(-1LLD4|eEl}0E{v@nTPraPWze^o^l7ZnhY%eP(f z-S&R>-p^OxZ9n^c-d=a`9u*X1j{WMDVMFTl2aM8KRf`FF8jn|;!Kx_Q{qP>Q%Ut6|IC2ki&65wFCD zYgfRUybjn9jg1v?I8^rm7T)3&$aBZ0FE9=~qrnD76YDAC|6B#V zoR0veQmJW%8Z$z*UNX6>_R9Nijeyl^#gr)_Z5b52rznC)_Bfu1HT>64j$uYvIL42k z(1y)WT@kYW50UU6iAj7ri19c%$q2{@$Ozmm0x~gt2LwexcOla-Vmu%mCgfGLLYFAM z9xiv`LnSAH?mLzi> zly2>6vasD)gr6@uf-Og0fXY^iCzkDF+bY_%&0#r$C+3R!pM_y#B+P5RK$@}!KcAb5 zv_mC`@%Mwd=tVeFbCK%y_Up;%7DTR+M6Rv67zWj|NR9M*{oT%vF>eL7S#;RBCJcsM zIx5p{$J;4>cx~28NIkFj=|g9%3KJfK-v=#NdJ9tMcJ&UHW5JWU7ve}v2J}iiyQH4K zcRD#%@{Ke}OdJz&dp*RjSPF^fph+RpK0lJaVxOFPj(}1bK#$dnJuf&SN-$QmX%Al6 zNM{CfEA}6%L5ez*B<^ZFk!u1sU{k%0^;&U}(%Ye{WH(^hrf8hKEbfEJIB1xNwS|fJ zLtHX*Yw`ZhHGocq#ReNUZFr9C^NGD$goeJ3jl0#iB!$~o6$Gu0-p$%gcy)awQk5nc zYz{0<)FBRRCsU+$3B8{cNF4xDSiFOXbl-jVNz38%M@(kFmmdCu70Vy}cs^>XKau3M zCr<3zYksh{y<@wClHEv6B2Kt0B|TElzT9safxbmRCWgC#X8>p7T>1L)$dJZUgdtg7 zfsNa2c>5&Yv(8LgbH$aQ)VQ$c6MChq~kBj2j2}C8Hxk^0th?@IpYuZ4)#0 zMd~Y3xK^Kqye4`LHU}UrD;*JCFi=-(_1MZx!MKX3^sPv6XR0sGL2><6sXcTwNJ)Ps2{=C|EOvUt z8P;H}b`QQvbjfILIkX)UW^ASh+%D|jTnbBz8O~NECjpCr;ZUS)c9Xph8;oYV%fnc@ z_Uvfjx1b_4455BjJU?S079KH@aP2Ul%*n;ST$GM2buEaO2vRl9mMJA~WxLG;qsEIi&1$dpXADOQ1KohC6R|@k&2R{!h=}yCibxd zvmUV<;z(96k!*(Vg?titu@4ovER!b9O&${nj-R{KT&iK_= zU-1=?idSR0o`fRe4c~wN1H6y<{#piipZc3t}Kp z$WA}R4@}`feC6w}I^~gf$Oy;?3?Br(<~1&^^}b9^#c7z6s=(IFOk^h2W9H~AG#Smwrq)m^X=Q*MFE5-6WLA>}Ri2-qK`_Wsjq_7kp7VN;kmeT9D)r1WN zWL(Ld>gVfVCfQoT_C7%kRi}Qrb{%6enX~ zl2AZvwSNs;^95L&8el$s5~dT!P*?jGR8{;J%1aL7Xk`gbef9}1SkB;^Yj%k^QH~45 zboDIE`SDK?yEsMqKkugr()P^A7)%R$0+S|B#rO#-j2`m{20JPI^;eg1=~7FNK^M=v zy1Kd^m+Q*{E)we|uhZ*&X?9rHQn=~d&JtL);Hy?TAkzq#)3xI^Ta7f6MTVgfl;YVhyug5WE*RJwVzzFpaX*+T9%FsuEq=K386K!NW51wz4ykONItisv~ z6Nw5SEip`}s&GTSys$alMDfFzPBGiNzYJh_pBx;UAkh|qdKg2mzIQYRj1elM& zpr$vkQjNDSlYyp1vpNK7PXOLdNZO=W!R;swbrSZ*A4Sowov_7|ZM{WuB80@v5-jxN z_qKsv#35=#OYXEPsN;lJ9f_Fa1niB`VJZ8cSK>rNX+G5P`3NH4L%xsAWB=({97JzC zW!ejpH*!O%9`S2(5kyzvm-mI>Unv8-vx6N$KD&b)x3!My$Wn458e3jUrj)c6)qyX< z^8O|XE7wsIUVEV!sgeuf5$qz#{yqt!h4HJAsEEd^X=*r(B&?x9xHcJy>l_FVP$AM3 zPqH`}_Z zJB`GzV)SUr$-2}ZdfSenP)_vs#*G_2ZmNjKIT&Jc3Wo)|{i<{>d)$fPTEK2bp`H_3 zOimOSG@T@v!xLXb9Oa;6q|1#HHwyJAAr_9^8)4U|U@;vNou}FB$ipdQlEy*&{BkhdK{gn~u zUj$@gxEuJ2nK)zpmH3)+(&NVmcB8~l&(g&k?NIMhAGBY@Op;?F^#PEwiD8St!yIgh zii+ZZg&mEJW_`HV3*q z5@r#{k(v{W>$Pb<-hsDiQ$HR0{`(vF>Z`Bm+1$q%_EURhvx5(TIBgtdpuO!1ieHDw zz(}mxQI3x}`9ZmP6`t5#gO!YdDJ2U%af(jQlC;fKAuu#h~ zBwLQw-iMO%MqW6qsD*OSJm$2ub|!yWQb7Va5erdnS%)^~IZ8iU8jG>EdI3J(nS*k{ zExVJbO>)I^NNdtwr9|9>VkwoY1j%b786y(at=keWe^(N2e3Z?uFq*NFGSV$Z65MJ( zdOvx+a7DKid<88qS&>e#{3rvfrdKi5slB8*?S#jzhG|wlTGDp7Nf-#r*E$TaMtXExdm)p1S>w3Vf9oDIKsBzJS8xpThigbKCtw9B}gfrio9($CuN@ zrj)|>UTTxH-okT9b5i>1@*4M=n)xre*X2b|5om6{$Z%J}`&&-kK_F^QG*0mTFVavV zhp%00MQdy8h$V()8R_o)y5&4F0x|;KK|m&kyMq$*1O+{ct5?1rA;fSuK^Z~WM0};X z&#Dpq)K5oHujQ`F2=opCB}ew6qhmPe{S{81KE;@0qa_dGTgCb5T`h8{dx?PX79MIz z4AOe&raQM?#P)K@#@#uuoI^%nWFX-35bnQg-_cZy!Osd*9TdL}IJ58=DaS+zt}6 zt6?)lBYm?!syDQ^<48-!sY6z*UA_0vPBlUGD3>pEyQzra4b z!z$TL*!Y|QYwDhJLqJb!?8mmk6s&X}mD<-rLOsZ8LT)MX4W)E+wGFSnq{i-zCZwh& zAP-o(WVU*I}pfeMmW{1@`hzTUsybI|)WK@P}i@FOsOLLk0qIy3ki+D|Q1 zQYAs{Pibb)16<4$Q%WxToolodVZz+i+`j{7FZaMZR7|Y#*zasr+9Tqo>o@2T>8FFz z$r$GLC3rb;GA!l?**0%s5uP~6JNM-l*6#i8AAb1Zj+003eJi`yg0pAOV&TG{bT2b= z3D48N{q6e^9cy>a5G02K0>(l7ABjnL#Xn3rbUDcg$Oy;?^aTQ=__1-bFANQL8{+1B z{OHGcdeP7Ny{ngPU*b%I5$c(9`@Jqvfu(Re%GEDoWu*5d_O=!CCHwgbN{XdvZkw$y z4_eNirc`MVLZ?06muByYt-9?S@BsTVF@EVissHwswxaM~vY>u56Xsuw<*WSQxqXTL zJo=sG94tAnW5It^_GdM+?S4j}rKLskAPxu!pu}G|9-^F`oQ6LF9x3T*Pu}|DyrJ|} ztSX&?^$S{IQzjsNiEBXHg^nE`Zu%FLXnu*6Ax;==Ay}DwtB?+M6t4IU)VbM|du)%b z#qb{T>QqSNnCF2#R&2>%<&|aQK=1Qw>hSyAS@>76%zp-!(*3A#%%bF6BdTn(kRE*= z|9UhGZ?EvwZ9`#xBNA8m#v^QBr?h1|ieE$?#+HWXVOlo_Evru;L+eD&x-w{2hr#AI zAMt9@SO@$0JA`ift*h;hMr=#`6*Rg3AGFrr;hCfJad1O|&)|O-b@g}`>sawAUSfYc zz}2NCThl4v=HC$UR6>`><((q~0TGK#6ZvHSb+)+@qb4mv!RhPJMYygFeZpvD=}x0I zEy7)IGqOfa!tsLBDAu|5)$0>5GfUUb3)oScjnP}D;%0G@RIa%)6O$IbhS@9Lfj&DO z5iY*C|N0_ZmJ#R$0)PCkf5+UX;(HaR)xj9N<#`oYnBIY~C2=CW-;^Dh4ne525g2AH z4?KeXmsd;Agm#Cz?1zo9fGgl+C=n^~JK0YYhozA&g2qAR7$-e*J674HsR7z4)NI7W z#oH%hMX);O^PMc#9;@5i1Ijn90M_Nxs~D7|-3KRSriG;KoiTP<{^HCjsDeW zRRab?xb>_L_gJ|=A1p#DE*!$JvzBZG_6wy&l6ODQyp zn0PUgQ=Q3(AS&4e22LEwFbw*>*VmsWG5j#&Xon8^w#p5Z5s(oW{0PV%!`(bbB8KMJ zvHp^D&xAqupme}k-H1@m5Vsh()P_<0%gPT<8(I|_#4y;D#b|(q@uFg4LSW-D@o}uu z#4ukqtgUV@DoTb`F*b`jnuM>-Eah>kH1M<4z)3riv}30fkI}*p>n_Mbi;BiLYquoJ_9{RXQYtu`zC!WJNMki0;5^CvLuvf0nqqx!59F+ZIRaNT&p ziO8pBL-P+2j6vq_UJko%%N@E02m}QMQFS2*Uw(N3fBowx(#J+vSQzfVfB45Ty9aO& zsVc+6rXX}d0#bCXcsi&IiRJTQSIvSN=SiG~aUy{qVxkxEIp%=BxmAh-W>?MS@iX+^ znSoF)jaCOejH01gGRqr3(Sw5hD3)(l;Nyw}X^;BFqiEsaxvi#-&n1$->KP$()RbD4vfZMw!{J zLcGR?=hrpj<=p46{)Km8feOj1pT{am3eySIv&*1XaY=WFsy+VlbevXvklTSn%j*vj4kQLiN0SJE1%u|PFS52A)LjGRzF12 z%c-iy$~Mm>PM2V@Q*uij58-|jr9nf)gWS$%bR9rjq7QPC5x5-!{Ynapia8jyj0@ra z+m@Pvs5WV7u{Rh~7X$isnYepuK)Xo}$Mb%T^%)o2%mmNdigPETkUl3BGxLw*^vyiD zXyvvn@`{YW&_%#fipg`+u>aT>9lUtirCWKwxk=%c@*Q|4*M{^%o7%3SHoo|li11mL z?3#4p&Eh3S6eM81TizV^a;-Dj+f{4mDcB{0g6pR-jxHEyYky zaX)JBjIpm3dA%vYkvD%6%$&u2&5#R|L>#L) z2uJUswH2^iUdLL!8Rp#8-~!)&^g2o?-IX(cH3{Jg95DJ}VT>A7>gtdjsNS_5EtK*x zY~0QPcNMBww~g_vEF{&dwlNM1iRXN1 zRv1sVLUHY{^wJS=!){1%dpyg5YLZ;f@JHZL&O+8|7jleJfy&AwIK$b=avIqP2)SlU z=^+&Ak07leffJGb6FDZ{hpct5`w<)d-|)d9e7Ns-sB!vJuI*D4)U?9R4}U*?4;gFh zP_!On{6Kmq@t-K-n;f*GTH#gSP?FdUwbjAGn1WS14v`jZpG3VN!R$$XBu}f(ehnK* zC^g65Hm*6y=VdGOJIYX3^eUf^myomYU+{6+dz71;i;&hjG~Dzbneto?x3jW14AqAYp+Q+h1e@met_ehKW9t;pW|DPrPgp<-PoPMF`vDwgwCT}IAZ zjfl~*tu)+fI*jsGWhdM`{g;w-D1H+@KDY;|+MW$Eig&s8|9e*NP|V#Mtin^);SUG% z@#+@FUiQdj55>+8qc&f;@)evy?AWo4**thA&y61+h_6Wu_c&dxMOIn{va&Le zQ&xYQ;ttg6b5PvjIeC@O;0%^eOG~>$`P-Q8gF_95augPpP`>%r#watR=ZDGH<+Su;J_keQvy|CQ|~_|+C?vpjz{ zNf|8fdUNxZ>$^4K_#(tGg+kdqPu;rK#C4X9gs220Wn`na*?UhC@4IOU2}mGj#kI`? z+MVc_A5-bA0aveH8PIy=%DRuhcML5tX3WFgFCgcX5s(p(5x5NkGBJD`a5^3eo-`R3 zFP>){iobO{bnmxG0!w4)Bxe2iFNkrWLeydW??yJoeaQh>!mVj2blxAAR&k%5YiwtuEQ{ z;6{MlDOB18^cY@+m2qKwc0G^CeZR&5OPEVmnGcG+^srsJ`nO1?2drQ8a;WqF2?e$= zgp0!TgthZKS}EPTIz5;qdAEvElD)pk^IQt?5~7}x{`AyEg?GY&^Aewd(;wzDaTbC? z7a*0~trHWWp?7VoI2N}IZ@2t!Japy^z?f&@OP0|)SK%E%R4+#K=Kl*O_49Z?>3uBQ zM^9e1TgiH)+Wkm&OJj{w5Ut^}ch(f?S?Hw-y__Ag!@&J#HW8) zEY#-TV|UGYUxeg!8373abHnEYjznzsMZ8(d0mQ6qq{U|7onvK)lCE{&_|{~kE;^2Y z*eo1*lLT=Z2P)HaIR4Htq4#g6()9GackR!(#xK=B$TrDa2(mjlQ80whJajSgTB zMOd28KC2zT8s(~F1o{sFM~ejwRFUc`*)3+ORCouuK^3b8v!xwb&{a8U9|!lPl6NTM z@U_o^LcZE=x53iltyd5Qo@8%vuk(58-Rn6jFF*hMG{j)@NJ!IXgi|(mOt-r#yv@7o zUEFP>cad@Ygo#qj>7JQrLfW`F013X#%uF;bnTgEG=FTQaXk}+4VNU9=+>@`|S(?i* zZcZgK^0JYamxX$k&$}f_*x77f?P(}{4)d#(NJ&&<*NkUT-RWXxXqny5Va}p;(xgsL zy>_D>+jf_bfX#=&8R88o89E_uoqs z^ZK_Y*}9B?jKD}iKqiKJc&0-in-0qt=XzMG|Ff$|0B_%x3w_a1*u;mi%|>rsE3DO4 zjE#?D%qh;Qq@;6nygw{O#nOyLb$m2-Z^*@g0=~$8p+Jmz51!w)2SxO}vY9JTZm>a3 zdCuLdHX%Ew6pk5MSa$6|K|wx>IFqscd$Xt5%O#Qu(o&}HZvmmayAKeUK79t_;^L*3Tj4?c<(FUffmPYWP(r}cSceKe ztGvUwLUwsRLNy|mo*gDmV5&Mwk6S|-cI_$S9wp*eJcGz+GPERxE8aTfx_5o>F;1C| z!6ICHeUmBymCrJc@Sa1crc`qwpONPq5A(UiI<1FLZaxE(i5|p`^RA`e0&GdLB8T~m zhJz@=^GMauCD-&R+i-~9#IbG9t{DsFV)vTgAba0o1U@|%8x#MT>-0hn@JH*uSMi}) zJSExQoZlf%qhy$eSFm@T%X`_zejBalNeZ`O8@-R~8;`NCd~Va**UbIqvZGW1nT6k% z$6{IdKclKO1Tl?oApCDa@>pQ(aadl8=gTt31mByYoo=0ZAB(1SZ4Wi#oTAbs!nAbsA3(HXME6R%R%C1 z)!Ntb%Gw=p(J55BdWQ1N)fL>g2RUnlu$JKK#XA~Kbe%U*g5TT(sx&kk5PVWq9mjcUxT-QD?HVK&tw!M>m^WRVkqrFq80Lu+9}o-vY_Le*VS*dUBMy?fVMGs=$Za6K;#v9U?WJ6FKc^$r}=Nb`9_K_JUCk?w@OApMqnr+Fp6>;H-}=w z?^T<{Z2#j&KgQFGe%5bIxNQ3pXBv!9&vXqS_f16(zJv+MufDM+tTdDtfgG|cF|Ke* zJYy5zE;&qiCD)EE>$N=|kh7dUjq!m&2%Yx$?P}=PV@}6)Jn-N{cO4hCZuH{`g=2j=4|8W7K_vdG59Y1+j?;DXYLjg&o;}YY=~4 z?^5}I3BL%ez`K{%LFq8y=>#hdmo4G5Q%ncuv1iP9|6no{^aeI^GL$M*gP^vV!Zu_t zFU89DSD+h%ejnMES1)-|~b^hz8xGmiw6SCzwytpoa~(YUI=j&zT@ zhNBiqqvznzvNutX)Qqg+sVFN>Cq;Y}c}Zz-=&0V2nu>X+ead(Zc3LxkehN2kI5Fu_ zs?l{fIgEIE3Q5)TA4sY}cEfgh<7#k0+*8`wF!MgN30s)Yb=zpchXo8p@xmsQFyG!I zjS$@Mf#tiP-l9Xr#tN)CxZcN$Slri=5Od}T7AoyH5Xi}>$E;W>r26d!Oqh|2W0&8P z$lrF=a-*T(Ih3eL635u^eBc7;p~LzmCKyB4Ved}fgN(UYY>30h=_-0Qmry~d5f=4} zv~5R&jmkq**^`nv4->Y9;H&rJJ63VqZ4rCAwbhO}(NEnrUsnf(cj(27Uou8-g!?dm z2MME*r8|wQmLg`kK(DB zuE~516_TdYBY}2PQ;To$JM5~JUGF=0?krUu|BkS*zKJO(cdS^{8b+-rzM~bh% z{u&z1;D3L)+rG->Wdvjd1_pt_{M9)y2=uTPF+($OVi1}yUg%-Td!4=g0C!)sCY%z} zDJky%cOr#ZA(guj6GCs~zL^-<7hUL)4L`-`yC#KuRH2+%MqmUX@X$jKVb&}Sy{Ts7 z{CO+t>gxDmD?B6RG?EZ#p(kyScD{G;wx^v}&O%D^GS`2dn-mr{_%YjUQrMlp05Oqg_%fbtvoc9Y8*P`T|9ySG1;)6lEZ4^^b&7Usz}&Yc)S$6 z`#Y}%F5P(nZ^hI?_grcDpSna0n1QF3S$@w~|Ob!!!jEu4~)2!=bBQy(F4 z*XPQ47Y(8J{9V_77uCx}hbID$Jn{(U%$X}mL7h5PM|oc(XO!O7#^!VH|=I zHzAE`Ad?^EuI>;@ciT3({9r`j8a*nFpPjg4(}Yso_3Ms7 z6<^rXXhGtM=gRf#*FC##vs55hsQeyp>h$g2b~)Upv~1-lSV}$r#=|ED35ONoecK;xFSSDs+Gz8nb2S?2G*!Oo82-Po|1+{QzKP` z)Oh#EKCD`#!Q{0SlB$re0p32uv=-JCf)w8a43$ve%E}O_tuA$T zCF0)Dpv1;|4kfVD_r8U(@>OwuLZ}qKgVZ_Be-?^HDxj#d+ZI?blPGOZKdDL*rZv!W)J}f~=K?&nfx>8GR zF}8hpR@!h}I*Dy>w2yy-4t9+n7NhFyCpb`e@)kfjQO!CmY(rJSzu}dg|AwkdqCu>? z@I4gPp7VaXu)gd!vha&#Suiq7OKl0Z?R)`GXO>7GS`8n4zD+<9y$WE@}jgnidOTOAJM@5l2i_M(A%T1J8OFKl5f<5xEQ1_wkN9E~`zhw*I<{?F9ox2T+jhrxa!)_+`0hCW_Mg4isamya&6-v79wDFcn|;*2 zr6O-1F{;Ib-m^Rz06@C>_j)H)tAK%R1qW|qI4@$5bhKt~BPNGo4+#!zr0?%G@^J^= z1$sO`ic3n5e@cQZw$Q9BF)gR2>#Qxs^KH0ZuK%Rs+XzJ9TQy@d5oQK{Mh8MOOj*@; zbye=bN&(wj`5^iws^Y$$^V~eFGPSOwft~&L7 zkT=>L0P2$F$W~0T)O-&XsSio+M0ZR+nt*DNn0z1b4H& zvX-`6ru5pPvAMpHpbobiTM?e!*MLw+L~V#)Uz0=5nHei(A=JmC-R1_|1G611%ECF8 zt3+m9eAQ}L=OrkA^3^6cDzfpYk*%fjS)@okD7uz3r8qb5}UikieQ5iQ3^Bbqzn5TP2RExkc#gcC>*I7p4mj*`wV+pEdHvEM4+iyZ_m<^Mp+t% z?4P2)_zm$6jV)RTDApC^@*xRrT4sWF8a-L-Km%daXCghhbss;zk6B06?Wax4a z!V@{$gY^pwNHYk+MIBcumPYY)L@3wY$dChP(zWm3m|ASz!CC$)q#}RgU0v8ziw9wr zI7n^WmLHjp*zwjwsTJIoTas-8?}Ws9qk9V_6K@_C>JSM?ecu*FlG5>YpLJeEo>73| zhq0TdggR3|3|{GlR+JKloRaLLaNKtsbB#wf?8+(ms~%yOOLO7x51r`ne3WV(hNue} z?2i~Eqf)BY7W2{o`k!MIaTZ7h7q5 z30xz+TyYj$ug(|P=C`9z@6sh;HV*xnEUD0gzcXjwFqh@5lgSDS@X_A!Ji@{Au zu+WddrId7Z)fcl#D@d9*=zO#*1p;mGR3EGMY4=Qf>BRWXxp|$aWN74RT4@=#0TiHr z6$IYNn$1Zoww{4Qq1ukk2P@2o#EisTrujICG1_``uoa6OJfE7b*Tc4u>qLV?FC--P z-Jf>@5#U~{<&51LuEr(h$;N^b%Q$?NmM#z6%hEpOz>B3arYNTuq_Z>e6{@pQJ4>$} zRVvw8@@pl$uBJ2S=MroA@sTwd(pi}k~bgPmIe7`8;b=9I0qBq?6*P>T4Jvs}W zyY$#mEp9~o^`kgB8)}0d>fq4G#Lj%?4c+h-N@ND_J6w&ls`1`;aw~Z|3gp$N!t=ma zoih+m+H57@5QMnKc8LQcm!f6ZiMq|XDcUgfFTq1_w)csBhq|n%D~ZeCyFUx|!6*_6 zc(323jBBgj%-HLz+Ez`rL)8wtu7L?`CWrn!YEoZX)+!Z^&}^{vqm~=V7-2ZTEp_@{ zMOnInzdmk36?fDki-DZdmARVfb>f$@e>S+`c8ZFB~}=Po{Y|?IHO3`r@VE$O2}kBJsVQ z$d2Z9`UaG7`deQm_8U;9rp(J3gu!b_ZoSK6u|sjUREZY>v%579jg9vX{d6s}=CD{y zVOirFZpZXuocTC%+FA7m@+{UB-K8-&A62`Isr1y^RK)0t~K zD#Y&*;&>7JStS^Q_b}tej!xskft()x3x**VlDUWZ5$ zcXx`i=3m#`CbmBzo$l7yp5?gENJoz3o`naWhNxyV-5gJ`Ix&8S*Cd%z0JBDAQxQOP zQ+?S#IR2`CKTIf)?o3=!V68lviF&-M{f^dIZxH$s+RJ&?gqX(%kN1=3IK|Ez>e9J& zJGkqynukiu#f@2d;%_H(p^ff}&5pzlB*KZeikvXC|E;nL^4`?fQ%jE|in;B^i=VnS z&mB4WQ1PBDUU=&p2<1eAIahm-DzUo>^>%t{P#7e{xI^>48f!BL4U7`Y0uqiO!dw_B zYG>s@Yhi^OMKb^y<~jvPY_ztacPLTB>(dK3;va;XQEWA1xq8PvXFntSF5=jyqS}5J zcUvd(I%305tjE{8?V+G*%y5r&Q*76B-+@|;;*=QzzLm?BeK5Ax5=+3M58Db%8K24= zl+1tG^{h;ME=D!c!Vl(}I^h$U|MRp?Hn%L*ob3G4ta2Fcd%*kr9$veZhuam-j!xIt z0nz2$)UXkY(=XiI)P$Bu;TS-z#JCe5)0rN$+DLn<5PootE6hZ3B3X9n>WHTi#gN4+ z8CvOTsQ6l8irbM!w)IVtaChTyflIn4JL#B|cX#v)Rh+Un2ksX|QJ*3s!VoIS400lf zXMFd|ek5R^CI)r|=K}%(@WnseLO_q05M{vC z-_&i8R@qCL*(%I{pPx)mAsM$=Rq*U4(DxKsB%~B+9XUWcl~y5$9?@v^<{1a8A-vOwoc69*#oT40rU2!-hvJYC%)Vt6EvU1`1ZY24!bod6@5@4 z$wRT~FER&GcV#s?I$x?#hqDHoUzkaG)#Bq3!3kB$9=)8DS~?EV#nspa0*KFZUlFG)(J7<&jRsc}Y4Mnqk{0|(3dX^$#tSuCenPM|oh z+Wj4`HZv6R2IH2bzfFmf2JheE0uy9s5L4QQW6ZP6dd0)j&}wpx^=JYTas;`kj?420 zYM0c{bUJa5BkrvT*UV4cZjGo@RgJ^~EooJ+W6icZ`ghpdEaZdYO^Cio~Brbd|5H%&*do~xQ zc_t8Yxg2!Rt(uXOjaBCGc7*%{9768htNJTw>4m-!1!jNaeONx9w#T!jj*0;O^8;yD zgknaxiUgm>u0lAwvKxh!=RKgY0!dG2fDvXcpUJv*uoR z1Q*cs=*NnsEd$xJGsT6B9G6vOj-Ufq{0>s(sck*V@Wu|M}D%CB&o|p>t_T#8!aW#M1+B+}v~0 z^1d~g|6*Dx5@1&R{?Q7YAE)A(_&!ua4w8N)tmN#D$j^D(A-V8+_+0e@e{L91fQh0| zrX3;YI?9(D+TmO^r^QuOp(=`c|8{=o=LDFp*tA?n=I@VEgh=)HSi%tx5O)kcy7Und zh+)`_-5oDB0Tp8e*6G-d))(-YcfQR-WKs$&ZiwckVl%&Aw@Nz9_i7w64PN^#N)uSu zxY}y{GjELnJVhsyQzK4Z1Fr#<-DTFrIE*B8LgKdM!r@Xf zEtAwV3q!&2&8p*mx77(NB=)b)t>;;lWm!$YSprPdo%ePBbxF5Nj>zc4L@A#)yx?t8 zP%-cQDgn_Yg%IRevho6cKrpQc;0__owsF5_;Y%v^O5)?p154o3|Fk8rDdP*dF`P)| zw%=x0ZANq=kD>o@gGOtby~W+2;G`x-%jvSNP_vLFh-P|#6a+@6R;l>7=};&;gE zg@`zx$;8BO__24(h*@rTwb{0}z}ZIO9q4BWj{F(JJj~c-t5%s@NE5s_8l;|dlGF--S}HK3!d6)np#%LZ8Iufrk*n98G1;n z*2(QTWk9))uJne?n4~I%hBwR%KfDGn%w5DiCjj77Kl}jNG21(xEAUjP_pN73z8tpF zN!oDxfy`0LvmyHqKI=$j#D-wMTNf30PvHY$Okn$WF)j=gk5@5mu+^}ar?7~jm{c!_ zRNn1qFoUDI>B&0sC<;+o(X1e|4`P!DO5+7#C}&n_m>lc z)VQcIXb3zoofrzX*S=*$N+hF5O0$0U3crB-n*Aa^M)y(C?>J+5S(z5{TiZm;=-tqfCOV?_(+Qs27~UQ z?UX~sK%lAbP2m`6NLOC&)n;uq)I4{p;|XB_)+|^B)#%Ljoaa`x`z{ML$%e$9e+3U@ znbxnOa3&D7k`{8NHII)MsBOILpY}c-_5mHleZf$-*-I*~T1U^yo*hMDbRVlm*}1=4 zCfsXcoDmwbn{61iE%THoI{^&DmwZY5z_YX0j*O4}^v6+>`jHzzb4hA4pzw7X)k`@Y z)Vb!~(pf?QiCe`Lu%^i5mbPu_9Z$c}J(vzovdD7s6x?QDFyQdSIt&3$C78mNOLT|T8FhuGTPtc8Vg!ZKJw z8$@tVwSEUxfp_mxeKze$e=vZ+KduIui*WW#=n!FFJPRb~#S^kwB`Tbz zGbFpkleqzmRv(sVwQQOlm1F7WLy-HqV)h-LQ?aSRMG&yG5ow8b3Q!S3s^$t0+nwL9 zrBMRD#5W_~Z?2Qx)c6H9NPI>7=U3s@9R>vOt7b%{?MU`osuH9jfJ#50+kmjx1ESKt zP2w>=9KDW1&AKA*N|EN*_G<78p>CMWk!7I1_B|N0*PY96@kpQzDSx^#Xr7*CNWt;X zRqOTOhGd#`p1NW2M=&TRVZF*EPO`;IgpMDC_P# z&EBQMYAgjKZg6eN1YP1mu+HdbdgZKJL%F*-9HGm15oO>neV58TSEqn#)_s=HGMudV zhsg0p;jzBFKpl_2FpV%>9ZN~?Pf7~Mwi5B-u&8D6kuN*%9!<(C)|e>X%82H+x7mKd z8u&iU5!}Xpzcg(BIkj(_IhTd>{eZIQEE@?9weX*j%N9^jUNmVEAW|5Fq$lvRe#pY00Jw0_UU zsSmdyzJW8Up**#??*;j!(%VQ!MW5>6{-v&ds^5aQb}kJa+4&U}dQZYJ3e-Xotm87c z(;+oor!MvDMeZ!`UN-EL;2UC^ZTaASLCoX(tE&rwkso%jjl+f`0B{+0wFnqa3nhq8 z5&F%+!GVe3xWNu}W&y!X9^;vCQ~2A8m4xTReumziQv^|=VkwQ;B!ZOTlgw<&k~Lnq z@W_GX9mjvVu(q@ggQeA5!eA`GQf6c8!v$xvL?pt7@0#hCO1D=%w{NH@#0FlBRK~al zl=^DjpK9jucVkc+|6bP}?+M9Y0YF%^;kx4eiqCA4+Cux^S-(nn@LcV*E~KR9iI$Zp zOyFu9a?I}KoJU6h$1pQ6y}W)%QMmFw)NgV3KGU>=@p!pktB>Z)1{)!aot_$SCJ(=P zvJ|2YrD7{9K}2yDkn;Z(vgtN688u-=851O)UOYK9CmEG0Ns^r1z_hGKw`ap1uWJOP zn}D>ocLb3=P=pK@^j#_iqTbsu6EY+D3nSrJ2>RGCs9_7G7?6Ryp&!_R?S z9w0$|jc30@ zm>l&V(wIP$4|Z#g$JQKgET;5ctGKbpxw{sh6@-lH+SK%`AIXK^_t1>xT8Ob`D~uh@mmlb!ih;@cJ_wzpw!Ft1bm$HiV9c= z{U`Nr_@g3_+Y$aRb_faj?S-e&hpGi$Oyi zYn$;y*65DxX>M@0H77q+wLvJhaOMrDLfLcFQOb1q&ieDb0gl9hV6CVL|91?W`%f&1 zwQfqPlTEn^?1BEcQM=Ws??2$V6S6VsqStasPOP2Xz+o4k$~gMh&xz1ZlWlYwYF28D zr96d%3$$^eZPb?MGrYl??;h(1C24 z4 zs;CE1N1o%OqUL}ORR6m67OZD>_?k?AFF+E8MrdhRcjP?FixiL^b4davBT_UGgrjh4 zO#lg=3Chzf675_Mpa8yK7cz49_&wJqA7wprBwXYY-#^^HmBz;o5B}^u$X=p;?Y5~q^~QcGd50}weBHMnw4!6s zi)+e5Fv`dAscO%(%<7)|EVu$Hj^!AUTUT} z*W37z7y4oRs}-j7MC==~3BaK-RC0}Pl6L_E2bYQ=@HVsx!@?@do)^Ag9h*upn(vqPzGdBQx%d790+jPGjBhQ9bRL#9JIa1@#$LX=mLRXgZR3%9aeJQM|xT#FBe{|cO!w$_p{Ix+)rNAKIWopY-h_Wt!Q!)gwkYnMa zY`24-0D3$I737{_{cpk~CKdSo7o3|oY&j#ZZ8v*cZ~cFHifH4S^tzq(*n$La#@#%8 zJ>lGbV|RDz$EU1FzR1D;5z#n%=fvEP6{lpU+eeSoh|PXjHHyk}(0k`(Rjm+RXLr9t zm1mQ3+AeIIEp4`TKiVc_w3sIyKbHv@GZt~Y7ZnlXlZ1bkfxN{Tq(1dA05^UVC!A>P-#49vjDc$d3{}-yfRzUiJ&yaVd{h=XN znZ8NtDu=?Wx^2XS34m`x1q`oz!A#O5BP_26_cQ{Q*WZaf zmq(;fF|giEw(+wYr6pe=PBXCRuNSUTm61CQEW?Gr$M-p-n%1kcIz-1G=GkJmO1klZ z?Vr~4ewULTY~}X=sn)*sr@_W|eU)%Hd+y{~wd(=PC&r5=)_$w%f>1l$lNov$}6=Bxzl zzXC8u5j4tqyEjOQfzMH5FC*MY*{$1Eu)SMC<=uu5)A-7F*-26Ch(ZZ!p~=5ztQcTq zz8LlqEQA!P(Mr=G6Q}$og3;ewf~217=-QVSF>gpAXpYTf6=0yzzkN>RpEZO=IxIpw+kY|kYkU?|P%!UjXV>mcuXWE@* zWW~2>7Uu$ooXQ|%Fd6Ui?tOk9`3QqCeXr$lm-{%{>2@nElgVK(Fs%I!JQJ^P^c9e^ zTe>Ij#>M7C>hzrbaQpUnKCfPY*^>1CL8{s8%TwtIl37($qmISwm%?w)X^o{|Hn{z! zu^*Bv;5pcIV$*zupl~FV`NkXg9D%IJRJ6KGjxlX^ zTtENb=jkSfw3?6Wy)X!3OB%%YuNB|vh+5@k8iTfn`neI!^I%1{=6vGDhRBFYoIY%z zqXu27`%pr##LPwAP$2$v#c$;Q6i@liN!p5t*5P8w)!5oF4x5t8E~B?a|;ov`6z{lgt>mc5?C@<^1MaAk(9rT1qMU27?6-r z!L!QdE-7Rjeh&6*8OW<8k250kAP9Cig5jd06ctEr{-HI`OVz&11GiE$d7iD%|=k6ce5W#ft}t>r4!RR~)AsR8Q*|9em5af+X~@=3Yve!1KQ*_mBj}O} znBtzI3nwSbfoX)OiqP_JJKHo3oa9YlqmQMFUuMy%DB(kAdLYl6Nl`Vq4lQ{7J0ny} zQK#AFmkn*eD4d0n3R4VQ8gBx*$v7uXB7HF&z>jdSS$w*igBY4klU5fcqG9|Km&!P_ zHkFn8`@nAPZNwFI@u4f)ug*Y;R}GmwmN~@5K=OU(Z;Ir;Dis~>#68p=D;T-kD(bt+@^%0chTbqCTM=f#m4=lG$$^5iX1Mrp-a*nbu93-wow`=_p)?(tl} zDj}+mW(1T!7b@!CR~^h~W2ss(=HZk17mmU~2E)u*GRWr!!)GySxnOc4*-N|^=bvTb{!VEhB))tKzgW)4SAB&SCL1qz!3r00%eq2nNnrcA~z|O=*Arar}q7p76 zM^2cL`Y{?pKe6BzixJ`yh1$uDv_ z)#oMHV$B*DOgt{efrQVxfGcsX9%9_%&v#5!=NFWhi8}uKK$Rt577yj$lv~&B$HXj) z`x_Z!Vr6*ADGdZviUnWaYn~{%t<$tS_q7!7@K9m0z)+;5vxamj%3=u^R`N1?e|?zD zsf%%DL|iNKOE#1zMKEmJJBH_M-_kvJky1RN&bwBSirWqQMS8-`+D@F&=r@p?n+PpI z{6Ue0Dh>4#c-ICq@3%T7O%q7d4_$1JU#*-{ZNIlrOMF?ewMAd=`Ge)f4C|s6Yn6{lyxhJiUhaFa{e3@@4V(+kc-g8C zJ5lc8JF}X6NaQYy@XLap`6>cKF;C9Uml;n#AK@B_!Cykhp`GxmM%?6j{Np>kZ{VxZ zuV4PCI_4kU7!vGi%BvKmTi}`ZlZbR`sla7IbdUi>7-Yt!(fY{1By#^vPp3)~RMR1a zSL(E=M~w*&AGp@)40D#bjVbHSq`ay!$;8(@!$v}iVV}`#!?fL!(BJ7M#>B%5uIYY5 zK0r*(eW!APxE9;oWJS>j)+H3MFF7?y$5x_hkKwCk>FRr!rDX+ESWvdS<60B`bYPbe z5CvsDh5Fm`agQZnrf3J9!$Q^dUSZ(2VhCSmKK6b;U>;rKzHpN@-}@S3p!iqZ$Tq@l zkNBd+g4ZjImmwx{cjwzXp0Z)*p$>UV?fau2?&V<`wbQc@czA?b#`56ndfC=Q~*P4C&=T$?ti#snaPQeuO7nTm9}1E&F0)XHdcF-SQYyb-T*HgHfd%spZcQo za?2rBZ1;x4c>fT-A8|#}gL#-8*w-m9tchuQ@l`LuM>4+8BMsFimWid|y`uSaCO8-yONP`Leo zKi_Bk{jdBB!e{BwZhRpj*P^*#a5 zQJ|w0x@Kk&aoi3IahAita#wLHIiUzzRoF%xYmNIA3jsj@)#{eI zOP7}-lpE`TRJ$jYPDy9+`NKY~KYINuE1m{OIsy|2v+p}xkrlAM(RGRFdyMU7SMQBz zI#)7#<>s2)2vuc@4?}_YG73~2Xg+Scd;AuAcwkm)a)N!or-?t79`z;KHbN?zScsbU zX}1}Rdii%htGWvyJy?oxZpyfOfTr5m_eS>_?3-TEDEn1%oj^AI$8Xyn-#uLw9NjYn z1^XBuIx(0X7r$oUtCE`nVau@VoZm_$qSD~FuzH{u458oxH(IfTov zO+KznChB|L%<4Fuf2_SxH7WYDP*Oa5c`?RcVW;&jhcF8Q7qs7>pDW-(egd>;b8aYZ z%Ep@SAMh4z0EfDV9rvp-rK>h)(35xl7CjGxJGxJE<)bBv9Oc?u^Ba7NzbCNzkco9M znb_@|Uz)s6X#f+M4$TP6i1nWTYtQT^_0c!Fr=WNj-h-HuD;ysjwxV%odq|X0elM|*=cN)1BN0=#*~0Kf2g{?4MP7B7^=DL1jUkbW+e<@2EF4eUFNhQR zk1Tg3H&$mnqZ+*zB{$1Aeu23iMOs7NkCmC?-OZVze8XeWnnv;YOFs@ldU3_8@MD2=A+LRDAra)O<#!!Wmzg$#!uxHHV|-v>zxpw!pNo9eZyO z5D)|Y`vbF1*Pc-(9*c0i=DW&A1bgMbyI#w;X;IC027V@aM3bU_Z+@7vJQ{;#j&M1F z$ee9@V)}tC2rjtLj(s({a#;mM5}!{LrdfGMgKCmC@*FBzP~5f+m4OdzpQwb z29o`fM7jw|?JbaZT(U7G_}YKIDoiWpA)ZLWfwO4v+_nL*w@2Llh!%uDv9rKRP! zf8^i*2UL&$Ppun_Zsn$LA5wGm^<<#Q(%gXt;9Qi!et$#_iWr@YaZ#m+DJdo9>|b!x z5mHTnrO4x)MI4YWtC@zc_$%8_6x13dB$-~8ot+0ZvqvCjS!8+m%-|8=gv!~bj6T~7 z3OcZEK81gx%|1*$L~a(qHyIJbcc7PzL6+#X&v08K_8N*p2Ze(a8oPeA6z+& z0zP|r*3XyQ5eY9=v#D8E<02K?jaA!b)^UEfh4l_gwz97`JD=BxQI3*)&rikoN3h|& zUbYwyx^Fmcuiw@RyvPoMyuo!gC5)y_8kh{UlY&yexq`$+peOcQUqo`#Mp7&QV`c{1 z^3~NHuyJvJMC3@@M{`=o_HJ(CZg#k0+}*nds#a|2l4wtm`}O z!tOf@^Zhb&5-n7Bgh);?JR7-&ip%3Q$vkm&04O*9=yGNBe%5z2VMi-Gw|{?nwtIU( z*jyZV`g7!YJJlwe7cb(uK|&axmgopde)H_1riOvb*J)FGq#dc90mTSJUMuHE7qX(! z>c!w{#>cw#jZe%7Z~d#Dp{idrQvdyG`qJ?4c=N^I*@@u&S+ZZ}->($2_pt;X?xg2i zHT07M>yaviXH1mL9=rn+o|Z5A3Aa1n2)g*emhG`IF+;5fb+sUc!Ne7q8Ezh85GY0k zvrDg-PKgJIcqlOT_Th-Babbpb$U#Adl}0pI36vpB8Z_zMjcGYKp$fF}_%IySvV_dc zzj(9(G^0I`2iA-2F3)o*?S3NQIjFMPFK^z>vTM6id<<25e+){Yl%%hiJMiNYl6(x~ zhXg+(+1E1&zmh3XfOqNx%b{T6VTnCwF4Usv5~Yz6k8DR@knI@{X=vLgdN{<`8o^)=o^ zqwl}{!p6b#|LVpU)q>lwWV(=E8A5Ti4<4$e7(SCAplMC}0^ptg4Q5+LMVF)Mt(6C$ znp%H|I5~&Nt}Z*;v%_6=e(QD~a0tTYZLd>DiOw&q2(MU|;8hR&vtO;4pX@}XqWx{# z0YeWk!XKM~z0}p{kjOde;l+#rjl+jS zr)~ey6f$a%TS`Yl0VfC}kUSEj&gnpYZAodyGfOy3OCu&g07^UEagSsLX;$AYp2FHy zXN9n(&;xiPGBPfmM5D3Yk=Z&HUr6psE-IrMcSi9llc7m=57Uc@R2VseQGPDL9$W`H zk)2vjMqmoGy`zJv`9|)id|%CoZetH-x5W!~G%j+mE4P_`+z4O}P;fW~9c1ydO6Gt5 zd_~yXU&~#p*(mAT>4JgUH-)p)3xyhfDJf0K90UKjp|r>_J~=ZLfjJ1|h@eP$WIP=a=P zd_O~aVFs-2g3tYqRJ+Fq4jz|MEOpzyc&&5hpJ8sWfg%>rVhkiHwSQ1t0|Zv(Z*)&K z8}tx49QJ?C&dj_GX}c#pAraDStHUxJT!}DTbH2j+XLYy;19Ivl+{3h_Zby|ZeiUdG z=9p`2W@eYx9u{s-LYg@>J@2XMd2N|+Pid*VM@VSBZ`u?OFotzYM&9f+eanJd0)1U#fEU*aFwR125cF+cB{{V?Sl0>1c ze1h2sD5{jciwinkvG>3`#t`r2g%>gHRMKA)FHSL!FWK! zCh0#=?9zUWV7g$YJEDbv=M2owI%;>hFSdoWHXA}s=DzQkH{K~L?PCu7Zr5BMX>V+V zJSZ4oWMhN9e=#JXFSfNaWRNZ)Ee)dyHv;Xi&Nre( z-us`)8Gs+^8CY3i`}_MpEcbc-d+bMmh&g0d!U20A3}Z|c;^p&YlLKI&+#p89!1s0M zBM(hkcv-<-ZM9jTqf6QcHe$~Hjr*(+QP{WJ@)zJY1O~fq@EnPIJxXw>~clbCj zEsoaXrc;sudS{oG9dGe{_)%*NILahsWcpo|seCxzFJ)g}?@t7>3!bjFTDrhn(E(9j zMjr-{;MxL>;;nH-DK4+9zyWk^9K`Q8i&LR!>HZp+=OWZQY!M)gt0eN5nNySP$^$Q_s5tcg_U2dl0s{ks_LCkz$`Q2ttsZ~6>n&tJ zb@%@M{zZ;P{WcObv!J2Q#nTfRO?t$k41}t?` zes`__9cg6tlb5OjqKXYqul>E4Ql=2*`6^T#fq)XGT}m7U9X(=ZD3Tfvu%4~8S5yo$ zM@r5|9nK9BdMZv>+2`wZdSfzIef?erof+xsLZeE=J*EF5?h2y5!Rk+3JR8xB6reWl z``p(rJaz3u9GOrc2Qa|PFUbGp5#09x>Ek&iyPMGop$n^SR~YOXJ^w2+d4V2Dp8M6+ zRX8SDa0rMwysx+|?}{#cn=3g3rmc|b*#FszN6>G-%pQ>H{R{EryHvm(E=NXQ=XUbW zBcE(eOZBr+Yax?HClyo(@qAwp#u=9tT4!*QHdkFv)o^2-41Y0 z#aHGty%KwG^m}aOqRfh}gci2MFhwvoBt7jA9|}^FlZ$nR-swT}IR0}1S-NfsxU2$Tb;Q{Glon8nJAy{!)vO5g;N_Y8Z(TjX!yS5oiE>;)+#Wg zH>)pwb1X+UYq;E&mXVV1%k3`lPFVexc|PxScL$l?15l^L#E<&rgT*RW2?l*&kU%!K z@mk$KGtB?nbn8%Y>QdWr`203%@5)v&IXY4sgGOqm5)xtZTCgK~{nt@ZG9Buz4FG+> znp$-7?cdTsh(A89vTRpOxD~t*0qMvk^?6P3Xu!^0S4L0$t~(3BA^84Xm}9Gi=`gN% ze{iS{hY(O(VfhJ{F)|LYSOAoWm?+Rt{n4Q} z@IwnNGxPjA$Q}~FC;!D0amdQb%HCOhf{Qh!-T1H0B}p!59~ko~j-rf*Wkltj8nFWZ zxHyHS8R0V&x2KD>kY{Kqf(D*$yUy6n^cHcx!zwu7hYJ)myy#)DEjFoF*X6}UR882C zH+Il$UO?Qmp#WqP8%P^Ff}oxJF%+@-)|bJbaCVYI$b>McoOJZ{ z6R7E6w#njt+T>;j#L21hJ<#s2U_zK*)q5~evPWrv$cGJ13jeM-F8uuM@ku;9WPowo z?PBfDC)2A0x;#1+KvXtIEQHT(3y3O!klo7;DI*hQq@G5$lNJTiklR`Zfq>_n8{!dJ zzf^m_60?2q;_yOx0>!x^WNXV%So~YjPc5gZ){*6TW*rR7b5G-Bfv!i1mv;+*n|{&( zDn!ECxD5DDE$7qsCcxR`fQ6NWZ_MerOv`b+|J5=SH9UB<-J2UQP5ZOIl;x7EBpM%H zXHaLTh8B1v`1TX1-i2Sm0W}7f8?FJ<@pRnw8!Vf*X=Vuawi1 z7IAo3%)rS>`BG``_MfL103&E=@obW~nnnI-i!I(c`Cp>;C8O^l1#wX~*}@N`ILCyT z6Bicg-Qn$-Z4S}VI0Sip14jED(ZF&e-D(WBFJ$MSWJ6Kma zJ-ga;5KR_k@hW8mw!m8RYuSdzK|=_IvXUd@;Q@wzPKIP(c$i(idF&CAUs;%K zOF|ABwc4DMBe!D%%gu*7fsFjQpUrV%q7o65Z@&E_1%)$8ZgRWp{f!v8rQ@ zAx|M%l(6gwgL$NTqxWsVwB(3CkbgfJ=2Ah;>mP%6;H^X@FWiNt>H*)^ky^VRBw(SR zweNb@5gvzMn%z(ZbQ*s1(Oj1hMxVR6`jGubT(JgfM9kwKjvV~#Fi7!=&BcT6)Z{mX zRbb!{Z-hO$kn=3{&AcccOgkGJ1>@>M4?6G18Q>hAPn*prGiU&(zp(~>U{Cw9`G+w4 zckJ|nCW-2Md1(iA*F88CRw}l;u#yZ2_bUx=d%x>!)B>g?N9gJyGks`jYW^XZTy|6{ zdp&V1A^vAM9Yw?`5S0VibPUWx8{kz06>E86?3W_Pv3?q&8%4nX_8n3|dr z6co%$q_cPaFQ8Zh!rI1h!K!wa4f60D+3o2mB<)_bcsUy!*uHvLbY!Rm`T?rz)~RWz zjhmWkiob|X#9m{7mWP21u(h5%1!+lfBmfyo5uH;DG-PT+Bmzns)Il~4#*ECTvkq2> z1hylLXb^na*RYZ-9rDtglllbL=hL7_kL>KbF|=M9JsZpUz%1_hR)rj3(79%fGEz}z ztLY+K5h9hU>1SMAb#Q*YF4Xkxz>bvC7R7VVUArJ++utTvD=owjjsh zbQ*^pI%8xC2t3iCr`N{^Pi(6lHKWm8b_@S!jI>@CNQJbF_&q_S1y;H(U+v^(-rq>W zVBE|NErCV7Ab^-`1(l73d2ME?`s-#TrJ_h)s0cpqLIU_GGBDaiE zISW5n*?rzx!6G7JH7yfn%KUmSE?EDacjgN&z0;k*CE_wUW7*j@t8I>{3)b%WK=p3q zsq>ys9Q>~GQK|3$0zM1qsgK`Rv*Ry#pf?>^ri=Op$0Qa?e5ik?0iX~N{ey1P#~&t7 zSXj7=4cykr>p&AE3D+Zh2Zi%TPfd+HZSKsJiL?Sl?HVl?3kwJ-ECIhyzbWVRgEw$A zdkx^W0kY4V$Fsrd70SWOd*G`2#%`kx0j-0MghW)ZOZVTALkFsk=>nsA%_hY_TrxNA z1YO0Ap-74^USZhfBN!HCEGt87FC#$8hlF&4bV+x2cXxM7Nq0A!ROyiJ?he8C z!O!>iKX}i)E)Vv@9W!gzS~K^WZ6+RJ0IOW<1LKIzWLxT|C*t&OpP#aLsn@z~#S?(? z^EpGT<>2P=TL{u%)>h=VZ{|}RD)kQ5?|fF{b2GNb&f1u`Fb_`52UPFhDS98^z2-Xn zis5E*RZ>|QE-9hT$IhXnvqnDOi^J!dfWngVe=V6>_mv-eFLWQUQx48}rrrG+DKYp~ z(Ann-&AfEPr}Yqa{r$|hj@Ocp0J_ofeV%vWei^Iyj#q;L!^6!Dfr*J(8z<1$dg8d! z?L&BVbv0>Ewq|1ED0)PhKXb?m<4H&)(A+KQZ>T@hKvB>N4YqDEuro%$tvC4M6 zvJDGZ`n9)o)iUDMs{dppT~W2Szwd7dbbB30L7t8-rTYd>a@11u>%iqSQmGG8x`yVr zN>P}@X?7s=sYJ5L>`I+D507&=YRgu*7Q44KvVi9~h9<-ul2@3LB&9z&>)|*ZYQS}e zdVlZe?4%w1x>U+DwP?ZIsIXP_QC(_K7uWrAQBfSnZIw-3;uFkIH#;G{K3`|t?$=2{ zj)=O1i*`$<@Me9C?t_F)s-lGUvpSLXj z@S~s#;4(MRx!zrEfwa&`>(oLf=+XgN56fB5B8XVCjRK~E0b0oyq^8381Tzh9u zg?deIxk@Sc94C$I7cu}`^W8x^IC*Cog${L?G;g8#A0`46i;UjhYhNth;e2zyh{Uk+ z^g1QkBa$0SmxD=X~;%VQIX<7(OJ-87ekiXBhGr^?b_UR!iRS6oimU%S*%(LDm!b9u}u1^UIPD0teET0xkTWkrAN-o|y}vlKw-aAyDQC z{9W&)HI#S9Wc-%AIK$FKTPUmzJ3T zsGF_hgwjmmKei_OW$*b@G5q&7pL+=xdajS%XJ#Hy1UWg?;M0PJ-yl8dTXBoZTrZ&V zElcN#{Bm)MQuC}@GO(EOX)Be{&%p?boe8|%Z(@JTnS$b20fBy$2k}30#ru$tkLOq`_F);EQ8Zcc?w_t_rbYaiZ;N7Eyh&uYN zah~L!i^ZaJb#rRHxQ6}Lu`ta3l_Y->A(#}?I?bmFjS(ywb1oDtC0c6A@PO8IEALRL zK{I;a`DPb^LmzyPx~(1lfcbef13Fo8;_l4Ci&cmh`}#ZxpJ8^_lU}cTv-qszJQ(su zbBp0v+2;ZWsekwc6AF}5Hm;iCPbS3WRB{

                                dDPd0is~dWdnaK(Ga_NKg>nF88*ZefVe; zR1x)kqn01pI7v76_ie?er<~G(7Z(?3?Pqz*wwO9`0M<-FbN{pW=R83=^i+L-vWA@z z;dzc~fAn9Wc|w6kNC=Dm@GEedvE5tuj$B5u10o%ZH+n7iY|Zu~&p^jK+@u$Sem!0@ zr-VZGd-b**bXI}YNAPwo9?SivCg}0eEC2csbCb!|*LSTUhatb^@X#VWDoUkS(j5*+ zfDi8gjPSBae@&F(j|mk@aJ(^Xa-Fu`Ucy`U{d+*>cgr%n1-t1dG@WjZm|gmU`Xh|S zl@B{4K6npW?p7@PiF=^^z^zlJFx6lmM#9i zzPs2EZfFVXdwDB(OhKu7NGmJEKz{k(y34v~DtO^x(a=IpyB_|2*>|+2i zl{PrJ7Pgeat{v#9`iP5()p4KfU|ZSPKzi!!4MK6gS8Q#811k5RzP^B;kq0Yw1dX0z?xDPeS^~&eniGzj6}JD-O>4Z6 zj(4Ct{%JpT8(j+eVnPNoUJ+~;Tiag`ITQ0Ap)w?AvuE<{4Gr%?!(e{y?Uo0{#?lxX zw0wfsA0L+)y70{1s=V`MXMKGfxnMOm**vHEB#oudO&z)#_dG?lU(OC$g9!wd<1~L* zpsJ82Lm8`J7FnhNvl<&>dAA)A`=i?SJ0QpMRby4ZB5la(CV?q$Sc6NqkQi#3mO%cd zQnj-#Dxn3fYEgWm`CQF4usOfnzfSEvk+-D_I`42(Qd13d@x>hDx3&a3L_B-tW#p)A z3%luJ|G^LpMx=t$LY#wp!ZkY*Dm3RQB5&2uL?rE0xBjts#Czz%OFm1;(CPuOVsJ>v zcLR$D@!DR6?gM;onZx(Dp&ggH9algR)L&D@vf^3L=I~Zgd%l2PQLcZ%CpTx2qB4?dIq~pQs{Ph%hma6;$@xfNQ>C z0u)GIk0ASdS)oTL$JYb$u9zx{&;&Oi{ z=i!eQS;z)IY^fkgkk2j8TGTdZA#<_rdC=TnTvvke5tl`H*P%*yu*D_ESy5XLrRnz8 z9#WlOe`yxG^%$On|BBt&F#3RQ_1iHam&Mc-7zg}^n3VJb-DbvWb~aIsHj9^O$qFLo zg%9Z3={jHT`j5=Vb(-TPd>ClxK0W78|Ix@mLh3bzdU}2~aGdU%c%OA!b#omSOB6JG zimKF`rShcM#V&|o@);*To9MkzT?VOuClnZbBR|litac~w9XfJRBh~S>SyPjzmDa7d zW~)a*&cWLN*W0-j9*E{dZ&KB}+E!Z33op=4LSp4#Bvce3ZAftk_CE=rp1*=NULv;(tIk3R9*Uch=;@hzH|*%aJYKI-lCl_Q z#pf&C28_AcnYJsXIlnXLE<)$Zev=XLPKv5jLD*2rB-3do&U5Jo-e2}0LKCnOXfLhB&AGc_$KID933oIGz~$)gV;Tp-v0 zN8$QT^kew5Xdr3-8pRxLvGYTfh$FfFtiBS4ioTeVcJ8J&P*-Qob|Ok@kc)t+$PWZM zY`+M1e_0`6sE-ap?6yYt@!)*p-;OWN&%2fnqh5I;%P$I$-R`(s^k7j`}XZwyD>)0IriPLds)_l{S)cUC+LzY!xyp|+9bB@=_C7c6iBt1aIvtEx^yia zMT>-Gth1$!T0*Ee(@BrBHXi!&gj`G@+c!u8$^TfKorzZ%G%n)IRq4>!(EULY3~cnr z0EQ5Xh)HFunx64{9HlI5&fiv$xNPE}8!#g!VPF3E5zSXhx5P|K8+>=?+HyZY{Klzk zfpm3`P^C7sD8_8%bfbEbexNiAT1`Hc88((5C(>B^2kEbhg?7n}PS7-N{#W z%V);JqCL!ubQ_BD@;`cC+CRh~ZfoyXy8jY<{_!5y*CM{{Y?rj*X{6i9hhGvGmm!X{ zwB`OGoLFI>YS2NfnlQM2%J5Xs!<$Aaa~q?GiK|Rn~}d$Xb}_i~q7AtHnP!T-ukB z$NBEhmYigTWni>iO%l#p-bvtu;7CATHeK))?|FD?aZNX}oSR*y>`+686kgsEW*xYH zU_dykuF=cWlb=ucpF&>>H#j)Rt(wQ+6)U8@EJ}tu{U6UL`_&67*Hy63UKnw?;zyHr zqCeoKdX7TvJJnwBar9lz`64Mv%gFp)1@Fw=&Dk~%ab;IjyVND^P zs`eKtbG-^WCp{2_Iqxq>(6>i6b5ap=c8&w@N^#-i1Lr(eGQ{e9gy}`zo@+U$If6fu z5na*Y7IbvJHfZkF>VhsZvnggZd0UZw$q#O6S!?oi?kM&4$uqbAN239ecIusXKz2Pn zlnV&~vZ!^X04kVNT{zZ&Rxa&0UsxYO&dRD^_maSNSD zGZ*q`sct*dN(U&79vTvjhdGg^>u2qMEQvblV6K;QktMBECnpT2g6QS`>)$4=Nq<%LPcHSIh zXdg6fO-Nn}NwDJsTI}(0!KPVHz<7EE-#fbb))U$KfruuH>MZ9NHgYN{^2!wU6{ULxXlpH0%$K8;fQAj7q@ z7g#sfkCMC6WQ994?12D?c03wMQE#Z!78DibiAP8n6dg@`b{4s8_Qomwt64fF^9iA0 z>cwSbj1a}Wm_@aoP;SPWAmWy_3=|9!1XR7-WdWmvtb&5}k2*s7ZB&uI7w9tPDPb2O zf-m~S!I{ccnr&y}DfSoM@UqpakRQJYd%GheRjUT!h}skrSB9;xRED0(s9yZ)i`(D| zvQjkFTdia&CRH3MDOJepzucxt7W@(y%_3VAkQSSBB?-I@F6Am;T}wcnu&9oyiG+)N zdOvq~+4+`dXagV`*|k*;7Tq=87_o4n?Ku6gsq^mO-dcP24x_bhJ%_m>5;>nsk_FRg zqe`Tk2t!L}#&XhU z_zy!!Yn+L4)tC+?;!GD_CM7wuROd5By`Nez$XJz<7}gJiehZdZ#wD zH@)V9J79DaezQHQCyPX)=M=@vw1k|VKGQGHHj7N%_-&~lXdn@2KKq?B{oT92brq$2 z)s>Qzyis7){^99vj<&aNM($SXr|qXqTS&-NJ-|?tOc3F+kRp2as7(Gaw5h2p$}yNX zMG#jUc&do62nWqYQ}D!{LVy9Pzk8)jo?Q^qQAL)tI#n`884208L9{Or@>E_w@riVR zKv*UhU#QU!nx6iEK!}ejQ3aKniUTBMU2e}4lP3ATy;ciy;2l%MZ0^mh>joZ=U%=<~ zRzNMLG^$@Z?aK;*p(MXFimJ|Ppodt@6Z{lc(%`j|DAN8qzTSYVdoOLcjU)E6{t&wF zX7<}}o^#U0VUHOHTgMzpZ@1i=k}lq4;lPWP6(po0)|$rInVHjijX`53S%y*`Kp@Fy z1YKUj6Y8NcSOxPFsDONYy83s^cV&EL*#EQ9ys@GL0lmFK6@J$$%1vnK=oVE7d7_~5 zrH?w5m0^IZs%KBQI$i4FV^dAR?v-L^H=3Zlc3|{T0igmR<{9c{0H?e!C@u&CAuq(X zNT$L>DP7vi{;)H=G34)2esd?0?3rHSQm62rm8jBJ)SLQ9*&h!z(M%Ixcc1?oGmbVuBfaZv)b{bbe&&e0BgESDXZ1 z+5-n-F%tqjQb<@45YSzPn3XIkFBg`s5qoS9IB3)XD;?Y4P zemC<|3g8R}Y-b1z3=DV9KTUuGZ;u&JZI)vTc)@R>0svoJ+Kb-ZpnDtYKQ3Szp5OZc z0@s3`doUIjA~a;mP)D=zS}2VEq|pA{mn@F>l^G?8;R*~E8^E3wRXN3lz=j?YTd4Q8 zda{^y@(pO)(zd!WxVF(SA)g>1NXz4MI3il2{Q>j^n!N`^DJ6aBLc%tvl2jm0|k%8AFEjyGOGL&POX zOUe)UV}lluROU>TA(0rv=lXzJFLYeszC?+T$LpeXp_zwyo`GR*(QV~9@~j3odC$PX z;UbFC_E>tpdQy4LWJnRU`QXl}_}hN!5eoRC|4GJ9ux|k>2%_o<=z9suJu{Pc=`quX z@6_6N$bHgWUrzive z>_k#fdVV}(NYmFF0=am52i8<}+_*3Z>F5w=`|?TzW+Xk%K?0nVjh9j8hm#OG%4 z{@5?ymKy?jrP>pj!^%jS%fR)d{hfeLx4RT8k!4wc{}u0bm_$^p^C_}@-FKw##=k_7 z6)_aympzQFTfe+R#$iZjYQG*afNF3BRLrw0;OeK+Q&Kh~*W@18qdd_JvT|dKX zCBeJ^CJ8t>9S9Vz=arl|IpyT$_OE9ho(L}OS2HSvzoozpP0-Dj04JyGjC@#F%Q?3B zjJVIopux@Gzws|59MTPQGDBg;goSZ4Cq#?n+ZSV+_6r`i=||ARMD5#}QS#0a^N$4l z-K+?UMcT!=*L9FoO}x(mv8yd_PMc$9=JX!t0I5o(hWZHL{3)M53N@4gUegs zlybqoV~Og&(?_e{KtVuh?g6EJd=F5!$TJ9t0;Zh3Hbj!P-+pVk6CSi80ISaYRxl!x zIbzE8?!)EN>fq}^53?j2R1zU$c|VZv;HfugW!VrBebR%-<7y!ckv+YXrX6=!Sw&|q z4MCiPRwPjjiWB=qrS+H_wq-w@#JNvUUnanRfTDy-3O7Db@azt)C`lgE3?WE6!8Sx+ zj~B=t&A=VY5ZU7oGayQvAN73F3iI*94igm#6kE~T=7{}=m-;iNrFAs);c=Hf1w0{A zDRT}X`R=b?Pfk{aO-BV?7^q->nb!#(o2GwwFzu>Ev2FhnK*44?ex8el7(U~O+P|CV zNIPWq9QUiV58Te%`lTXFfhCo&W5v?U)D(uAdZ>kd?~9wx}HaI@~Q-%SRz9f z24K5xIi#Yc;0M7>CB@fJI=&~y9qzBK(NV~S#Z)8=fcRt7UD7Ok?GA)}d!~T@Nh0t8 z2AdbI!~8nTsQyDoQe`~0+J>`6;Y7%h>B^R2_5So_n(-v|I}L=*dnw z#pG>i*m*1W@;dHJ!b*=Hs%ySRN_MujXXgDsK>sgx|Jxi1cqC*LA^ssdO5C>WbpIl# zCDJA#XKNy3^qnLAv%A{FBlKvK2)5;TbkMG=^y!0Za zP%!PoIN>;ATpx8pfHcbULNds$w07wQy3s3cYJ!f8;_`##W)nmK=ydys5v9Bhm+c`J zZu@+^!oostLqYyGwq#bUSHKPa$gsBva2fU{_bLi>UO%1>KnKyT==s4zuS2xX22WG8 z^M9v@_lIy!`=W{ivAGGUXbUb*sP59+Nz=9LPYug&u7|4f8OtYFC4mhNGkVdQj1Y8D zRM$n>#ibACm=wcwnhU%lpnYvI2h(GJBrX_u1}r?2&VQQ+ZcnOM*>8wUOLFjO+mC(s zogQuig|X(Fik@kWL$W0&Z7QoUyuW{Epz?*>oop=NBc9bSbWEpVR%L2WLGiEuPVey2 z@6a=^D7EkfcGqNAF#r()G{#)5ZHk*bKy#sD#N)MpUhNnbmmA2p?zdmPr#sKggkb*} zt0Yzmi-gG7&4sxGZUqgK70ujhN9O?orW^@`O4>|sM8=Qswom`*Gt>bfX9hVDi{T{K ztX*%a8TO%zr_N@akn&2H6eBOO&C}#kUa8iHMcqPH@aHby7lO{arDH|}Ol#QbDBKEG zUiKX!v$EpX&->@~Eoh!8VK(U%|*#8mtM&@pq~x9%sh zy~t3swoF)Q1)^qj*vYCwJg3t$GAj;cofj~cUC?;vrpVOiK&{u|65XJXQ3(;MZyW z618I2PpJO~Ys_*t%pG~~1ub7Kd7w~FK0#?JKBWtBiL}s;3A_05ktctyx*0#f?l*k|7T(xopIaj+iXlPBU{j9@C2IITqFxH56}^3SJl{`A5uXnp6@YR*T|(}| z<7)y+WG`Mt#fqI+Z;R1aRuKe(_8C!f7EQOal>h*-%eU;tAy4wXU)>3Y%i4{*cALwd znVxY-=z3a}lCk}^trHTm{I5-rTNWU6!V(;y-+b22qVw;KsKJ_)OWNF#-#y(?Cod;>8VTsw9)u$1`5@qmbrj-ZCClu7dw>2n zE29e&tRkStcf0ZsX0(!Zc2>=_S-k!3r#~uq__t%fjz4^B07O+ir(8lpLP=O>jWX!0 z-cgATg@p4BjQGQIOMP{Ah8p3GN_vI^q>G@zLE~1Z=aOe$C86;wZ6pQ>QUu)pn+5RI z-j)c&WJw*z43wX)Ml9Xy&ab&${e;=)6SF=aWECd-McbQbmOIV-weAs)4(?2(d9 zQbo%qD)>#Uc?Nf`Au+b+4}#9)(SrREY>i>(rXmBCj+>>mvtp~-biQP(2|E-8yNOX% zELv<`e3xX|%22)Yo|$66Jeb|I%infsdq}IKEq9GY&>5-P_jY~KMv*-@xb?oh&CnL| zpxJAox|1nuY-EvKO=o}aY^9zN7g(CF?*rhy$!nYMK>8xoHa~Vg{J+Q!0mKr(uD_HB z9(+iz6EjPU_yKbAF|QP9l8Vf;br+eF zxy?-jfJ_Jh+UXyDxa>rfr3o1uC)?|P;^IPVteO8dBWF-~C16P`828pqMM~C-GazV> z?tviNn*!CyLk00ulsd4`1BqywH4C|flbasO;5X(Ae$({%;zlUs}a}m%d zVc+A%2c-^6%TR^M_Xa($GuUXz$IuXM+emy4eixzrMkd;4Lv*DZDJ?qKN>>Ww&|2Z$ z`TqmMZ-t2+x@2#NDI)@(!Y6Wac%aV$7%cK=rO|wGvgLieW*4Aink2IeG^V-xu~NS$ zvttO0BjVuM&Rl(c^~ED03G{i6)R`e`>4)MZw+C`xM~^yPxz=Ud$~QW2Udev0#f>Sj z+7%CVR}gPxgDy~LKA$!1X0QdEqSMlbp>C8at~06H^?0LOD(1gP&54;GSp-IL=tKOu z@hP*j4C9SfiQ=&@--OhuE)Qk7=sC(9pPcccw>M|FziFyB^p{TO#62&+66-;>C+fIse2>Z33LhOm(rUPLVEzKbfSO2 zuFzcyF=ymn)WOT0jmev{RlMTKF%vmgk2A3a`o9{Ldcy;Bf4(YSV6}8j>=Y*`Lk7xQKFE0H zWgfW$Po!d*E%Ikaw6K)$ofWmW=fb1^>4j`AyuZ7>4SQ9{cE>+Krb&wIzkp-bP_!z1 z=r1oX|9{7x9L>Mti@Qg6oQ`ZR4CW&9{~sF;6;y>>ARt$As9Lv3g&iGE{h3=4QG>;O zwr$ zrKa;~6=2lD?3BZm+3>L;)~UYu0oVMYpvLc+MbY!jX0ybL@3u?T%-0u1GfdlO^6_eX zz2B;)>#VB4p+{DT11dA?Ow?gicrH2(7BF7_&u`t0_yDx}(BpuC`Mfd)@3%MK>MsSTMZ?9sYR-ui_(drp6-D?U+>WVL`=T6< zYz9+0gauVK|Gn35+F}L-4i1+FWa{ecoZj%d6TI13!Ng5m*dgWBB~VAO75VL*^FN9k ziGSKQgtq~(P#yZ*$`YFiVdirb3Q=en>Y26EueA#Ciajnb{FKDRK->65%SA8sFfTPk zNSu&4$Kqy^(m#p5$B8d-|YnWz>l#mm2#{?tnAWyFEL9mHO(g9Pb@DJ7Zu%# zhz@)mg{D&cMz#^Bb;Qo_RREsFxAx5HahIOgZlz} zHFR}>8CkG-_v!b=Od;bgw2@xl+^*#v$1FFlpzU<*t{tphlE44#ZT(<%z-ew@QTTn7 zhD#D4r1l&yg#;wOI$VD}A|Zly+eHDLp2n?AF}D1lR`>NCBu0y}@`=-Lsi=_Bk`+Q* z^8tvLjlne^*g+?|YoA-DizZi({(cc9JiW%$-Ag9`c=lqo7rUrZC~@=f;MdpJ>&{WO z3_z`j`1i-ed}n3E<*_a9`EYr8X}j4U^Pf3{3MgH>zO@ozUWkG+x$PvAA=VC3bsjsN zPm)`OpZAV%0hG--)NmRA6x}VlkHLdj>2=Xg(cL*+!mHW~o_zNAxTFE|d&|q^z^lao z6+y^|L)(lrjDPo3ya`Dg4bfJEh=icLSmw@MO;PJ+mr#+p<@$eTxHbAMrG>+(=V>da zLE0OMdK}2}G6}rHHS$9qA0LaHI6i1h!7_4R?|wle+|LxdeWObOnmm85geNk1`~zeu zoU^lYI-%U+lokkKU}i=IWuc+Sq6H@-JzZ!b#G2_uZDfTT*jHC{dp||Fj?li4e?PrO zBgFO<5g}@D0$f9Ap z2#q*enmC0G60WMU<;*0Q+ss2~;RhQP=*Y+*5?S}=M@HbZK732Z+4rH|XaTsdwfEhG zzKFfBH1a*q2lvGP^U5jW1e{gNPnHzF6F_|QGK4vMf%^8XMA%uDXr*=DpF9vH(#-n) z?jU#m(5b$b^*nc|Ym#0dORwXOIGf)?I^|NU%RjoqnH&;pO1n3k{7U!l$r%}~wY#QeuBSF3C57Eav#l`~6H*Z6+z7!4Q|aj%%OTjQ zgaLV&AfJ}lb7MaRT$ov#>gdus}PEWC&ye&UlRC)|N%6J(>yePiEb zdnMo|5sx-D&`2|o6+{oA4)ivF)|-JFD??UU76~X zSpEi^+1$(tNN&edzHJ|<^PxaH^?t~Iw|6?AfEF%pwVZQ3yNvBJ`Z@U;N9qPL_fCK57o5LoQIeV_!dxUTM3Tm0GiIWBpO ze4bzx{i`Jjqb8V|Y8m%h=jZj!>>?&+QvUI86$O`l=T8+C6?oOQI6WOl?6&rvTPtr_ zBJyn+C|D3tBY|jEj7es|MZlzbILtovlcX(mdL~XU4mAc*gnPc|K<1MOg!ug|CDx26 zRaYe(;0OMQ0?xavLx<~Eecs~VyF~Dn>7Ql;o1Yzd2U<(`-_4~SIEh4%pae|`xEdQ% zYLy(5{Ssp@G<23hO`eLdXK@pgS|S{6vmLud@I8 zRdD3TSX~Q3np2?A>zN1uw}Q2~dV&%~St9n0Xfm%gR6T9)O|y6U0`?zBD2B=(m1Whh z4jchPY3b7DSS)(Jn{Y%cZFZ6s+@xDV`mc$JHp-POEAb`|24kilmmysH13bV1a8Ct7 zdhYJeuD4cKSSZPZD3OF9Urw1DG;!3VC|V*GCZe5;Cyo;VVk033(qOxel|^-u;7jE#n5o4<%p^J-|i`%zHY+k{MK!-!wR{oM`&Ec zxVm|z3VgxKMF$7w=w|NL*3luGauE)pHE3kVQy-&EXlb5^hez+>Cf9kMmIwcJM80LS z7B~&WO+zb2plGJZ68UrS62YWgJuU-o9bm&NEJp`#uF_(a7N6VeZrfS{kEk6!u4>aU zt+q|703(15l{|fYyIV?nU)Ukv2V7n{M7I&z%~j;q#m5jMgs}$LeEyowRZQc!`m4Wo zx&|XI4*mi4&9Aqwbu9~Qiy|7N)QDJsTU6FU-4wYFGGkk~R)5&UE;d$jTIyG9qZ!7+ zd|8|k85xyYieS^oP07FpO5U0A=*2~MZ}U0CDQ>tb3R zqk*bB(Az)TZX7=gAN&Xvu?E`RS?`=ana?Eu#ptuXaF0)Gd1cK_PNrRv+TY#P#Mw5Y z-cW%uw(`i!#8McFhG4SJ%*fcqB{lu>PhX(Umj$V`ON9@LmEOqq!Y^tqB9aE$dsF)s z-*A}w*pnLF$G)}gvPAd4G9Pw`6cit{Wt~|ahIM{w<5lXY);WQGS7Zo#r<(hxIM+cnhBO07&#2S^&O{$fKwFy!PKeFLCgVR? zl=#+~7F7#GFowhL5BnOCC`7>l`#u+|E&A`kWNVh_O*C{<4d(#Y7YrdbVI|Y5@mx{U zJ-B}ZQJ4O-GpfS92A76XUU7^syLEqETr`|x>jtr^;O6EwFwTI#|@??b}j(zM%^nL$`JYG`;3=e?kwJUc?vxo7VA*9c>tyh^wSZq~vXw{*L>2U46DV;cXL z&sqb8Al5W0+X~5T-NC(}YsJyuW_5&dg zJ#T(v1htQ{!NDVos;eI9nn?P&9u%l*P)0Gmt@BnLcNl6PC2LQw6P8_uA?r*~U2>S( zkBZhf6FU8+LPC~C``jr5os2RKrPwXLV|yxQD$k8XF%u8{CF#O?2U4)*5>3m}%?1$~ zS;V+w_aPhn#FYoe_k}pAR+PbQ2&KHSbiw2(NXF63ngrVREpl115 zM!QeOEC|0Uz(Q*#w2TMOBox1*+;OL%cpTKx+Rl$Z{bAl{yt1l`HGHfwMaO7-tASfQ zK~s<=YQpM)I-IfSF#T#|H%`YCS=}0OiU4fGqo4f&ZVrpo%GGp9BUjB`MK`m7k}_$x zfs%+2+5{_q6dE5#%x%+vmH%V#g8MHGiP>UyVGYz4N9}(4%q4annx&y`+PJX<$r!#w z?50g`GMme=%Ie)_sgcwp>Dy)p%{Bx~G^i03|8fRtoRF98pt|s=pCj1ai8_K$upYTo zZ!r*%iN(q2=qwr-v-SaH#(#_X`8!q9&rt@(20+*L<|ObBWzg^K8yF_z3L;hY<-{%oJTTnNWWRQ~?gGOdAH%q(3LzV&f;Ca?A={I?jf&pe+s?sU1DA_X;}d zA1e*Fj3fN3QO``0@5YrWJ-HI6 zp@qjcV6m=Qnv{IbvS{H8PTNEN-5IROC7u zUy|T#Xy5BAlxH)_C-rvfy9rR^C>SWf<)9yPC=>nu+a zHA|9HbeYsjLc7P9R(!{n_KN;k*x4#by~T?@05izFTep?Eq|IV?u<%iz0E&a@Nac5b zm)F#mF3VGq-!}(ENP3DUI^xk`3W+0$UmI0NaJ5vCN6h%B|4mk+oLuon-A>yRZNz5y zY(&0h0MesG!@xk0h|Tq{t}eBISyH8C<^f^xju1vv1|2>co0zOE`T)t_VI7ZVQ|Go{b@mt6?`vCM zh#H@k@t%bdG29~Cynr{tUsK`?m~E8BBP9+TG+yYaQNH_8703L+3-`v^tv>+ccFlPv z(kW7ZSI$7gH$5@f`nb~Pva+_GI&UqV5+1W|Od1{fenM zZF5Vj&|ERwHp*@WwUiJw2tXM;&ao&5pQN`sfk}`2L^rMO{!ci&p9NEfi7mB~KkSU! zNdA^b2EL_^Zb4i2<)`gUSV zMHA(h*(vNtB+wQuFq`LP)}Xl?!?JS%0qxvIG=ara!!YP+%K)54Fqr}{tE)+c^O z`Xy#iHZz#Zg`&tBz9o!=O+QLwfoG8Y;ET6!c{DzyhS8=a)ilsWRS5<;>b5a?Flx^M zSIVoV>;Qt9@w(oNcv;k$JMApvVEAKa$UuxeG#Gv4=TFg=pB9tee^Jb5rpa+}Kf1qH z`m;7ak3&AxE_!l!dfGQpW1Jwn77t84QbH57o=fbis6ZTvX*4OE_}kk{_N^GX4LsLm z;^%Em3VBsF2h5ywKU}1Hrnjf-fS)Xkd24(9m6o zk{E~5kteIz@(YO2UIzxo2b=R1{qb}5AYIA#g0H3R{H31N{BDVqqo}NbR!y~Lzs$_e z))obbrunt@HJ&i1@844){&s2E?!FD2B~CjS-FAJm-7CjIC&mjK)|Ho$M+^_89kjlG zEvmX)?fMeBcB_&*(#v&N&uZ94MN;A;wR`yOi~bJ&a^j)X3;r?}oZ1(hs7S$GrgA=I z!sHfez1AdXfv&-{BN-d%=ZBiI@O?@3cmlTUr0dU82@)X4CML#>5JFKN1>3>N<^m-) z6n-%lI6A3YaP>#=m6Y*#R5Ze|J zl(J?UuxBJCIGQHkog&)}9;R3*j2%h6zUb8ePbQa{tZ;EspKf?~M9;e0!$qFJq{Z*u zA|a=L;i@vTMsh3r#z>@$Z=nRutbu0Hm2)fbgOvo&O;)}tFNp@11RWC5sXk=dv)f^! zcVx1BwjsqS*`Okpqi&Sju3<7dAOhMFd~!N16R}2Pw+H%CnQS~hT`PPEH=|JAkWtJ zoS}za1qO-6Gre@_ePUrr|5l}w*KEj7yEFyjInrK|Cebi2$mQ32`T?)Nrm@~y>@$_y zc-sO_ABtPzbfuu6*c=>H->{J2`?&Ui6N%a#++S`c%4A|{+FvAr3f?EDqB0?DSnM2o zcu3cHkf0K|cs1r~|Fzb}FkuPp$n&x@YV^U%;K@3XirUAnY3YlkyzA*hB}%ZulAM3_ zc)@$%QBy8fSOl2ueP4pV&Gf2xzeY!0zH;g$1GkKN!xzxlI`Y`=dx0i#vfH`8zaFm0 zKe9oyk4-RmcJgyCL)|=iM4u8Ebi~K)o9^!jvuGjjpQ@GCN;6F6eez>AoSYODprOwH z0_wQOYV|fB!mYaLPDwI^SBz$SefhRHKJX53ME1tPr$>#^-fADrItm_Urh14diMdXD zlvA9}teckS7O<`0ImVdm@={JtgWl1z94UK!(Xy1(!Jop}9bb@22EQN3AM_aDSt`{A zl_Oh*-d$9VbDj@Ro*hlV1= z1RK9fBe;m<7@oJHN0ph&=ounu&)8E_Duyf4YNUVm-rN*BsVUSThW^l?asle{RU~PW zJDmzdK^P_vHpWT~QdFewOCLPS|GI>VgEP6~6B4|ycoK9cMYdqx4;I13FaKnHeT5i& zdy#W)Cj<eKW-)<1vwiNOHQB!|HNm!@ z3$U`aaX{V5Ke@{E#tZyO7n=Ed_epg9lOITl&ut*Xj^vpQ{#L=q*&SjFBXJPH;C8~) z>q9f>gj zq^t;=M|D0E{ID^Td{meK52;r*?W+D-kJCE=xpXh?+R|!^3~;dt9OCUsATYSUw)FT;J1dVqM}mkb}p#?aoFac(xoE~j62m0 zO(Zk~9Z}V8yZNE!{v9s`{^6_8m9&w72pTOv-0I8J!FseR#C|fyXBFfGMMxbv=V0UG z2UO^~0DAOsm`1>LZXfJvaPVj7*yykwIuI~M6KDcEEkA1|{cqte&;kHGHasrso-ay8 z+kKRGVJ3pHVU(BKJxe!gM6wS1*?d&I z-+{J$`OaBOYkHvn4*yQUPbg9zVcl&9S}G&o&(XfjFQo*X&~F{FMOYpjwisEa^=2!x?b% z{k_BlBUvGn+Rlvm!YWU67NoP48<3$VOj+WUXb-1LqQcTLFSsE3=eY`PF}-GBsCpz zXne6hBFVb~#wsvxXbe7Ex-frr!)Dd`wslnd@uq{4N(>P&=^SM0^PCUT+O{$<73sPl zw-W!`2gHFt_`v8Q>dD*D_5P?`>~MO|j`0_xg*N-T)uflUD5HVN%gtwC8ctla z3<2D?eAYjW+vwGTEJ{>Ki;EiR+1WrV8z(KT;+mUEilWCP3c9&%dz{11Mb80pb3vVS zy~h8Ksc#I=s|~hp)Yxupv$35tXl%1_8rwFTq)8e(jcwbuZCl@N`<`>Yf4TB!Kl{e) znOSSr63KQ%{tu11;049T{>jH$)Y%DAldK)EqBY)^rVJ)RgjI=8#)PGJgk{pkXyxY~-vYtDiA6wUQ=QMGNhD5VqDje59e~ z>Z9}nzU~2JRbSabBH7!~=RBUnBosU$%-dokSg z_0{Ig_02~&Syq-o6p_HxsVdcy3^=$~0@NX1XBede^Mr~cod$+d!96)k=O?=_E{K~7 z^D4h9!1^XHaMZ#n|JaV`38b-as1T(BWTSDrnJ)dX^0W}~A%XSV0|y;NeEdt8?f~}) z?MQDW^P+$mo@apAri%uQ5Q2-B$w_;1H0yyzv9j~-47*+xlDf7w6M|O5&Gk0Nt{9S6 z+x5YuFh51d^nb%gtSE%O_RVF{yN?RL*LQb~|BQ(0Q%aMQk_(%tAfTb0L83V8QhDNi zP3MDczPf_~xY+Jae4cRg?aiQnC;-mZ>mA>Ia*{Of=8?Iqt;4Femj(BqMy(o3J9>QN zc7BDZxvA}uneh@s&46R_p5UqIG9)AjXCu#kctFL^3tK|hbXjxB!6nD=MgKdHWd zQ(gVSqV$SZY0(~z8rgrrus$bMXQYW!uR99=@MQ;Ii6v!l%LBPx3l&m3yh35T^kznR zOAU4~t*U0@kkuyB{iO|pLRUr@BGSr?TMUwuhUas;?c+-j;1=NXu(~uoz5T;igw#KE zhlw_6YTg;1MwNP8UXcDp?a$;$iR3SWw@^krj6P!keL z6iVxh4h@yhe)?VQ2bE@JnF-Hl{KhShWYSyIq%Rz{4(-8P zS_=!~941I}MN&AaN;8P!Yv9Q&_H0!t_^3Ld@w_~=yuOSb9))2LCnwa<~LKYnf zojlmwILb4dmbO1I52&Pr2T_(kW{a+cijj7)EfYvwuKp&ECPmN4EmF6 z5`uxAFwy!4cToSwI@yOVR3cKK{EXaXN#1KTkyBU*PA1x0Xq~--Sl{GToMmNny zw4on=F$Z!&ZcsY9eX9Bsy2Zm@7^)edYkc%Hh z@!>@DF}C*y=W8HsNkN;_{5^e1vQj}SIX1X{RA~`iq(3b41xQ?HrlgdNFss;JwcOV2 zZ+O#4vC+r#^p6>2vrlhuB%bzRk_T`e-%AO*?O+D2h2M&fse2gQo zv=)q3)Rh`WzS@!zR+b{sS-s(*pBM<%^#nV`>hS&@*}a))eUL8Q4Gcp=c+MtqT=i{F zu*T%CieJWGIWeQK6Pra^TSl7o4JK+IJZMC#+86g7NpN>|Wz}rndV2-KZOfZ_kRX(2 zoRHhL3%j~A`t_y_k-MvMJM6<|pdba4i!7xFY60@SNZ5@-G*G0``Y^5x!FI1tj#n5u zRFKMQkbm!s6tG(-D6p!3i7k5sAd2s-$%n_jxwqFgc8Vha<>smUeygp~LxTpnvi3tk zkXWp7k)VJGRFrchv8EwI19l^mW~}`S2TZEt0L?;}iX*0^J&WnwzFtWiQqGTFMr_GL zB~yg48&wiR1ge1FL7O07e8>5?1M#@4I$ZfqGa%cYgMBWh4$jXDaBb|z+xN#FR>a%D zdk&u_Ci1S7V_5%=S}}r@BQ4aJRjcki2_IZsR3wB2^47cvuG>miHxf7x8q!lr7`@ac z8YjHlQ|&S#sEX@hmrjEYSX@}Xnk}Cm>f$hDw+2QOK>TP(q~&p*-wd>QM}l9q#ac^^ zzKz%R^nKv*hF8d_z>ThJ>AyT40p*EJ3)XFUf%`fqhrf04O)u2zqxYly z3mVsr&xtE>DWhj>@YNs-j|rcj;w3tQr}7}-_}=}+NgGeVd1*&Q5d=B~$f;N6#<<(@ z{yApPLwjfS%-ocL5QKUa11@L4j;FT>%dGZsb+MjVQJ1|k*n?EU#=WpoE&7HJ>}`-{ zRF=LCy$(tF!3{xc@V?F)6f{R@tG6r2@uj#{b=dYfGm+f;F6KhzHS$l>&+jv8HKxd% zkhBHeUxlHdp)ZfY%P09w5J*nv#XJ0g==hxg*lG^~0gu0y0F1g&g(NEUlsOeH)|;C& zdTh7r_sA+3yC62{LWyc8CDpbs=z55*;LDhXGOTvva9NDpIE{f^N<7drHJ^$?p;;ja zwti$=7BzAShu2>aIefI0MT3uVr^!aaK1^G!*SaI z^5~5nPa}Ce8fty?Yb&8?0j90YxCVL!>I%AFF0P#wt5mPC5EGA!KT6=P*^QGVs zy<&Tvy4c!#@o4s~+hPn&agp9rGG`;En36UpPzh)$K(5JI9_qyN=Z?PRFb2=0*wuFg z{5~cab~;IC;a>@g4@R?$V=tEwC(Gr%jr{!4`vb%3)CvcO(1z}6Y8+9A3>xPUkR){G z=!v(uf`+NJ#haw=aGGBRwz+WvTi=DZSj49#c_tN&|lED zTlvGu2NudmRsfF(u6zDGha&J(PVFPcXh5ZOyr7EiFT+Ap8MeUCu?j1unAhYKi`>9Q zHq>8zia1$VNi` z>L#NFs`5J`cRU@{g3?({i$f!@*bx1}!hf{F{0B;_Z1_w6bu2k=4tvG=eW2 zI}VFU3QJJM^k9#Q*E)xr;zQQo6$5zR8C6X91H*hN3qLtLe5(SBHdKr)so=v5#&P>z z^@8_O@89qvAw~7sBN7>`>0w6<^x<3(FBPgLm z1V^7`C>1eDD&vHtkL~n+&vhsNLgZeq%8|fS#iZBDys!`iT!y~eCY2<2+<=R`vH5RG z@jU45-M~N6|HCo=-BN(C&E%WP4r%*TEgMs3+3KycvPtaRUpA!jkdR!(aNskjL{~Wvu`%$OTIVYyBWXWn z)&1b{zzgf$G~enH3ffTGNjpr6=*s46KS9%Z%KU)5gPxX(>`$Pm?d10fT3xgws~y&F}eY#8tk$#A*!tt1GmwG(K{fE!w!3+0zNq6PW_K%6Bin zIw9#kU%J+?HrdAl)Z5b)J&y|Sj zXL&)n9yjTVHQUwQKgM$r%kn>GsEo0RHUeQ3&?^W>7T+VHbP!3eHbYam2d= z!0W0nGL?riR`f4u%_HmM497d3K*kKxj>=(sfR&BE1ZS`KSz0x9QY^?1wVjVRkT>Nk zr~Pz>ykMWM{VT!u21Cw^K}`-eY0i|lH;S2C?XHsdH}tJIV)?smlK8I+Un!E#nLxZz zkYLN7cd^Ily&!JKk4!bi(NL*j`Fffm?SGr&z)u`oG=*A#lu4#Yl*X=0F-`vv& zuBn$YpS63th^UaM32Vtnz)YUL4x@#mZmgn?NyVbFmKh>1&j^U2{Xdlk&I4&PAql7@ zR^nv0p7I}$61dDfv*fRhLHg^cnm)@N7afF3mBam4I}2C4(k)AU@VfDS-_6l~G^MtL z8zK`l<1H(Y9J;akB?arxzm0~Fk8gX1k}5jD)ZOl=k`wBJ4tICiy1P8}){-}a_ph6a z)zyKMEqTnexx)k+4*F~FNc&9_*M5Kua4lCGDghtmcoOcCtzdxxF3eV3_Jw9awtKIic&rH z$Z{wdf7AYN;AcFC4v6nGp3Y~99=jg;Aw@skr1W2|7#5`XZTo?y1HV=OYT*bD?T5;? zr$*v(xtMh6%v_V!hhF78FR|D*r{8LN%#pea)Q^r);3M!{JOwt8OScbSUH$!QKCU`n z@~xUr^G08NG_Wb_c20jLb7+?qwyZnjgFIQjcso|EC>){mesZme-MO-9hau`~tNAsf zznh{}vvAZbyLIUOhW8bhH{iUbwA-0@`@6$QdR{B&dB#cI`PlhB$RE{wjgm{YmU@D` zkW9ztJ4O+3Xzv6Iw0ynYA@nz_l>Wb>CL>`Vg5%QB>8(e=69jzV8loLG2;Rk^Yh-r} zyf2s%bR~Pr5Muc`pd&{|C2+oCyRSyyI`yrlOO2Wm^7mVH>t@k0L(AjoX11E~Z*iqe zPXF{xEJo!(meMaGSd7|OGfA^Xfn7mEsLc%^2sd+RaXzOXd7ZByw)1j}rc*}=0fx|4 zTHT$O6jK*Pe=tr&ML_ftx}Ugw8JL~S?sDVg(%{gsdGE{qDqvlSA4ukeS0pIJcRO0( zO+l)fdhRmb_O5guNTepx4Y)9_wOs5Zo2P5>yMw;I&NDGH3x$6TJL(989`Wf2gx#<7 zdJV#^*&+W|JpW0(2{RF*zuO)}&A}RVEN54$I}O&QUXscg_~cP`_bx3E&n}+$3Rw#| zF# z{jHiu^fcz{VXUdQVAjzI^*~DZ|Ux^aaj#aXf}eHC);u zCo2z9{_-%S&i;w#@~J%LC1;(mMKsu3<_*7$jDqAe2^8;p+{ci2k0spovC-{u}4 zXa1;%`<(Ec-MbI9_@hX@Jat8(AqQg}ZuA(fz)Q)xsP>W#qYTWhtvb+IqVyH8w?`!= zQJqY>pD*9?d1d5;1iBP_;`V^IG$}>-{bK_U;h)p5R|mep$fIen0ubDMI-V%Je4^7U zs5BzprZ2YZod6a6p`PL;3s zx5MDC0c*}%QhPa6KDK%*vjin3C}K?4X`k~)r^!j+{Yh1$DlcIYzKaof1D%@PtHw%4 zxU%RjA8S!z@@ddOf6H3E$_N^mGwKe~cLo`o_R1m2u|!KR7@yOe4vY5g(9BlQu1ZylhKLH}nZk20h3n zEE3~Kqs58YT_%LPt$;C+&4zQ#ohIE^e5(#$FgAZ1FfV6I9Iy9JoY;z#N3EC5q>lcB z?yp`Y=GB~7onUkvZdb%3ye39_r@f)w=mLA&3wY&S^rvh*s*`^FX7RlKK6#8F{HPLN zzTE!&*hR==nI#d%#|9S;_6nqTa?|HF^ncH9BkBeghMl+2ZvxZ{V&97yJdTT=x61NW z2V$oq1MEyz$rD1iT&yX@`fctZQlxwxCY#8vtQX3@%b%YM ztdd@u1fUl7Q!o^DD(!Ybe{#xBD}wLY3G^y*Rp9=Yp%M668)62o=DrAPnTQGG1u<^V z)p4a-{Tgjo46kN69;8h3|148*f$}q`Ud(h-dKI-Q%tttygfItc6q@sdj)zs~e8tu+ zz_AJD~V~xslqf_VWx^ZAPSm?8}pCNI_bc*-v@Kc%sIwA_AdW8wMrE zg8uHP@IpncJxCB#QB#~;VGb=1VZvmDJOcZyH8-K7Wml~12YxHwUHXTDPJ6k(wo<8)|{@eJjaqG{Gre>(g* zX!_e!n7om>e&<~a24^*>g33F}GVVdy6+9r8KW6S0SV+CasXT=l*7XQBrZ9>7op8BD zRFbPdqd2 zOc`J~2EWI532AaWc&h|nMe~chK8A*hO4;xZy+3i@K7amt1G*YSjr;Z+I~Y+}z7AJ4 z&}a(FinQvvTJmKFlg#D)GqO_?;%+;A)-iu{B;C{9=7sxvXh8;#Pqz%%%$lvoa9$2& z&SQ)0Q`>uZ#zuhAIu@b!SD$g|CWCRubaJGvA;X2Kh^aX9Cw2o7XtJx>@X=(daA?*i zg`KeJXTwqRu+N#Z?6Ql7M>t{$=t)_QM;{TK10egeMWejSfU({a;`N`x>}|>7;6i5l zC6hfPIoOv<9)cT3vn6dcGZfWoJ8i*;^I7#bGoD{^j3k4 zXUT^C0knu#{W<3@BR?M8vKrq1R?c_R$EZ;UFN#{5W7l*S{^18V8F2)c7nu3Gi?R$~ zloLC{v9@#z0TU64TNPQcSar4L3Z=7yVK>=pRz^99X;6F6`bLf z4RJ5X&XNpq?P@-wQ*tO&BbYGFV;c{K1}|E7heDR;i!w9J7GEB2Pp+N^z8A9iGog5i zTs~rVI{{L9FWp1Iz`5iz`CeiUCI4JhVo>NRrj#&*2J<}$@2@L-_9J-}mB5*=g9j0CX6mqn`X05p zII&fCo!C*D%1*?#b~+4{SQQ?RcHkesrX8VX@r;_Fs+337+Jw1vCoRNXW(u$FO6f{b zfX@F8#VN-OALoA|9X7AacrA^T5R{0T8PXa!P5AD9>W{IiRRmVM{DQrCr<4*fL3zT=iFHvN`pmBrt`f$W*@18t^Xgjz)Uqz5QmBB z=|H}qZA(MmI%BR+zgQQ^INns~t7^#x#No}?c>{;wjy1At>(C$|KBf(_%2Ar477rtA zi7K2_#-Wg+VG?tTMkZ+C=?t!gX|)8>O0k;jaQY3Qp%3Io_+in}?y48|&`=J_T;3#L zl(igaKiunDk_flMJohDf9@l#JWsnjxY}8s|s3|>{iml&(Y8}&jH@aQUkk^HEDp)SZ zRt7GDM@w0`a1$G9GpsjJt^DFg0p_=ob9NQZ!RLclKFFWNH#}&PteY;8JJCsJ@r6}8 zIRj0LpLIrU02(qh3+pdo0|ON7{?qqY7aO)t!A_*-mNr^;YdE1?kn34oPfm9HaG)vm z_@!eK!pv(d_FJADXgB?pARGdMBtgw-0qNTU4i!V3J*RV-t-=9P<>K1n;^u^s%Vj$M z`i>k0eUIAxStQ3yc>F-|WwJ18ecW7GY6F&gk^q6*Nn}^H+u@XP$U!4lQK_e>lqbP% zMHWh`pH;VEW4c@P7C#>%aSq+Z)q5c*v0-d_O2}=T?`&JW%errnuU-)|pCRP#Y{jQ= z<)UbkH^_HPHZOOq=0Ul%w;n~8vrF;Ig$)cYx@EXk3jYuoeEfSxYm#m2DkGAp9*ccP ziS`?ew(EHW5$|oth8vqu7ejYw`Uv<^jUS}D6lc~=5n#{$X?+Ez(%eDvq94!M48oR2 zcQ~~|n{)teGLu|KEqnrdY25aQpB+Jw*w;gpwBN&UyYEs(e>@gVq)m}XRUH?{YAOZL zjv8Im+z~Jo2Y^p>zFx+~X$HJJJ66@!VUixrEKVfN6Xpjvd7mkYn6~tWKaSseGLEJ$ zZ`n*Sb0zcy{@3^Z(^i%4Xb10kT3@8JoTh9pLI1UHrAFtVJA8QovLDBYAdkhPTAP-3%WoNDJ*MqVbOLKb0x7>+QuKv_w*{@|`87m)=Q-8R$Zyj1byR?ub$2NHuYh}(Mq4@VHt&BL5)*~6$ z8%Ibz|Cw;NZglqEi@L|cvp6oEgouv9XPwtuRl`O{i3qSgMk5Rlf=N%Kg*=otb4af{ z6Vi{ryCobmkro{FqYc+ndcJI*^Ice>@l!$4eG`M>-&J8grkxo>7-sI%y88e?Ku!s)CAazI7Fqn+?c{l2RMa72iu6$rdKCp>Iy(cU@q4mS5n*st;;y0oA0rSw&?<@v z3H(aWR>MYli_pSzx(F%{@Zg8c`Lp6q9XZH~sx6M=M z7P)r-0@#ZQekNyL$nAXgU_hxJMRaG7$R%oeQ_BiR9v9xR$_KH2maAGy|_mIe< z09hx6*^tB>P|VuipJ_uz2F$CMheKpsWIB$uPR!4T*U^+By!Q5n%9@kUhKlZt;;`c$ z1s0rYU%A=QAB8}{jGkbj*v}SIUj6=sOG06>Z@qtp6r}x)#M1OY0SbGJjF!hk;X%1_ z^Q^3MPQ9(ZY`VQM)$TdHL%xdr)si-%hT4(6t9W2Iv5Oy(zXrRr6^~=pVUUR5M%LzY zG2Cdb3gg`#M2?>w96JI(Szs*R(;C49Mk18GBCp0rl1i&lI}x(p>{vTE=l(MRt?!T; zi8jG^$PvR4l5j$)0}w0jp!}}oFcfcV5iPG&9JV2L*xnwXk^0S4BP_cFZx7KND=+A6 z)y?1q{EuK>c7?>#z?3(Hf|awkVggc?rG0a98n zvw`gfISGNUwya{$vLFPB**{K3Mw=|r)L^pa4{eWD`!8O3Ik!2(1aSnh3xfq&(y~J! zatD}bg-|$?&}mc%X)Uj^(Dt1?=xjiBJ#=VnAk?{gk)Yt=;$l2`rgF(r`_zrT9N=|yR=j=nh9wi^y^q{cGk;+Pc)|I z*)q=BpiO|vWc*G-Vi=@v`1y9E;<(f=#p_1KkacV3Eiv12@Vh0^_NkI+UjBOd76BUi zq0&1BT~(1}K!p3q63$0Y-k7N{b5Anb6d@(0!Yrc4xonWdMEy_gb+fW9VNkG&u5cj} zPGgY9CW;SlOtam-a<0G|F?R4KT4u4Nubt?zb*W<5Ju#&^U@;zDk z+B_hxDtXo`w6eW>l`4V>h8$|U&BE2Kt*t=89_^j(VlJ)M1_ZVXG+C9jJ7iJImgTUE zB^3P#(R4LUEg8N zH#Odok=j+Q;XYA~&xUN-BS_(QvmnYV9f2RtzAYzvI%k_J^!AietDfjyA*t-zB_FzZVhW8@+7S*Hs08PMiuwnN<9MCJdmW%C)6d;x8NV+rsK`ZJ0o&-`9+7< z3@J%-Dja{!`ONF;1oPjJk$5b_y08?0y0StT-uqRa*CyqLnCv;XahDluyOPDVCvkhN zu1@*jivV8oZU+4R5sl^Zd7Iv?Myu7!rJnfDKx^cAVQuI2k^?4?n9eNZ$Tb<^xTMNRROORz1JqL1_xOD;SNaf@&i3ar20)5~C z{&BHWa9jm9*L6b%kq(C6Kir$@u3{crA&aF<3%WiRRe1nC0UjB>uA@Vy^$S6i~TXSjUYvr9h{mh8lkoY%uDgH+5EJNL`Q_5v_d!l zv@V|@d{jWDmrQ@1zi4Ab}0dHnQNx@cX`bTI3rO-7g%Kku*b%?bB;ADVb9qMI;H2L zd0$%aXvExQN>~WoPcFJW+WMHtJ%=9!1jX(CqBG)raF_*-c~S8JOyl#xmU1=JZaGD`Je^ zDTSzcoI>sK0@KQ6{Fd)K&JydXu$K^m4jE82bM~*gL;%o{E(A$znp5%x}b z>bV+?*>xe&-|)m*Q?q2arIGl&)E?OzEv*}tPNOE7$C|=@GC$AeXAO3{!LHg zl{6lWQ)1vm^aAQop^^0n2M>PGBOx8F7w8Ym>u)%>w;vrG9UFO|m`MazOa)P6yxyk- z@r!bIwq!gAW=rRW_l6V_Vtns&URM694-0tF#rVnjcT zDap#uW|`jtYYATgKOEYve|vlT0vVi!qtoVLHnpy@&*pJT0BS&FscUfXIiMY*@6PSw z`B9LN_gDASXf(xO_22f-Ly}L3son07@jErq^`t9<_#UE!!nmJdyQN^~n}bNf{^q^A zca$MrXGnN7$+*rY?@4w9!9s02W+a6UcR>3IS3sCz|0M$hA|Yo3q+?{HshK5M_SWRX zOE-t5POwouo|C3Ty)<&=l1A6GywWSxl=l-2OU&25ol%M$dkqt`ksUpS%NfM1rFzWb zrfC(!iizg_wM?sW{`PO6S42pkn$RYls1Q7heunt$!**9Z;CzxsM(xG?3p4t}K{ddU z(E;TOy_kEn>gBLffKZgyE|yaRFy$^;W=){;*axqnR-@CG&(aT1gRH|zW=vvbx6JoC zVaCmT0~4+L4e`^a_OaGnnUq+}G=m0m*`hMCPQzF)pF_@R`h$;6M(VuEcsbCZ9`F~C zd!8S7o8!-HZpHy-2sp%D>r|(RA_3I%$p@SF@Iw$!jS1b3n7|Md4~C>hk1f5q8v#+H z+YZiEY@8-|x9McVP+pLH!crM?ajY)0Q>=FAq`@-0fcU9H-LQf=`y_PE_Ai0(7kRX= zL+F-5W=GYO?L0ef@dnao9UULGwh1aCx2}|T(9w$!PTuR9EC+t@kr5)a!Xv;Dld{be zY+vd9FAVenH5vYo@K2Z?DpM+bl{w8_aezID&Cu{s<%1wLde>G|W+h%G<!T^GntzfPo1YUi%>7OB0 zQaO(8Nh8a_){;C&qJzr<^T`1L?HzB9mSF`;8u%Um8KA0!{p`(G7hM!4=4QeY)ut`J z)&<}^@0=nt2i;KqP+X&;oZw%*JkSvNtCDhfo;G8lQ~Q7%sD-ZzisY19G-n=i59Dvr zV^3O9xOPDn6pR-==;-9M^;F9TISF86ffr|v^iqd6(Go}2x_}{v_FmO!=1S8T&b)!J z`z&?8tW;O37?x*R_(10{1?#V(3szJ$Ebstiz-JWi`OXv7Vy@?l{;Gv})OJbv5t;vG zSLQ~$IzsZZ?e3K8I~C)6EC9AAU$HNSQHzF`O{tg;n_DUCcsjl;fAiBxMV$TVwL>9& zu=CqzVWY|QIzK_9<1zi!kpnN+F2Tk-Y5h6e=V7FZYmR9sq}^fDb{`TXXOe@TyzAe! zV+2u0Rs(P#ExhccA92%^BnU{{1urT2oa-t5;CHbF=bNhQeWCH_96#@PPhigb2LBMB zENWnz(<0{iLb{fBl{sF9Nn8%=T}68Qu1=IW09^cBgfH-(%F>>5_XGVxV#Mn6-6VdG z*U4%#tgCA?(uxzDjjEOiF1AH{H^rRYAlh2v8H;)zz~TzbQ7+^X)9G8Cd!2)AD!91O zzv9SOP__N!?yP>#Lq~`1!t$()%cm7pcjFPU_*37kP(W(WYYFU&Ff(@5@KAA#*xH1G znT^QG{eb_1TkpEDwB9`X-6daLMtbza@*ZroKEPcpfE?)tFm}dopdc8-6NRrPk7;C8 zAAk>VKH2xX$fQbA=1(Peyi8WyZP5Q8Yw9yu)ES^CZSeGTdmIv~F0;9&I^EZ|69T3P zvw`!OTraDl!Pfz4fK&P{0^*@EYtaF3KeeqZ>enKIhMF`+VgBIdG2pv`$wGU^{(E7A z%lnPT>11KEGgdu;9V%j~(_bYlAuc(22mTVkStP)F*15d{4YtMqqsU3?5uuvq$Ss!) zxC(Lze!s;1Ke|+J{4pLZ9vWe^K6g&3R3ue)d|->4HnwUY)x7d+0Pc|#UD|S*%QJjo z4S#%#JH?XQlQ#R1E`LyKIl5jIcciEJx)+A`+m10Ot^4O=SAeO-b9=njx=NgKUN^vfw~}ML{T} z1SkSN(hPl~PWgZni2nMZ=K2p4l4As6Ev3VRpjEhl!-zYgW`-HpYg5Du6qWtve{N(J z4>Scw&yu`Cg5v2q=);Up^9-y_`^yMi$0$$8Sk-A!J7!B%sjAc~hC?#jI;u@44Oa4% zz}9GqBW{L%#IE7`8UH2vw}^EZN9mVG_WAwg?&}Z}cJ)9BS3ER19w*)qDFvip5EU94 z&R0zKNv-@Kz8k}1hJ%El64m}9TR9LC8u~MK3;+?QzG#h=vXN-nTeI*;bN2XAAbbM< z`0-1y{2pyG1S1GHXcy`)#li)U&H8^Ka)TAr;FVM%KBPuRiyRdSHZ?TQ){ehS-4t9& z;yznmZ30eq9Q>Vyz9xglc#NHoZ>>BmT*8^;{>)Vw(!xuh4bB~%85U?hcUb(vlUQqL zlc5{P8HLhI+1uNE$n>w*n@{k673=VDZGGy2GY@u;#3J%vvy?KW+~w45*LgzWoMzDC zKt%2n+acGfHW{_-wS9IK*r0#KeWVG9ZGHfp-70Oj^RXQ<@h1(0WpM*Gwmd<ihi@E=|;z{Uw|ySWpOUgy5uD)K_1sS${ z3mCN%-5aVM9nL6MrPs}T(U3yUyVNPekR3mdLX*_s#P8nPS9Y-iwrC6rA~-D_nLL`+ zAg7{Vt}4?E3ZNE!;_v`k*?%aqJd%WOzTnYA*FP9-85M9r#|9RTN{C$lBDfu%(BP0o z6)Cu=4G+;ijBtqXt5+$YCXy!jC@9R^yg21lUH{IM^`G}k-Dto;{hriObz3y>@;AtoinZI4&Y-@vDo%Vr`mHfpqRFLKqF2Fq97a|iw@AH{C^E$Yb2!D>^jR! zFNa8Xw5XfDNI~`A7ONek*Yr6JQu4EZe!7HiS8p}Ak`d$1mM$o9Le0bKX=&GEV5?~2 zE)X#{XaH8y9l9BQFf^?ks2wBBatVCn6wn)b3A|_j zSjJ3KYi(Qd9vb{3#AcTE^9m+me0ssL`Q-d^q$j6rQ(kOk30NzySgy_Do{INb5BQE4 z;b;5ib!C*S+$7q|v8SW4U))H??3+eie_Q>)^mH}&H4@4K-8p8&mUvq&}+GeTPKe&|p|Cb0!>q&xA$a=Bt^0svX z*yId2Fw!weblvQ*vC`U#AR|rNb!flwnBP|fxyc1U8db~v3GzPWPyi!cH5a&0godDz?RC>Dtw z&btxMPSLI6dre0 zjaCj|<TT zTV!*|)ad(IclXo4=me7(C3Ply*mpPN=hS~+OiA*NAbm1^-nn0Y%(-6POM8Qo-U@DZ ziDJVrs@-nQd9DW7DRXa_Jzg%wcLH6%OkQ6mUJ>Um?Lk(zkgXZo*{onGDUFeq=qF#p zx}QMm!3Y9Utm24)vHM-%FM=CvqM8j(rz!kFdrbf4&j4L`Qb4COw;_QvD=RA@hizfk zqahCZ!OsVZ$a8;8+pN$R<;=r|DNgpn<5w?0o6}suCV)7ce7h!MzzV(G{6tA(fAH`UMMm= z;PflDvw1-4DcdiqjEB*)8W;`2A*3asG8pgfz)({|K3!Gq{rUZRfUO{LB*=fX%|8&9 zClG}SB>FePiMzV%v`nvh<#>YpfGLj}p!X!SyIdczn<|%<-+v@q@d<%5gD7Bx46J#B zI3W`gvcA6lnd6-;!zGCG@f;*FPV>jw+5*a!n|Z!Dfwpb{ukM&(SQkAW#Q{?*MvB&t zrLdxJG;eBZnpj_FSSP^XH)FG`)N2&-nty;sMmz=s^>>g6gaw}TcT*ctkchr>4?M^I z`Ojw(!Y&DhY_M~LK>Bi>U(L20_Wkr)JnP`d@?qi3P->LKF^eq~^IODz{^i*mE9V75 zA_l0B>Acz^UVl<;vtrsm6DHnBe?IGl*U7*GC=-1iK0F-cEGoDhHZ^f+6gFlEOH?AI zp&>%41uXA~S{)^QYm*K)mOu{D*JnZ53`wNZ+!JxxOX`AUqNM!3hqq@YwGW>lcZGm} zs5(BqcvX`iARv;41Q`KLm;6f?V`xBrP=j|04h_z`17Oib7ER+D3msgmh|A@&vo*K$ z-PtehhJ&n_ZEhz%zv+yO1R*7ExGu~p(h1q%-6YyO8B=$4(3qbJ1~$FZR3|;_X&oH` zI`e}k>eXC-x4;L!`^@+BkS!=Z(a%t&~=db1NAo7GZCP*6D~=^YtE zR4&}4e2N+{6*csAQFG^!5Ca?_saH*psuSf*N^pt;a6okv0z7268 zeZ4rBG%_x(bg;eupdvHURx6_zJdlSBnq8y`)sw;VuhgKF?|~^%a>@UUah*h;u0RsN*v4y zba!n)yW+plXU)8f`t|=0TY`}Qs;0g+PM#2k$N?)J7L_qo2CKGiwre zr-x8p#J`!vpKzrKo)|wF4U1ZVj8tR}^fY(O2qN_)v58xPL?xVLv9m0Ib#HXkt%g zif#I`%+Prbf;iL67ow-ovSG&R_=JG}o{;=dnX5otm1sa<;2^!7ssNDkx|7QlLy@#f z3Lau4yiWHl{c+TU{gW<27~=!_n7$CgdfR<6YK?YeUw=J02)cy_28wU=ZTQfp-&Ytz z<&cm-!D~~)dgd!`!R+<`qOZWXa>O}y-Pqi>*y-enval9@=0`V2D7g}@XSR@=);YIntnItt_M z{q)oG9j&{qy)Kek4W-ZBt{4wODn?Hbh*lSVE+af&$QgNk`@Cto z3Lf2a%MUf5_N=|%9amahyV?C+^%DST;oO3P?Q`#U96)5cmC?^bv{*=pDj`t}115}d z>Ij|2IBVEJ5*SG&=F$K|-Wxy#^mw*gZj}J`6pwF+F(XJcaNtK_uNY(c1*-)9#jXn) zkXU|a?W>RNM~u^*?N7z{uyhJz(u?1@*HMvT4bIlC%k`zg&gT zLyJtL3oF%pLvU@z^`TiMuW-3Uxx%`O&~GT0b%CqaUpNi!!~-&d7(9^i6QN;ijo(PX z_E!_d-0@3YR=hRbu%>#gnd1mj=-aF`9MWC##Wq_m+IbvnzWY>v!y$t6*7A@Q2#AeR zBYHic;S6cpIZD)$;YT==D-N_l5o2VsqtX^JFX z**8!=62iF?v7E_o+oRT*^3k|!=xbfEu~+MwDR?;6fMsom5JgAOX5brY$MrW*W-`JS z>wV$Dp(SX2#)qfl^8IcHG}hqbc{gNaBAe(<&3fz2yVK>|Zvoj0PeSUO5I_n|8Tf%f zLvASEfcL*~{WheFeqY+y@~f4_@;z9g^k7J6sOU}idk?^Yk%>xOGSwmP$2~UB1D1LM z4!HGN%VFig|6}SJqw89?c7rx-Y@@MlG`4Nqwrw?b8Z@@mq_J(=Y3zP0J@jV`-~u}?oeW3Zp`ZsU?ZV27YSZK_!V=T8#U19}`vlqi{5XflyI zz>;#T?7DZGLY*=M;2@?cjth5NXbv21kCn@H#@2hbF*!UTY}Z;pN21duU+);Mq0xgJ zTT_#L2mFLQ33b z&mL4zu!(y+{@A|Hi=3XCI!Yi@^wI8D8aygLM~MGanrmvlv8^q9Xnc0SXH`I6bF~0@ zRXMLS90P~}jH5=RbOWMMcGvTA*?ORjUQS6NU^}0YS@v7zN08mv*ZY$7s>X_#AKBIWVY-dbBBTZ#6BGtp`|M>jkA+MQQ1n zTX6;*GU%BO^PYX*-w$@26s4F5y8YWV0n`~IG&>y;adIZzs!ua9nNqxafywx*uM_UU(HOO<99iV!a=jMy`98|nf#(&SI|{pyD=3z?h7LWQ>cKoACX(tRQz7I*SuIrW3%> z+k-~+k53KS z1MmfH?O;zZmu-h?o{G)@0p5v+Pv8TYjJTz zJY2e4SOBdCO$fNl!QA93iBN8d{HuKCHCxXRg><$tJC#=PRi?b(05DLp-zHvneka(f zQ3R<}euY(HcF+xW5>x0*s0LE;0*$3#)12|pghgX+2}Os~xIIsTW^`m;g;WsJA;P(2 z9+ikdkWHT&&z2^Zjb}|eYW-Z%l>XNT6C<1hwSx@YDf~as93l`9DTOrH{{n3Ok0OAZaD5hjz#*rFFj@Xus4)CjrCBu4rXUGuFw8`PN~{(*@+v2 zZxFLMW!WN%oqJHAu7ip$w4X#}4+$VJkB*KIAe?tK0s;b#I9jUK8Y~xbrv^Q3hhCTL zW#4(36ToojZgM_k^8xqmLtJgM#t91#FSv_)rzHO)7^*qj!DdOSLuE)L6htWwC&*Hh z4Ab?@ljX!QZ-htCJv3N~pzIJ8XE^d}NF!|eix!1aL!cTuI#|(3v%6t;AMS$g@%483?-N^_#&DSKB#(#?5UjVc)1!hrN=^@!mbPZXQ56yToGO0}ttj2k(3;)w!y@ z?VZ%Yc9s@lGn;ztDEb!ZkqtX2~T?g(JR zR9A3;6xzNH&(7#4ChRbxtLX~OCX<=q6-JOMq-qb?jo-%@OsIHLk4;Q?tNzQ0_+#}j zO&K5k_v$;P*Q@Q(c$$CcLN%Lrp-)Zx%6kq@eH*Eoh=h2@x=q2^lM5!~uKA_-JHfI3 zR6v4B-zEgWpTtU5p&8ORc_7ydbL?z|=riVi7lZiz;W$bFWq&e5Jh%ttWJFF&;j^*} z92^=tkzf!@BXdD{JyKE4UBdl0QW)V!^~5hy$~ErS$v z-@^(~N!H;ZYEs#kN{VI=h@_@d+5};DYNGagk6Arpt|0X=% z?+6AY{>kvzAfWSs09N4`OXC7neP+Db;=)1NoH@6?8DmZa)uA3jJ~fBoq+#xZ`{_q; zY5_B|k~0047^sKL?tI}$f=&^U^QjYqoY)KQ+&Qw9>(Sj!%iaK&0yrUQelcuRc(%bWu>LJ385l_NiFq={Pv5T-hp8Tr7XTiIosgmD1Qpm5V=f! z0s9ZZ$2{vScqWUa5<&Pf72|#O6uu=tDh2v5~6$J|hYi9`v4B(}$Q53+9 z4L>_LP{wPf5@n%D4bceM3_D?yxHy>pR>>53xf+>S?DQU>_K=>N4V%uy!KiHj*9a}I zwEz~Dj{D6=W03J7 zpJwJU9i=ZiU%`LryVjTh-G==08ab8EIN{-zH9gUGlR!BOMVFluGj^!)Yn=M~Sjp9Q z=(K6dUX+x60%}qqYyLC=ME;?=G2tg$4S^M7kTkGJ z0vq?G_#zm8H8hCzPnRp!x5Seu&!WtH3Jqc9ieQwJynvY#l~YfR2G`8otMN$~r!33! zEVq!M13>L&k6TLjM4PNc98FV118KFbVpEH}%hg$vClS{88_tzG7wwLh#+_r-)Tb(a z#iv!Yj&&tPj6e8p1YdulUAxkFwifO$&!9QA6jvB<= zTh&kT)hSnnx>#yk&Kj}e9(K^KA=^$v5$j0LqM;RGxu)L$*M)Nu)%- z54svIOl^9I8DAk<-yBv_6vxN<a#27};qsEm`aBpx z@R11;^92bV395~I?8@eiCSNV;Ihkj32Tf4WI)=B#JPYWh=G+?Jq{~EUX+WG> zS|*hfRW12H45#CQOT1=vg>&PNw@78Jh%I~>7PDpE`J~Olh(~;(7Fg1Ns(<+Xhk1Ex zghupWR~geJu$shhG2jWGFXmSm0=U`jPG0qAV-1v(vOFqSei`*T>BUSPRe9d|$w`Fz z2JN)JH<|qOCRw(G5gfd`)PSEKJcFL2(VGYW$Mcq^o>T@4gZICV2{08yLqj`kP&yqC z;C`jBjU;sQSIaME1gSUDL4|F!I6^V)OKQ9ST@dpg$aNACC{Trk(ccM|XZQ_}!hI`c zaYMSLXQzc8XcHS7s4~m?rp;`Ff;Q(wo7yv^p-R23rn~g{Y^rH09fK9xGwJXJf%FR2 z(-U_e?uQ#=RJa*?N>}HmjH^AX*QaMnewUgta_W%0K;&uHr=lS|HfTxLUwkh$S~*dJ0T(~5O+tgu@x-F-Bf)4BTq7eJ>N}D>X^b)tZg3 zTkJwZv-9;QnjTw0+?weV!xk<-dR~$*Uz%6E`(FW=c}g}?MHaQDWoml6Ih_7pYcYE| zW{=*#1sS2G0Q9ID?7wPKFQ9v~`$L8JCo;-I?Xs`38;)^$O^{B$B(qV|g8cTCYBV0U z-h1>QoqE6~fNG=PNULopYhbPCrCm1OrA}fk*A^?~!lP!oed-pLpV#{{2E}WhjTz>P zif*ji71C+WnrCsm;!pcq2I*$E-10Q$L-d{Bt0c%cCz7g+r3lE$Au+N#0(f|cy6k38 zxg6f-5vKYD05_oa6+Tkg7<8Rz@=cdhi~N=CXyg`y@+!ZOtDz#1w?wu9Q7`X>F`T63 zFek}&IN&${UM`cE^+UJirF1rBlN;rZuWPoUuZ!-lT0ZO)LYK zlQJgL&Y-aV-r)DT%dk?XgL7?;AG^7d!~ISY5JpLzI5w*X1|rXtaExZLU*u&8_apP{ zOCZuIgwts6VI^uSTx%nAe&)4f7@3Xa4&giE*&X+$NOfz2My7x#XuI7dZvmT6t}sk` ztJ_vv@B!Hze$TlWbCb;{K)GdgACh}(YNx)5gkXiB!IVQE+Whmmq!syotCA->EO@U5TAM1oiynSV!UN5MiAvWU4w z6`9y$(drXfHJ-(g5@*0JVI3J+&j0kur0_)!)maS;)9MJsT$*2BTiD#x1EB2umZd=I zRb>&vSI){|t|%u<%d#X*H7IsE?Wg6h(iC4F)x!8fv4KH6C=#37eQ3cJ;}-w=c$ah_ z(gL6q{4kVl4T)}LE^4}Kx}so(_>3sdd6VaImsaztnoYc6dm||uz65lQsWxY)efsM4 zQ9w<@N5kE0ug|@p+WmoCc6-ypVbz07w1Abb5ogMyE`|)&{+4(Z6Zub65xa+i&cmz@ zVgD$_!5pe1WD$hc4rZ`JKA{?qB`GfhTR*_DVmAq-D^uP&?Sv@Y-(YK1048vY0kATj zfdmo;kUpfaXEGXAuRpmrEWA*W;Yb%UyCu@O@b@Kj{4~mu3T0Hec9X)pTvQQ=-#B^7 zkNh*@k!z4!TD?kH^BY>Qg!{hjctTXn6?SVr?vRPngeX8Slnc-{v}nD3;muv`%%*zx z!`)O=Em6fqjsl)&$cM$_Dx*Ur4lUCu(8u3EJdvYuHrzdj*Zz8}j7 zeAV=;v3W>mJtRjG(~<#+Khjmtye9spR7i%I;0|iayp-1SmNtHthf0|$K^WS$1C45B z{nMAI8?6I6*5;RvA=U*BJ6}>eK2RLAQ=gy*-uEEzebg5P);}|K4*0I0o+P5qh7>%H6U8}Fc_?y> zDS$cPd%rupHM8@+pPAcCEJr&=e+qMwVxnSNQAH#ZxxqvvAK?pwT_$E!u&AodM;cnB zA{rL9s`!3_^5kkO#8ik&HJ>A@e*U$D@k*Y@BMt5rKj3E;Pk5Si&zTA_F);=XecPHZ zuQQ4a>`J3CrI|zzJvWzg#bfZ2rkl%b^E*@{@ugZQT%vCLoefg_#4#KjHpm1o4aui0 zMGTW#``HO2mz=zrUXdXv3&=cQHp_A0F~= z6oNT)cDq-)eHfZs4s<7f*z|^tPTqXbY#E$SCctMY@xDi)WKyD!-*P)p+2)r_G9A2S zFMD8&DAC!)SHbtdX~C?AGAREgxkr+CMc$@llKk!HDC75(D9d7->qb3K9}(4;jUXSe z8e+++yRpon?BzQoC5pj(cN7F$OL@Y*il*GOJ#pV3bitr>}iLnW;b@JEwh{dfE{qr74Wb9QRLR>TS#N>PD(vfx< zQYAv|%p1afr82zYQw_-JvzG!r_}<=o;s#v!Zy{uTHRbO7dPBg{B&r#l-f=g4A0s-8 z7!^aHx>BDsJDzDtRots76>fV*Y~uXa1K-7chMXBA0a*jTg1%|g*?6KE)^tzqANXHp zEaVfcJy!}G4%)k4T;|sn7S{S@mTeO*2%U7V<)+;Vh=~}tPpNwW>u0j>LL!~$3}hey zxJ;P9uRX9R2KOXc45*4p?S3KEBa~IS`r=|8>g;)p27^fK16Eb@i9k_Coo{B0B#&q*S z8{-839uT#?9L|ZZJ%AV4i~DmrEtHq|Lq)3(BT^aea)jdG`<60x_ZyD_VB2eou2%#u z7yfOCTkPQ9ps(3}=8Fj);<$GM*9_m+I7I;*|qMp6>U+(`q7} znSand{Qnvn0;D&M^9yN3Mv|r4;kJb|y(zADb!U2A47DGW)YsgzVG@etg{RLMMP`Im z7B#pp_wawjk z5{;Gcu>HlS$kV!CU8BEoa{(nN^dNKycC48mCXf`dKd|%B=ybev3#t*gh#!0Cd2Bcu zD2Pd!kD&jZ1#nENtYO<~WqWdvrm8>M?0!uul#Q&~r=}Po=rqi$Sv!y}C!Mzl3hJOw zKvfNSmi!ejmqQqZHC;#WP|}oM+#o1^Q6;@>gJ!z zNit7p2MUW#Jz7}A5G?&r6fIA#zjrF0YV1~7hxiYtjdhryBjuMhy84I39z!0FPETKe zLDksRCFj%=ep_4n_V90|Cl9slf}~;wiyP`7eFP zX`o9ZT*)_8<{lq6JMLY5=?=VX!kv8&T*u`Fv|^tyu>|&N>Hq*Z+6={}%h_@f#{dN{ zM2ONW>I0q5k<&KesbQ@0EF!1?KP05TI#FCBhoMjby(}N`hAr8HkMoYm4mDz&c~JK+ zDDZ>#29e`5|VE&G%7KR zMdyKRH57E#n>rXS`+NF{+t{!{)+>Qv8HXx32d6EOj=u2izuniW?Gs$~_2Cz4U%9NX z@6LRKkbFqw&kx#~ozH>NbL5^sE0@ofKD2_Ed*{n-=_>thYffg2*IC zkFuR4Z(e=m?gUc6O@)}I;WwT#Q5(gqs;G#J z`CXveY$`wAX2L8h+R(4<+wFQAXo}bT?uF5)#sWX3)}V zOj$$9ffgJhKM#1o{)Fl@`47?jaPityR(aB@jW9>ku2eM$KJ&R5LqS*9lpHgz&U64d zN2##ATVU-^vARKfeSIz1aB7>Gn-k{fxgfV>w`l?%3JF5EnF#)i{xmUGISC2$P1LV9 zI5{QfTD{NEQ1z!-d(o~UouCv>i2n7a9rD&CT<>zT>LiQm*-~OC_m#xDAYtLX zRU{S~=d!!ede)MD8V6YPHch)n#dT6CXOkz)z(lwdkbz1~bT?KYq+bBX!p0^Ce+y_q z6WmAt|ATsEc5n9)PKt^=HYew=8$pue^%|*N^&>SpVX6oXY@S>(+M@W17{@0T%O*KR@kvQR zk}0LyPEjk5kmFo?PYoOG9Ge(c_ZTkhv9)BEkNz-sAo~V<%PUKki-Jo(aCNK2)v$wk zc9mZ)J9|q=HLJdHhu&LrF&jBmQVrk_4zQ0h(BB@nTYq(&8QuM3VQC#A(o1OI3|FJ< zY-O(h$Xr*uGRwiOps7g(%n_}A%yv@#ji4XYZH1`T=@oosYumV==nk+n!aD^XIQ^HY zK2_ZWWF8&#WRFCm(PST)8+p+Y>D^=8W#jaon-LeN=pEJCDQUkfzb5PIkbNOlbYf(H z^}OzdhlB11#t`wu8!)CJAR;ov7fp-&y;WrJ051U;d4a!wK!6jOi?&Xw#R7S6eZX)> z^ow)BgG#=k%|XNxhrhVScG-u))*pbh`fyDE3f$vuQ=eN%KZlR~3Sv?^bNSZw;iVf{ z;*a3K3{bU4;n@aetGBYkWxtES!dcY^0go&2Tths24$tmoL3W4F7rs;GO6WfHN7OlX zvj7_(Hl(7GSNKeaFNnQ$hdgq~Y=n$z$(dj&~a}+_jTXFV(S@i zVP{j5tBimuJhB93P&YN=W;7zs)kuvQGW}2VKk7)bMgJ&IfOBubiEiW%FS<@{J;Fc* z^opRsKYrYj$#M07IowCNd8)0x+ z6@Mul%nc0xR5BeE1E(>Arye5m*6}+Hdz7JTY@EHvzNG4bbyChN?7i=ftcg!8#pvYx ze8}=L)!^VFWAOU4FrfH{5H_oihK5cEKWz=kB{sergTLIH;?l?T}Bj9?fv`dl|hjtJW6-J=OA1HgEmBeq2Gm9!>z4p^WHgy z%mQ;Um+wK~*15xab0)NSbqBP(oLHb!cDjKPR9==YQ9ayU37YIO9WB8? zd5HhRLz=t)+wo~i6n_N3&0ydUd)iSwSN4Ay`(3;6fje<#Sw!_Tkw-_)EuZmS3ePY= zjb@;Wt>3;5Po#eC*xYa3MNu1VvMc!AiY|7dj+kM?D)Hb&_8muO2|K!{95mDwK9_Ij zn`YDUmo8vM^=>Ed99~g=0rBTmV$|TE?p>%~FOQu=t_tSxtO)gujS4YCGC5=LNcdf! za(px*P^t1Ea(V<&I6XAE_CT}G@}+z7u86@}BDBd&i93ovvwC}bH&4mM?(!)Yhw^)R zwjl+W0Yhaf>5JU@o*dp7Ma9=jWIAxKhU6hfnL#qfNI8N`v1+5}08aTwe5Jzp@!i8* zT%D)-mp&p}&_#RY@Qanmh&v+T;GEtL7uiS*sOtKBnm1N&UO%}_3j=MRGUPqt^6k9m z>k2>Qif4sEr_B^&Qf_P+F-HLHhf5mH;7CtTk4s1>mB1Au|I4IOhzPM;X+%^zfRdv( z1qWuP{8lfZ7u?fImzS5{jN=^_#@h^ds$TzC{4DL)= zNU6DOuhd#+p9M%|)xPpsE{bw=4M^siGqS`tRr^|bUDgfI9lsw04zS0uU}82f?@yZ* z^NWtP3R1FEZ{qztLX^)i?N`8ayVk;VWG;^nSB#>1R@2yE+=j_{q%eLUfI13wFTwb%b3ZO~ipG8|LIwS+0{F;)ZJ&X`Fz7!5 z0+y`$rLXjW69I&AOuu`I8>kNaom{cv(zgi7TK8yj=r3T7|15a;@E{nYEdg5OV8{I({)$234NZQVDlmNPYg9C3M}ZX3I3L~I&g z!yQ5rRZqrC!59J%eO-bdws-w$SI7q7>wc1IyDfn}J5C!xI-6>TJ&D;PoPYl0?DRaykYRV2WBL-vz3o7buMLv2uLh2tAv?<^x_(NEjW&ju_r+s{IOk^|0 zSsoUCeRzXT)hPe~tg$giLqCsCqSe}5&cXy$wA<;+d7VCS<8(e9Qv*fiA!8({0^J#q zO3KXJ4`p^e)JJKdBI z`b_W~vt&*{e@Od923f9wdVuT^hV-u~_KNS`AHyt_D{E`hj5qul@Ub*bGzbB79DIKw zM>em|dR&>;9S<*0)He3>H{EN}b5Ab?QD5cKii+s=bx-npo1_I|$nTTq1*msu$uB(x zQ}G_a!C(CS++d%3713~myCK0rDZWd{N+NT@qKCewmQi^Pldmo<9nGvKwUhS{s%E6y z#9V&wXc|^?RUe|m%2U075to+!jD&RB5=*D7O5t9S6@FsI*6^30q}}eDSuml0QvRy| zA^mG0Q->^D3JMI%NgZS%M=^o!D}vRQ87|Z7iTz(A1%_t0M6fJ#y#+>NML08QWiMq+ zz3W@WOxbiddt;xswh%jWq4%EgUN`c00Y^cUTH@V>_zY@*k^PDLh!XI$`A>b_k^CbC z{XR_p`Yl*Y0_NQL>hCkT>2YSmooz&%a{u2N6^;$6nfJH1`i2^ehWRm zIK7t&CgyPsBKM9BVzeW3r*j7d9&Jo&CC9+Q(CV^|7D6&MA*3StSJOk)@sik0i~mPi zcHkYdjG!7(Dws`!fPv`0YYVP^+vTHN`qS-v3~srHhU!8 z6>+oL0w@tYJj3OQjaX)RdRj$S>u|vpP^xcM@HsEjUyKqd02aekf2vc;o1^8|T0K@z zmj*%uMKS_xjG}QFkAE$b9E?AUCDOO*8jE<*T?9}I;%=Q1R|wbjGU?W|Z>BT*G|eim zADfmnOkIfJqt5BvbIAga`=dpeSy^R@B9B+bi=$tzSGhyn$D(?T9chgz{@$lADM5(7 zug_C{8*tO{>TN@Yi=BbAZfST^zR3r5TCHtu9m{5%@es(!$dWp}{o%~Y+8Jf476>AF zqr?UI$|RZs+nng`i`@+-W9f*3NG;5n!7x5)TXx0@L4M0nLPBCCv<-a3@v{F?-VK~x zV_eJkzPzGB*wOLYEq~aXke&>jy*6oVnTO1=On;h2v#H>?$K7fDTrQA30=A=rr=-ip zSuVS*0T=}$u^af60E`Tf>Gw7}&jwZ9`@5UmjWNUKA3wy~gFBvnL|g*ra*F^w9UftY zene29q2-a7LxTP2v6ViEw9uo5)G%_K4*c`yg#nx0Jy%0RLwQ}>?=M+A%`O#i#j?Hu zGVq-@t7gq2g!$>8C>k~_Fu8NahfoDk&twlpPfJ;5FikYPIetyHRE@)78&2g52Rdic z9Ruz2Y8{+D)iN@G$Y96-vCc-JLUAHOBrX5$-^i8VT?qiJ2volr0CB70F_&T%CpDUr ztLxb8C1WKz5FECx!F1hd}fYHsSC}e?J*|aO>dyBh5(ELiS%NK31_zA#PY{W6{^QX{iD+og#F$5=N2ZYid9c5fPJe7#7QJFTY<(rUZLB zuw#ylK-saI`;gtE!;enkE%a`z1}FYG@bxdSA^cEpzV^n8i-g3ffgZbX?IEVRAh&3? z-tBRAY|K2VAp-a|zkc<*d&ywR@qk;Ylu42w6_F+e#j8y0Ad0^;q2asb+kqgMdB*pj zpN6mTTJY_!J>zF3kB$fAXXS!@g*bNKIqLfx02M$Pv|F20J{JpHy5iMOrI=RPrO7m1KV|pzlg$!Z#&8?$B(C{xVZs;Q-`EZhF26+|^l>Av)bnx%4W)17| z^EzFoL-czKC7?G7`by`Z6j4nTUfEskLRMftFlCrAq)82%njB3RBA+o9oVmsS%t6O8 zL8*l0H3vQI==AB}gJb#Wy6sYrkn2b@*Pfu}3!8{?j zJYnE1>1Fx~CFf8Y-EABRVu|xt(LfzV2x8h73jYnofz#@-LN<$nq(^fY!x7SBf+m<^ zh)Hfpd}{u919#p!)m2r6uUdsc8tABDy|S{R1v~p<#fZO1D6(ZPf15qth_|9ge$?2= zO0CKTMC9{hf%Oj1Co!UU@p@{YxNgR|O5T`y?|NG4Ou!=|<)C%}02-QCOb4cLVi zuI+vO1Yudj?SYEt^To91vCpmeoDARFulYf!JS@f;b3zea#ggqfdV!lIlW`m<(?-C= z+^fsMjO|JI`4ZsgIrtO|(`Pt9hu2O{@vm$55xl3jw?@zZNsD2m>j?=LEfN|s9MVym z|2M{dd#jJu%@g^{(DwqikftF^&HvRaytI2M+x@2!^@F{U^xc^Z-O^sCk zBZv-uIvd@GOv`jOs}g&~cuM|o1mIZ@Bp@3SwMQwja!F{QJIH3G6~RmM{vMKmx7Xk6 zk`>kYnf1HP8hBPAT5(w==+xb1@4iN>YX=yo1G}`?N{j?Hc8GP!Lq1megS1#wwP$_| zUs-*sBxnX}p}!zyQ+++`$PXse7AZEYNm0Bm9Ju2*2v-C9!C&Y+0M;u-=ks~c>r$4K z+nHkz+{WDcXNTs6;2}8-^_da-`Dy!SZMDVC<{2n-9`>*qac5_i`3gl@NOPa?nCR$? zhD<3L@?E8OIA5tlhV8~yrux4^@g}ux2Hl3Q8ylFVEtgFciIZtR4?IO<9@aP) zMEj5eRT#5!hb08%(qdThA%$D#Kc5XiwN;pE?=L^O_>vM*JMDWLxWqfQZc9JZ9KuCQD^p$zr)lZ zf6WWRB?)NR&cbLKCk{s_TcE=*4q$tt!51M1b#5)_UTiz1>5ey-d-q2pt&UO2el0y*Ier8e^ zL<1+_DvE7Ux?IFU;|U2d2A^*~OvVxu?SgM9b`bxhUZE|f)&wXAsC-EyQ zqpDPDaTH(+9VmTGTRnjSa$7oaPsOoUugg~2Vk=kG3rwnQpvtJGW_2H``hE=1m%Er` z$HfYYyE;1q1u8vao&m*C?-^ZNM8H3_<&m8dfs7L4546DHvd5yJ;Taq~`B{UXBQ(0R zi~8bgv%|OO6WL4FSn#l*8h`nq+x@^+Ma+jy&RvJ-i=^=xEFtcipSaWW@?g>a!sT@2 zHd;G)Xb9Vc#Rx7m0Xh{u?APsm)I-!uP3=#&kF1Pvjtp2;dB@wqgawx$;@&!a>J`L} zj7NI%7AAB`TKoGyQEN5J3GBmhLvTFMfiOTnU(}(G{k1Fr2}!XPzdOpmzZ58mlM(0(Lgo5XZAc!c8o60>`guj z21ZzeB{B;4RSH5X1?WQM93d&GOHoLQ{l7$q1i>fLqgNtk7786K+2j2_ccV0QQc%R^ zcXI~?Y6WC~T?fdV?B#o`y2H06?D&oNV@FS=ge%{K)PCOR&|3VG-G}DA;$jk1|!6* z$^eWL3|6bq_5Y9@|M{nlXf1}Jz1U#6xn7N$9&1w>Z41b*JAfhc1>1Yp4L zy1LsA2vYFIfpSZ~d!*{Q{LNkq=#N-29ZXp;srw#}1G+m9p?A&gkZv&Tw9sd>OG{9` z&j#g<2L|l<1u_kU2q+jqom{+!3{v#<>NS(`_yMd*S%{=lW6(~nt2P(Z$$qb0_`p9&;QHLyRuLq_j!fW#yd4#ypr9)E zI5i?sOtc3rjs%li*5);XKa^!kcs-MOWDbiFR2deNeGS<}zl33CrzE}@fOoX2#**D0 zN|Y_Q4(ahppmSt(B-YwkSqQ{KZT|tbPF%|rMS}FQ1L%L8j&UW^zBuZfQyw3|ivxP;OJ|URBfEWxVmX+9AE7X3e zMXD8=nZQmSVQ-~yVo=nBTA*>|jr8oo$ckLgxBHSgm^a{OPcCGCoPrK4$ zuxI?zfgh9iSJcoabfVCbyr;sFD#Ue+2^vG8_Wk+*;3(_E0f$bj6Q+RRH$9~QVaNw& z5UR86`J)~$4N-ZS|C)0i(5b1ZNwZ91qaUK8Z$5qE_VpT2nx)yrjL!++@`oBZHyETz zSkZ{UpP1_#yZ zZpObzc(v1k6iqW~@!k3aoy_ydhFMD^Z^aKFZn43^)S`5++0wkIgyjAW^ zyr-^(D-Pplb}SA3%)Me3DGEiKD*+)d7Q?-bsD%)>L2saaQvn!MMx)^cpDw@61N7-c zS>N?QY5dX^HuoQ4`o_f2YX7J~jUXZ_uI!gU3aQ&2&%un;E2qWE{7s=9ehk73y)O#T z{_&7XN?y@PD7VJjGE!P(I$6X#^gl9~LDr4Bw+j9@P6xnwn{~5a6`I!BSmP%HP%xSi z%4OuI$tYc<2q?P+c)jx;N=cc&YKQ_yuGijf?teSUaAJ!1&%W-;Yu*s8)6n)E1?1$C z7a=?=_Qu5_MiRYC?mryhPG~taTPEuX`KpeqG8R~x=eS22IhM`|#D{`mF z@i5R7DJSA+@`oDxh(k8-VM~qsZY@U+D1VK&v9bcUE&W|QJv$qe`}p+=?o<|D+X={U z>nVVLNxJ!NCvHfXYXe$j0u8l>7+Zd6v6}-gdagJ{?tbva08ckMAwZU)YLB~z0>|k! ztx7&V5ga)Ya7Q_+GF;&8){glsp?C`mKu)|yBz zae0sUG4n*BuoL|ubBll6An~3@Hnux-y|HWVqH~TzzD!F;@GF`V!qyWn80AiY47gtX z?4g6b-v202g%0n4@710^{lOpTfEckce`NkQ2tokGBdInTQncNd(0S9)u#N=>6lzhQ&N3V> z1;@*EPmWzgscWN7mc!LD$+6yn;&K${$lb9~rKrx2k7VDRX^a&Z@ebauT)~iywxAqf zN!g%ZO8f96urNh`59`odg1YW>k&}l~9|3pKK zV!I*cdp=*QF&t#?H)C@SnoaT#IFz1$ z`#milopJd`cc!Ln6HaleQ4q87clq|Ms=lR#1zMk-mL;=+ff_LnPp_5=z@Y!D?*K z#{2mVEtxlXr7N~6g|N>bJk)N#ThL2>)ZJW+hTZ--+Iv2&5fyTkBPLyTbR-tP*Izi) z?z~$+YSFuZ*tFW_sZNa27|le%Y5U}% zpe|oOd!GoNWrG0djC*QOgmN4yZpe<7)F_I5!-ffCBVvDHa&jYLW|dgw*3-hwYiOtC zr!43ej}e9!MS@x-RK_)nzy+``hb$BF-Q+rERN8~k1XkrWoE^cvFw@n~Jgd@(X4ck) zVd`uZ>NP?t5vkHLXgcLu&I1-If++d}WYtz0&D%u;3E!5{{@NDr6?J=3cbSSkFt+u# z=>O5G?%z0zF*8CLFpA*+a1}VY*RD`^%8_if8rd!kX@73(YM^!rmeG1ZABjHbLO*y> z%~Lp9+BMR18AwPKeHe4rx7(rld?I+*Rg5zXi=eOWdbhEA*jkG6;X^QoAg8C!2-J;< z@WHtYedd0E14#BRPao;E+INIR3-5igTwatWM7d3@u8oM z=X%H`RoCq!L)Qaaa6)6Zx*MLcjDYv>=R}-QGa4S~d^WTX{O*u$-R>C^J&moY>ZwP= z5z_q@%~4n|5+_oHd7G96MK;Qrk{;e<^VO6hP|}IrH%C>g&vob|zIm4t-2YTKLfx*= zfP(=|^6|Yt-ufATAKTb(v|A*;N8SyCg)FsT(kGYATwX{!o;UmIoB0TfXX`PA!%jqf$-BUN;@6LZBTJBvT9d0b z?0&5X9GGgNJY5@DOpcC7T94jnSolm)%C^BZn^>=tD}KlOd3e!o>}x?$%2z>ytSJP- z*oxmW69P}-;Fg^U$~Uk&wQwSjrSWM#Nu8UNBGj*C!C2QK@=IMIn9TD^OGmJihgGR7f{BG#{UM~v!-^&#y z^@Mw8Wt>()48-zZ3$>QUq zS+{LH&#dV~&Yd=_J-$5M8Xkt^+OM0zUJ5i~$Bx7Tg?d@Rz~^62gh2Hpn8Qjht)gnGBaF)$d6r zIP+M$yL1jDwPl9O@#vX}*xCHs zeZ;EdWJZHJ=jnBUbU#mF*;uq5u6-!nuYQhTmBt`s$;Z86kE$oMp`=0OU5M1RmMxJ# z;SoN~6S66EJh}>Q`BKb?Ykl8?IHhmHB#c>_&p6lSHyD#geT6LoDFVgtVtKLIuS@fA z{S#38x?A-;yZ#ur`d8!5}f6iJ`8oBq?)wvr^V zs6u24Vpd4YhT6SNkEvTzH7K@LpMr)g@sBYjEc{De5ocsT9ew$Gkh;|8*9~dLM#||_ zK;5KhacyHbKr<)=@`+lTwRDu&L7l)uD@r0a1-Hpg1{GuGbBtxE^5OxmJ3CsNBXfwZ zx=y;=ii(sJv&~wkOr+YU4p|of4h*#1kTj(FKlS5B{@rlBVq1XTxYEmh!f?So>rclI5OPX|ACrCo2>JKH*?Gqf)DiHsu$93xDZMOY z$--!y9-yFgEjrM|qqzkw;xYORZe}ETz}9mV1^PvfA-cS%YlU90&s*B}-}_>kF<0S_ zb(?j*uHoNVkh>OplHa)!raawVUpKRhsHx2{wlwqaK{zwuZ+9H(Hv4vMMc#MIoQ~g| z20yhm?YJ-RZN6q^W}dE?|CYVJZ9VMvSnWKa!E`*C8H+c?)PFR#VRPa4LE_xNuNJlH zU4`6-r5{SQ%(uKmTg`mJSbf^n!LmxURz;1~W)!cno+&9jF+zFu+ z_zFR}OJ#hY7#PF=lEcifx{{-WGgG+0A?f+e+|D7YB-y_Wo4LaZUfNHK(uYVp=9bcx36}y%J;ydCgcY_q@kEmL?5~O}JqhS+mO$6{=^+a6 z1)P`1T5d2*CP@wTxfF*@tJ7%b<2d!U@e8vWixa#v)N+QhGG1VAk0h&K+bADK-hmc#*fSTb%&yn*&5sZ$m65vMk=Um4d zx*-K;{8f#FAVV1lr+8AyRHXw0Eq{OExS|KCQSl9!h4X&yjone)T0mUF)xU4A8Z$D# zTCk#_;RAqiiJ{qH{$hnZAM)qhv#Cqu_sVD~h zy1zt45%7_PA3kTo?yYOJI+c?A$nOL&f9ANDO^XVJc<%l_H-~PRY!pffOln4CkRmmh zCJrZ>__LK#4$9Pn04so6`aqL>qhm|d^NEgyot>1JcoO)(@l0+heHpfvedm`)X9K7& zVuS@JeXa>r5)8mH;U*g?oh8M{Z>toT|XS zwDUbbSGn8izBcD_c#KF9cU|qlZ1mR_w;GgiXy}o>^HUv9USD0H5;k=I<6vQUHjdbD z_rNs!a}e>mp{bHGM8Si1x26i*&;?mIa)*tiH-*Mp1Gre2C^09~>EwBxy4%n<*}BqP z(&;t}m^(JT(VtGl_D_N8?2{Bm3x~#x(f=-X57>jG=ANoxkvq%edt{#mAk6_uEp7z# zC%?9;BZRC+t!i>=lY51yvx7`HPycn~d7Hs3>U&xsV-9VD_`Nb}d)KVx^=`T^tb_=j@AP8=zWkD`bUt9GJ8}xlq@0(OHw01W|8bA5*qi zQ1K+tkwStC!)4pWSd9D{*9Wvvub+~9ddf=9-$b5$W6+2h3H*Z~ZeC7tN_zmJJ~hLUsI*4+lu2%D#{Z$0sg$Ms1wRwQM0JE=QJX|E@nvS zd4p|9CPqfGPTI`6KKs;U&qT3)E3qBmzk0{6sLJuSGqo|&f+=USM0%FQ;?@#nkMwyy zx$~Ir5cd#wANyYoNgqQgskx#b&Dow0xvjE6{ouU%{uj6v$V^z-0^JAG*~_E9mrtkS z;RCFwqDZ#V^Q%Dt&yHV4RMPg!)MB@-TRhRrs|xc}zd{VyHo0JMlNof%L>(?Y#F8A0 z49@^{Dr6k4ZTF$J!+9v~c>NS(2X?qCFkiD0Qf25NM@OSR2Y{_L+A!3w{>ys7(++@} z(L2;As1#4PUFLs+rqWtA37%e^9zmY|v;! z{^?GSzE!v)Kdf8tB20q4T-uo(6=4baLa6xIlVtkHI`*cOrWYHeX^k87NAK@)ZM zjCR-MJJKc)O;lOf0gt}NCw4hNN4i`{V@aOnyClgO$o%aMb4~d1$+o8^QLln3cv6%& zk;y>*dVZ_=#P@?I^Maj~$g68C@m|W49?vCj#^^KkEkb)wH7I9SJwckg`?@RfYOzxC z*Ra$M&T5rJg=Rb6#$tqa@-!*?X7yO_YcP`-X#p}F-@Pz|E|1yQr&Z}QQLaqv5252E zp4kMxFBzaeIts*kG~$Py(01F^z6o3<;rJad|MpMeKwWjqMSJ=>itSbEsMg-&Ci3t? zn7#k_7U9V)r*kD0kd}BcmqI3IpJ;Cq3*sxbK{!mzGHpI#a&AKhe z$1JPbckMUN?F&wueppfsf2U+T<(P(x*z!?SI%hj%CKyCO_*$}A=dc05AJeOIo4UH>79{o z@KndaWq3JV8|dDny=55+SB1WXS(wo`};fHagj=qR}(3 z4taWYY}KfwV+G5iYuu63s5YB>U{^oWNM#K2&`n$96m*MvP3aovuy1^gP%2Ps$lTU| zFDbpdipVg`izK5qnFnT$x6fcbBwp#cS+wCrG0^WqBD{tX%JSeQBt zJR)i~UerQWggV*GijQb%DAnw+XcQS1ZfkHeNt5);a7+SS+6IEUY$wYNO(8Sta+8Tu zxzWmCw7I2Ie#;p=t(FY+Vj(rTMKFYGCFbyxi zUvbXYt&KrI1VALd2r9ofN`N43N7+3&DZNefE%7*8*W#2XFIlWjZMY#DSub{@lUta2 zE{}jKC{}kZF!UB*h(LDZ%J%_o5IvvKzmz*TgYtIs>+Fw#3qVLr@s92*pTMzJ$>FM; z=oYS<_nz!AcYQ2vx7ayDws%fYbX6qSE&Up#}5UCts9NyK$UoIU&;A z3{{0w_vuTUo>gA(2hAT?4P8skHYwowv9655DGwYd?gZ4jV(Yu3=|+Y*zDTmtL_Rk+0sT=20;qoQj8bRn( z>mhS3$d_Y%$%M-vJ4w6+UrhrKk?+43ANV;@U1$W-INu?%kTZOTFFF7UUc547*0smz zK_h1IYqjYmaV;r2SvW+l?Q;Trg%uinj@ciVaoMLyeJtZ2lf<@ir{e>Pw|LH2GLSKW zA7}jS@vTd;mS`^FM|fCLybk}mt&yTkPzs2hacRQ^eY}X zE_NO9MitKeE|ugmFp?lJK=9;#Ac3Z4p-20O_OX`uEkfIW6wte2cA1Ps`<5UdfT_#2 z!G1ZKhp)v@nBuMtx-+SyPE&%$AJaYzc>De8E?sYMjzN6J`iW{~N z_nwKotwB1DcWCgh1H#w;qrUSUtfSg({YuJS`9~Ri z12OSXR;J>EKZjI>8%~c>Yrtlnl$xt@jt=t(wE_nQr|%65JtHu|Od~&dC^F$9gD*Rz z*j&TqPJF>3F02_29WR}I^5wKf+;F)OpeaK8@%}7!1lVc|@*|=uTndZaD|`0t1Wzw< z9}+Z)*UKTegi{Qt&L6bR%msVO$8%{P6pWlQAWvVUwkZ&U9kOA=O&n#%)<$!WGW+Jn zcc1ge3Uwl_P885maP*h%;1nTO4;1U_&Y$B*m<|`eb&{gqJR})yvnuI2yrP-MHK;}Q zZYr8t#eUK+h+KRAV36hWv1_qMwwIc5K;FxY2ECBY=(JdH*l|9mjqu4ud-s@g#8g4- zVSdzfI4Io?du`#IgyidpkhwXA?ys5+;}O`zK$OD-uxLI=ZYtX*e<2w)d4e2T@(kAC zYa7Ib1xdE<9vVl2sVyy*udK8X292Km4re9l_OsYiU z9#jN!^7FwnE)8bNIMBsON&eGS7RZFKS#A~--7l=yn60T($#jTNewFb9V4Q$6rh#Bp z#k9K!!Ks2Jp=Z5EahmDdA1i^^IKz7X7jwyAV>woJ1!br}mB6TDtL77t;zF3kf+~qY zmk~D=1uv8&3L;)^$Z$j2oSDSr_!L{NL)e(S9Nkdwr^}EALQ8E+C2|-kIPu|;fT}FO zYoyN1hpsX^k(iCyFlO$Q;&n(<^E-9Fe#zRau9da5%C)JS_y6$KjDW4_b|%xJOMN&{ z&H!6Q9;$k-{mLYi;Ig&LqX7djX=y=vJU-{wr+(aH8MKq(+sXG{r#tQk%wp70G_zp@ zgURurzl&mVsS>d@e~=;T8b%2?F?YoL_-mRod<=^fM39&+`l} zuRs@ct%DB^_3T3uloR@MMsqzhFfh3bpC6@Cp3qL`z&8;IzK=xch2^G{eePu(6^+sN z5!@UFF*iTF!XOADrxfyodM76Uvhf%ge>J53DNhWM%*@Sm?^@*Ta2OksxzU7DeU;5C zls>T#CX@%x;?pZ98!o*dmZ{e1N;0p!g&i z|IFssh+XSS+4?yUmeR+JbQOo(lI(g;PcZ2J+vEA+tMX>Y-PN)x!|}@Zh}axjHbm^A z1S--%n~(#lSSYx`P3mcNh-e=fUvVA6!JxR9x zvA3oi!yGr$X}>=MbBogF&PjU&Mt(X>dTjx9b*#L6ojC^b!Rl-uqA%9KGg5r<)A4wp z#4jv4Y*t73c=?M~^Mgc2!GT zIK%J^r#s%4VMnFgKF%jebL$99%H|abtf)e_rkt?$ z*hsTq?fF>eyGxqK;u9oHnTq=4@>u)VPjRNM(gbEKx6PRJ@|smVmuPJ1RAQ~r(EJ`5 zW23j6R0f&|RC!tnhI}^!m~@(7jI>(L|38bYkdd@VLw_Hjz@eZnT5+-tJye7I=&G72&#Y%!G%KDxm$d zz92-830XMt804$L6=kW!9+M19BV)OJy&5{-!j9o(8s-S}dhdEHIGk}*ZZ{&OdV@W` z!M*{Qu7CIS52ST8YSxr8FOf|10|1a@Kt^6HZ3%a9yaK^dVEr|l5IY2Z@S=zlyrt!7 zDD{c$Qsz?)uO;T~jtQK{6I+_o1mZk{H5<6uTaY5KS9=oUg2mI*@@6%@eZOLf@V!)G zVtNCUORfkWQ;j7h$0#@(!NY@9#jV$%zCH5yJ~JL1+YI*>UhUnAZe!v_lw0Bx!49tY zXgphs_JS6ilte{C0^6u4&6pY@Jqe!VAdd|g9GK8*)S~(OC$3Iangy_?iXo8vlZ7|{ zN<5+|2`ithUID}2$3AkH&(doUIwLx?>ebzaAq7AFC;WucPUm->FA0W2_aF0I+suXq1 zbP+JMl^o5r9}4|#QK1kJio#Gnd22~b{s$=Z2`ppH!T2}LyWS2uSUxhqKmrr1zDyAs z{xPJoS_MF7xuZJA$|azoZ>UtPs@PIl+khU#Tso-I!RK}@HxvdudLbnv44=1GsiBGQ z-)`#gehwV>ddgXzZ--!Jwnymcwq|^^!Rv@SQ`#C(Q zQrafmj=QkSu4@zYLY*yM?kpJe+WS+o`I7;@UO$3J?&Luo(EEEYo}_+In_|CN@t>+y zod(BCkdNx_!NSq&lnnqQzxcgjOoCkwE`SEOdAj0Lp#Qp5Np35O-GtA<-O5naS0HcKcXyNa&6Hcp z1Imts06NV9o*^%X7SZI2V7ox`+$9|OI}EC#(#b_8s$*wt9y_f4qF%r&q`Oga1Ib&> z8R^cPtv)|P2ewmUtQ+ReJ!^hmGt$EVZF>{{huH`rv~+{>W2pmSg1$wp{o&N*FLw>- zgVnEE<3wi%DD8UUJx^!+F}=`HmV4%31dZX`aR&2VPns@le0Xc`799zfzJ*J}s8kO0 z;*R0s;u=}|6N~|-QZ@R4U(DpU_LKnv#XIX9>{L;qDU2i&XvzSti0p~WHDd&wR%kYs zmMT&HTd|CuboA|)cmchn$Z-vxw-h&1X{}Le`d)j*&2KMC(^EM=e#p5Kr}Jm`8jmZ~ z)HmgBF7Ju2HXFx~$*?dInreeB8mQy2OBhU_o(yQTi5XedjIQfB^X%b189QUtsM%Z-`ZC@~M7nyQDVW z@nXKTxPnou!4BIbNLCem2cHcX3E|hECi({1iyfG=RqJ!%KT-1BQh~!OtEprNN-nbP z_a;ZL$e+qafOx{Pv$DQ->qu|8?^Li2sNyp`54(_Yr3&8*$nJ3{aVm3u&-K+Jdfe;f zUk_J%%jHAd=ky%KKOCU}ag|Jkc?~|f45`M1aD{DcQb%*NtklFQi&hB0SG5Nj6i633 z@l(EB09QZGbDrbjg&99@O6@-hLl^?+IbXu$R|7o+7B+1{6z#F+7y+cnf1^M^HQF_sZnkqBGYT!qjXhek_V%D4W&t&iX{A^0rwn* zX*`kEzc20y0O0!Ns-;}k5|^CF{;N29`e;d6E2H%6{XJ{nVKT#4!H}+pzQc~%yazZ0 z%#4BX=dBWZ*`dw6DEMMIv|Oq#r~!Zze7WWJ@TJmW=K8})#`6~T_Fnd`Gy{0yhYx4Z zc(LA}Fh8hZB<>LQy87JWdhKbg^&Oaq;m(o9IzDpk;J$8hWcl78t-j=aFyo75_i=&p zeXSHOv5Oyf_wn1!tHHmsv{oyNxL)o%ru$pGU-x7s+!MH)tz4BAUY02?Y&}uev9Nj!u{*I&yk4 z-+_KV?3b%HIX>k#ZFF2|-q@q56~)efkn6IL7}&2%l8}I8p&!DQh~`4HhkHkYFG5w( zpk-S*iebcevv#rS390ZbL8|D0xT!Y&LZ0R3g^5C9mSSwpD(kDjTfa2r@G+Q9V!pE$ z+}8K0N&J5I>w0+QhS?!hkN+ORCi{43ej?oO7$z3}xgb(vpY@nZ95D;_jqqjsuo;kr zab8JI!xFR2IBe~J0MLhzn!g00q{BfxVQd!@i?(sor$Cthgy$0gyj2(-G(KVGp=w8& z?h*ab3`yyzt)^O~!i;~3nnK-(PWD?04ZdY>&0 zZ^M^VfBTRuX|>o<9S=AbvXSV19%56`5wW?oFl&K!KS}mKqTBZN`q&z_E{JGoDNO2g zG5LoIkH6IkqO{@17B?jh61HvAz3QJ3qEFUeK;2q%^Pt6O#@2rl4)0657&*>JToTZ$ zwug{5*@Tu_+>83>j!koym$n4O#1L=YT#F{GT9C_YX!xh5Vgb^erLtdiku+HuUHa&$0L_cPot(;jAsXJVaIBXN7IgOZY+ zgaZ=mzhh!|xSyq>YB8<@4TLCZ_XZajn0BDOc85nWkGnIyuKh9@tyQz2(dhSve0aK> zFGTuE91qWm<|P9faBk8|TzW*Y!gNA$N%)A7GJzA{knN~%^_Xx%eM*;ERMElB+d^;@ zQx9t=bmlvzY&c99^t~4mT7L+t+OT9jm9MQso^^zX*WT5pkg6ai${QWOd_u!Nk*`Yc zqzbXQ%NKWAcEN*Oa-7p^BQR25efrZh{ObWOf=g2mYIwk3ropKFBMB>8stIGSjlm{Y zsF9-&+^iWjrVIZ_*Yj4?uPHe#l7p|*VBmi`*yH;wtUK>;r#J04gvd!quD3!Ezt56Q zX+Xgt=^t@z)tkcDjkm+`ij8G zUi1VzSDc+y#FK^Cyg%GlU%&W)-Wi7}=pr_87+L&f*9DKyUK9G@S+Qz`8}s|j5WF}3 zhaDsL1_d`$E$}hbg%X)5Jw9|xM_5UItDe)<&@!cHO`t{#T5`M;0_C z-Swfa)tD*frHjR_ySz6_FF|}BJ=66Xxv_*X@!_xBnIJ-a!}nn6h&)*w zYU}hXX?h=Rvwup-`Gik-5(*P8?m=>&P^6Nj z0-{pWXT?Y=IKgxnumORA2X}eT2pQXkD%OrZ7xfDj>lwE(o1GFP3JhZZTteR~cmFiv z?sVS{@-J66N1`5T8Zkh+9EXF$R+)jgZz<;-Ja2dRS4Tq$xnw3R4Kd_DaWJJs{pvYB zMGu$T;2&JJaeNX0c<(t1=@&fo{q+5p{s6lD!uet?)i;=g!vLHBmxZu;v&o4nt-1wi z?rP0yj~g6@Y0;HU-GAYWSOJOz`j;)v?9>``Y-YlgX5vabK9ut=0w`mN2Rx?z;Us1R zL!u<^xA957aPGwp*Te{Pwe`P^q=wtnDc?I>iHb0eoCf`#QIS>zQ&$rL&BoW zZiU)0{)rxj2BJ#4vjA_dLWlATg+NYS9r%v%cGzW((w{cy>#H4#j4TEoo`6{k9i_8} z+A-A0lj8*@&2ru7LaCJKh3CJ!^M#Cfb-8~d+U|+{-F-^x*2=ZDJdLry*^JJ|c=qz9 z4}MY|!x^cLhvEjiKSBcy`wKL$ZySo%4UCc-^ZURl~>l^w}suf|k#G@kU zawrq-iwg6^%V=rr+@Yf?5=j!2XGFwfQfu^jz*4wc z{>HC@{{4DWJ;AKds_hrafY#LxL;zTza;BlW%st%9UR)~eYVWi3{D$DjKE&eUB1Q67 zw`=0TO zKW50O3yH_R7A)BDrM-cJnOBOw>n8%s5%tcz z5uD5zHpZo|0^+WeGk^Ykqcr_tfOg9V|HXh6WnD&{-G;?r6ld78cwmo|=^w3KB(P55 zoZARc`|`O~tD!6W6N;i?AS4^0Wns}|TcMK?^lkCY4IDXdQ@6uKVuVI5%@X1Sg@il? zepi}}Q-TJJIhZzHy=^AhD3=xfR%Qj5oLC{I=fsXfShp^b;r62kzw{MWq@;h-+|jh$ zDu5A(<5usSca=%Djo-ac+svsLW|@Fa`CjlVlP|gT1_celLU_tRLO?`?j#!?4?eIWX z`!P$x>HbpS5;)cvP+3`t)=MSray`a&FY$YD<0*q({{tjsq=FmDb3y5U)~ZNS@8#n# zCYOrK)HplTyI^RH8(i!Iqh;9`=~YjrVdKS4dJ4UY;YusnSJg?wR%aI%8gq1G_z6RC zV{xx<(Jnz;wHubIxs@>wac z2><`d2KI$s2$UUAs1UlVWkY|NvtZEgAL00oNYH7+g?cr5ld4+ooC*~mZ-EuB@M->n zhK9!C&y$1j-$9b%oqw9JRajs30ElFxuD6aIja?ye3miX*RzN@tfUw7rRQ4BDkR|VA zMQmqDC@CdvoBjn+U7ChB&U{kl2*HuRZAylAkioi z9^Z^g1`0+5{G9CZFR!;JH^S3P0R#769d|FW*Y~HqcWrBzZHQ+pPnl;Kj>Q@n7#Px~ z1A~;}W#re;QN0fjABr57i9u23vHiot?FCoSBVxO^VhNqCPFF^CNrUb>ydG+SyVOvP zp`5sk%&3W6w0g_(vi6)~ELJ-sE1cX$zF2HW7@5F7A0z}Yb{p*!Kmgf}rJqe) zPYeP{5)XkCu*u*q8!V@ET?2@_&X9nN$Wrt7?>6&J*x1-?_~`!7L{Tj82mTB4Qtv;s zMBFVu_0ht=x5nrBB6LLFepz0!o{%Icp9Q8jTv6N)B0#G9uDgrE-2BL0RZ>zia7i4> zqEAxZjjhiR88M)|yz?#z-HNpSgnq{yrx+WfCIX8gD6JQEX_AByYHJq|xfQdpJc1Zd zg@Lw8>E8K;xib`(|2o})rn|yVW%CUL`hOpRL{u{?C$+G{++5JK?-}1ZSm7{nqX}28 zui@xOFft^ljvzGCZN()tW?FlNwP0bdrk0m!ArT3fq9Y=cWjGq^nK?O2N0SN*3ak#= z$#$w6EHS+|8zG{DCHx@rLInQcgv7ngnfdu67k6~1AmA~+*=gNf40lK42SbPx-2<*u z(>LjjPj{wd+}xD+@E=M6=Wmf7_`~17qljENRxfk{&M>ezF)=V2sxNA4J|nJf)!)s` z=#)KI(9+SBhyElN#UeDC^@bGYaMg|Erb?4nmn^L{^Q9vRQJn8Wa96Y@FYEN?~ zI(pLO_4Ig92jY@>HP9t;aBu)Cf|{50=Ai_H>~WS^C9sw!>)23;K>zo#Bk;#%uaaEI zf*B6m48C@E|8R&M0IQdIcK|0Bdu{5C6Ef${Q2G$NdfMi2+2rf0b1+5s+geYyxViZ! ze?W7yoBa|PhVLGJD`+U-E?Eh9->OaW9n_pnM2^_Rfk1!B@Y{p$Q!foBG&a=jiHT_& z8H%@p5d;mCCL*=V!RtZpvN#5TcKaq^Y8q-}Vp2NSde?#4_p|#KI{TZjaNzgPm>-w_ z{82XU9!s8@;$3XKcrqzZf%#~Fl`=WDyj&3#9c@m~;Fc4#;dOVaY%FlQv%XMQEbXpT zY~2tZmMC`b9Tag2c&$f8NmGCNMdf_);TSPbKMuBB0E;i_P}+X*T&tQEACcwN(!>H;2%(LeM?u z^zx34mv?2`DF~c94e?U#H$19;PY)=k&vTH(ApT!3+CLNd{PzlVufX_k>2#qnFd4@y z>(U>#j4zC8s*8O|=b@gagk)JVU|Pg}{n+X!rf}eaNRy%rua$o=4{OgMZm|PHSqvHB zf`$TNgr9CKr!Dr5-f)YdL?X6nlUhw%UV5P|q}+<0{r@JLegfz{m= z8+%!)AL7m_frxyESMD3)u~t-8w$e0eztYqIhYkt>A;F?&UK9&>^vUq%2ICxO(=t14;HqT~KwLW~D5omGxRy;GDhZ_W7 zsS8?LHDOUtwqGB4f~Td~f2j+A3)5ZRZ+aUUed!o4^BREF%+l7zzl}kf zfrjp6oWZh{{!MR;hH0%rt2)p-5i7#cJPS2_wxm1JxVO8TM9d)yycTkP{;z-wo+@QrW5xT-mIu` z=^X}WP`s`xK?z#i@bKqw1<|?Z-W#v>-1UH#n4TWNB)*A^gvP=`5#F^qOGiSFHXuz= z2!Fn2#KVmq^w8)O3jw)=JzM*Vn>MgO^S)!;QvD3!`k-d~tMkw8m|@!C>*_{D$+l+- zfWLi-0TB}1IzvL_Y$bY*nSsUnM2GCMK)1;jc;46CyB>+j;}RWk#KO&8j_sCOi@#vcgoY?$u%-fHdh;@&uXW) zCt8YXYPJ>}^6Jh?pr`*!9e?Ezj%0zZ@6!?ragh~{yh|r`qM`#Xa?$hd5)#8S z{{z+cOTImJpm`-UR&4G!3NEt1sXfd;$q{%$KUXNDvfwiH44hGe%)JN`j7c_^-Ns8srN-u?rV3uo*cZXRbA(11zCE;mQyUTJ8IriH>|`FCyXhA^XlSb}0V}I^Ygwl& zQ_o@}Em#NGbbJIxu7XlPD4YcztyN$=!q|AHad|V0J}ExlfGeAOmDrDQsvg~K&%=QX zSe`KwB;`IvI9k=TtSrUy2A8xyA|mA1s?5k62+%<>0&;Rqm6u0zKNjHo0#|B}OyBxd zXMdHa|IqEoyIhtYDduyY!f;sl7yvVlD)8zdc@Kqk6&LzLrSZ#u;?TMYn43>NWKsGL zJ*OKTSn>|MmE3|S&oc>4k0Q9(DDx1#ElLn%@)SD#*|@ypiQK*cgT+RMh9q~N1=TQ^ zaU{PcI|XF?As$CTP9)$>3?k1b>tn5kkdpQl^#Jn6mr9z2wY8E4hNLJpi;L)|34W$f z-LPvoF#yL>61Z+!8ER|R@(1B@yDTRXs&ku5yu6fkZJ8l$Q$Gy)KEDCBY08I3gpnb{ zj#24E@;ak-O6lG8l_WAUbJlw;pZPPak(B>?Y=V+N6ptakd%{>!Hcrl?WHnJMh=GJ` z6dF6Ci7*IuuaQKxiTV$o0W{&~vf16E?@e}qA2eWbd4DrMG(2o?^@mMKtOeBt?BxZD zRHn~vzNbzQg~-2z_*}g2{O8Z+6EPosQ1<#=6-_`$83oJ#{Rs7t`Xx;O_T`N*fU*jl`uKzd7UALsK+3vM1%2kJ$#xCHP2ug<_AO?6XNNQE!{rYxOi+%_>0=^jb*RJ? zHFcI{@_&l~lrRjiy1F_xxt^04{P89mIDF5o$E2Lk^Yq+Vm_A^-msmEowoRilQL(YG zubt5W%iW=fgpTI)x)Ks5cnnQ}av)=jfSPH1dOGg&hz99j2hdNn z+X(CQq#-mTGd*32psUCrKt=c2VV5!tqEQZneSCI#Nmy8zE%vM1CS{!h)gs`I3l5D}<$} znFJM;nWEZ@iwn3+1CrVf{2+FZz09TtmGZ*E!liODFjHewQ|1aqsFuCGz0m60{mRzP zPGS$p@wkNltM);l=b;Krjl|tKNi`O_+|IvA zgyL^|&cJsz27;nlyM8Zlu+3zmaLn}t;Zf!d0c$R?iA0*&b7Wus<#3E;JyvwxwdmOBlc**~j z=zo6+69T)quqSqI?C}a^O=Q0Pq1|GTpP7}VKaGxwxkMt=`)U3V+lu=FIRc&a>+H-V zjf&?Hp+bD9M7Ok_e$Sp$LQ;}3UpMdH)o2b1BX&rjCi5p!&`=b=;?wQzph{Pu02+bf zv7TD%^8Jdmxj;isUf6iv353M>xHxl~i1V@GVSwo+2)#81+*>?|T4^ce_;3eQ7ZR1A ziGsL|pCFLXduZf%Z|YV0z5g49QJ}E>E$6BLNqFH|tWOmF_$Xn~(J2=fHFR?ZGQ1%$ z0H@Bl+|-~qs|XI(8Ih3B>Ju&;qO?{aF4ZZ^*972_$;Khc3T-6~OufItz_^^!wcEq; z2>lf_LBLqxt{m5~!J3IhhxGD^j2wY`ghHYF^+g)hOW?cV_|QyCwoNjspoU(VukgT1iAvL=?jxVKNL{}Tg%C2+&? ze|+=+)Wf~ik;MpvoobSI(_@ZtxzV}6G^q~I9qTy_E!EqjKAecArKWxZBqH-Amk^9- zKhe`GAi$W&t!H{XE#j=^8OZL?5?~X2n__Y-tEW@#+f0a8sTBG}i>!3`f37>gA&rLm zU9zt|SEakSe_nLsmgTxda`N*h88t1_xQvy@1noWz*r!jQ0`?tSyE)oRF#NuDTD?6R z>bn8OW=F|wR$3Z0(8#2~cd4zbv*x0tIc;2te{sIW>z6(L^t4S27Pc97=E_e0YL6jt z8}fdL2xR<1HpG|>!ts#=Y*3f?ag1$jWVyIbaa0y>`y&Y#oES06J;4&X?J$M}6m)fS z9h%6}MmBRNzyF$3_T$bX0}wca4#)GK_E|ADd=|fZjJT_X^Lk)`mXm^w+}_^O#C~;@Wa6NUimnWe zjfsp*Nt!`7K5pQqB5HS(961eTJt{L)N*Dq6@KC&jZGq}l!5kyb6mc5V^MD;}aUzZr zriW|;E;H-)z~Xs6gPl3K4OxPnN#%FzF|x86E1Mhhz1|BaAaM8f2?uHYBOx(4*JT`xx%94mf#MbOkvhee}B*(9=mEI&h8AC>O&LW_iA+A1$dse z7Z|?0H`RRl2-1RRXAx2x2Ve|iTn^8vS?TVnFnib!Yk1-h4r#sD*Q}?5j!T$L1Qjhz z?5~H4g^i8u#RqJgKpp3yqrO1X9P}Y#+xdL>bw_!X{tVIB)^_#nz#*9buVO>71NZOj z)YVdEV!uxJj-mzq9j$?nH<7=)yHr#?J~2AZP-1$8ZuR(KT$)nWtG5ftRZ!0*d!^0u z92yFMW5=(Okxx-AJ;xbdKM<1up)ydn1)wt3qN^8&6FjMi|2u$7`i1C!LdHDaGQki< z%zsbZLN@9<9d|y~Dy116cS$vKUOs??d}3na;s}XR-HjObYUJRIG4o@|a7Q5QoezAmQWZ=>N`TSlV{#zFL zB|rluj>P~a<(++g=SmlUe$+Q+T>K&*TnHrUk=AaUk416Fj>=>O9K!Ra<%vm2^@ zRL+dICZ>Dpkv5+E^n9|($)k>TOI5#nC>tA>zkTQOfaShN;cT@8ghB*wFkG(n7C7G{ zupJ1fCNYT}vfj`B(Q<`#Iu6DOTV?Z&wDD};@q)gw{r#{LFDzSdY|Cu-U8TmWtINw7 znJU0uRfwywcqzK0F`<+Q$PeAUVNp?VOTwALZI*`^QH}=(*g&b@C<=o3XlR(P#XY=L zScyueev_5`|G2sesH&c?3rKfLccZ|gMH-}}LAph{yIVk|yF&@-?rx9lh{z!c+4StQk^Cn{+k}^#kD?->uQf;v8d8*NNgPysEG#D6G?bL0<(1OU z4!?%}y1B5fuhwd^$gIS2*?5=!nK9dE$j#5xG*PQ<-GM8-H3lE|jRqX(l&`Aa#-|fT zd9e|y@K792{;B?0oM{co~rdue5eXY!X9MV0$1B zB|WqO{W#dJV; z*5xIy?#lA|y0N9beI3s0feLk_1cm3%d5hLziI|S;6h?)0G2;OH0*le|-k`~158^J< znGatH$*rs$RKfCRliXdfBP1XQ^T}^eTcZ`pk6Xsp)l#Rq*Crij)UAo9P zT87Z+Y(HCeu$_}O$3|8svV4||T$|HNoNLAojm=cm@MN|`{m=NigMV)UH#Y~KVr=@& z7LN;TX_G(j$YTk*mi52H9~&P}-hAb3fK#fm&`>d>arE=vP2bF{V02C{w;Y3%XW!PU^YMT4E$ljw)V|`O zlVXj4UEr32QHf^AfSPiRQ2&0j@dR>`~^V?|+wiSl)he%aDy;8q@r$`pN|4z}E07jJB zh6Xe;M5gz&5DpG%JiKigPvoPe8MEj@Bu12y7cX9b6gf&ZvZ=L}+j+%M4HoOj;(ea_ zGYR&gB z^00s$EK5f%ik|rqvisSjU-ghtN2E%1E$QW$S1Nm46E9wL^9qJ0Yqsuipev0>wT!B^ z9dWShF+@>|!;2G0Jr(aUuKE3{NZ|Z>jt@$G`%E=7lA4JlxG)es$;v#1j7rNY8di~C zXlTrLchE61a$yy|WpW3T*G=5W!9gY@w!qkf5q;U=aAc&Gw3+yeu$!A3vc@(k0`=zy zlB1BMb>4qh5qOR#siHye;LIa2cQ$__*4WowM8+jkwsOnl=H}KPF1NTVg+A^#CkiDb z{BBSp9VN&%!_7TEKVQz4mG|jD=n?9LmxM=Ho#gMfw-4r5Dm*3EFM0biA zs&G9$JbKlASFFq*Z0!$y`cx-5I%n1PSm{5^geaUMZ9qty10)BYA%ICtBihR27SSu| z;OMAEJ?M?jOs&;gn|ZWQVyx@fxCSwS00TBD=wM-P=B5`N&l134?~o%s#A224h4r$} z6#n?W4>HBpVsXF*UaUDXJpDkWxrGB2xW#fB2tWTWNiL+@(U_jM$H4xcHndMB@FBZx z8^cbP4uq+|?u=mY(GtvSJYP}H&^h7hu=HfraCta22Rk(5L+QBwZC>#z!7 zatr6v%KEPRW1Kf?6g`bI2Dn~m-n&*(c8}3%$@wpBQlXoO1<|%SG{vifFZlRTZ$ss6 z;@k*E%XKt~IO^`#eDwpZYZ1WvVvYXt``XKRx485tHT&l)vOK8UkyumN#}Dk9WdQ+6 z=hdU!m7No7Kg>?JxzbV_K$YFDbxH8{uw~I3ALlnl!+hXoV`Xoy*dRUkF!NGF+!K{S85xmBQ|-4=KRrFQ;dgA%0hK>W3JR#I z4~P*cIw}3{VpZ~Ofr-N!5o;sx!-tmyLrwB(%gvtpqynmS)Yd{b9;Rkr*ri6}b z^%lQDE-1j%g`0tVwIlyJ_bsNhP;#m1TGEaj?)E!296Igy7_=^^Son+;mLxRya>{v) zZp{zQ?z$A@lT(abp^Vp^JC8zSZ=Rowbhpx|C=HP7BVUqx0=^D zI|Yxy7U_nDh1p)Lw9eD@yYMhoRzldr!{zF$l>{A^3WCk;K}xF7K`!a#70StpG|fkO4_$wPwD(ngVSFv1u`^Zrz=F!O0U$WWPU^&@)pQIp&-EZCMC-@st>ur+HP z0N%XwDXh>zitF^H*V{pRdU|?UV`B@6jc0xd0!Ll>a+F7{amceU_QA0@XYlyK={^&0 zk3)>l{#`esa9LCkF0R~&#%;l}jiG%a{;){6o@2nrfVrTlc|;(XO-#?lC3kvu7Rh2O zphfYi{$0@<9k^pE_m z=0SoIBl-%($dxbBF18J^%j*7QAR3{hxbjO)WhGT+<~B;<=H{!eS9t%M(8w4$!y7T7 zCAjS@@Hjtx_=T67n{JpzX@6oOXH~S-`^qk{Apgr3EdbOHK-;}3;{hxDdV-uFcySpR zimyNJnzeOw%ZFDMr1-D`ech2^J5R#+rbMG ztc++CDWb^3gsStst?MXZ`KW4;wOrGwVDi%N-*gfRT=3yFG&LWPcpoh_ZSZ~D``-N| z;ERApQDI?iab9upbGgX}8)-jFLu$pbhPSLsda2*_^&t?Gk~_-S&qX?5zlm0gAs{3T z^=@9EXKWC?$0!JWK)84e2?S}_r@=w&*IIvVen9uY=!rEMPXeFrCJKWG=k)|M?ZP`( z1IpCk$S4P(tToeqKu9)q4@Jjr9GHiICR*AUG?+a z(CA~64x{lwfTP1fOsuPZ03U;~J0~qJ?(5)tMMXta@o~WFUEhZ7qd=ANzf)Q8O{EHi5qFDzscXsvbMHdLeco6>zHgPF6o) z-x*>lc>gwOKhm+kNO{Wcg6Pnqg*D%sWx6}+heh)%GHYaHDqk2sLrh9x+@OW;>TE@= z=Oq!_=13A4(3@p~%lN)M0DZqOfw25nH%@R} z39hKB0NF;rzHJLQ3#p)>01%Q_=q}@SJg6Ia;6RgfjJ1=V-+da4|oJVS!!W z)^<^Fu-s9z)QzV({%QAf#qj<|!}x}@2czW7Bo8#V>IkulzFChC@9&Iw_E%(i>l^Tw zZGSZI)GtTO%5i!yR(ND$NZA?^{vqoDEO^$K06gRg$ieH9PT`n#gr;~}n$*jS!r*&1*El_YQDuxiiT zp1+)!sBTIWwLHcDn9L7!IN%BCm{h3sxIUE(oNZEBBZvhX@C(QP4nzPvnOLXS(K|(I zx}Bw^j3R$Pb5Bh=&gS(1t3$PdCTJw0t*y-<6w#fUnhFw5FdS}DFe~+s9t{gXdEf?K z!&Oh@-7!A;{o`S$y^Gn+x(Xro>@v9|_p*5DsmB%g%mcx*t8t4*txWzWr^ftOodHXr z^A5jHxyD!)KdreU=Z9lJ_MRVtY##Xy&Km5^Eic4B;8h^qG~!8MZl7d~5V>ZA5MwCmH|cpXYktTr0| zM;$RWKT(Q3Q;|a$gJwv6p)kNcv*@`p@bdD4l$h%O*}<8XSu!LV=R$hi+v2q6@*Y+C{sT*m9YXs}|D)4|riRUf zl9tVDzO*{$`dciD4-Z0Q7VUfm_$%7mv#7sNz+|MSFQW|QWTRod+ugO)ZIk_pRq`GC zf3YF<3pli)PEJ8Vo02oWj_W!FqzZA9F++UO7wIMgBiFv~*_oJJ?wtn#3%;~p>;1&U zCvX!;Ygv%T5mD&2mP>(J$~zQrTD?_}j^pW=sj@(-NE?gfsrbA}SS$KSLr3Q}=8iWztsgcSJg zmp=5n*}M7j8S{4JvxFE74jYlwQ~X!jjK4!?Gzk8S8~rshoh|SzRy-2Nr1tt3k&Z^9 z!#JgjJ`XTj&zAX~wcn+Eu|nF}Iw;~gU1+JW2sK$szqN5-Sv@A~U}rQGq_4>Oo~)MI zYK_%9HQEd)gA37zP1%X_^V*iy);!eDm|9OyQRAZo{)-9du+hQUi$e8Qhf7T+TyX5b zg>?H$SH<&Y*W6}kX-N>!;B~ug#WG6cF$Wo~3RqaNxvf;!2$HJWrdJ1--E&V61p+-1 zO*~BJh2G~Kt!5|f7NIb+6;)!HJxaS)XSMOVT4@8T*3mk1u>ftm2B)B#UnS*3X>wzLZS;I@7$XbLdHhmVF`Y zw)~a*j8S1X5&M`&WVeBRuM(#)kx%$XmW$td<$>2vN&Xk-rQ2e9vBY!Sf~!7?EQ#jF zKlT~x($dDWV%ReTS;M~A-iq!7=&W9&S!$H<@8pXcs89zRuq@D5FxjsYDv?*$$%nL{ zfP}eN5++cDv5SJZwGSvi^3yK~cq2O*=%5C?fA-rs8rVGQt{{nA08fU?boszK^|rM9 zR8Uf0p42K>^BynMfXJupD*^3CS3TW%q~O}x+Omx9YPz+ja8*@~)wMRi+8y>pb?gn3 z+ipqRR)h%j4__B=1*MU4%27!N%6p!iYisM0CLb}I9A{^?EQ z*``nKhQeh(6p}FQs@}h+79+~AAhdoWXg%1Xd`e70QoH3EszUOp>MuvcU-Qz44o2dr zxA(P5egu}a(|R`&kQ-vgXRRs~9ZA*M(A>+!s}G0J=a82tzScIg4E^^k-E#IR>y7KVkLhj z_Lo7=cL#1O1{+X2SjT5fKk@6*ihUC94w;4KFO%UPs&~3NL{N3E5{&t-GnT&zos4E*AnP_Qg>tPL>T_)=T z9Q^zg0d$o&HNF$_I!^%-=#n`DBV+nGMS zFuhgV4>X0$R*Zd`ZGSx5?r<5HsTmUPcTISTW$3-4X|z_HA@H&L*|<`njB}>nP9U1S zk4n4C&88Q-I!6RzS5ezZ>mDc>pPu*_3DBbRts$wGJkNo7VJrN(Kk4lu9 zVjm>^96fv!@2>2|5wtE+>0~|ZG*>cGSw_ag!`d0gv09l8Z@TueoN)Kc?7owSnn&j) zFD!JDtCFlV4X%>fH2M2WO}8v^pCDpI0-vlAU*8QB1N?oF$xy|ZLmPU(diAQ%VWjCN z1#p2>@RpE0ahP~0X_ku+a{M*-Sr&}AlagXo$$t8;!Ld#YN<6&VK_@#VhmTuHr~(F5 z+Iq)(p~H2#!u>^k^mfNY6eI_UKVCokG>E=JbI=`MF)ZMJ`ys<;%ax!0Xeh-0hv>C-_-GsWSGh^gzF`at?F?|D3v@>K@Kfc_qh&}KC3BXS@_!UK zKmjQl9WrQ0?*8h>oyc?fm(@PyvLV`Pe0CoWtNCOewbrnWjhCqB3~3$k@!D5313`+j zVsD|r{?{eTnzk;@n(jKW7yB--lFCU)ubIE#x1SsJfzZswg| zTr7xlH`LcZ2h}f@=n%5*H*yvFcn_7nyDZrzSD&K3El^(ip*PTbplY%WhoIz}@&FwX zO?$=vh@Ai0a%*AF$n%%x5Yp8*wYX{lc+U<#F2cMaEynO|M#O{$#{zsih**dx^<%w{ zPvSeLOEmLpU7{_GH5Hob`Gqo^Bt>)>!v)Yxq%)8p@~w)q*hAIEG5OcLrkUq<(BxDUj{sS zx-9rZHIw)R4_`k3zLB`tL_9!%AvUHq<-o*C$_`l?)8agjv;Z_zWJ!3w-q@FAT#a}1c+oSsJpHM8Q%p=)c;H8e)}=bp>Sxqn#{ zjSnRt*f$<@f5ETxUkMn*wWSA`n3!{W&ESkSKz=FQG&Ol@8`P6NrSQKiEFyDz7aneU zb-2tRBq%|wGxhp46faQF=lIWRXV+wMFL{%*s;YT+%Id!~)Kd&-3eoq2ork&rl<;zl z=RPMV2h+kH;ZF3}dAh%jC7lOI3rI>xWe6;o~9`z`mx!s->cS@x96b z7x^J9qc?{8if!!D-AjT~5e}^$Qz1Gkpp5~4=QG?tAA$*xY2^cU)E1xy99zJp)S{aH zWG3RuRR^ZF{G1#I-5%+b9Neg=OBCA1bwi;t(lpP zY~_HSCG`q(-G#aa22ni>Vtz)bD6i8x&03kIrKJ(Bb=qixgD)jX4Twnxj2W;$wi{+P z7rw8%Za&CusJsqxw3mi=@UL!dr2!h7K(RR^aBIcB{?r#gmkTY6;cV)q`G$7{qFu z3TkUrdhdFh`j8Dg4Frm-DU+^_=95vmM_nkVynfE7n#h~4W#IHS~~D1^+^Emzt{7Oi{4L&8zGxhYhs zhd=8J29>$DRa;dUIkNWM!n=Je`1I~H$0ZKf>7OfUw!F}oeOjb@5RL@hbCB3*!oZAM zvxJKGH>XYxbZh!>$nk^+cYGSOAKiD$qR|az2Z^tk09;n5Mjp-T12UJamDOIZ;+EsT z%m0`TR^CfTVznE_Mxi9odqniT{nhtH#=+0l_|NP4F?|Ej6H=fbz@_L z_h?qyr7JNE32}tK6fR_gf{d)T3Yd3QO0GWZ@te7&{kwhf%E4T{28>U^*SQX_i+8eN znSGMpG85h1;zgyUoQZw+8o(I`{@0nHxwjr!`f;t+?RfBljI#S8fsbi2ISl7-S%vKmC4kKm(m+#<}gh1`b1WC z_J;fkU>B-Ogxc1qJm9f|mPtM_dDPV~;3AU;{`di}?W7#FKGwooU2$mi4RItbH%Zjp zJ=y3z*&jlwvkBz!ZijWo6dHDE-0Xr%itvps$<#x1Wo^_oE!Xu#6 zd(#?bn~lcYaG}|!812N0n{;Rx5??9S$`!K89)Y%2N^&$?>rUdj0~r=|022-}<9GPf z45IkmPbi<*nH+k?qSki^Q*Iy3~N{i3{5}aCD zv70hx6kf4A02N<}Ae~dwCWlWb9S*T`4qJ9cv_cS7EuxI{QOWV4=}oQG~~ z0XyxR@Njo|Cd=)Imt#9ambAM^NAX|3zLa)(6s4j^=14w=0@i~$V14IOXG7Y6X6=Ct z3X)JpO@2^IQg{{uQRbs2q#HXUEsX(iIwaws3TAQ0%Q~f3THNG6$&&{>ERlEF`wYh; zUhY?yFt3r0fkV`$u4~SEv@IPlmbaJRYZ8H#(d4rV)OBMAcRXw8nz3fVtV23a2D zJe_)l!1?I_fz39aGe2Ik<7;~oTd33s972PjB!LFC)%Q+P=MW|y&a zrETu$Tcb7U+-SN&eYK-wl~th5yQ0VFB7ro?or`=#vBvU|j=%8+_(2+ZQ7-g~XTk|C zKu0N>UnMdo0mom!XKb<_NVb#VLBj)lJV^baZXWR8yTxHbjhFGQ^)r6#rb*RZ6r#%Fl|q}@)6)Q z;s6!L63)b+l_v##_P|VBB1*~{R^fTeOu=mUZZT0bdUE6F^`9%=aY2E5X68?M(&vfA z#a2MAzY*tJgk^zF3@Ul}si~=HcMYe`nW3Q}n^kjIv}T#q04B5+y)VXYuDbA*IaZdQ zmbyEL8+j{-m;jQtt*>f87L3Rz)Xu;|qW+Q5mgPW9x>0geG zHD+dFn&S-p`ts^^P1h6qWvlAQljC(-Kc(G;g{O;-zwh98fL)S+i4`q81jB&j5S2KAML34#VZ)TtBN3hiU0B;qfBJO z?jvg!9zWb5M=P#a^!j#sa(=6o;U-L_sS;l2OUcmK%X9keHSpMiQedl!)>p<1gKw43 zX=u=V7tXiCO2&khg*X2rVwtv}{QE+k91BbF-P27h11+uNBa;X5NdMZu%yBx8TyvDi zlG*fYU0rN!h z8CTqPVfEhA=GlUI?g|4$Q1CIJkn6qG?W5Cje`95L=mc1vjc#KMEToxOT%=7*B#0*C zI=!U2O2F$QLB!1xpOH28xXsHe6@dUejI2SZ27RNyuWlvLXswsFO+`hYwokl&{fy|u zn_~&2@l8ldVu@}HrFjSQ~9T|K?M@LWj zqUGTBt9^M+S3gqFcN>{vex6@dOUvRZr2z7+{Ga$YCkXq@h=`Q5E^}gL=Ai>@R9Vh2 zz6^c9D(Slh6e>=c#)`AdZELW}1~hazx!}+SAS3|G!s7Gmho_1aA*~3!073!vo*qnA zYj$!0MYu@`n9!;6a<=)F2D2Wq4KW=;qEK2^JiLt|YtNxC7#;}fFJ7d%%w&Q}p+(Ob z&VRL3WO*YC3z>XFtqw*}W_b-BzSa6nh=73kXKGVPu|WQD6JTvkNKRfHqDkPI5>fv1 zYJ!vi#VrORh7G~&>@3>DSucftsW4Lyj|uCZuO5%#Uz%*Z@?`cwgW29b93DIlNJvuG z_3GBgMaG2Peu#-FJ@b2~U1z}d+?Q>X9=Qa+RZn^i6iMMS!RHENd)z(a%plT`(E&cy zl_Vshc+%*&+FI_w2AscTs}Hd-ermHbBg40hjEsr1Df3TY?9;J?Jyt^pcS1~fXUxpZ zhJN1H0gu$xVcqW9Ckc}Z47A@gHMSev54Q616%S*FIRX5yh~aXVh03M$)OI1$(rKb( zf}xt-=0tXFzWSHbQ@T&4W|xP*UtL`l9hK9tW5t^Mp4CdwEjKC{>YPD^sbaUsh>u<&z#8m{r*v{8Nzn3z<)X|u43=Ro)kn(6HYu8a?Za>2VV61ptPah$+~hJa z(2fiGAY^PA9SLfFZm*6?#?Ru6a2WoAV){@hHhb~XUY4pDxl;gnrSsww*YAiOq~Zl9E5D zkwb<=)XK5px5z?&3>HXtWH6}e;M-XG0A+3vGm}1Mc`eM~ybiLlu&CS(E=x&Gt=i&x zw#d)F$c5g+w6tuSEsEvVp-uT0Eu)13JY@^5-sa{{?ib;2v^l6LJDs zwy3r37Pxw0Mk+^nAOBU>V-pPHr=+7}H+*;J)ytHJj%?mrXzSv=_))LJ3(6YQ`wA<$ z2m`HM_p|lu53^;XBdlbo<)zMFY}nHU2Q zq`^V#yr|GEWA}Kmxw6t|Y5>&5TNVlJEP*0Zn^1kCKs;Pr`5ouK!B@A~T4!L-&~eOx zJ?gmSAo-D`rLsvKTkq-DC%K;T!qMybF*HQq_LCBpE#s2LS}Uj#$hQ)EbcxVh|DGvO z=0Ko=)LQ{Ai*90hxy+NrcTbJ+9_!ZE*B36=suG@>v+Vsq%tj^1G+Gg;OdL2-jFv5ooWVC;ZGoI?SO3#A3x>n@{m$on5<$01 z$a{#6gX2@d>RUkKbh|tiPuCWzkw^H;OSHxUCnx7N9yK|sQswuHmZc90)vFNFV0vG@ za}`H0Xx-Y{sy_p?iS5(B!37lw3e{+gYn3{;(^|^1EDS{t5TB{{eTK_QRGVfggcx37 zRDUg`o0y#?bqKV2(Y=-feZjzD3*y{vh)IKN=O{dg1Y4l8)Cu$q?V`I;QxYoM;(ylO z^F8!~n6C!E*EvcF%eUM1%Iq#KGo-fQ(wN^^gNh280j;zRTCW0M=b2fs+ zku-P0@C;0{Cl&&f{RY;rP%E~jYcaC^rXlC31CzFOIXMOMrU3x8k;AC%*&}y;dMKxp zX8*K6$DzbA1KAjH)@ojyCXLeJ7{?`o`5Xjw~KfavQGVlwm zCt}4PuNG)Q6%-(X$0j%97o|(foQb?$242t8C3E49&&3|XD1r$Aq)uoeE-->JzoTvr zPL6R3B|Jb_Ik*8h9%g1bo^az9p16Red*PQ(C&t$6a}kpcDpWnSx;k$QQCx@uR2W!o zed8$Nf1;qA6bR?a=b(70y{G!F*ZL!tOrYM5%Hs=B(3i)5oKJ=H0dLDwQ;9+3hj54v znmry7lM&Vj%tM`Tt})R7APdfEeqI69>Q{Yx;92R;-oTIFU>`a_*u-#?=Oc-knWV&n zHavfzi}vy&qOMMQh1}@Rek0A{8<|ciP&E`y=DAex@sB~EQy+fDd}?Xh{xS*VA3^Zv z6C5=)SL(>A{Jnj{2AwA2yi@z}jJ5Hy4D96o%ez&6)A+dAhTx!A&ei<<%9`xj- z!>W*>nx9cQiXN-4txvEQa-sH;e=bofxcA3I1}WL`>s`X0+n=-1zRh=9ARyGYwiT9CR}UFxw;S`| z?|c1+4f^ezL9w9d8I}|KuCufJa9(p~8GBzWq;JUW8F(uXSbLXM@&$kUNoA;LKrDzt zcH?~xw@zKz++0j-Wjvyvy1H2ct#lNL`=15}S&RWkPCf&q9XmKPlpVBQb{?Xg?$_Q&ZH(iBXAy5v9$xqM zrS{x!G;CH4kjQUU*4VH5rH_#)bZZ3s9aTWdEgb|LmGx-&5oaMy6v)og9@2QDAk)~6 z77gmn^P@9=&)+YOmOLZUaOUia+ucPWrX)?ezX%Ibr{AXz#6anUkTH>uhcX`jnG*pf zD8P6$C)X1tDF7?q+@pmead>lEz1rAP9b`-7U6C4>f z-{M}e&0p$03mWEJD}5Ro(g=N(9jm3;y%v%Dd2=d1d`Q4U$Q^QHKBBu@`?FdEy8Hmc z_9L^?9@P)cMGXE;R~I#C9P(Lx;dX%1KW{67GpVm>=177lD%TEai z+(up3Z%kKdeJ2vEbCEdCW!PA~&eTcWwW#8VR9}BD;_N67dR0s-WZQq}DB2BOqb8GD zPffKHOELEd<)0k123AARrR;sTVY)M+?mLHM=vGCh0MkKu%p|7ho(sC=57)l~5J3UE zsVl{taCKEn=G8eI?@W*F-`vz+qVyWxkI{;sfLHukOIPffl{pAZxi0m5!?BFQP4QM9 zY$!JGU^19l9z9YRPe^~t5flPi_%V484XInTv?5;yDM0z404|hXYQdcL1*D@JIRum! zi|vU#fzh{!dC3C;HY5GM=9sB%PN=Xx25@agFd;;%Wn1SP?VQ#++6mhF)BAeUd;O03 zN4N4vQ-XHyugJMb-F!`FT{(t=-5edo9+hP0b_^6In(tR=*^>6_++lQ5?F&3Cu^s5| zx9Hbv?TLBkrGgl0u(=YVLWpRfALicb#xi&j&OzMfW-K4D4kNWPByy+LbZ!5OP+Q&P zT+XaL?+(kKt_tOC&|Ty=TBsg*8MV~qA+}_JPeDnk_Gr}Hl4z!!>K91H9Y_MJs#F$x zc*Wi5K`Fd*UG6xjKj+L7XV$^!8JxFH+}mr@NW8rN-hbq1yg)*W?{q^pvOD?dOYlil5);~616&@#qD#P~GA(2D z<$`#_=vmO3zQ6XBnyP9oitL7?39&Ef5%#iHsr~*D=y)--;b0&T)vT;2Qebb5IxRvr zRVo5!Dt@FjzOK8To4eLqyl^8pk1QmLG zbB;e2o{2tFat^v9L|lAAGq>~zaVD4b-sfI#mA^4cCz6DApX2*r@J5OYqFjPDdsr~h z;LVO$1=fzZGOxC03e8fiU-^m8etmoNNskdq1-%WDS0HomP1HW-1IC+&cr|`(L&W>q zt6>!H1J|`luR1MCNZnMBqD&|kg>%{Vx_01>p4j;y^jMT&9N_#~<0`t6U`I89Ng+PF z4C<@1)~q|u_Tq1)U1fKI59UH&c#0+D@=fpF@oiaQ;{(LXWv zWVKNS>9*N{r&clOUyK6{LTiF>MV7l*+cotw4c3~%F;%f*MJuy84^PaCJhPVL%2$}_ zu&v;bY4!E=aQDo#M1JqKqC_aYnNLpM#_)b5g*_>^&+QVu4Loli`(d|qIbB35;`nO0 z(8^}qeC|tBaeduOteYCUALp6Yg4>JzO*b4wyAiiPaf?;SYU+z9XUF*tbsN6#JgQ+# z``p{HzNjm5Y(#0_&iO6)sB+w>n0yj**Y%r;)V(nI%DL@v*QJ!}x2=ey{!a@D zeJS0Ib~gy>Pq8`E7cKUJwubtZNpW7%$m;f`F37tI zG!KyeSfP?#ZNZEs#l@-mzegh!jsc~5&s%tb9Gd2*H0npJf+oapm;a?sHzmG$=Vz+e zMwCJX@%v^j&KZekJux4mr^$1T*Z~M%5;yYk(c_vS5pt_~M`E0g1rRey|CcYdyDcb4 zII*zoCEVQHTIxC!?&)#=Y;&-Hkf3|JAlR3|+&7b^K2JcOa<3_WY zASX!?ATIM;TIA4ptPj>M_BBmc+jUr1i^?g9zRjYSNkt1T^}4yZ6jtBf_e(9+g02m0 zKx9m9HDF-q=TVX}d4lS}OJnoWa<^Fp?R(d)J!p2N_CrUI2&irI5h7}8@z0YF?J0M9 zj1a55mUB8zPEZy&z?o}~>U?>7I_)iQVT7fR^Xd%jiLlo%?9OjO2-$=wXJl{c>oov9 z*Ux>b+b0b`HJAlSO%9{sctk;ct>fNNNUSx>S^{|K<~#QyG}U29VK5rv`3xw zn%s?_dB!p+$MHDWb@gfnhI5k z!TMP>a1gp&T+9NhXBKZ3Up*52qoDo;Cf>pvW+x>*l)thsfTNi2y8o7umJ4k7<2W9# z-lzygXc6>{5mq^z5kc&C!_&fQt%aonx6?KA@5fmA9X9de43%52hqU70>qU*6oW#>L z`vh73qN@bpUy_hw%?T13`*4!vov$CR8k(oWhltHuypYm<{gsu8>5I}?M~}1872R|q zWQ@9@SY1N{duIMI#7)~i3&Md`L0$p~AWKB^Tnb}X# z#fT`%ZdOM?!TGOk3V(O(h?bU?#RY=hgM;J!bEF{PLi;6-QrWkPB$#0QICO0t)}K~` zgCq(qf!ZS(9Hi=>ft#JhoX>tASm&X2$-&@z61qYqZiaMYv*B!c&jvc#Rp}G9Q9zOP zGbC7_aUK5#h|}G}Z>#A~-+Es?we9%$B=q=JqlzTNu{9@0lvU%5b#QX{_R#Xn74zS$ z>+ebQ4SvnRVXYHq@#|3zAO1Qj8tOX>{HS9dWYaUPwMsIhu`^@av6XCHL?pR1@;70=%B2ffEf)GQ$rzH3yckBmej=()h|29>?lb#<kHOb zu0lim$|(`)=2@bM639D=PW3Cu=L)``X2(IDR8c;0Qe92QW3!SKl>OHFYx!8P4Xv$$ z06?KHH~OuKS*V^LZA6PqMdhyEtXcsr>PG(drjYyv*nQz7YShaO4ab?uveVe+!=_g| zKmKYeohDCQ+F-oz2M>_XDcMo62 zqWpI%{Z@Iz#bC~4kr~?vnkr~o%LI?{XT~Kqd-^2?@@q#ZGG*9%+;QiafkK=@u`94O zc=ns|v4kJd5cznac!AVU`+BnKIf%%kcuqz}qDEv~L#LI=N+8X7$bb}@Ai zXCeb8_NAT>m7d#{UVg^d_Og&UKstRI)I~Hf@$d#QFjnucuFhZ*7h1Tk=u91csX&G0y4npm%8TY&QM#ih5G*WK(xVCy9^ z($(?FnlUOOEyW4d;~UuvwLNI4yB5rhloBU0TDP>qCt`I)loIL=)JFq4*0~oNa(b!Lk7=R|ZYX)#P;*U3wv023oUGn!&T5{O)045!<&v1=Z0<`1{ zjRi)jV{fbbG0vI3|CfsZ_Z$-J6XS1ZBI&kAKSydyA75`{J1V|Ztrk4lbXIL1_<2w> z|5Q5)o>$N{W~YNvJ!=5^)&a_Z8Ym%YCb6%Jjv!Qfp-OGC9>Xu;w61DHC_+^| zg!bM$UQ|Ptx@uJU2KT($k0JtoIzkk4B*M})0NjELW{jxqw}vqhXf-a2zkn#}3iUYJ zIyxIa4tI96Ei*NSm*O{}oM0phIN^t&Ml?c zZ`1;SrY==L%ulUzW4(!>BmYv)@)9m-2MfD)+wi@BLc$;VC^POC51Yq6Kq2Yh7aLW; zt)$@oet41ogsEFBygYn!%Tt8Vm4zFr_@BlCl>W!{=;ya&#%s)XUp@*yvScA33V|1w zT|3R|HOUBvc*@EY0Qg87){rdFC!gBkqE|Itg>0ps!jvNL8X+$}?8qLf9r; zLt^=rwR2-(cf^nRx%_5)biP>g;!D`ym+qNTUPLL6x43^yTL_FLK{T|cI26rl(!kQH zoxN`BNW7jjmaP!EE8On!YTcGI#Ip8Ix3n>KkxBct&Et9V>)ME`PaCwaF$#l+WBt%Y zL*;QoqZ**Xrq@U%9ZkXGEArA&Q!j&`0HM7DIKRvV)fX}G_b8c3|I!Wq8o^2&P`Qtp zsutdLH9NET@U6W|6zK)I`y!o0{_xP4+gP_PpOeeWY>w!$Augx8VM$wP7%lZ}tpCY4L5 zVX@Ngs~bgjvb8wfg3zXpJ;R|KH339t>&bwAX$tKyM{kb@jw%LM=m|{29d5L$q@|#SBPTUKj-qZfW&$2>*;%i6*$k$fAS_feJjoRdobMxBKC_4lGB|7^2L3`iJ4nE0&#e?g|(r~);6RWF?eSIUW zt?G7vs?_bMjX2SJU?NbAayv^tlN1wD2x;U(#)>LE5G2eq-t-HHz<0}1DL3u`f8EwS zuMOHQ851|E)B0~5+Gz=2c}lQqKl6=v@P1{&2vauH=kQIhk$xU%nuR6gw$>@Os9Z&o z`Dn^k>wgpOz!;o2n!D;u>9m!#wM@yvH;J7ddx&Dq_0!Wlo>!Fq)kTLls_kV(*VFLV z(<1i`3YmDt;zhf}PMdRFEcqGy&tDWSn6$;x1~h#ZRcWW0rG?g{f~AHn5695skdr8i zzE32-RQl)zyaQ+xqY5ej3K%N8N0T@BCM&RBQFV3Q-NE@2|L$}Q{M%Gc(gmo*=IHT2 zH7MI!=JAv6Vv2Y}q0!^;b|~8<5fn(2JlCxS)UwIvf7Hi+7PcJ?M1=2=+|Xox`H3T+ z>tdpBo9A~ERzY@*p7K_o^uu#N89!!cN0Nta+baq%n^Jtpy{s`TAPuh5{@sZ)L?26%EHtZEA5JX`9j*=%?#*EAhsHMojnjx4M#*5`9lgDxlB(~UtALOYEAZbrt#!hxVNB$f zs(_ZHHj{it*!2J(Vove>LwH*p4@!qzU|7+y)3+f0L z+1EOty5)CBTc@hDvqh7(wh4x(5Qi~v)DUYQo}N~ZCwV_wQas|xae}S$1gZ=aT1oE6m;0V3*N5ZL1Bd;uGDF{IdEYISqZgvU>dYy*Yi;4At=$JV@CZp8UQ*6ro#t2}C!!h1YS8$ZwP#t`7Aq-j=c_>g$p7XH6A23ima@g3$qdQ^fC>)QI5gQMjO zZPQWe((uOS92lPr2_t~CfTqH4xSk=`odu<|L}id62`(~~Qik~u7+O9vgRJYWgB~oA z7{;t8#;6F9Nc_YuP&MjE9FNMcbSe*9(twBUr zuhK)6{pFACVY*V{QxNxvQcg{2~Z+B(7b<~lzKY2b1i>FkDGTkpLS?n5}ZGgzcpQ|CkXMmK`Rg;-( zcYhY~yJ_sbVdg(B?P!8)D?D^E;>!%LN1)el%!}l0igo6A$_N#CJFrFF-G)Y2yl9fY zu5WKiHG<;C7tSXbm34K?FnXAZ>!4svP>Kr9_n!2PMUPDI|Cp=)`C>;C_x2vrl<9MW zm?l4&QdmVL=WEsVw26dgYx@Cd5>(;@+?BcX-Yq@IPN=)mybme6+@2b`#%O9sEuaXUGdFsb z(!j6oQ2L@d0W`2i=d%|iQ99qTPK36l`YWUIbGs=Rg_U)8RBe*{#{tA=%clEb<3;g! zjkv)-Xa2?a+PMph|0So|ij2db(w-xn1N{gH@qbNT;g#v1AHAT$^B{l~(bpyphGt`! zvDekru3$)9zn>ASGI?htbcC(*9?Jkd&J-$Fd>IPvC2Mpg#RXtgV2~0^Eq?~SIH&h;_AnUv6kcKUs z89KU=Ao(&6N7Ax<&-rdy!gp1hfflu0HM)A#m7|Kx-;OW{3O~|8HQ~fQFtb+w>g(%3 z_~Q6G>B5oxuMJRx4|hefjw+gx9i?23@@PY_TUqM`yK@K4V30wH6ez=y4pRipILhuf zbdB5_z^;A0Q_=5zdeZxQ_~sTCwtx<8{lA2Z$Zi^ei#9?eu9acXmH;jp(92J9QWE$b zwoxD&QQ`k~E&1PIFm(R1Y5};76^5ar*JTxzmC&l#Os#Lk3yx{NUhTV2f+}BgiT8&6 zmFemH&z;%K7IyFLzl`v+BmP5lft=Z+vP9V-z&CA@l1HDocgC{^| zEcUxpjm-Uavy=0Ie1iT~Yrwnh)=NlK2JxO8MB)Ad(+nX@o^NDPXWl)0$ye>0j#*mq``HXg zySVb(dfv3e9KUD7pF$wok_PFrE=R!W)9>otSielWtXFR@3@IljeVVpBi68E%#OU&PRXMPNf#k{D?NG;wJGgMC|PowB&aqj3- zeG+!I8&oo7Wwh^3(vb|-424fN|Gggs@qYE~S;YenW~}fBngH2vP_RkO7iDX8u25XR zimJ{1EE{d@Pe$By<6YOUv9US#=QAadix7Xk4GBBWjWQbp8ouhyYns)+#L@nrPdrp9 z_0<`Ls8Wvx-!o#m%7AOe=MhPCJ;+UEBi{aL&v2yssk8d?gS$Wd>*7J|FOYu;>wtZC zrH^gWR~Jr0QmveoT;8$zMA^1pGWVKm-+LM}Bewg?969j)*{ER?{g(vDzODMi$cESk z{dXl_&BCoup7*85L%a9%MfPz>Nf~!V_G0w@_urd+rI(_S1g}e&6Tti%$>X4r^Q*wOU zWn&h8KJ{_F(?>N20cC&DFaRguk7YM<>GdIf`t{ph2l$$GP!FioVr;5kg}nYJ$^{g*g|9J z0GS1y>WWH`T1fb8MOw`;)va_Sk}(`Rr$t>jt&C> zHU0fnVe?!NuRNCKEH>sA*CH!12cW_8X&tI^s9BgnoZ7?EoS(nyQ@2tMEjbEJgi_h} z-J`w}{7r=XcZ3N&*uC$RRaD-NjC7%xhf5@8{UEC-qtKb$qET{ywVkROtA`|2`>4IV zeA`Hw%@IH12_W*(eYv!FE$_G}Xx>X%^WOc*)l{FiMw^tOy?ZdzaQei8_&p~%WiAoi z{W@b|*4VD`@{!ab$NLoV{-|9FQm*yJl(K2J81Xf8Bp34MWb`b#-aa$w5`7fr`6lNV z#}*ofiWwQDfCKHGID3xW12$xqta8RhWmnMbD(g%Y^WYeZ(yS~C*%?~13W}ZEdAYCO zh^H!T603Z;J3+pW@>RO=(*8|r^|W6Psh)U|Kh;+UOqXO|h1MzxF^dac$M`(Th$lC< zlgWSm=}WQGJuTUDz^0GK*1sq4SE7OX2$gfVCRhv(I%!Q)KcQ;ddr+)i0UPdDd|X`a z2F?RgfPPkE<8{+CXLB)TL%2BC zR8n~5NO5;#9+9$JV1pT&{cKX6fEE@m7_Ycv6DKUyDF2%T`9JQQb`uZoCD*epYi{c7 zpzDF+K3FL;f#bQ*bw?1>OyXrLC;VxhDl6%=yVD&zX1ndyw;N>&o)#0kQ{ppqpeZb# zQE)F*sbNse!ajE*V!G0{pDIT7WT^#@%*pA*G=(ZtXy|6V--5x97E#d-ak!apsg*d> z89jd07NM37Kez@qA_Ym7GXds1t&udgIqloE4fpGY;&zLgT1=9{Mw{uia;<8>^T|QQ zpk0M7I}6%)0>EZ1A+)=z-rRvI zbiMgJYmsFzy_qEV1WG!D?Jn1R2iV3u=zL;_=!7a&#DKJnOT0-ncM)ryXW3ajj0smW z+&4@7J>k(Mhc(gwn*{Ezu7MYVm4|(yZka-6 zq+TStX=#FkNTF#89{t*xLRN^GXoVINpH$4*k&ZT!mbk7zE0RiFe-+<;My|Q`U@2R_ z<8PoX%7rBPODXH$Yj$X08LE+HKj%_@w|^$Ku|4{*OeTYqb2L2Z&IfA4KSxD*xdwf! z-Ry!(d_8`ZsC-4Be6&9Ug$m#n2rC*5PoU9Gj*&jqZrS_*#Ha_|S`hgMh(c z$Ne!Yi)j?)F*rfN)*8vL`_l%OyCXjYfpUuc6HQ58AE3jULbF6{fYXJo4ETGL|9X^? zgpFu!mwMo=K?XNzmU*--^hZwWg=wKv4V4+=Z|g3G9i(*q8Om8C|7bVbe|MeCc6aR@ zYYZGwW1NVQd4Ld~JFO^jMsWqI0fvKkL0s&D*rB|@i&!PQ{&luVqn#@07KHZ^HYKbRH!RZw3$_nV)$;=|nCv+lLN}yT~uQxCEypDn=%tMA79@;QX0~m^) z%46YFAAPQgU_rd+AuOL7znPEPZyvHy739muwC?-bR1^I$mgUtm>;WoO_B~@0$WdUM zG&Ah7u~s8+aDW+W6BI%!B9HyU;^9L2NJ)RZd&v0~kMN+}_}47-)Tl}5VQg%w`9XG3 zcMmqcdba}FTySM&-D-sWo)F|yIl1zA#};K-94gTU2I+bS#R-g_M~i+D!z**FY#zsd zD5)J`)UPE-Wv}{5#E#3dso$ceWF!G&w%%c;-Fd_4^Fr-Y?zXvH=||8^*;D^W)ocGn zxQ16_yZ0R_9gEYTm;hq=q6lO15YssV*?_Anw29ji+fsF7r&J|5vd5H$@ES)3bmyU4 zQ~ye2QX6A6>pi~6#I=Wcd#jYkD=RCD>*!7zmEu2PS~;n2u~wZ{Qu4o+_U}idpNyMV z4Q_j1sO~aYc$2F9TxZZes!430RQZ#g92Zpn=;&d3U!@=F)41{t&5`A#KK(pW$udP7 z%s%4$btIjCs*4^bhl4RMX<<_)n3We(spDWUU4r^417LKzLEBXwuQ}qDr=z%CU;8jF z3LzeCUyNdqtZxL150!hb-T`nwxWa&`bfVHFP>Cv%eL;o-mGP+qz`m#%V7=+Joa%m& z@_MHwKTFcxQ2T|@5m=K6co1NLOu6icCbw9x)ECOIj_Yih6;=s%Fp;GZhSaYKyC3 z?0L>A2~Kc&*hRVO)DHLi2ETNF1VbpOXo{~nRnhkI9ba+PQ;2%>II49EJ?XyL~ITVVFV_rkC zRQ8pMlfeJ~fc`buPl3?1;qLzasL>;BlCaY*ql??!Uh^D6^c&u*wic)quw&a6fjRL+ z{m)#B>R33tC(a@gFejOR6&Sya8_UYm(*c!)ubn>#p+ES-SBI67eUTcsiFeP-V;@54 zgRW%%qq8DCR$}MFou*jq%St<~Bd&Wf~%Fz|^&6^_{X$7tr3okFB3P*m@;U5cLZ_WV* za-BoUo4;Q#-b)u1(p6k({(E zt%7^0p;F&l4QaQAxFxeClQkc{5)~rW zhV|h>4x`@|_Kb)1-d*hAdNwvP&=`BwD@#i5Vgnfn%vPxSb(hp^3?CJlniteXXL_*Ab?Aya;)2Cj70!EhmiZyw4ex0D;bxCaP~ ze6~h@FksgfaASS*b%(mmzu#KI1u;y7M9jNMa2r}Yehb;N)AN(;BazQYHUaHOYHGTD z%$}G+TV+LrGhP;2o!!$xr|Drgxqo+p>skwgZ|Ix z|BJ7~utJ18rTAr_A6!%f+FVQhrl7J3m5eZkC>jPZu#jQ0`Dl1R0xgsQ_gu`(?psu^ zR)Wl(^a-79`q?LB7wHU`htU*I%9Ld@k+tuuaqCr^Q0SXVPGUt+l-y9iq?qrt9!~bW zH!EfHro=Dl{@!60o8R!O=BaY+g}^DN{6l6pUK-Qn4)$cx*2_2FIx3phNQm;w?&Z&y zZTc0myp*s8IE<*z1re5E_)=RvS<+vnwo^!?OK$(C&_F59h`6kM6$O_+H=swC;puvtEn!pLiuLd$wJA2wuLs zX0WaMVQ%wqNTuSN57&My&qy&aky4b|8cyxj{UDINrV}dxMC^Jt^p8DS=uKK&o$9%` zz4*0&Z>TMHbLHrmVRoC97|$i!>g;Y;VUjOEI1T!5({1#d1qTBum!=5w`O@b(mNTGk zcwsxVyCO)=7@5QWp4j6w&>&c|dH+TK6Uzle5BrxfV~1u>D1XL{QU8PMUHnrehYuQ^ zr*!wH+(CGyDE!OOVm7lDXT7%org8Yyvz=PV_q%ntW#D?S2cdYcTXW+pH;mzq%D}XD z8W1URD^!0QMcux4`;5=n5G=>|=8EfN$T@b==!{A$&(e=;9bAuv4xvnG8DSaU2fc^7 zGa;&5aZU4)+4_EiK<9(7s>X8%@#crSe_auXnH)gDUv-g$-a7dDQmm|?)b?3j{Z>hR z&op!W$?kM2DjrA7T9jX%@Tb?Y#b>>11J<-=obnvqpqy7ADSIOyRI(U>S!~t51s=~s z|6&A{(7m{*l(G>n9@SEG__knMS#)zFmg;5Gz$0Y&A>FiH39I}BF3+oM#i{n?!rUV+ zC@J;@9ji=_IlN(J?^i}@aNnGOx{V*2KaNo*KL_HeR7DEWo#U@jg%1FFu{lPG2cn?x({FQe{7eq2bjSH{XC2bnhOtSOLqA2-UYJA6jaad>HHg?a zVg`R|u+-_4RyT32VcYu(I1R0aqJY3T;Gf-dnsr*L!y6>@D2|rpc zweYL#qe$eUXw2D!AIxj!yKIctC#1*_;j{H8e4Tc5Fu;cZpK2w%jA&*%*Jwv({^5vX z59JP2OIThrKqyfOCJS3V1f84jy!rF~NxQuBw|`hOoYeC7t8=mXhu{CKB8vkkU@Ny} z%+?Yob?>tx%-B5imW;a)R3I~KJeJB8Q+b`Qx#^}(9e#wp6UR?CchjOh;O~Mke%)T< zC?1#MMWkf^48!pPMD!W&?)?Ei-tv32viSjKV5`!ph}zkF+!R$GQHs6_Mf`PhHZ*xV zY&;^rc}SJmtM|%I308@Pa`E+A3BXNSxnFW?pvnP(!%5!j!YCwbNWgliN%V_S-3}h`5=BPF*YUkOIdO+7C%N&0r)Dcu&Euo~CvP-4 z99Cx&&pep`i0+&Ra}meTxWUf>QLpOWJ=dQt*%)6D(=#&Ynrg0Y4-5Zs=KZRHWLRN> zb<=4m0h2l6_Mn&u(m=5H??H}kh0H_RD+0*AVK+t{luh`JlGda<-ZDD&*R}q$$d0>l5LRyPyV86N> z_x|LrA3d44!ETeE^WsL$Q?Pv$y0s39+eiCYZ9I-wO;||D0kv=|I^flmVB?l^<<&Gg zq45c;?db40mMVCC9RT*iqD4huhmOfXMFc|tA7tPb&1m84w?Sv2Li&~RFb`TNE+cJW z7|wWXTPxnL9Y8a8*f*A5rGF?@&hPZuPOqHU*Y{@U=+7UR*NW2aZmNUHPeWgBWgpvx zgeyNygJTWCdyb1D`~5MW`Pkx9waVt*jG>$bLLFfpznoCTis&ARMx zlCo$GA9V@)kErq=$8a8sMoUL$GWS!(P}`1?kc7vam7Crwz*%a-%7^GnC1E=dVIY~B zZ9Viwj=jeRDt{#LUG4?mSF=o!;Pfz^5Ng;H3o1LZZ@@T>bD5!y2!!)-z>>J|qqq$h@& z>)`&pHF}f7YQ9`kbM89g7ZQ6hF_}H@W2M}-Qqn3~ae$92zv3K~gn|KC$9BTX+O7=E z;vzf?;K|*_$CT^Ef$@d;o8_SWwmuP;NUCp-iVesJ~TXg_Fby$)Gq4EkLNh$K-o(o)x$B;O~=2sl=fEs)X(?! zB2MgV*WVSc>P^hi>Ixz=o|E(O>ltK_>Is4;SKT~^gwEi_q6%7XoW){WMUkDZe)-xd zbi}e7Hf@0QCl9(WSDNff4*qsy|CzOc?$Vxl!f=@_xt<&5o#vQWzoNyY5Rrm=o7$iq zL7W`_WCDkj0;e@@({B)K5OeL70>{y<&A{xdy7}Q*xQwo*NB^ zh=LlTu1H8HfPBEF1;ueTs`i6Goz{@h?4C;!148B@*h|N4X+@`LxnVlC5j3mZcnr%* zyfGViWN>c&&3$Yi$WAVX-S0Z_M{oZ5y#E?)YPj-mD;|J5lV{CB;wQwM4k2BHiixSzJUJatn_xW60(6-v_`TL-*f_t4HIM$o zXoXJl+wXPr!%0+I>)ZCrP4?D!{K9ahzuQLAZ+!Iw2XEPH&9??3OrXe#q^jzS5wu_6 zR?ijb%}Fd(d2e)wk6=|z#!t=Ku)@KX>lPH_i7e45t8L@e^ofYQe9#^q@s0^{J*ujZ zuuyz*wpi*gX)H`S(+qoG;>!z*_0cV8xGA8?qqc)CaZ@Nrpxg3?0DUhb!$F7x9rdj& z1`?;_%Y#{3Kvi>zmXR)%^biJPz=+qQsX=oItWF&}G&*kL`>2Oc{r?4&ukHlKo9ngh)kA?HNH-5lD zP2&oefH!O$(&jJo1;B#x_0nQDtSQBJq|@~Z+VwtLCqSSzrnzvT{EMB~gV2SxlmTnc{Xebx>Jg7+ z54$vDhAkgYHpayLt7NMx<3B6pn3^+9foaqCL9Ob+0=V9s3|@7t&Znd%YvDiyd`2Vy zP&f7W*U<70vzjdi3DYgF>aQ~ZU~kwUFU)VocE({Mx6zq zs-RT8V>PPVFU5F{{ogLvh=gV8ZSW6l{|7E}!nJ2Y4V>JEDV}h>MvT4c_KUuC;y4ao z#8thxR&76MFV=X)0%jX8J3+ote{aKNkFMn*`&d6S7E+<>b+EkGiqYd8>BiAI-Q>wXJ5=?^okVM%CJA!%4OS z&U;qc26zK8!8#t7dr8~N3M&u4)Otpf&TYzjk2X3(-lddbv4L}j7p^SM3yg`G0p0`| zzC3X$20@s>=;sJ2YmtOHbo-{tA6{L$Li!qkbaX5>&n||Q^quqkr4j~fOxNw)S`UR` zP7i-(nN7`<8n4+f_IBoni~qJeT~PL@QEEZx(uI7SIX%0U7FB%A-2Gp+;tf6hig1=K zV%I*LusCYrGLyB!9}zm%#vn=E1}&eb~d3RVWmqOR$c^|zAV?Gm4IT#UiO z(>iW$d7UPi%0DPB*%w=Sy*w)pCUc~c3+mIV^iW+(zo%LDj!&4t83K*T=;bkjsjE!B z3FjqiXdQh#$0q}dBhP`_sDNvWKtQifqd#oLGn};dtH`{>7-GE!z|fg7fl5 zz!)Be=wtrkWm}9`1qEjNMN`Vg+5eHkiKaGNwxdRJEI=5=5dg`O#(A?W3B$==a2*Mm zuvbUKoQg$9!WtJXHIw3)} zoj_65afh&ZDfhm(xBFS&^LEu}`jJxB0Es7&nLIbV1sO2br-{n>RNs;<(s?|@9>36M z+sLn3;*(fOX3v9UyB6e6Zo=MO^h}SJvY05oYQUNDv3Ja}PszpdiO=G+LYs3g8FCNq zk?t8hz`n!2VuP@v`NL^!W+rJSg}jdzRK9|-#l{?xHct!B4}n;uL+wTRnJ}6;xGOk4 zgKVBUDO2CO(?8|$GJEg_R`1%??%Lq}1o!Xg4QTtfoMe;Ni!;Gl>K-wW+oXd7Y)<2X zJq};=DL4xrRe;kbQRG*}ZD!a~(`+g6f20UnV$eu7C=2H7Nh}&I%yQZM7x#p^QZo1K zhRtr6&YLsu$xhrv!pP?LtFgnrCnK6FyLS{RU6nU$JrKcNK)`S7!m^aaqVI^;2WLL$ zg~Ir#YU&`#5T%eW&}nwXjCy1VUrHhtEcA^r2M*5DRquGy%XV3hlvhs~-5ss0Dgwox z&h51uEaOj_Pfq4ufVSmG{flLZ>?P2{jv<36{rO-6rc#vy(7{M85ik%EF^XuK1H)FX z!61B}p8f{$%Sxqh`Ww-*A8|Od@(4A5)EnUB?F==pQBS)bDeF_yXP6U}f8Z?2H^>XQ zH6XdKH};IFss-sJD=1>=A>mriM!Fp}kn1f=TP+sK{;)Mlg-M$mv`*`fQPO=BU~^mc zD;XsGkb`PwBTTl9?y@L1wZd?&0jt%gb*~n{zM}p?@6qdMf{Gi#dC2W;E~t&wGofg$qtC8vME#2^ z#d*3hMt5^nuVjMaK7i8;&M_m4p3oc3+U(|FX@K71LNe&!us1N z3s=!tiA6I~5qz?!rD-IBeO?E_sVK_8t(}BDPgYx=85ms-H>PlM8n7yru8!e3GJ-K^ zGag|XIaX?g>JPrw99+q8G*LKPj|kTYoo4!i-lz3Rl`Do!3uVr>IO&dMR=im}StbMhr7v@+yAw6o)cM}W+N3?EjeUEb zg=D7X&BzOVz=+|>ADWw9EI61R^#$R#ZLZYBZv~KbrjC}=NrFY#*!pk&(2|s7xE@Og z*g31OUQe=T0@w6EoSU{9GU$q6PDys$>^k1Z)a%)j3#o^~!LBcOhfyltVHNS?0-f5G zs5vJ6Ca33xn;ZR{A>imU!{cU(<2)qAav<>83-Euj-axQgAXKF3ov<)?!O+#4awG+K zy}VDqYy|UzVng1rDmhQ*!7FepqaX$wYzPkBzAl$MEwi5h=rK2!E{&8&oxqoO|5@iH zd8vzB^V$Os8vTwYL0ffASws1=06bi@k4Ne^G?aqob0t_fT?k1u4BgQXc`W3<0hS^Y zYmz8zH96%`Q4q5tG>sZY8|dNY1-=zAZLN}jL;q~YGrLum>e(>l2nDMTcEfscQqqUPATwg&z^GW9iVEK6T-^w3< zbU&{Pqz9QLOl@Qsfr-3%r=MHHq{EEP`OAOSy7z6clafoIv%GNa)2$tHud@o*90Eky z*%tyjjn$ZWTHe)ER`W9szhzabGnQcpk6ILP6&)UmOiFVxSHqv|jos^O)N|TcHMuc) z1Su6*@AqqOrfBy^b;YViaQT!MFYO~ajtGq}h)6zL9u8bsBStaEqqGloGRDOo%%%_9 z7PKC_F3865tI7w+2x+Z`n9aUh2^byP!~jxWqLR%&+XYTYd%{__`fK=gYg4sL-nPTG za5*99j~KJDnHdiT#j^*6qNBHvM}!Cnu1{YaQJ$sj4P20Z#?e;j`B*N|FC>Um5X?O# zH-QAC zu^KFeoWHEeh}iom-nSQ4jJY>>$5EfR_PeX>8J;TjoYqyMQJ42pLRJssI2)j3y{|SM z0WM-Cg$60!RpEOc*fHw9KeMIwd*T+F+~!)#J*$O*m5-GeFIujPr-O({_>9EuWgva2G5nbq58yEK-b7a7r6*UUAomO?tPMH z>00nHE?>6!i|6|?>_&C6PlqcH>y@xSHZ*?{X&9L818=v6ZVb6-oVrjb@^4}2_1cs3 zTy!1qjHO#t&8qze`=YB2uHItu<%n!!NKbL10XwqmJGNOW|5~VOU?0D55pi|jQAVd) zXSbeeU_D-BY?ylgTPBmJEr;9(l7A((wUmt#dDdBvQw6v%G{%IMOQ|q>gbW1gMe@>k z*tssV9C6b46Y+%+#ueoejf?8Dvm!^cDg~8bSUg=q%PSnrvcV+DtB5~(-fTt%7De&u9~wT%D5-~RrFcaoTmZh1MI`>m`{I;t=JfG+2U z!CH;Ww|8*383px;*|WVjH+~g1o$+ z^j(p6NeA1aEtVN!r^(+tYU&@RU)T6lh{Uc8STB)t_F3&0Vz`DcbnK!+o)RnwHr~#e zsV2jkgG~#8($Z}b7J+rDR3!@B34Tv^j(7|!0bfLlHLHm!oa{^FeB9s{NQOyy`dCcf zC#d_Jv)ELN=;^StyAcRI6Hn6wOL#o3r3BYiA-gg_d-PytJrvqd9RWG|cEk!}Sh%dn zS2!N1wJ>g;_C)73cSL41?g`0PoAr8K#c1x}_Y#zC#4;Yegyy{i9MY@CJJ&T!Z^IM0 zBt$@q^SnLor4&}BrAImw+VkTUlYvBu?h)>o_(9H`5`!{S#JVT2K;P(#HC-NiEge2-*(~F2H9_ub?O#UD;xOYPOpnInff)he1iM(w81;; zD`jQE{gZn!sb@SGUo$qr{W}jAeIt)2qPzu)5d#iCe&<0$WOGnZS|~JZ^Ml-?p^DcH zBoE&~LZ)`uxHj&er`8wfuUCX^eT>JmSZh`~nsso`IN0?rZG@-(3liK@qZRPXRaprj zASA>@XS2-A{qaxu{839HgCK$(tql!l6Fq@qgFcaNfOqi|h%BTtq-k{>&K315hn&r9 z{Pt*SKybh!Og)@|!Z~x+%YFxR@%+Y&D1{%atUwd4$vhv}-UhZBT+Nm_Df(W9Tiw!KCJa1mai>tpU~4z2_G!t0C8O?YFqsZxd)?44C1xvpW3v;+e2L(GM*hRC|pP z9r7xP!QSwm5h|AH=&m53kg}cQr^>$QNFv#sX)jfCj5pMZzaw~?{OrHTd9E4dESb4E+QkmIB^`5gwrL2e|B9u>y)*eN{J}%9B0-Ln0&ea2@cpcao}sN zgtr4YwXzUmp+qGKUPD{X7*K=FvC?#3HQ3%7a4rT^6rY?`g@vi5iU`X2UZ%QUuIDzx zmAk%QgdV7u_s!G)>7N?lq+|mnKN>(BI3C)ql-%F!1v7fGJgpAnk1(!@!4|UQ4f9-4+eiJT}`(^Q25^Ne3?9K z9vN{4iG8+{$K=^95M;0oNjtx-3m_O8CDMIM(Hq?;FdDAFcsdEyw~iOF3mPb=Ea|a- zf4HKn$3+c}AtiHLTbW;un5c?D;S{kr%{of2S-`I>ScW>cETuktC0{C!Ym0NF?kJxj zS%nxv?l(~lyOgxUNx6(X#LKonwjRyNBD*3;(Y!vnr5nD6eJ2xtn?Hj((>f_`vE8Y} zf4rdXepCpjbV&LYodb*ZcOon*lM3rv1sJRO{sRid;JY&~>#s1s>hNq9uDf&b z7piN!-Ft?HE>^of@zT}rA4~Omt)}}Ah>2f}lMW}--%+w}BPO7er-)8l3-L*>rlVi+ zO5A*Y@AYPY%~QEGlE2v=UtrQ%m}W9y2_bN9kc~QfVSeG`@$cn&bldZ&nzZ388qHaA zV_%sV@}VsEbu;r)CXlKc@F$w}AW5g>b zjspSYj0+ggmx4i@%)=T9^W{IKf|*NrQkA>AVZyxQNzur*6rX#20Kph(TL}Hb0|h-n z?Zg=wWlSbAms!6K;?sW91=Qx32(373vgRGSf!oA&C7qQcy1Epuuhjnu?5djKo}OLz zUEog{Q(ZgD7p^gN5JfyLw%$~{UUJ*`Dg=}Vd<~ij@J4nb_Ey=rVRREu{I0;!auI@v zguUjMZMp-!09O0s$!F|)etJMjI)37K)$Qy;x z;l_ps4b2=YkY@VZzX@E1T7hI}VavU%45$2JTe` zOXrqQTGj+Ybx0i-oV6eY%>~i&h!Rj25h!JpT&r(&Q7W`YI;lB|ccj}}+4|)AX%4(0 zfN1He05p^|l=N0S^tw(Mpxb-;EI3&pJwn_BLpCIQauN^x5CCtGTWl^b^+h+`rR5u& z^fIavIv0>ZOz-v9m$1cq%UJK5=$2GR%iAXU#TG}r0H6^M2d){hJANB9`W>VC=nw_8{Gv+A>|*?LUPP7m&lxcM3@pEy1nDS`DXH#%JS}!Pu z^~6T-uFh?J37<*DiA)Bqb#nc-6fOuzJoIW;tEj^M1N@N+jySrnMskUeUSDv#LKdEL zD@X?qgVD2_Y=oxt>)U=@&6Qj35 zm>pd7@pd`%TRvw=U8V!At<~$HK!2LfQD(~;!zZcsc4Ii;X-+oh*xcJU5HE@Yk8h4W zK|HMCXeHGA->=_r9#7ALrC`^Er;Qc#kP}j6`T}jHk?IAZfu&LkEZf9KdosnJW8BlL zcKFnn?!Adj%fa&wn+JZLcC2kB9#DuYdKsFtDWB&Se!ORs>9JL4?sE@p6#btRj$J0) z(}b*?Tr7#U#c6zZ5xs??3Z=)L82OjOyISkQ5~WBX2Tw+dgYRNQhEd3Yckc_^qhGQE z4hUB3W{vbI{Th17wTUH`O@J4DhO2N9JGIc#E^6ls_6jRKUKHivi`#8?vbuRlm2d?NfYr3@~(>q#Zir769yX6YfuqSj&fmO*ObIs6KD-dQ>-d#mrv=X<=l??mGSr17 zBhe&k&o*t&N!wKst|+| z(a3$R^oYr%4qeBffAL*c9q7)OK_tuAKQ220sYdXOGaLrB> zUeRIjOPF6|bJQVg{Fe7?J=ap?nL`*a=lWuo9I@o(Dj?u8>yie`IbK95iwVkKwx$ua zOO4>07M#80dQ10*Tep&IB(=VlPkY2f*b{~_ zP_Fp7UuY##`=Q z+PZP$8t#3bYv@_Md7r-yujS=%Wcr;v1;gQoS@NEzMzHD7n}vCDl%9zRc2ea&H%Lc% z#6_3R0$P}-e6;s5LchgCW_-s*lRLGrzMATQUJwQjC%%CTKQHeWnICJs7Zy3bk*&@L zP`UtNEZLuLjk-w?k@s>K4s9<@^b4S!2HiMSPf5nvEwZ z+TAa{OcaXS4oudN`@)wup}A(h$w!N&PRKRphs-v59Wd*7Bkb#e;)H`V)a*6rhRnDU zC;c~d(k*qPxY~~xGw^^pubsFYTZ{%d4ufwJqk5K1z9SAM6t0s(mu^}Cc7+T|6CG>V zQq6|{zTW(RD-c`nlyY4Fv`VJ3)M)A$g#}cOkx>kVw91yvs=H#zb)h9in;+Dn z2DpxO9lONX9a~#s%9L-MR$=k-9>A9cx5Mwy7s@h_SL$NG$V=cbz@&0&KMBY&xCxW& z%pbIeU$WVbUONZ5P+LT_OQrxjTnfo(M8qE)u$>S&wbg>=b{ab56)=Z&YLn+F0yTN< zo;};b=}c>ilanve-mON~EUhRyXD4S(5R4~8)v7WmWpA@Gv%8oTc0?03yA93yvgPdH zv$2cO@Xe7ne}_YOhZgy{;_^5tIt~M2C{MfL*VYE8X~pw7Rpy#3uEmrc(+&m13xWk#M_dhL()rsuut*hpB!5iXigg4nPRRt_<-;Q!T(6SJKmcrJ8ZiS*XFo@9 zxyOW*a)uBsT};x_k{Gx?JdcbW&|(DN&nlNY?B={--sW+UU-z3-TnvMV6l?qG{t~a` z0SgM_X=-XR%2~5~6mvhVSXo~g>2+4t^XBeTc(dk-FL~+3jsJmW&7XncTfejeg{Y_{ zr)`r=b61B)- zA|!00aM_AmewugQNYQGaRq&68T9gXhvNCE-sPaZtvNH%3 zuVf$ca$J2{D(3FcAsBd8q8eNgZ{PGhHBc}7KLK$Uj_9q$|9s(fN4Ty4+#8P~Yu~l~ z=F6VH3i$3y{Cam57Wm%BlhTIw(!^*&EPr2+pClX0B_mDRBomj!MP9x6b^P$TLOii{ zK6Y#tBV*TFn7AR<6FQmI|b=RFjFipX&pkBm$aZH5VNLl-S>cX zQO%FDbTUV*)ET$E0?r@Bw1Nu=II$*n;L;MwS=L(SR-dOuaJ0_xd~rkVOtcQX?C9{O z2Kzs$z~X!DmQBOB_%%Yqs4gmIcxUSUcgB6)>8W@Oi^92Vrj&qt&YM6O6d5uJHna zLn&U~kKzOanN#hSm6!b8$jF*57Q5lH^n!8zTqEwBe~-Dj((BM?2T(NUE_F_+Ki|8j z+$RLoP7r9DsNgX{vd`y3tANqe^h|YbSdRGv{eHC#2X66PFt1xcDbGdS$#!*4)wz}O zJ>sUDaiUpP8?j-8Oz)kiRA&fLK~&MmAglo2k?rm6DwG5Vt}>(qUE&(QCHmB0K6>~Wlkml!v|2nuP19C}Do@5z z0jY$c0T|}F>`gE+DdG)l+`*Q(Yfvuumqx+X6z|HzlBIcAurGkj=V}mGy%HPR+*n>& zBefdesLKnpu;kC>*gd@jnOKIu*1c^9u;DSL)~ch=3jl7ft3*YOpkLBoaa+AW#<*6! zSP1XSZnPH%@oNFzPnOU%bRM2~^9@x`^_J&RxavW?_P}QBZQ6q()L^HZ$88=^v;lQ$ zQ~l2nP@tuyMM4@)u>H0f0*9p!K`WpY&y$7^7Dwt-u#4z?jgq`ZfQ$y8Hrz zJHRPBaVMroEJd;WrKN95TBcZKC8~M4a<(RR%F+^wP?#XNy}eZ+@C7tAO9yIl64-H` znwFtrud+jpA1>C8QEO+gwcg=9&yV?Q8(n&RbP6I6jFb4wmfCK16D+$nXXygcbR%x& z@yB9K&0)-+ztGGY(o@0?EAZgKvJ-saqR3I9w8-PVHQE)n(zAUVk=NaTQtUO7G1>pt51hjEmxv6Rg- zx=>=)J5x?BA*a2=ir^|^(qv~*BqmEdd+~~4P1Gha$sXgL^{D|dAqxrfT<|#P_So9OU?6mM*PcMZOv8mC!6mJm2~g>cW2{(G zo3XT&rw_3ro|u{{=ZDtK25|0`XL6rdLI))_vpUyuj%lqc92d2h&JUL3Ib_&~J-gmj zx1sRX@Q!V8Fu$Ztyp&UY!akDWSM<0G5va&qj~5A!)FVA{0Ee09N_8-}JF2*Kyjq)FlP z&G+%?GxfN`F%XP{Bzb-6fn5#}^`cflE1(r{D8TR{Y0|f#zEd6R^y2NKz_DY;Kubsd zCNPuryNlm1Y3XU|ThLs8wP|+YD&T=~_?{?KZl38XI*Zn}(!T-uyt4OR#fuwe;Kiy& ztj^1mL6%Z@U5VjpS*(Oxkc@QMEFj;K+%D*C#PU^i+sx#`g5qLSJeMYQlw*m@huzzO z-?Vx0#HI&u|JE9`OB;+7kF+fDKpk2#C$|2UP-cs`sdi@5`bKZUwD?`cPssPtZ*IPkw#W;Ef=@hVkvD&(xsx)5LJNp zP-bShpJ#|3rammKfL1^&pcVKM3VeQGmM>9}E_(Ybzz)l9v05SQRo1`KA!>kNzv}QL z%pD`~p*c;>fB!Ep7?_u9M-yRl_|hwvhS zkM$MEd+HS|N%o^+=MfaGSQ2&L&bEA=Wm?cigThTsjnc6zzrKb^iq;vDIVC&d=#!FM z%Jr>v1p!UDg7_gbT zSRu2i6TyxX+;Lrget}tJa60)aKjaIG<|)kv3(5=!Svd#F(2}CBPY%qH=yEw(Ky;$S zb2U>_(`mK66$~>rbF2VWGqDpcCMFi#zcbM)n)*AzRpPi7fyiOE-Q3PAVE_^Ypjj#K`+|U#e+Tye9Wx8(2v?IlId43tm&6rykDTA6B(aW`WrjxSQ`RH_bahB5 zii-x6=Jo{30dbw}ZE~ynj5-K!M_|ui-cudNBS#to37B`G<+M6)1j`Je!sj6e$~5$J z4nkz41P_SSRicuj~+2;J4$Z#yn(MgZvSl!=vVCLq^a*vcG8m5=~FaoufA97vEX zK#<32eXi4Ln#X6o#&`|0z0Sn8m9odDCiFYbrSR)}uhW+=_`7!wi_A`U4USkB6x7EzARLMtdX3vj>!uLbM< zMXUFA`MaaQ?oFgYzQs8x#hPfj&hMk)a1N};t>?7@T7jXXfY;liymB}_xj2uIAxiju zwT2jRmbo35o0}U|=oNm042Lvz>Qn`Wt;cGF34XVR+XhfuS&nU+-Ue2d<8P$|zybKSmEc8eL!q}A zzgum8Hy8ip7kFsvL40q6QGdWwh3z}`NR!G@U7UrYZ2mH;!K}MVu=kW$B7a}u?z|QC1!rGVL7NG3K%V|&H*%uF@Xz4nv zHZ}#^2jN|}ZZLMTI!OJ`kWqlYb@{D6Z{D3l=9u(>Xa%$aS^=%V*H>VKbht(K5`O)9 zbq%+$0{kfG?({3`s;&;7>d@?zX)w^O;vB}xFhRP9G$AlS@aPbLGUds*>!DN#sB#_Qu~8Qy?@2$ z)EmUspS~|3_hERpK8u43|2tMsH^8~C=>)2qgUDMn7rvd(; zD_9yV!y_N$;+@q62($`}Pt8TTe?NY>H5tEITYy>typ_!cOb*sbeQiL|q5=cdO1VuR zrQnGbxk5$+Ja0b$*TM&}H1z-`F4&KKRX;?2vI+5}oj>>u=Kt(r)NF4+$)aZbqW*5I zPdS3BloI&g+J)sjh7WhcjU1HTCv`HlR^Y|`ld*yO_?*<;*Z|M(e~EkleedU#`tqwh z5}!AkE6Fck)9~HGBUVhAQ>NPBgy&3yvXDx#fFA?YT#@@dY?(ZKRntd)J1RgpOu(k# zu>ym=A>eFG4OnQvNHtHZWx`38mG>>Dv;-u4WgW^YS(Z5^*fE!l`7mTw%b{{NQa8eL zf^4&cjr(G}a(WA3yk;};UH@s--?6y(+h&%U?kWHOFn#(AWKRu0&uLXl06M#HuB|LP za%o*`-Pf0KnH;Sw+eN@TW^6b%EO&bPbiG(>hTFuvvuB&s;FlC>gP91)4jrmegNO)M zX{F9-gA8O#nK)6jp}T7Xuy)9|Qcq8>42&8b0@KEMz8nZ*^hmK>mTQIEn!uS;bKsl_ zjCsCkwa(65^(XU$(EQG#b-OAjc?Q_+m+vx{fK(1JFa{p*7_zc+R7_~b>Sp5iRzNI~ zopAA^kM`hO-+DlmG5FI%x&80$PD@ zQh{^l&dGahyc#6)O}68k+IP$Ov+@idA9e82H`S&az26T%{F@4kV%-maU-BE2p+`Do zFdf10tfITEMXo*{@QD{@7hKmk5;Y)$-QvYl(6yxiT3Ui|rMn^ry2>|`X<_WFYv+>> zBmRYVvD7}!&RI;BeNum%e4|BgJip7F;WQ*m@}g9wvV7Qd|MMvR%NrOBH+;3Cl7G0W z0!vC(*aoP5PI0~J7Es{y=?3-tH7_s!7HG}QZNkx`)iRJ~vh+iTf7jmJ7U;cc1+)TM zfm>IB;W5PU*46)pwv4fVy959e{;EH*XyNpVSn(t#xSkL(d9^`9W?%VRkOIwYEs-l2=&)O`Mo2t|Y~Mj>JE-Ze!igaGM|FZ-)r~ z1&7^?>W(<9lv3IA7NSz1y7JT7x*I>=pMzKaA&5tQP=;3@pNpbk?x5vu+RPOEV&`FG z<(`%DMu&L3Kwc(OD<0;5p@SpMWpZ8(h%sI&Z z&SK2M2GrLkqk2&gW&crubkGG zA{rDvD3($47Yq-V(_d9L>vmQMWaiUtEjy;IiJ;{8(Ic35mt9+SXfPI|)#Ayzou1bU z+$stva4W#>>v*vs5LTdA?gztimq5{+m)K|mwKza)aGiiMV;ciJS|PCskQuUp(2>i= zpTK4{AD%M*i;~sK)GW)`xXwfiLnjnwnQ!0!59+(XTAt7_MqE5Q(}`o%NVw~6Bng-_ zQ{AarfwBF#V`kXWkt&IyQCnMwaxqn86j5K8m=Ehw;=0JiCLi@J8M$o0Z&sK37tP4zVbpL+$?Njz%; z%o0aNKQcQv4bH1E!Ty>=z;zLT<*Mtfj)`1Oh_$x{iM+HM=Nhy zSDA^HskHF6g5gg2u4J-;VKI!AIL|E+V0hF>T9w4-~p9qjq^-^&2L#Nm}XhJ=+4cxyL~1UWm~PC ztAxq+U?XPV^%lcJ@yXvd9&n5L=b*1gQ#VmDo zC=66=5i90*uMG;D_37#DrNG&nOfjYkOo6F$X;Bq!rK#Xa%$akqU%+ zyCT==oZCbJcK&gMWT*e4>R9gVka_t_N;W!n$BO&svEm{&ZF06)oQUf<>GZR9sPW_a z@B1oHyu@w=lql~1;vIoaCJM-LrcUWNYZVyW>OC(VnE|AxXCO0c8s^?<2SLv5hQqQ) z;CiOGEVg#m#Yt?%F9ySzC`vk@B=Q{J4a{Ap<^yeQh)7QTBnjcE&3Lelzj(fBQXt@_)U8 zbnzrg>njy2RKV@l4^P0|)P}P99Q^nDq)oX6D4O|w^?5_r%HBPhoEO?9G`HL&AI-8K7922 z3goR^kBs^M+04G~)7j#l)S04a9Xq&m7?KI}E^`0ZRbHY2i&z(6d@|n8izLJPTPfJTvZMCi- ze58A3XKHTph+AB{1u9)p`{g@?Zl}$}XGTLqomi0Mn^|gl@#2N3u+dg1v=GhulzGwe zoluxnSY2$J*1;*M8M6N#n{~5#7WR)2H_kb>X3*l9VAKlh{1UgB`E%wNZs2&Fybj!A z0h*a9&|BaxzX@seOsLr}ogjp>gvdSO@ufR7Kw&_(v068q^Ji*fC6q{~d@Itb*?`6u z&&wb|xh5F5Sy?Ts>1Y}J!PlmKbEJWdnXeX-rE%JO)*%{Z~RN zo1HbZgm$`BZxrtyjNNOG<2@h%vI8k8;qOs)4v$F~W8ICKpD6Q$oEs69;_~##U}wT_Us`T8p?%IfxuXm*t&1#00001_ diff --git a/develop/doc_cn/_images/pprof_2.png b/develop/doc_cn/_images/pprof_2.png deleted file mode 100644 index 172ba20399ba974d27f4c072425277b69b02520b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194000 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�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 bg1?qGymXmRYp`!_b>? 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%0Dek1 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 z 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 UA!c8H>i_@%07*qoM6N<$f|2}Ij{pDw diff --git a/develop/doc_cn/_sources/design/api.md.txt b/develop/doc_cn/_sources/design/api.md.txt deleted file mode 100644 index e6a4638d910..00000000000 --- a/develop/doc_cn/_sources/design/api.md.txt +++ /dev/null @@ -1,262 +0,0 @@ -# PaddlePaddle Design Doc - -## Ingredients - -As our design principle is starting from the essence: how could we -allow users to express and solve their problems as neural networks. -Some essential concepts that our API have to provide include: - -1. A *topology* is an expression of *layers*. - -1. A layer could be any kind of computation, including *cost*. - -1. Some layers have parameters, some don't. Most costs don't have - parameters. - -1. In some topologies, layers share parameters. For - example, - [the network for training a ranking model](https://github.com/PaddlePaddle/Paddle/issues/1311#issuecomment-279121850). - -1. At programming time, users specify topologies and possible sharing - of parameters. PaddlePaddle can figure out and create parameters - required (and possibly shared) by one or more topologies. - - -## Starting from Examples - -As a summarization -of -[our disucssion](https://github.com/PaddlePaddle/Paddle/issues/1315), -let us present two examples here: - - -### Example 1. Sharing Parameters between Layers - -We use -the -[3-branch ranking](https://github.com/PaddlePaddle/Paddle/issues/1311#issuecomment-279121850) model -in this example. For your convenience, I copy-a-paste the model's -topology as follows: - -``` -A -> f -\ -Q -> f --> cost -B -> f -/ -``` - -The following program trains the topology including the cost, and then -use the sub-network in the trained topology in inference: - -```python -def f(in): - e = paddle.layer.embedding(in, parameter_name="embedding") - o = paddle.layer.softmax(e, parameter_name="semantic") - return o - -# Create 3 topologies (subnets), they share parameters because all -# correspoinding layers have the same parameter names. -fA = f(paddle.layer.data(input_name="A")) -fB = f(paddle.layer.data(input_name="B")) -fQ = f(paddle.layer.data(input_name="Q")) - -topology = paddle.layer.less_than( - paddle.layer.cross_entropy(fA, fQ), - paddle.layer.corss_entropy(fB, fQ)) - -# Derive parameters required in topology and create them in model. -parameters = paddle.parameters.create(topology) - -# Estimate parameters used in topology from data. -paddle.train(topology, parameters, reader=read_ranking_model_data) - -# Inference using fA (or fB or fC, as they share their parameters). -[testA, testB, testQ] = read_ranking_model_data() -print "The sematic-vector of testA: ", paddle.infer(fA, parameters, testA) -``` - - -### Example 2. Sharing Parameters between "Models" - -We use [GAN](https://github.com/PaddlePaddle/book/tree/develop/gan) in -this example. In the following example program, `d0` and `d1` -correspond to the two networks in the following figure: - - - -```python -def G(in): - # over-simplified example as G has only one layers: - return paddle.layer.fc(in, parameter_name="G") - -def D(in); - # again, over-simplified: - return paddle.layer.fc(in, parameter_name="D") - -# Construct the first topology, which contains both D and G. -# By learning this topology, we update parameters of G. -d0 = paddle.layer.should_be_false(D(G(paddle.layer.data()))) - -# Construct a second topology d1, which contains only D. By -# training this topology, we update parameters of D. Note -# that d1 share parameters with d0. -d1 = paddle.layer.should_be_true(D(paddle.layer.data())) - -# Create parameters from a list of multiple topologies (models) for -# the chance to share parameters between these topologies. -parameters = paddle.parameters.create([d0, d1]) - -# Iterative training of GAN. -for ...: - train(d0, parameters, reader=read_from_rng, immutable_parameters={"D"}) - train(d1, parameters, reader=read_from_realistic_images) - -# Use d1 for inference: -print "D thinks a batch of images are realistic ", infer(d1, parameters, read_mnist_images) -``` - - -### Summarization - - -Above two programs reveal some important design concerns: - -1. Users describe a topology as an expression of layers. Every layer - has a *parameter name*. If the users don't specify it explicitly, it's automatically generated as a unique name. By - specifying the parameter name, users can specify the sharing of - parameters between layers and even between topologies. - -1. `paddle.parameters.create` figures out parameters required by one - or more topologies from parameter names of layers. It creates these - parameters and returns a `ParameterSet` object, which is in essence - a map from *parameter names* to *parameters*. - -1. At training and inference time, `paddle.train` and `paddle.infer` - requires both a topology and the parameter set that holds the parameters of that topology. There are some reasons: - - 1. This prevents users from forgetting to call - `paddle.parameters.create`. - 1. `paddle.train` needs to know which parameter set to update. - 1. Users could load another (pre-trained) parameter set and use it - with a topology in `train.infer`. - -1. By specifying the `immutable_parameters` parameter of - `paddle.train`, we can forbid the update of these parameters. - - -## Reader - -Not all programming frameworks allow users to define I/O functions. -An example is Google MapReduce, which can only read from text, -SSTable, and RecordIO files. Hadoop MapReduce allows users to define -readers and writers by deriving from base classes `Reader` and -`Writer`. The former is less flexible but also less error-prone. We -decide to provide the flexibility to users to define their readers. - - -There are some open questions here: - -1. **Should a reader return a Python dictionary?** - -1. **How to map multiple outputs from a reader to multiple data layers?** - -1. **How to easily compose some existing readers to read more data and - feed a topology with more data layers?** - - -## Training - -The recommended way to training a model is to call `paddle.train`, -which simply calls `paddle.trainer.Default`, a global variable of -type `paddle.trainer.SGD`. Equivalently, we can do - -```python -opt = paddle.trainer.SGD(..., paddle.updater.Adam(...)) -opt.train(topology, parameters, reader=read, ...) -``` - -### Updater - -Please be aware that a trainer can accept an updater as its data -member, where an updater is a class derived from -`paddle.trainer.Updater`. This is to make it easier to customize -trainers, as discussed -[here](https://github.com/PaddlePaddle/Paddle/issues/1319). - -### Event Handler - -`paddle.train` and `paddle.trainer.XXX.train` take an optional -parameter `event_handler`, which should be either `None` or a function -that handle some events: - -1. BeginTraining -1. EndTraining -1. BeginIteration -1. EndIteration -1. BeginPass -1. EndPass - -where EndPass is sent if and only if the reader yields -`end_pass=True`. - -An example as follows: - -```python -def event_handler(event): - if ininstance(event, paddle.event.EndIteration): - print paddle.test(...) - -paddle.train(topology, parameters, reader, event_handler) -``` - -If we are writing a PaddlePaddle program in and for iPython/Jypyter, -we can use metaplotlib in the event handler to plot a curve of -cost/error versus iterations, as shown -[here](https://blog.dominodatalab.com/interactive-dashboards-in-jupyter/). - -### Distributed Training - -If users want to do distributed training on a cluster, s/he should -call `paddle.dist_train` and provides access tokens to the cluster as -a parameter. - -For example, if the user has a TLS certificate that allows him to -access a Kubernetes cluster, s/he should be able to call - -```python -paddle.dist_train(model, - trainer=paddle.trainer.SGD(..., - paddle.updater.Adam(...)), - reader=read, - k8s_user="yi", - k8s_token="kube_cluster_tls.pem", - k8s_job="hello", - num_parameter_servers=15) -``` - -The pseudo code of `paddle.dist_train` is as follows: - -```python -def dist_train(topology, parameters, trainer, reader, ...): - if os.getenv("KUBERNETES_SERVICE_HOST") == None: - image_name = k8s_user + '/' + k8s_job - docker_build(image_name) - docker_push() - kube_ctrl_start_job(image_name, k8s_user, k8s_token) - else: - rank = kube_list_containers_in_job_and_return_current_containers_rank() - if rank == 0: - master() - elif rank < 15: - parameter_server() - else: - trainer.train(model, reader=read) -``` - -Please be aware that if a process is running on the Kubernetes -cluster, it will have some environment variables pre-defined. - -If `dist_train` doesn't see these environment variables, it knows -that it's running on users' personal computer, and it should work as a -*launcher*. Otherwise, it knows that it's running on the cluster and -need to figure out its role as either the master, or a trainer, or a -parameter server. diff --git a/develop/doc_cn/_sources/design/auto_gradient_check.md.txt b/develop/doc_cn/_sources/design/auto_gradient_check.md.txt deleted file mode 100644 index 773b7b6a767..00000000000 --- a/develop/doc_cn/_sources/design/auto_gradient_check.md.txt +++ /dev/null @@ -1,150 +0,0 @@ -## Auto Gradient Check Design - -## Background: -- Generally, it is easy to check whether the forward computation of an Operator is correct or not. However, backpropagation is a notoriously difficult algorithm to debug and get right because of the following challenges: - 1. The formula for backpropagation formula should be correct according to the forward computation. - 2. The Implementation of the above shoule be correct in CPP. - 3. It is difficult to prepare an unbiased test data. - -- Auto gradient checking gets a numerical gradient using forward Operator and uses it as a reference for the backward Operator's result. It has several advantages: - 1. Numerical gradient checker only needs the forward operator. - 2. The user only needs to prepare the input data for forward Operator and not worry about the backward Operator. - -## Mathematical Theory -The following documents from Stanford have a detailed explanation of how to compute the numerical gradient and why it is useful. - -- [Gradient checking and advanced optimization(en)](http://deeplearning.stanford.edu/wiki/index.php/Gradient_checking_and_advanced_optimization) -- [Gradient checking and advanced optimization(cn)](http://ufldl.stanford.edu/wiki/index.php/%E6%A2%AF%E5%BA%A6%E6%A3%80%E9%AA%8C%E4%B8%8E%E9%AB%98%E7%BA%A7%E4%BC%98%E5%8C%96) - - -## Numerical Gradient Implementation -### Python Interface -```python -def get_numerical_gradient(op, - input_values, - output_name, - input_to_check, - delta=0.005, - local_scope=None): - """ - Get Numerical Gradient for the input of an operator. - - :param op: C++ operator instance, could be an network. - :param input_values: The input variables. Should be an dictionary, whose key is - variable name, and value is a numpy array. - :param output_name: The final output variable name. - :param input_to_check: The input variable with respect to which the gradient has to be computed. - :param delta: The perturbation value for numerical gradient method. The - smaller the delta, the more accurate the result. But if the delta is too - small, it will suffer from the numerical stability problem. - :param local_scope: The local scope used for get_numeric_gradient. - :return: The gradient array in numpy format. - """ -``` - -### Explanation: - -- Why do we need an `output_name` - - An Operator may have multiple Outputs, one can compute an independent gradient from each Output. So the caller should specify the name of the output variable. - -- Why do we need `input_to_check` - - One operator can have multiple inputs. Gradient Op can calculate the gradient of these inputs at the same time. But Numerical Gradient needs to calculate them one by one. So `get_numeric_gradient` is designed to calculate the gradient for one input. If you need to compute multiple inputs, you can call `get_numeric_gradient` multiple times each with a different input. - - -### Core Algorithm Implementation - - -```python - # we only compute the gradient of one element a time. - # we use a for loop to compute the gradient of each element. - for i in xrange(tensor_size): - # get one input element using the index i. - original = tensor_to_check.get_float_element(i) - - # add delta to it, run the forward op and then - # get the new value of the result tensor. - x_pos = original + delta - tensor_to_check.set_float_element(i, x_pos) - y_pos = get_output() - - # Subtract delta from this element, run the op again - # and get the new value of the result tensor. - x_neg = original - delta - tensor_to_check.set_float_element(i, x_neg) - y_neg = get_output() - - # restore old value - tensor_to_check.set_float_element(i, original) - - # compute the gradient of this element and store - # it into a numpy array. - gradient_flat[i] = (y_pos - y_neg) / delta / 2 - - # reshape the gradient result to the shape of the source tensor. - return gradient_flat.reshape(tensor_to_check.get_dims()) -``` - -## Auto Gradient Check Framework - -Each Operator Kernel has three kinds of Gradient: - -1. Numerical gradient -2. CPU kernel gradient -3. GPU kernel gradient (if supported by the device) - -The numerical gradient only relies on the forward Operator, so we use the numerical gradient as the reference value. The gradient checking is performed in the following three steps: - -1. Calculate the numerical gradient -2. Calculate CPU kernel gradient with the backward Operator and compare it with the numerical gradient. -3. Calculate GPU kernel gradient with the backward Operator and compare it with the numeric gradient. (if supported) - -#### Python Interface - -```python - def check_grad(self, - forward_op, - input_vars, - inputs_to_check, - output_name, - no_grad_set=None, - only_cpu=False, - max_relative_error=0.005): - """ - :param forward_op: used to create backward_op - :param input_vars: numpy value of input variable. The following - computation will use these variables. - :param inputs_to_check: the input variable with respect to which the - gradient will be computed. - :param output_name: The final output variable name. - :param max_relative_error: The relative tolerance parameter. - :param no_grad_set: used to create backward ops - :param only_cpu: only compute and check gradient on cpu kernel. - :return: - """ -``` - -### How to check if two numpy arrays are close enough? -if `abs_numerical_grad` is nearly zero, then use absolute error for numerical_grad. - -```python -numerical_grad = ... -operator_grad = numpy.array(scope.find_var(grad_var_name(name)).get_tensor()) - -abs_numerical_grad = numpy.abs(numerical_grad) -# if abs_numerical_grad is nearly zero, then use abs error for -# numeric_grad, instead of relative error. -abs_numerical_grad[abs_numerical_grad < 1e-3] = 1 - -diff_mat = numpy.abs(abs_numerical_grad - operator_grad) / abs_numerical_grad -max_diff = numpy.max(diff_mat) -``` - - -#### Notes: -The Input data for auto gradient checker should be reasonable to avoid numerical stability problem. - - -#### References: - -- [Gradient checking and advanced optimization(en)](http://deeplearning.stanford.edu/wiki/index.php/Gradient_checking_and_advanced_optimization) -- [Gradient checking and advanced optimization(cn)](http://ufldl.stanford.edu/wiki/index.php/%E6%A2%AF%E5%BA%A6%E6%A3%80%E9%AA%8C%E4%B8%8E%E9%AB%98%E7%BA%A7%E4%BC%98%E5%8C%96) diff --git a/develop/doc_cn/_sources/design/backward.md.txt b/develop/doc_cn/_sources/design/backward.md.txt deleted file mode 100644 index 20fda7a98f5..00000000000 --- a/develop/doc_cn/_sources/design/backward.md.txt +++ /dev/null @@ -1,158 +0,0 @@ -# Backward Building - -## Motivation - -In Neural Network, most models are solved by the backpropagation algorithm(known as **BP**) at present. Technically, BP calculates the gradient of the loss function, then propagates it back through the networks following the chain rule. However, when configuring the model structure, users do not need to define the backward part. So a mechanism is required by the framework which can complete the model's backward part automatically according to the given forward part. - -When implementing a specific `op`, the developer is also asked to implement its backward version, called `grad_op`. A `grad_op` takes gradients of its corresponding `op`'s outputs, and calculate gradients of the `op`'s inputs. During the building of a model's backward part, the framework creates each forward `op`'s `grad_op`, and then string them together in reverse order of forwarding part. In this way, gradients spread from the end to the beginning of the model, in another word, from the loss to parameters. - -## Challenges - -The motivation of backward building is apparent. However, implementation it correctly is not so easy. In the **Fluid** design, a deep learning model is described by `Program`, `Block`, `Op` and `Variable`. The `Block` itself can be nested. It means that the `op`s and `variable`s are scattered across different blocks rather than all be gathered in a single graph. Our backward building algorithm shall visit blocks in recursive order and be able to insert `grad_op`s and new created `variable`s into the right place. - -## Usage - -Although the whole algorithm is comprised of many functions, only one is exposed as API: - -```python -def append_backward(loss, parameter_list=None, no_grad_set=None): - """ - Append backward part to main_program - - Args: - loss(Variable): The variable generated by the cost function. - parameter_list(list): Parameters that need to be updated by optimizers. - If None, it means all parameters need to be updated. - - no_grad_set(set): Variables that have no gradients in Block 0. - If None, the set will be generated inside the function and - contains all variables with `step_gradient=True` from all blocks. - - Return: - (list[Variable]): list of (parameters, gradients) pair. - """ -``` - -By invoking this API, the framework appends backward part of the program where the `loss` is. It takes three arguments. `loss` means the final loss value. It must be a scalar and is usually the output of the loss layer. It is also where the gradient generated and backpropagation starts. `parameter_list` marks all parameters needs updating. If it's `None`, all parameter will be updated by optimizers. `no_grad_set` marks variables without gradient. if all outputs of some `grad_op` are in `no_grad_set`, the `grad_op` will not be run. - -This API will be invoked automatically before optimizer building. -As a result, in most cases, users do not need to invoke the API by themselves to append backward part. - -## Implementation - -The implementation of backward building algorithm is in `backward.py` file. The whole algorithm can be divided into two independent parts: creating `grad_op`s and creating new variables. - -### Creating `grad_op`s - -The creating of `grad_op`s is implemented by: - -```python -def _append_backward_ops_(target, - block, - target_block, - no_grad_dict, - grad_to_var): - """ - Create all grad ops, and insert them into given block - - Args: - target(Variable): the target variable of forward pass - block(Block): the block where forward ops are - target_block(Block): the block which is going to hold new generated grad ops - no_grad_dict(dict): - key(int) block index - val(set) a set of varibale names. These varibales have no gradient - grad_to_var(dict)(output argument): - key(str): grad variable name - val(str): corresponding forward variable name - """ -``` - -Given a `block`, the function will traverses all `op`s in this block in reverse order, gets corresponding `grad_op` from the C++ core via `core.get_grad_op_desc()`, then append it to `target_block`. - -However, some specific `op`(e.g. `while_op`, `if_else_op`) can hold its own sub-block. For these sub-blocks contains `op`s as well, the `grad_op` creating should be recursive. - -During the reverse traversal, we check each `op` whether it has an attribute named `sub_block`. If so, it means there is a sub-block and we need to deal with it first. After creating a new block whose father is the one in `op`'s attribute, we invoke `_append_backward_ops_()` recursively, assigning the new block to parameter `target_block` and the one in `op`'s attribute to `block`. The *pseudo-code* shows this process: - -``` -******* pseudo-code ******** -for op in reversed(block.ops): - if op has an attribute named 'sub_block': - Get the sub-block(`s_block`) from op's attribute. - Create a new block(`grad_s_block`), whose father is `s_block`. - Invoke _append_backward_ops_(), with `block=s_block` and `target_block=grad_s_block` - - Invoke `core.get_grad_op_desc()` to get op's grad_op. - Insert name correspondings between variables and their gradients of the grad_op to grad_to_var - Assign grad_s_block to grad_op as it's 'sub_block' attribute. - Append grad_op to current target_block. -``` - -The first invoking of `_append_backward_ops_()` is initiated by `append_backward()`, in which parameters `block` and `target_block` are all assigned with root block(the block with index 0). - -### Corner Cases of `grad_op` Creating - -In the previous section, we show the regular process of `grad_op` creating. However, in some corner cases, the conventional algorithm is not enough to get the correct result and appending handling is required. These additional processes run after the algorithm mentioned above and do some special adjusts on its output `grad_op`s. - -#### Shared Variables - -If a variable is read by more than one `op` in the forward pass, its gradient is likely to be written by more than one `grad_op`s in the next backward pass. To make the gradient result being the sum of all `grad_op`s' outputs instead of the last running one, we assign each output with a temporary variable and then add a `sum_op` to add them up. - -For the debug convenience, if the final gradient name is `w@GRAD`, it's corresponding temporary variables will be named as `w@GRAD@RENAME@0`, `w@GRAD@RENAME@1`... - -See function `_addup_repetitive_outputs_` in `backward.py` for implementation details. - -#### No Gradient Variables - -In our framework, variables can be marked as *no_gradient*, it means that the gradient of this variable is unnecessary and can be considered as zero in model training. Apparently, when all the outputs of some `grad_op` are marked as *no_gradient*, the `grad_op` itself can be skipped in backward pass. - -Another situation is all the gradient inputs of some `grad_op` are marked as *no_gradient*, which means all of them can be considered as zeros. For `grad_op`s are in essence the propagation of gradients, all the outputs are definitely zeros when all gradient inputs are zeros. Therefore the `grad_op` can also be skipped. - -It should be noted that all these zero gradients still need to be creating and initialized by something, otherwise following `grad_op`s who take these gradients as inputs take the risk of using uninitialized memory. In our code, we employ `fill_zeros_like_op` to initialize them as all zeros. - -This features are implemented in function `_remove_no_grad_branch_`. It checks new created `grad_op`s one-by-one, removes who can be skipped and inserts `fill_zeros_like_op` when its necessary. We can get the `no_grad_set` from the `_append_backward_ops_` argument `no_grad_dict` or generate it on the fly by scanning all variables' `no_gradient` attribute(True or False). - -### Creating Backward Variables - -Up to now, we have completed all creating and adjusting jobs of `grad_op`s. However, backward variables have not been created. Now they are only represented by `grad_op`'s input and output arguments. The backward variable creating job will be done by: - -```python -def _append_backward_vars_(block, - start_op_idx, - grad_to_var, - grad_info_map): - """ - Create new variables required by backward pass. - - Args: - block(Block): the block where new variables will be created - start_op_idx(int): Only variables required by ops in block.ops[start_op_idx : ] will be created - grad_to_var(dict): - key(str): grad variable name - val(str): corresponding forward variable name - In most cases, this dict is generated by _append_backward_ops_() - grad_info_map(dict)(output argument): - key(str): forward variable name - val(tuple): a tuple of (str, int), str is the corresponding grad name, int is the block index - """ -``` - -Given a `block`, this function traverses all the `grad_op`s in it(The argument `start_op_idx` indicates where the grad_op sequence starts.) and creates all the uncreated outputs. The *pseudo-code* shows this process: - -``` -for op in block.ops[start_op_idx : ]: - - if op has an attribute named 'sub_block': - Get the sub-block(`s_block`) from op's attribute. - Invoke _append_backward_vars_(), with `block=s_block` - - for var_name in op.all_output_names(): - if block.has_var_recursive(var_name) or var_name is the name of empty variable: - continue - create a new variable named 'var_name' in block - if grad_to_var.has_key(var_name): - set grad_info_map[grad_to_var[var_name]] as a tuple of (var_name. block) - - do op's var type inference - do op's shape inference -``` diff --git a/develop/doc_cn/_sources/design/block.md.txt b/develop/doc_cn/_sources/design/block.md.txt deleted file mode 100644 index 907a2def557..00000000000 --- a/develop/doc_cn/_sources/design/block.md.txt +++ /dev/null @@ -1,336 +0,0 @@ -# Design Doc: Block and Scope - -## The Representation of Computation - -Both deep learning systems and programming languages help users describe computation procedures. These systems use various representations of computation: - -- Caffe, Torch, and Paddle: sequences of layers. -- TensorFlow, Caffe2, Mxnet: graph of operators. -- PaddlePaddle: nested blocks, like C++ and Java programs. - -## Block in Programming Languages and Deep Learning - -In programming languages, a block is a pair of curly braces that includes local variables definitions and a sequence of instructions or operators. - -Blocks work with control flow structures like `if`, `else`, and `for`, which have equivalents in deep learning: - -| programming languages | PaddlePaddle | -|-----------------------|-----------------------| -| for, while loop | RNN, WhileOp | -| if, if-else, switch | IfElseOp, SwitchOp | -| sequential execution | a sequence of layers | - -A key difference is that a C++ program describes a one pass computation, whereas a deep learning program describes both the forward and backward passes. - -## Stack Frames and the Scope Hierarchy - -The existence of the backward pass makes the execution of a block of PaddlePaddle different from traditional programs: - -| programming languages | PaddlePaddle | -|-----------------------|---------------------------------| -| stack | scope hierarchy | -| stack frame | scope | -| push at entering block| push at entering block | -| pop at leaving block | destroy when minibatch completes| - -1. In traditional programs: - - - When the execution enters the left curly brace of a block, the runtime pushes a frame into the stack, where it realizes local variables. - - After the execution leaves the right curly brace, the runtime pops the frame. - - The maximum number of frames in the stack is the maximum depth of nested blocks. - -1. In PaddlePaddle - - - When the execution enters a block, PaddlePaddle adds a new scope, where it realizes variables. - - PaddlePaddle doesn't pop a scope after the execution of the block because variables therein are used by the backward pass. So it has a stack forest known as a *scope hierarchy*. - - The height of the highest tree is the maximum depth of nested blocks. - - After the processing of a minibatch, PaddlePaddle destroys the scope hierarchy. - -## Use Blocks in C++ and PaddlePaddle Programs - -Let us consolidate the discussion by presenting some examples. - -### Blocks with `if-else` and `IfElseOp` - -The following C++ programs shows how blocks are used with the `if-else` structure: - -```c++ -namespace pd = paddle; - -int x = 10; -int y = 1; -int z = 10; -bool cond = false; -int o1, o2; -if (cond) { - int z = x + y; - o1 = z; - o2 = pd::layer::softmax(z); -} else { - int d = pd::layer::fc(z); - o1 = d; - o2 = d+1; -} - -``` - -An equivalent PaddlePaddle program from the design doc of the [IfElseOp operator](./if_else_op.md) is as follows: - -```python -import paddle as pd - -x = minibatch([10, 20, 30]) # shape=[None, 1] -y = var(1) # shape=[1], value=1 -z = minibatch([10, 20, 30]) # shape=[None, 1] -cond = larger_than(x, 15) # [false, true, true] - -ie = pd.ifelse() -with ie.true_block(): - d = pd.layer.add_scalar(x, y) - ie.output(d, pd.layer.softmax(d)) -with ie.false_block(): - d = pd.layer.fc(z) - ie.output(d, d+1) -o1, o2 = ie(cond) -``` - -In both examples, the left branch computes `x+y` and `softmax(x+y)`, the right branch computes `fc(x)` and `x+1` . - -The difference is that variables in the C++ program contain scalar values, whereas those in the PaddlePaddle programs are mini-batches of instances. - - -### Blocks with `for` and `RNNOp` - -The following RNN model in PaddlePaddle from the [RNN design doc](./rnn.md) : - -```python -x = sequence([10, 20, 30]) # shape=[None, 1] -m = var(0) # shape=[1] -W = var(0.314, param=true) # shape=[1] -U = var(0.375, param=true) # shape=[1] - -rnn = pd.rnn() -with rnn.step(): - h = rnn.memory(init = m) - h_prev = rnn.previous_memory(h) - a = layer.fc(W, x) - b = layer.fc(U, h_prev) - s = pd.add(a, b) - act = pd.sigmoid(s) - rnn.update_memory(h, act) - rnn.output(a, b) -o1, o2 = rnn() -``` -has its equivalent C++ program as follows - -```c++ -int* x = {10, 20, 30}; -int* m = {0}; -int* W = {0.314}; -int* U = {0.375}; - -int mem[sizeof(x) / sizeof(x[0]) + 1]; -int o1[sizeof(x) / sizeof(x[0]) + 1]; -int o2[sizeof(x) / sizeof(x[0]) + 1]; -for (int i = 1; i <= sizeof(x)/sizeof(x[0]); ++i) { - int x = x[i-1]; - if (i == 1) mem[0] = m; - int a = W * x; - int b = Y * mem[i-1]; - int s = fc_out + hidden_out; - int act = sigmoid(sum); - mem[i] = act; - o1[i] = act; - o2[i] = hidden_out; -} -``` - -## Compilation and Execution - -Like TensorFlow, a PaddlePaddle program is written in Python. The first part describes a neural network as a protobuf message, and the rest executes the message for training or inference. - -The generation of this protobuf message is similar to how a compiler generates a binary executable file. The execution of the message is similar to how the OS executes the binary file. - -## The "Binary Executable File Format" - -The definition of the protobuf message is as follows: - -```protobuf -message BlockDesc { - repeated VarDesc vars = 1; - repeated OpDesc ops = 2; -} -``` - -The step net in above RNN example would look like - -``` -BlockDesc { - vars = { - VarDesc {...} // x - VarDesc {...} // h - VarDesc {...} // fc_out - VarDesc {...} // hidden_out - VarDesc {...} // sum - VarDesc {...} // act - } - ops = { - OpDesc {...} // matmul - OpDesc {...} // add_two - OpDesc {...} // sigmoid - } -}; -``` - -Also, the RNN operator in above example is serialized into a protobuf message of type `OpDesc` and would look like: - -``` -OpDesc { - inputs = {0} // the index of x in vars of BlockDesc above - outputs = {5, 3} // indices of act and hidden_out in vars of BlockDesc above - attrs { - "states" : {1} // the index of h - "step_net" : - } -}; -``` - -This `OpDesc` value is in the `ops` field of the `BlockDesc` value representing the global block. - - -## The Compilation of Blocks - -During the generation of the Protobuf message, the Block should store VarDesc (the Protobuf message which describes Variable) and OpDesc (the Protobuf message which describes Operator). - -VarDesc in a block should have its name scope to avoid local variables affecting parent block's name scope. -Child block's name scopes should inherit the parent's so that OpDesc in child block can reference a VarDesc that is stored in the parent block. For example: - -```python -a = pd.Variable(shape=[20, 20]) -b = pd.fc(a, params=["fc.w", "fc.b"]) - -rnn = pd.create_rnn() -with rnn.stepnet(): - x = a.as_step_input() - # reuse fc's parameter - fc_without_b = pd.get_variable("fc.w") - rnn.output(fc_without_b) - -out = rnn() -``` -The method `pd.get_variable` can help retrieve a Variable by the name. The Variable may be stored in a parent block, but might be retrieved in a child block, so block should have a variable scope that supports inheritance. - -In compiler design, the symbol table is a data structure created and maintained by compilers to store information about the occurrence of various entities such as variable names, function names, classes, etc. - -To store the definition of variables and operators, we define a C++ class `SymbolTable`, like the one used in compilers. - -`SymbolTable` can do the following: - -- store the definitions (some names and attributes) of variables and operators, -- verify if a variable was declared, -- make it possible to implement type checking (offer Protobuf message pointers to `InferShape` handlers). - - -```c++ -// Information in SymbolTable is enough to trace the dependency graph. So maybe -// the Eval() interface takes a SymbolTable is enough. -class SymbolTable { - public: - SymbolTable(SymbolTable* parent) : parent_(parent) {} - - OpDesc* NewOp(const string& name=""); - - // TODO determine whether name is generated by python or C++. - // Currently assume that a unique name will be generated by C++ if the - // argument name is left default. - VarDesc* Var(const string& name=""); - - // find a VarDesc by name, if recursive is true, find parent's SymbolTable - // recursively. - // this interface is introduced to support InferShape, find protobuf messages - // of variables and operators, pass pointers into InferShape. - // - // NOTE maybe some C++ classes such as VarDescBuilder and OpDescBuilder should - // be proposed and embedded into pybind to enable python operation on C++ pointers. - VarDesc* FindVar(const string& name, bool recursive=true); - - OpDesc* FindOp(const string& name); - - BlockDesc Compile() const; - - private: - SymbolTable* parent_; - - map ops_; - map vars_; -}; -``` - -After all the description of variables and operators is added into SymbolTable, -the block has enough information to run. - -The `Block` class takes a `BlockDesc` as input, and provides `Run` and `InferShape` functions. - - -```c++ -namespace { - -class Block : OperatorBase { -public: - Block(const BlockDesc& desc) desc_(desc) {} - - void InferShape(const framework::Scope& scope) const override { - if (!symbols_ready_) { - CreateVariables(scope); - CreateOperators(); - } - // should run InferShape first. - for (auto& op : runtime_table_.ops()) { - op->InferShape(scope); - } - } - - void Run(const framework::Scope& scope, - const platform::Place& place) const override { - PADDLE_ENFORCE(symbols_ready_, "operators and variables should be created first."); - for (auto& op : runtime_table_.ops()) { - op->Run(scope, place); - } - } - - void CreateVariables(const framework::Scope& scope); - void CreateOperators(); - - // some other necessary interfaces of NetOp are listed below - // ... - -private: - BlockDesc desc_; - bool symbols_ready_{false}; -}; -``` - -## The Execution of Blocks - -Block inherits from OperatorBase, which has a Run method. -Block's Run method will run its operators sequentially. - -There is another important interface called `Eval`, which takes some arguments called targets and generates a minimal graph which treats targets as the end points and creates a new Block. After `Run`, `Eval` will get the latest value and return the targets. - -The definition of Eval is as follows: - -```c++ -// clean a block description by targets using the corresponding dependency graph. -// return a new BlockDesc with minimal number of operators. -// NOTE: The return type is not a Block but the block's description so that this can be distributed -// to a cluster. -BlockDesc Prune(const BlockDesc& desc, vector targets); - -void Block::Eval(const vector& targets, - const framework::Scope& scope, - const platform::DeviceContext& dev_ctx) { - BlockDesc min_desc = Prune(desc_, targets); - Block min_block(min_desc); - min_block.Run(scope, dev_ctx); -} -``` diff --git a/develop/doc_cn/_sources/design/build_system/README.md.txt b/develop/doc_cn/_sources/design/build_system/README.md.txt deleted file mode 100644 index bf0e4dddc1b..00000000000 --- a/develop/doc_cn/_sources/design/build_system/README.md.txt +++ /dev/null @@ -1,152 +0,0 @@ -A few months ago when we were trying to replace CMake with Bazel, @emailweixu suggested that we rewrite those handy Bazel functions using CMake. Now it seems that it's the right time to get this done, as we are facing problems from the porting of Majel and the development of new the parameter server using Go and C++. - -Here are some initial thoughts. Your comments are welcome! - -### Required CMake Function - -I think we need only the following few CMake functions to make a project description mean and clean: - -| C++ | CUDA C++ | Go | -|---|---|---| -| cc_library | nv_library | go_library | -| cc_binary | nv_binary | go_binary | -| cc_test | nv_test | go_test | - -- The `_library` functions generate .a files from source code. -- The `_binary` functions generate executable binary files. -- The `_test` functions generate executable unit test files. They work like `_binary` but links `-lgtest` and `-lgtest_main`. - -The difference between `nv_` functions and `cc_` functions is that the former use `nvcc` instead of the system-default C++ compiler. - -Both `nv_` and `cc_` functions enables C++11 (-std=c++11). - -Also, - -- to describe external dependencies, we need `external_library`. -- to build shared libraries, we need `shared_library`. - -### An Example Project - -Suppose that we have aforementioned functions defined in our `/cmake` directory. The following example `CMakeLists.txt` describes a project including the following source files: - -- tensor.h -- tensor.cc -- tensor_test.cc -- ops.h -- ops.cu -- ops_test.cu -- api.go -- api_test.go - -Suppose that ops.cu depends on CUDNN. - -```cmake -# cc_binary parses tensor.cc and figures out that target also depend -# on tensor.h. -cc_binary(tensor - SRCS - tensor.cc) - -# The dependency to target tensor implies that if any of -# tensor{.h,.cc,_test.cc} is changed, tensor_test need to be re-built. -cc_test(tensor_test - SRCS - tensor_test.cc - DEPS - tensor) - -# I don't have a clear idea what parameters external_library need to -# have. @gangliao as a CMake expert would have better ideas. -external_library(cudnn - ....) - -# Suppose that ops.cu depends on external target CUDNN. Also, ops.cu -# include global functions that take Tensor as their parameters, so -# ops depend on tensor. This implies that if any of tensor.{h.cc}, -# ops.{h,cu} is changed, ops need to be re-built. -nv_library(ops - SRCS - ops.cu - DEPS - tensor - cudnn) # cudnn is defined later. - -nv_test(ops_test - SRCS - ops_test.cu - DEPS - ops) - -# Because api.go defines a GO wrapper to ops and tensor, it depends on -# both. This implies that if any of tensor.{h,cc}, ops.{h,cu}, or -# api.go is changed, api need to be re-built. -go_library(api - SRCS - api.go - DEPS - tensor # Because ops depend on tensor, this line is optional. - ops) - -go_test(api_test - SRCS - api_test.go - DEPS - api) - - -# This builds libapi.so. shared_library might use CMake target -# api_shared so to distinguish it from above target api. -shared_library(api - DEPS - api) - -``` - -### Implementation - -As above example CMakeLists.txt executes, each function invocation adds "nodes" to a dependency graph. It also use this graph to generate CMake commands including `add_executable`, `add_dependencies`, `target_link_libraries`, and `add_test`. - -### Using Package Manager For Go - -Building Go binaries and libraries need to satisfy their dependencies, generally -we can do `go get ./...` to download and compile all external dependencies. The -problems are: - -1. `go get` will always get the latest code from the default branch of the - remote repo, so changes of dependents might break the build. This is very - different with what we already have in `cmake/external` which download a - specific version or commit id of the dependency. -1. Some locations can not access external dependencies through the internet, as mentioned - in https://github.com/PaddlePaddle/Paddle/issues/2605. Using package management - tools can package the dependencies as a "vendor" package, which can be mirrored - at many cloud file hosting, so users what to compile paddle by themselves can - download this "vendor" package from a mirror site. - -#### Choose A Suitable Tool - -As mentioned by @wangkuiyi, [Here](https://github.com/golang/go/wiki/PackageManagementTools) -list dozens of Go package managers. We choose the tool using following principles: - -- Most "active" projects with more stars, more pull requests or commits -- Widely used project - -After comparing all these projects, we shall choose between the most popular -tools: Godep and Glide. - -Here's a brief comparison between Godep and Glide -: https://github.com/Masterminds/glide/wiki/Go-Package-Manager-Comparison. There are -also many complaints about using `Godep`. There's also a new "official" pakcage -management tool has been started at: https://github.com/golang/dep to resolve -such problems, but it's currently at Alpha stage. So the best choice now is -glide obviously. - -#### Manage Go Packages - -- Dependencies: `go/glide.yaml` will store the dependencies and their versions which - is directly imported by paddle. `go/glide.lock` will store all dependencies recursively - with their commit id. Builds will "lock" to these packages if we don't `glide up` - them -- Vendor package: `go/vendor` directory will generated when running `cmake` command. `cmake` - will download the code corresponding to `go/glide.lock`. If we put a vendor folder - under `go/`, cmake will just check the commit id to the packages under the folder, - if commit id matches, there will be no download at all. diff --git a/develop/doc_cn/_sources/design/cluster_train/README.md.txt b/develop/doc_cn/_sources/design/cluster_train/README.md.txt deleted file mode 100644 index 177a5f5d54b..00000000000 --- a/develop/doc_cn/_sources/design/cluster_train/README.md.txt +++ /dev/null @@ -1,182 +0,0 @@ -# Design Doc: Distributed Training - -## Objective - -In [this slides](https://www.slideshare.net/cxwangyi/paddlepaddle-a-complete-solution-for-businesses), we explained that we'd like PaddlePaddle running on general-purpose clusters like those managed by Kubernetes, so to address demands for AI from both Internet and non-Internet industries. - -This poses technical challenges to PaddlePaddle: - -1. Support fault-recovery. -1. Support both offline and online training. -1. [Serverless computing](https://en.wikipedia.org/wiki/Serverless_computing) of distributed training. - - -## Training Job - -A training job will be created once user asks Paddle cloud to train a model. The training job is made up of different processes that collaboratively consume data and produce a trained model. There are three kinds of processes: - -1. the *master server process*, which dispatches tasks to -1. one or more *trainer processes*, which run distributed training and synchronize gradients/models via -1. one or more *parameter server processes*, where each holds a shard of the global model, and receive the uploaded gradients from every *trainer process*, so they can run the optimize functions to update their parameters. - -Their relation is illustrated in the following graph: - - - -By coordinating these processes, PaddlePaddle supports use both Synchronize Stochastic Gradient Descent (sync SGD) and Asynchronous Stochastic Gradient Descent (async SGD) to train user-defined neural network topologies. - -When training with sync SGD, parameter servers wait for all trainers to finish gradients update and then send the updated parameters to trainers, training can not proceed until the trainer received the updated parameters. This creates a synchronization point between trainers. When training with async SGD, each trainer upload gradient and download new parameters individually, without the synchronization with other trainers. Using asyc SGD will be faster in terms of time per pass, but have more noise in gradient since trainers are likely to have a stale model. - -### Master Server Process - -The master server process will: - -- Partition a dataset into [tasks](#task) and dispatch tasks to trainers. -- Keep track of training progress on the dataset with [task queue](#task-queue). A training job will iterate on the dataset for a full pass until it goes into next pass. - - -#### Task - -A task is a data shard to be trained. The total number of tasks will be much bigger than the total number of trainers. The number of data instances inside a task will be much bigger than the mini-batch size. - -#### Task Queue - -The master server has three task queues to track training progress. As illustrated in the graph below, Job A and Job B both have one master server. Each master server process has three task queues. - - - -- The todo queue holds tasks to be dispatched. When a job starts, the master server fills in the todo queue with all tasks. -- The pending queue holds tasks that are currently training by trainers. -- the done queue holds tasks that are already trained. - -The life cycle of a single task is illustrated below: - - - -1. When a new pass of training starts, all tasks will be placed in the todo queue. -1. Upon trainer requests for new task, the master server will dispatch a task from todo queue to it, put the task in the pending queue and wait for completion. -1. The trainer will work on its task and tell the master server once the task is completed and ask for new task. The master server will dispatch a new task to that trainer. -1. If a task fails for any reason in trainer, or takes longer than a specific period of time, the master server will move the task back to the todo queue. The timeout count for that task will increase by one. If the timeout count is above a threshold, the task is likely to cause a trainer to crash, then it will be discarded. -1. The master server will move completed task to the done queue. When the todo queue is empty, the master server will start a new pass by moving all tasks in the done queue to todo queue and reset the timeout counter of all tasks to zero. - -### Trainer Process - -The trainer process will: - -- Request tasks from the master. -- Work on the tasks -- Upload gradient to parameter servers, and update local model by downloading new parameters from parameter servers. - -### Parameter Server Process - -Parameter server processes hold the parameters collaboratively. The parameters are partitioned on different parameter servers. - -The parameter server will: - -- Receive gradient from the trainers, update its parameters, and give the trainers the latest parameters. -- Periodically save its parameters to distributed file system by overriding the previous save. - -### Optimization Algorithms - -The communication pattern between the trainers and the parameter servers depends on the category of optimization algorithm: - -- Synchronous Stochastic Gradient Descent (sync-SGD) - - Parameter server will wait for all trainer finish n-th mini-batch calculation and send their gradients before broadcasting new parameters to every trainer. Every trainer will wait for the new parameters before starting n+1-th mini-batch. - -- Asynchronous Stochastic Gradient Descent (async-SGD) - - There will no synchronization between different trainers, and parameter server updates its parameter as soon as it receives new gradient: - - - Each trainer uploads its accumulated gradient every n mini-batches. - - Every m mini-batches, the trainer downloads new parameters from parameter server. - - n and m do not have to be equal. - -## Fault Tolerant - -The training job will pause if the master server processes is dead, or any of the parameter server process is dead. They will be started by [Kubernetes](https://kubernetes.io/) and recover in few minutes. Please refer to [fault recovery](#fault-recovery). - -The training job will continue to make progress if there is at least one training process running. The strategy depends on the type of optimization algorithm: - -- sync-SGD - - TODO - -- async-SGD - - Since async-SGD does not require synchronization between mini-batches, the system will by definition make process if at least one trainer is running. - -## Fault Recovery - -PaddlePaddle uses [etcd](https://github.com/coreos/etcd) to keep track of the states of processes. Because etcd is a distributed reliable key-value store, the restarted process can recover its states from etcd. The model parameters are periodically saved into distributed file system, so a restarted parameter server can recover its parameters from the saved file. - -Now we will introduce how each process recovers from a failure, the graph below shows how etcd is used: - - - -### Master Server Process - -When the master is started by the Kubernetes, it executes the following steps at startup: - -1. Grabs a unique *master* lock in etcd, which prevents concurrent master instantiations. -1. Recovers the task queues from etcd if they already exist, otherwise, the master will create them. -1. Write its ip address to */master/addr* so that trainers can discover it. -1. Listens to trainers' request of task, dispatch one upon request, and updates task queue using an etcd transaction to ensure lock is held during the update. - -When the master server process is dead for any reason, Kubernetes will restart it. It will be online again with all states recovered from etcd in few minutes. - -### Trainer Process - -When the trainer is started by the Kubernetes, it executes the following steps at startup: - -1. Watches the available parameter server prefix keys `/ps/` on etcd and waits until the count of parameter servers reaches the desired count */ps_desired*. -1. Finds and watches */master/addr* to get master's address. -1. Requests for tasks from the master to start training. - -When a trainer fails, Kuberentes would try to restart it. The recovered trainer would fetch tasks from master and go on training. - -### Parameter Server Process - -When the parameter server is started by Kubernetes, it executes the following steps at startup: - -1. Read desired total number of parameter servers from etcd `/ps_desired` -1. Search through etcd keys `/ps/` (`/ps/0`, `/ps/1`, ...) to find the first non-existant key whose index is smaller than the total number of parameter servers. Set the key using a transaction to avoid concurrent writes. The parameter server's index is inferred from the key name. - - The desired number of parameter servers is 3: - - - - The third parameter server joined: - - - -1. The parameter server can load parameters if there are already saved parameters in the save path (inferred from its index). -1. Now the parameter server is ready for the trainers' requests. - -If the parameter server's etcd lease expires, the parameter server will kill itself. - - -## Parameter Server Checkpointing -See [here](./checkpointing.md) - -## Store and dispatching trainning data -See [here](./data_dispatch.md) - - -## Dynamic Scaling - -### Trainer Scaling - -TODO - -### Parameter Server Scaling - -Not planned for v1. - -## Training Dataset Format - -TODO - -## User Interface - -TODO diff --git a/develop/doc_cn/_sources/design/cluster_train/checkpointing.md.txt b/develop/doc_cn/_sources/design/cluster_train/checkpointing.md.txt deleted file mode 100644 index c87ef2c7d26..00000000000 --- a/develop/doc_cn/_sources/design/cluster_train/checkpointing.md.txt +++ /dev/null @@ -1,44 +0,0 @@ -## 模型参数检查点(Checkpointing) -模型数据检查点的实现,可以有效的避免parameter server的单点或多点同时故障。模型参数检查点通过定期向磁盘上保存一份存储在parameter server内存中的模型数据的完整镜像,来保证训练过程可以从中间状态重新启动。在一个不可中断并缺少备份的训练任务中,可以通过阶段性的保存每个parameter server的数据快照(snapshot)到 ***分布式存储服务*** 达到容灾的目的,比如每隔10分钟最新的快照,并删除更早的快照。在出现单点故障时,只需要恢复这台节点,或者将这台节点迁移到另一个节点并启动即可恢复训练任务。 - - - -### 快照保存的设计如下: - -说明: - -* parameter server在集群中启动后,自动挂载分布式存储目录,并把快照保存到这个目录下。 -* ***注:每个parameter server的检查点各自独立保存,暂时不考虑多个parameter server同步的保存一个特定时间点的全局检查点,因为这样做也没法保证消除随机性。*** - -检查点保存程序流程: - -1. 如果满足条件"每隔10分钟"时,parameter server会获取parameters内存的`read_lock`,启动一个新的线程开始保存检查点。如果已经正在执行保存检查点的线程,则忽略。由于对parameters的更新需要获取parameters内存的`write_lock`,所以在写入快照的过程中,parameter server会暂停参数更新并等待。 -2. parameter server生成一个UUID,向指定的目录中一个新的文件(文件名为此UUID)写入快照数据。在快照写入完成后,计算这个文件的MD5 sum。然后在etcd的`/checkpoints/[pserver_id]`中写入json内容:`{"uuid": [UUID], "md5", "MD5 sum", "timestamp": xxxx}`。 -3. 删除磁盘目录中不是当前uuid的快照文件。 -4. 释放对paramters内存的锁定,停止保存检查点的线程。 - -这里需要用户额外注意,在您的实际环境中,训练任务的运行可能会占满trainer和parameter server之间的网络带宽,如果parameter server此时还需要通过网络访问分布式存储以保存快照,可能会造成网络拥塞,而出现阶段性的运行停滞。 - -### 从快照恢复 - -在parameter server第一次启动或任意时间parameter server故障后被Kubernetes重新启动,则需要回滚到上一个检查点: - - 1. 从etcd中读取节点:`/checkpoints/[pserver_id]`获取最新的检查点的文件uuid - 1. 从磁盘文件中加载uuid文件名的检查点快照文件,并加载其中的参数 - 1. 如果上面两步出现错误,则使用启动参数定义的初始化方法初始化参数 - 1. 开始提供服务 - -## TODO List -### 推测执行/加速执行(TODO) -在异构集群中,如果存在某些trainer执行速度过慢会影响整体集群的速度(如图中Trainer 1),此时master将负责启动一个新的Trainer(Accelerate Trainer 2),使用同样的训练数据block。哪个trainer先完成block的训练,则把另一个慢速的kill掉。 - -### 动态扩容/缩容 -目前只考虑动态扩容trainer数量,可以减小系统复杂性。 - -## 术语 -* model: 指深度学习训练之后得到的所有参数,使用这个神经网络可以完成对新数据的预测 -* parameters: 神经网络中的参数,包括权重w和偏置b。一个神经网络的模型由大量的参数组成 -* shard: 分片,通常指将一个整体拆分成多份的其中的一份。 -* model shard: 将一个神经网络参数拆分成多份,每个shard分别存储在其中一台parameter server之上 -* parameter block: 多个parameter block构成一个model shard -* 单点故障: 任意时刻只可能同时有一台服务器故障。由于集群中同时存在两台机器故障的概率极低((平均故障率*平均故障修复时间)^2)只对特殊在线系统考虑两台以上同时故障的容灾。 diff --git a/develop/doc_cn/_sources/design/cluster_train/data_dispatch.md.txt b/develop/doc_cn/_sources/design/cluster_train/data_dispatch.md.txt deleted file mode 100644 index 1f5d22ff5e6..00000000000 --- a/develop/doc_cn/_sources/design/cluster_train/data_dispatch.md.txt +++ /dev/null @@ -1,160 +0,0 @@ -## 训练数据的存储和分发 - -### 概念解释 - -### 流程介绍 -生产环境中的训练数据集通常体积很大,并被存储在诸如Hadoop HDFS,Ceph,AWS S3之类的分布式存储之上。这些分布式存储服务通常会把数据切割成多个分片分布式的存储在多个节点之上。这样就可以在云端执行多种数据类计算任务,包括: - -* 数据预处理任务 -* Paddle训练任务 -* 在线模型预测服务 -

                                - -在上图中显示了在一个实际生产环境中的应用(人脸识别)的数据流图。生产环境的日志数据会通过实时流的方式(Kafka)和离线数据的方式(HDFS)存储,并在集群中运行多个分布式数据处理任务,比如流式数据处理(online data process),离线批处理(offline data process)完成数据的预处理,提供给paddle作为训练数据。用户也可以上传labeled data到分布式存储补充训练数据。在paddle之上运行的深度学习训练输出的模型会提供给在线人脸识别的应用使用。 - -### 训练数据存储 -我们选择[CephFS](http://docs.ceph.com/docs/master/cephfs/)作为存储系统。 - -- 无论是从[PFSClient](../file_manager/README.md)的角度,还是从[Pod](https://kubernetes.io/docs/concepts/workloads/pods/pod/)中运行任务的角度,统一用`/pfs/$DATACENTER/home/$USER`来访问用户自己的数据。 -- `/pfs/$DATACENTER/common`下存放公共数据集合 - - 做只读挂载 - -
                                - -
                                - -### 文件预处理 - - -在开始训练之前, 数据集需要预先被转换成PaddlePaddle分布式训练使用的存储格[RecordIO](https://github.com/PaddlePaddle/Paddle/issues/1947)。我们提供两个转换方式: - -1. 用户在本地转换好再上传 -1. 用户上传数据后,在机群上运行转换程序 - -转换生成的文件名会是以下格式: - -```text -name_prefix-aaaaa-of-bbbbb -``` - -"aaaaa"和"bbbbb"都是五位的数字,每一个文件是数据集的一个shard,"aaaaa"代表shard的index,"bbbbb"代表这个shard的最大index。 - -比如ImageNet这个数据集可能被分成1000个shard,它们的文件名是: -```text -imagenet-00000-of-00999 -imagenet-00001-of-00999 -... -imagenet-00999-of-00999 -``` - -#### 转换库 - -无论是在本地或是云端转换,我们都提供Python的转换库,接口是: -```python -def convert(output_path, reader, num_shards, name_prefix) -``` - -- `output_path`: directory in which output files will be saved. -- `reader`: a [data reader](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/reader/README.md#data-reader-interface), from which the convert program will read data instances. -- `num_shards`: the number of shards that the dataset will be partitioned into. -- `name_prefix`: the name prefix of generated files. - -`reader`每次输出一个data instance,这个instance可以是单个值,或者用tuple表示的多个值: - -```python -yield 1 # 单个值 -yield numpy.random.uniform(-1, 1, size=28*28) # 单个值 -yield numpy.random.uniform(-1, 1, size=28*28), 0 # 多个值 -``` - -每个值的类型可以是整形、浮点型数据、字符串,或者由它们组成的list,以及numpy.ndarray。如果是其它类型,会被Pickle序列化成字符串。 - -### 示例程序 - -#### 使用转换库 - -以下`reader_creator`生成的`reader`每次输出一个data instance,每个data instance包涵两个值:numpy.ndarray类型的值和整型的值: -```python -def reader_creator(): - def reader(): - for i in range(1000): - yield numpy.random.uniform(-1, 1, size=28*28), 0 # 多个值 - return reader -``` - -把`reader_creator`生成的`reader`传入`convert`函数即可完成转换: -```python -convert("./", reader_creator(), 100, random_images) -``` - -以上命令会在当前目录下生成100个文件: -```text -random_images-00000-of-00099 -random_images-00001-of-00099 -... -random_images-00099-of-00099 -``` - -#### 进行训练 - - -PaddlePaddle提供专用的[data reader creator](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/reader/README.md#python-data-reader-design-doc),生成给定`RecordIO`文件对应的data reader。**无论在本地还是在云端,reader的使用方式都是一致的**: - -```python -# ... -reader = paddle.reader.creator.RecordIO("/pfs/datacenter_name/home/user_name/random_images-*-of-*") -batch_reader = paddle.batch(paddle.dataset.mnist.train(), 128) -trainer.train(batch_reader, ...) -``` - -以上代码的reader输出的data instance与生成数据集时,reader输出的data instance是一模一样的。 - -### 上传训练文件 - -使用下面命令,可以把本地的数据上传到存储集群中。 - -```bash -paddle pfs cp filename /pfs/$DATACENTER/home/$USER/folder/ -``` - -比如,把之前示例中转换完毕的random_images数据集上传到云端的`/home/`可以用以下指令: - -```bash -paddle pfs cp random_images-*-of-* /pfs/$DATACENTER/home/$USER/folder/ -``` - -需要`$DATACENTER`的配置写到配置文件中,例如 - -``` -# config file -[datacenter_1] -username=user -usercert=user.pem -userkey=user-key.pem -endpoint=datacenter1.paddlepaddle.org - -[datacenter_2] -username=user -usercert=user.pem -userkey=user-key.pem -endpoint=datacenter2.paddlepaddle.org -``` -## TODO -### 文件访问的权限 -控制用户权限 - -- 用户可以把自己的数据分享给别人 - -### 文件访问方式 -不用mount的方式来访问数据,而是直接用API的接口远程访问 - -例如: - -``` -f = open('/pfs/datacenter_name/home/user_name/test1.dat') -``` - - -### 支持用户自定义的数据预处理job diff --git a/develop/doc_cn/_sources/design/cluster_train/large_model_dist_train.md.txt b/develop/doc_cn/_sources/design/cluster_train/large_model_dist_train.md.txt deleted file mode 100644 index 0c4b5bc24c8..00000000000 --- a/develop/doc_cn/_sources/design/cluster_train/large_model_dist_train.md.txt +++ /dev/null @@ -1,101 +0,0 @@ -# Alalysis of large model distributed training in Paddle - -***NOTE: This is only some note for how we implemeted this scheme in V1, not a new design.*** - -## What is it - -We often encounter cases that the embedding layer parameters(sparse) are so large that we can not store it in the trainer's memory when training. So we need to put them to several servers, and fetch them row by row instead of fetch all of the parameters. - -## How to use - -Specify command-line argument like `--loadsave_parameters_in_pserver=true --ports_num_for_sparse=1 --use_old_updater=1` when starting the paddle trainer. And also add something like `--ports_num_for_sparse=1 --pserver_num_threads=5` when starting pserver processes. - -Accrodingly, configure your embedding layers like: - -```python -SPARSE_REMOTE=True - -w1 = data_layer(name="w1", size=dict_size) -emb1 = embedding_layer(input=w1, size=32, param_attr=ParameterAttribute(sparse_update=SPARSE_REMOTE)) -w2 = data_layer(name="w2", size=dict_size) -emb2 = embedding_layer(input=w2, size=32, param_attr=ParameterAttribute(sparse_update=SPARSE_REMOTE)) -... -``` - -## Implementation details - -```c++ -enum MatType { - MAT_NORMAL, - MAT_NORMAL_SHARED, - MAT_VALUE_SHARED, - MAT_SPARSE_ROW_IDS, - MAT_SPARSE_ROW_AUTO_GROW, - MAT_CACHE_ROW, - MAT_SPARSE_ROW, - MAT_SPARSE_ROW_PREFETCH, - MAT_SPARSE_ROW_PREFETCH_FULL_SIZE, -}; -``` - -`MAT_SPARSE_ROW_PREFETCH` is what we use when configured to fetch only row of matrix when training. - -In `trainer_internal.cpp:L93 trainOneBatch`: - -```c++ - if (config_->getOptConfig().use_sparse_remote_updater()) { - REGISTER_TIMER("prefetch"); - gradientMachine_->prefetch(inArgs); - parameterUpdater_->getParametersRemote(); - } -``` - -When doing actual network forward and backward, at the beginning of each batch, the trainer will try to download one row of data from pserver. - -In `trainer/RemoteParameterUpdater.cpp`: `parameterUpdater_->getParametersRemote();`: - -```c++ -if (fullSize) { - ... -} else { -getParams = [&] { - parameterClient_->getParameterSparse( - /* recvParameterType= */ PARAMETER_VALUE, sendBackParameterType); -}; -applyL1 = [](Parameter& para, real decayRate) { - para.getMat(PARAMETER_VALUE)->applyL1(/*lr=*/1.0f, decayRate); -}; -} -``` - -Calling `parameterClient_->getParameterSparse` will do remote call to pserver's `getParameterSparse`: - -```c++ -void ParameterServer2::getParameterSparse(const SendParameterRequest& request, - std::vector& inputBuffers, - SendParameterResponse* response, - std::vector* outputBuffers) { - (void)inputBuffers; - auto& buffer = *readWriteBuffer_; - size_t numReals = 0; - for (const auto& block : request.blocks()) { - numReals += getParameterConfig(block).dims(1); - } - buffer.resize(numReals); - - VLOG(3) << "pserver: getParameterSparse, numReals=" << numReals; - - ReadLockGuard guard(parameterMutex_); - size_t offset = 0; - for (const auto& block : request.blocks()) { - size_t width = getParameterConfig(block).dims(1); - Buffer buf = {buffer.data() + offset, width}; - int type = request.send_back_parameter_type(); - sendBackParameterSparse(block, type, response, &buf, width, outputBuffers); - offset += width; - } -} -``` - -`getParameterConfig(block).dims(1)` returns the width of the current "parameter block"(a shard of parameter object), -then `getParameterSparse` remote call returns only one row of data to the client. diff --git a/develop/doc_cn/_sources/design/cluster_train/master_server.md.txt b/develop/doc_cn/_sources/design/cluster_train/master_server.md.txt deleted file mode 100644 index 4bf3c506f10..00000000000 --- a/develop/doc_cn/_sources/design/cluster_train/master_server.md.txt +++ /dev/null @@ -1,91 +0,0 @@ -# Design Doc: Master Server - -For an overview of master server's role, please refer to [distributed training design doc](./README.md). In this design doc we will discuss the master server in more details. The master will be implemented in [Go](https://golang.org/). - -## Dataset - - - -A dataset is a list of files in *RecordIO* format. A RecordIO file consists of chunks, whereas each chunk consists some records. - -## Task Queue - -As mentioned in [distributed training design doc](./README.md), a *task* is a data shard that the master server assigns to the trainer process to train on. A task consists of one or multiple *chunks* from one or multiple files. The master server maintains *task queues* to track the training progress. - -### Task Queue Creation - -1. Each trainer will make an RPC call (using Go's [rpc](https://golang.org/pkg/net/rpc/) package) to the master server, telling it the RecordIO files representing the dataset specified by the user. Since every trainer will tell the master server the same dataset, only the first RPC call will be honored. - - The RPC interface is: - ```go - func (m *RPCServer) ReportDataset(Paths []string, dummy *int) error { - } - ``` -1. The master server will scan through each RecordIO file to generate the *chunk index* and know how many chunks does each file have. A chunk can be referenced by the file path and the index of the chunk within the file. The chunk index is in memory data structure that enables fast access to each chunk, and the index of the chunk with the file is an integer start from 0, representing the n-th chunk within the file. - - The definition of the chunk is: - ```go - type Chunk struct { - Idx int // index of the chunk within the file - Path string - Index recordio.Index // chunk index - } - ``` -1. Chunks are grouped into tasks, and tasks are filled into the todo queue. The pending queue and the done queue are initialized with no element. - - The definition of the task is: - ```go - type Task struct { - Index int - Chunks []Chunk - } - ``` - - The elements in the tasks queues is of type `TaskEntry`, containing a timeout counter (described in [task retry logic](#task-retry-logic)), and a task: - ```go - type TaskEntry struct { - NumTimeout int - Task Task - } - ``` - - The definition of task queues is: - ```go - type TaskQueues struct { - Todo []TaskEntry - Pending map[int]TaskEntry // map from task index to task entry - Done []TaskEntry - } - ``` - -### Task Queue Persistence - -The task queues need to be persisted on [etcd](https://github.com/coreos/etcd) for fault recovery. Since the task queues only change once a task is completed or timed out, which is not very frequent, we can afford to synchronize with etcd every time the task queues change. - -We will serialize the task queues data structure with [gob encoding](https://golang.org/pkg/encoding/gob/), compress with gzip, and save into etcd synchronously under key `/task_queues`. - -### Task Dispatch - -The trainer will make an RPC call to master to get a new task when: - -- the trainer first started, or -- the trainer finishes a task. - -The RPC interface is: -```go -func (m *RPCServer) GetTask(finished *Task, result *Task) error { -} -``` -Argument `finished` will be `nil` when the trainer is just started. - -During the RPC call the master will do the following: - -- Make a copy of the task queues, and update the copy reflecting the finished tasks and the new pending tasks. -- Synchronize the copy of task queues with etcd using a transaction conditioned on holding the master lock. -- Replace the task queues with the copy and report to the trainer with the new tasks if succeeded, or discard the copy and report the error to the trainer if failed. - -### Task Retry Logic - -When a task is dispatched to the trainer, the master will schedule a function for execution after the timeout duration (based on the moving average of task completion time). If the task entry in still in the pending queue, its timeout counter will increase by one, and the task will be moved to todo queue. If the timeout counter is above the threshold, the master will log the error and discard the task. - -Please note that since a timed out task could be completed after it has been dispatched for retry, so it is possible for a task to be processed multiple times. We do not try to prevent it from happening since it's fine to train on the same task multiple times due to the stochastic nature of the stochastic gradient decent algorithm. diff --git a/develop/doc_cn/_sources/design/cluster_train/pserver_client.md.txt b/develop/doc_cn/_sources/design/cluster_train/pserver_client.md.txt deleted file mode 100644 index 474b8c572cd..00000000000 --- a/develop/doc_cn/_sources/design/cluster_train/pserver_client.md.txt +++ /dev/null @@ -1,171 +0,0 @@ -# Design Doc: The Client Library of Parameter Server - -For an overview of trainer's role, please refer to [distributed training design doc](README.md). In this design doc, we will discuss the parameter server's client library, which will manage communication with parameter servers. The library will be implemented in [Go](https://golang.org/) and made available as a static or dynamic library with a C header file. - -## Parameter Partition - -Each parameter will be partitioned into parameter blocks to make the parameters evenly distributed on parameter servers. The partition is done automatically by the client library. The *sparse parameter* require a little different treatment: - -### Sparse Parameter - -The sparse parameter is a parameter that is updated sparsely. The name is somewhat misleading, it does not have a sparse representation, it has the same representation as a dense vector. - -Because a sparse parameter is updated sparsely, the trainer will have to partition the sparse parameter. Because the parameter server will merge all sparse parameter shard into the same file when saving the parameter. It needs special naming convention: - -If a sparse parameter is partitioned into n shards, they should be named as: - -```text -name:sparse-0 -name:sparse-1 -... -name:sparse-n-1 -``` - -The library is unaware of the partition, and treat each parameter independently. Only when saving parameters, the parameter servers will merge the sparse parameters according to the naming convention. - -## Model Optimization Using Gradients - -There are two ways to perform model optimization using gradients: - -- On Client - - The client does multiple steps of forward and backward update. In each step, the gradients are calculated and a new model is generated. After some steps, the client will calculate the difference between the newest model and the old model at step 0. The difference will be updated to parameter servers. Parameter servers will just update parameters using the difference without any optimization using gradients (such as Adam and L1 regularization). - -- On Parameter Server - - The client will send accumulated gradients to parameter servers, the parameter server will do the optimization using gradients. - -## L1 and L2 Regularization - -PaddlePaddle allows L1 or L2 regularizations to be specified per parameter, so when the trainer initializes the parameter it needs include a parameter configuration when L1 or L2 regularization is necessary. - -## Parameter Initialization - -The parameters on parameter servers need to be initialized. To provide maximum flexibility, the trainer will initialize the parameters. Only one trainer will do the initialization, the other trainers will wait for the completion of initialization and get the parameters from the parameter servers. - -### Trainer Selection - -To select the trainer for initialization, every trainer will try to get a distributed lock, whoever owns the lock will do the initialization. As illustrated below: - - - -### Trainer Selection Process - -The trainer select process is encapsulated in the C API function: -```c -int paddle_begin_init_params(paddle_pserver_client* client, const char* config_proto); -``` -The selected trainer's call to `paddle_begin_init_params` will return with 1, and the other trainers' call to `paddle_begin_init_params` will return 0. `paddle_get_params` will be blocked until initialization is completed. As illustrated below: - - - -## C Interface - -```c -typedef enum { - PADDLE_ELEMENT_TYPE_INT32 = 0, - PADDLE_ELEMENT_TYPE_UINT32 = 1, - PADDLE_ELEMENT_TYPE_INT64 = 2, - PADDLE_ELEMENT_TYPE_UINT64 = 3, - PADDLE_ELEMENT_TYPE_FLOAT32 = 4, - PADDLE_ELEMENT_TYPE_FLOAT64 = 5, -} paddle_element_type; - -typedef struct { - char* name; - paddle_element_type element_type; - unsigned char* content; - int content_len; -} paddle_parameter, paddle_gradient; - -typedef int paddle_pserver_client; - -/** - * @brief creates a pserver client that talks to etcd for coordination. - */ -paddle_pserver_client paddle_new_etcd_pserver_client(char* etcd_addr); - -/** - * @brief creates a pserver client given pserver addresses. - * - * @param pserver_addrs comma-separated pserver addresses. - * @param selected if current pserver client is selected to initialize all parameter servers. - */ -paddle_pserver_client paddle_new_pserver_client(char* pserver_addrs, int selected); -void paddle_pserver_client_release(paddle_pserver_client c); - -/** - * @brief paddle_begin_init_params begins to initialize parameters on - * parameter servers. - * - * paddle_begin_init_params will be called from multiple trainers, - * only one trainer will be selected to initialize the parameters on - * parameter servers. Other trainers need to get the initialized - * parameters from parameter servers using @paddle_get_params. - * - * @return 1 if the trainer is selected to initialize parameter - * servers, otherwise 0. - */ -int paddle_begin_init_params(paddle_pserver_client client); - -/** - * @brief paddle_init_param initializes the parameter on parameter - * servers. - * - * @param param the parameter to initialize. - * @param param_config_proto the configuration for the parameter. - * @param config_len the length of param_config_proto - * @return 0 if successful, otherwise -1. On failure, the trainer - * needs to restart the entire initialization process (starting from - * @paddle_begin_init_param). Or simply exit the program and wait for - * the cluster management system to restart the trainer. - */ -int paddle_init_param(paddle_pserver_client client, paddle_parameter param, const unsigned char* param_config_proto, int config_len); - -/** - * @brief paddle_finish_init_params tells parameter servers client has - * sent all parameters to parameter servers as initialization. - * - * @return 0 if successful, otherwise -1. On failure, the trainer - * needs to restart the entire initialization process (starting from - * @paddle_begin_init_param). Or simply exit the program and wait for - * the cluster management system to restart the trainer. - */ -int paddle_finish_init_params(paddle_pserver_client client); - -/** - * @brief paddle_send_grads sends gradients to parameter servers for - * updating parameters. - * - * @param grads the array of gradients to send. - * @param len the length of the gradient array. - * @param learning_rate the learning rate for the gradients. - * @return 0 if successful, otherwise -1. - */ -int paddle_send_grads(paddle_pserver_client client, const paddle_gradient* grads, int len); - -/** - * @brief paddle_get_params gets parameters from parameter servers. - * - * paddle_get_params will block until parameters are initialized on - * the parameter servers. - * - * @param dst the destination array of parameter pointers to save to. - * The parameter pointer must be pre-popullated with required parameter name, - * and the content of parameter must be pre-allocated of the size of required - * parameter on pserver. - * @param len the length of the names array and the paddle_parameter - * array. - * @return 0 if successful, otherwise -1. - */ -int paddle_get_params(paddle_pserver_client client, paddle_parameter** dst, int len); - -/** - * @brief paddle_save_model indicates parameters to save the parameter - * to the given path - * - * @param path the path to save parameters. - * @return 0 if successful, otherwise -1. - */ -int paddle_save_model(paddle_pserver_client client, const char* path); -``` diff --git a/develop/doc_cn/_sources/design/cluster_train/remote_parameter_updater.md.txt b/develop/doc_cn/_sources/design/cluster_train/remote_parameter_updater.md.txt deleted file mode 100644 index 6e8e5938455..00000000000 --- a/develop/doc_cn/_sources/design/cluster_train/remote_parameter_updater.md.txt +++ /dev/null @@ -1,21 +0,0 @@ -# Design Doc: Remote Parameter Updater for Cluster Train - -For an overview of distribute training, please refer to [distributed training design doc](README.md). In this design doc, we will discuss the parameter updater that will use parameter server cclient [The Client Library of Parameter Server Design Doc](pserver_client.md) to manage and update parameters. - -## Parameter Updater - -Parameter Updater is used by trainer to manage and update parameter, there are mainly two kind of parameter updater: local and remote, since this design is for cluster train, we will only discuss remote parameter updater here. - -### Remote Parameter Updater - -Remote Parameter Updater manage parameters through remote parameter server with the client that communicate with pserver([The Client Library of Parameter Server Design Doc](pserver_client.md)) - -In PaddlePaddle Python V2 API, trainer is implemented in python, and the trainer will hold a instance of parameter updater and call it's functions directly. In this design, we will also expose the api of RemoteParameterUpdater to python with swig. - -#### Sparse Remote Parameter Updater - -Since we will only implement dense parameter management new, the mechanism for sparse parameter will be discussed in next stage. - -### Interface Design - -TBD diff --git a/develop/doc_cn/_sources/design/cluster_train/save_model.md.txt b/develop/doc_cn/_sources/design/cluster_train/save_model.md.txt deleted file mode 100644 index b755185c81a..00000000000 --- a/develop/doc_cn/_sources/design/cluster_train/save_model.md.txt +++ /dev/null @@ -1,111 +0,0 @@ -# Design Doc: Save Model - -## Overview - -The model is the output of the training process. There are two -ways from which user can obtain a model: - -- Save model triggered by user code: user code asks PaddlePaddle to - save a model. -- Convert model from the checkpoint: model being converted from - pservers' periodic checkpoint. In this way, the user can cancel a - job at any time, and still have a relatively fresh model (we - checkpoint around every 5 minutes). - -### Trainer Saving Model vs. Pservers Saving Model - -Both trainers and pservers have access to the model. So the model can -be saved from a trainer or pservers. We need to decide where the model -is saved from. - -#### Dense Update vs. Sparse Update - -There are two types of model update methods: dense update and sparse -update (when the model parameter is configured to be sparse). - -- Dense update - - Every trainer has it's own full copy of the model. Every model - update will update the entire model. - -- Sparse update - - The training input is sparse, and the trainer does not have the - entire model. It will only download the sub-model necessary related - to the input. When updating the model, only the sub-model related to - the training input is updated. - - -#### Pservers Saving Model - -The benefit of letting pservers save model is they have the entire -model all the time. However, since pservers are on different nodes, it -requires a merging process to merge model shards into the same -model. Thus requires the pservers to write models to a distributed -filesystem, making the checkpoint shards visible to the merge program. - -#### Trainer Saving Model - -The benefit of letting one trainer to save the model is it does not -require a distributed filesystem. And it's reusing the same save model -logic when training locally - except when doing sparse update, the -trainer needs to download the entire model during the saving process. - -#### Conclusion - -Given trainer saving model does not require a distributed filesystem, -and is an intuitive extension to trainer saving model when training -locally, we decide to let the trainer save the model when doing -distributed training. - - -### Convert Model from Checkpoint - -TODO - - -## Timeline - -We first implement trainer save the model. Converting the latest -snapshot to a model will be a TODO for future. - - -## Trainer Save Model - -### Trainer Election - -One trainer will be elected as the one to save the model. When using -etcd, trainer ID is a randomly generated UUID, the trainer will -contact the master server requesting to save the model, and find out -if itself is elected. When the master server is not used, unique -trainer IDs will be given by the administrator, the trainer whose ID -is "0" is elected to save the model. - -### Model Save Path - -Each trainer will be given the directory to save the model. The -elected trainer will save the model to -`given-directory/trainerID`. Since the trainer ID is unique, this -would prevent concurrent save to the same file when multiple trainers -are elected to save the model when split-brain problem happens. - -### What Happens When Model Is Saving - -It takes some time to save model, we need to define what will happen -when save model is taking place. - -When doing dense update, the trainer uses the local model. Pservers -does not need to pause model update. - -When doing sparse update. The trainer needs to download the entire -model while saving. To get the most accurate model, the model update -needs to be paused before the download starts and resumed after the -download finishes. Otherwise, the trainer gets a model that is -"polluted": some part of the model is old, some part of the model is -new. - -It's unclear that the "polluted" model will be inferior due to the -stochastic nature of deep learning, and pausing the model update will -add more complexity to the system. Since supporting sparse update is a -TODO item. We defer the evaluation of pause the model update or not -during saving model to the future. diff --git a/develop/doc_cn/_sources/design/cluster_train/submit-job.md.txt b/develop/doc_cn/_sources/design/cluster_train/submit-job.md.txt deleted file mode 100644 index 8377d5489dc..00000000000 --- a/develop/doc_cn/_sources/design/cluster_train/submit-job.md.txt +++ /dev/null @@ -1,127 +0,0 @@ -# Submit a Distributed Training Job - -The user can submit a distributed training job with Python code, rather than with a command-line interface. - -## Runtime Environment On Kubernetes - -For a distributed training job, there is two Docker image called *runtime Docker image* and *base Docker image*. The runtime Docker image is the Docker image that gets scheduled by Kubernetes to run during training. The base Docker image is for building the runtime Docker image. - -### Base Docker Image - -Usually, the base Docker image is PaddlePaddle product Docker image including paddle binary files and python package. And of course, users can specify any image name hosted on any docker registry which users have the access right. - -### Runtime Docker Image - -The trainer package which user upload and some Python dependencies are packaged into a runtime Docker image based on base Docker image. - -- Handle Python Dependencies - - You need to provide requirements.txt file in your `trainer-package` folder. Example: - - ```txt - pillow - protobuf==3.1.0 - ``` - More [details](https://pip.readthedocs.io/en/1.1/requirements.html) about requirements, an example project looks like: - ```bash - paddle_example - |-quick_start - |-trainer.py - |-dataset.py - |-requirements.txt - ``` - -## Submit Distributed Training Job With Python Code - - -- `paddle.job.dist_train()` will call the Job Server API `/v1/packages` to upload the trainer package and save them on CephFS, and then call `/v1/trainer/job` to submit the PaddlePaddle distributed job. -- `/v1/trainer/job` will start a building job for preparing the runtime Docker image. When the building job is finished, Job Server will submit the PaddlePaddle distributed job to Kubernetes. -- *NOTE*: For the first version, we will not prepare the runtime Docker image, instead, the package is uploaded to Paddle Cloud, and Paddle Cloud will mount the package in a temporary folder into the base Docker image. We will not support custom Python dependencies in the first version as well. - -You can call `paddle.job.dist_train` and provide distributed training configuration as the parameters: -```python -paddle.job.dist_train( - trainer=dist_trainer(), - paddle_job=PaddleJob( - job_name = "paddle-cloud", - entry_point = "python %s"%__file__, - trainer_package = "/example/word2vec", - image = "yancey1989/paddle-job", - trainers = 10, - pservers = 3, - trainer_cpu = 1, - trainer_gpu = 1, - trainer_mem = "10G", - pserver_cpu = 1, - pserver_mem = "2G" - )) -``` - -The parameter `trainer` of `paddle.job.dist_train` is a function and you can implement it as follows: -```python -def dist_trainer(): - def trainer_creator(): - trainer = paddle.v2.trainer.SGD(...) - trainer.train(...) - return trainer_creator -``` - -The pseudo code of `paddle.job.dist_train` is as follows: -```python -def dist_train(trainer, paddle_job): - # if the code is running on cloud, set PADDLE_ON_CLOUD=YES - if os.getenv("RUNNING_ON_CLOUD", "NO") == "NO": - #submit the paddle job - paddle_job.submit() - else: - #start the training - trainer() -``` -### PaddleJob Parameters -parameter | type | explanation - --- | --- | --- -job_name | str | the unique name for the training job -entry_point | str | entry point for startup trainer process -trainer_package | str | trainer package file path which user have the access right -image|str|the [base image](#base-docker-image) for building the [runtime image](#runtime-docker-image) -pservers|int| Parameter Server process count -trainers|int| Trainer process count -pserver_cpu|int| CPU count for each Parameter Server process -pserver_mem|str| memory allocated for each Parameter Server process, a plain integer using one of these suffixes: E, P, T, G, M, K -trainer_cpu|int| CPU count for each Trainer process -trainer_mem|str| memory allocated for each Trainer process, a plain integer using one of these suffixes: E, P, T, G, M, K -trainer_gpu|int| GPU count for each Trainer process, if you only want CPU, do not set this parameter - -### Deploy Parameter Server, Trainer and Master Process - - Deploy PaddlePaddle Parameter Server processes, it's a Kubernetes ReplicaSet. - - Deploy PaddlePaddle Trainer processes, it's a Kubernetes Job. - - Deploy PaddlePaddle Master processes, it's a Kubernetes ReplicaSet. - -## Job Server - -- RESTful API - - Job server provides RESTful HTTP API for receiving the trainer package and displaying - PaddlePaddle job related informations. - - `POST /v1/package` receive the trainer package and save them on CephFS - - `POST /v1/trainer/job` submit a trainer job - - `GET /v1/jobs/` list all jobs - - `GET /v1/jobs/` the status of a job - - `DELETE /v1/jobs/` delete a job - - `GET /v1/version` job server version - -- Build Runtime Docker Image on Kubernetes - - `paddle.job.dist_train` will upload the trainer package to Job Server, save them on the distributed filesystem, and then start up a job for building the runtime Docker image that gets scheduled by Kubernetes to run during training. - - There are some benefits for building runtime Docker image on JobServer: - - On Paddle Cloud, users will run the trainer code in a Jupyter Notebook which is a Kubernetes Pod, if we want to execute `docker build` in the Pod, we should mount the host's `docker.sock` to the Pod, user's code will connect the host's Docker Engine directly, it's not safe. - - Users only need to upload the training package files, does not need to install docker engine, docker registry as dependencies. - - If we want to change another image type, such as RKT, users do not need to care about it. - -- Deploy Parameter Server, Trainer and Master Processes - - `POST /v1/trainer/job` receives the distributed training parameters, and deploy the job as follows: - - Deploy PaddlePaddle Parameter Server processes, it's a Kubernetes ReplicaSet. - - Deploy PaddlePaddle Trainer processes, it's a Kubernetes Job. - - Deploy PaddlePaddle Master processes, it's a Kubernetes ReplicaSet. diff --git a/develop/doc_cn/_sources/design/concurrent_programming.md.txt b/develop/doc_cn/_sources/design/concurrent_programming.md.txt deleted file mode 100644 index f022e67fd3a..00000000000 --- a/develop/doc_cn/_sources/design/concurrent_programming.md.txt +++ /dev/null @@ -1,163 +0,0 @@ -# Design Doc: Concurrent Programming with Fluid - -With PaddlePaddle Fluid, users describe a program other than a model. The program is a [`ProgramDesc`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto) protobuf message. TensorFlow/MxNet/Caffe2 applications generate protobuf messages too, but their protobuf messages represent the model, a graph of operators, but not the program that trains/uses the model. - -Many know that when we program TensorFlow, we can specify the device on which each operator runs. This allows us to create a concurrent/parallel AI application. An interesting questions is **how does a `ProgramDesc` represents a concurrent program?** - -The answer relies on the fact that a `ProgramDesc` is similar to an abstract syntax tree (AST) that describes a program. So users just program a concurrent program that they do with any concurrent programming language, e.g., [Go](https://golang.org). - -## An Analogy - -The following table compares concepts in Fluid and Go - -| Go | Fluid | -|----|-------| -|user-defined functions | [layers](https://github.com/PaddlePaddle/Paddle/tree/develop/python/paddle/fluid) | -| control-flow and built-in functions | [intrinsics/operators](https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/operators) | -| goroutines, channels | [class ThreadPool](https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/framework/thread_pool.h) | -| runtime | [class Executor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/executor.h) | - -## An Example Concurrent Program - -To review all above concepts in an example, let us take a simple program and writes its distributed version. - -Suppose that we want to parallelize a naive Fluid program (written in Go and calling Fluid's Go binding) that multiplies two tensors. - -```go -import "fluid" - -func paddlepaddle() { - X = fluid.read(...) - W = fluid.Tensor(...) - Y = fluid.mult(X, W) -} -``` - -Please be aware that the Fluid's Go binding provides the default `main` function, which calls the `paddlepaddle` function, which, in this case, is defined in above program and creates the following `ProgramDesc` message. - -```protobuf -message ProgramDesc { - block[0] = Block { - vars = [X, W, Y], - ops = [ - read(output = X) - assign(input = ..., output = W) - mult(input = {X, W}, output = Y) - ], - } -} -``` - -Then, the default `main` function calls `fluid.run()`, which creates an instance of the [`class Executor`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/executor.h) and calls `Executor.Run(block[0])`, where `block[0]` is the first and only block defined in above `ProgramDesc` message. - -The default `main` function is defined as follows: - -```go -func main() { - paddlepaddle() - fluid.run() -} -``` - -## The Concurrent Version - -By parallelizing the above program, we could support very big tensor X by splitting into small pieces {x_1, x_2, ...} and sent each piece to worker process/node for parallel multiplication. - -In this case, we can write a transpiler that takes a `ProgramDesc` message that represents the above example program and outputs two `ProgramDesc` messages, one for running on the master process/node, and the other one for worker processes/nodes. - -### The Master Program - -The master program could look like the following: - -```protobuf -message ProgramDesc { - block[0] = Block { - vars = [X, L, Y], - ops = [ - read(output = X) - kube_get_workers_addrs(output = L) - Y = tensor_array(len(L)) - parallel_for(input = X, output = Y, - attrs = {L, block_id(1)}) # referring to block 1 - ] - } - - block[1] = Block { - parent = 0, - vars = [x, y, index], - ops = [ - slice(input = [X, index], output = x) # index is initialized by parallel_for - send(input = x, attrs = L[index]) - recv(outputs = y, attrs = L[index]) - assign(input = y, output = Y[index]) - ] - } -} -``` - -The equivalent Fluid program (calling the Go binding) is: - -```go -func main() { //// block 0 - X = fluid.read(...) - L = fluid.k8s.get_worker_addrs() - Y = fluid.tensor_array(len(L)) - fluid.parallel_for(X, L, - func(index int) { //// block 1 - x = X[index] - fluid.send(L[index], x) - y = fluid.recv(L[index]) - Y[index] = y - }) -} -``` - -An explanation of the above program: - -- `fluid.k8s` is a package that provides access to Kubernetes API. -- `fluid.k8s.get_worker_addrs` returns the list of IP and ports of all pods of the current job except for the current one (the master pod). -- `fluid.tensor_array` creates a [tensor array](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/lod_tensor_array.h). `fluid.parallel_for` creates a `ParallelFor` intrinsic, which, when executed, - - 1. creates `len(L)` scopes, each for the concurrent running of the sub-block (block 1 in this case), and initializes a variable named "index" in the scope to an integer value in the range `[0, len(L)-1]`, and - 2. creates `len(L)` threads by calling into the `ThreadPool` singleton, each thread - 1. creates an Executor instance, and - 2. calls `Executor.Run(block)`, where `block` is block 1 as explained above. -1. Please be aware that block 1 is a sub-block of block 0, so ops in block 1 could refer to variables defined in block 0. - -### The Worker Program - -The worker program looks like - -```go -func main() { - W = Tensor(...) - x = fluid.listen_and_do( - fluid.k8s.self_addr(), - func(input Tensor) { - output = fluid.mult(input, W) - }) -} -``` - -where - -- `fluid.listen_and_do` creates a `ListenAndDo` intrinsic, which, when executed, - 1. listens on the current pod's IP address, as returned by `fliud.k8s.self_addr()`, - 2. once a connection is established, - 1. creates a scope of two parameters, "input" and "output", - 2. reads a [Fluid variable](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/variable.h) and saves it into "input", - 3. creates an Executor instance and calls `Executor.Run(block)`, where the block is generated by running the lambda specified as the second parameter of `fluid.listen_and_do`. - -## Summarization - -From the above example, we see that: - -1. Fluid enables the imperative programming paradigm by: - 1. letting users describe a program, but not a model (a sequence of layers, or a graph of operators), and - 2. call the `fluid.run` function that runs the program implicitly. -1. The program is described as a `ProgramDesc` protobuf message. -2. Function `Executor.Run` takes a block, instead of a `ProgramDesc`, as its parameter. -3. `fluid.run` calls `Executor.Run` to run the first block in the `ProgramDesc` message. -4. `Executor.Run`'s implementation is extremely simple -- it doesn't plan the execution nor create threads; instead, it runs on the current thread and execute intrinsics/operators' `Run` method sequentially as they appear in the `Block.ops` array. -5. Intrinsics/operators' `Run` method might create threads. For example, the `ListenAndDo` operator creates a thread to handle each incoming request. -6. Threads are not necessarily OS thread; instead, they could be [green threads](https://en.wikipedia.org/wiki/Green_threads) managed by ThreadPool. Multiple green threads might run on the same OS thread. An example green threads is Go's [goroutines](https://tour.golang.org/concurrency/1). diff --git a/develop/doc_cn/_sources/design/cpp_data_feeding.md.txt b/develop/doc_cn/_sources/design/cpp_data_feeding.md.txt deleted file mode 100644 index 40205350f99..00000000000 --- a/develop/doc_cn/_sources/design/cpp_data_feeding.md.txt +++ /dev/null @@ -1,79 +0,0 @@ -# C++ Data Feeding - -In training with Paddle V2 API, data feeding wholly dependents on Python code. To get rid of the Python environment and achieve the goal of "wrapping the whole training by a while loop op" in Paddle Fluid, a C++ data feeding mechanism is required. - -In this document we show the fundamental design of C++ data feeding process, which includes the data reading, shuffling and batching. - -## Reader - -A new concept named 'Reader' is introduced. `Reader` is a series of inherited classes which can be hold by our `Variable` and they are used to read or process file data. - - -### `ReaderBase` - -`ReaderBase` is the abstract base class of all readers. It defines the all readers' interfaces. - -```cpp -class ReaderBase { - public: - explicit ReaderBase(const std::vector& shapes) : shapes_(shapes) { - PADDLE_ENFORCE(!shapes_.empty()); - } - // Read the next batch of data. (A 'batch' can be only one instance) - virtual void ReadNext(std::vector* out) = 0; - // Show whether the next bacth exists. - virtual bool HasNext() const = 0; - - // Reinitialize the reader and read the file from the begin. - virtual void ReInit() = 0; - - // Get a certain read in data's shape. - DDim shape(size_t idx) const; - // Get shapes of all read in data. - std::vector shapes() const { return shapes_; } - // Set shapes of read in data. - void set_shapes(const std::vector& shapes) { shapes_ = shapes; } - - virtual ~ReaderBase() {} - - protected: - std::vector shapes_; -}; -``` - -### `FileReader` and `DecoratedReader` - -These two classes are derived from the `ReaderBase` and will further be derived by respective specific readers. That is to say, in our design, there are two kinds of readers: file readers and decorated readers. A file reader reads from a file of some specific format, and yield only one instance of data at a time. e.g. RecordIO reader, jpg reader, .... A decorated reader takes another reader(both file reader and decorated reader are OK) as its 'underlying reader'. It gets data from its underlying reader, does some process on them(shuffling, or batching), then yields processed data. The output data of a decorated reader can be a single instance or a batch. `ShuffleReader` and `BatchReader` are both decorated readers. - -All the readers share exactly the same interfaces defined in `ReaderBase`. So they can be decorated for more than one time: We can **shuffle** a reader's outputs and then **batch** the shuffle outputs. The interface consistency also allows related ops use readers without knowing what they are exactly. - - -### `ReaderHolder` - -Different readers belong to different class types. It leads to a problem: How can we drop them into `Variable`s and fetch them out by a unified method? For example, if a Variable holds a `BatchReader`, we can not get it by the following code: - -```cpp -var->Get("batch_reader"); -``` - -we have to write: - -```cpp -var->Get("batch_reader"); -``` - -This requires each time getting a reader from a variable we must know the reader's type exactly. It is nearly impossible. - -To solve this problem, we introduce `ReaderHolder` as a wrapper. It acts as an empty decorator of `ReaderBase`, which erases reader's type. With `ReaderHolder` we are able to fetch all types of readers by `var->Get("...")` and regard the obtained object as a reader. - -## Related Operators - -To create and invoke readers, some now ops are introduced: - -### `CreateReaderOp` - -Each reader has its creating op. File readers' creating ops have no input and yield the created file reader as its output. Decorated readers' creating ops take the underlying readers as inputs and then yield new decorated readers. - -### `ReadOp` - -A reader is only a Variable. It cannot trigger the reading process by itself. So we add the `ReadOp` to execute it. A `ReadOp` takes a reader Variable as its input. Each time it runs, it invokes the reader‘s `ReadNext()` function and gets a new batch of data(or only one instance of data, if we use file reader directly). The output data of a reader are in the form of `std::vector`, so the `ReadOp` also needs to split the vector and move LoDTensors to their respective output Variables. diff --git a/develop/doc_cn/_sources/design/csp.md.txt b/develop/doc_cn/_sources/design/csp.md.txt deleted file mode 100644 index 10d936860fa..00000000000 --- a/develop/doc_cn/_sources/design/csp.md.txt +++ /dev/null @@ -1,224 +0,0 @@ -# Design Doc: CSP in PaddlePaddle Fluid - -## Motivation - -Concurrent programming is important for deep learning. Few example applications are: - -1. The main thread keeps reading the next mini-batch while another thread uses the GPU for computing. -2. The main thread performs the computation while another thread uploads the local gradients from each trainer to the parameter server. - -Most DL systems, including TensorFlow, Caffe2, and MxNet, can asynchronously execute operators in a graph. However, Fluid doesn't have the concept of a graph at all, as the design goal of Fluid is that of a programming language. - -## Concurrent Programming Models - -There were many concurrent programming models, implemented in various forms: - -| concurrent programming model | implementation | -|-----|-----| -| mutex | types and functions in standard libraries | -| semaphore | types and functions in standard libraries | -| communicating sequential processes (CSP) | Go programming language | -| actor model | Erlang programming language | -| message passing | MPI | -| bulk synchronous parallel (BSP) | Pregel distributed programming framework | - -Since Fluid was designed to be a programming language, we would like to implement CSP in Fluid. - -### CSP v.s. Actor Model - -A well-known implementation of Actor Model is the Erlang programming language. In Actor Model, *processes* could send messages to another process and receive messages from another process given the process IDs. We can find the three ingredients, process with ID, send, and recv, in MPI too. Indeed, we can rewrite Erlang programs in Python + MPI with possibly fewer lines of code. Our concern with Actor Model is that it doesn't seem reasonable to implement process management in a programming language's runtime library; instead, it should be the operating systems' responsibility to manage processes and libraries like MPI for send/recv. - -## CSP in Fluid - -Fluid has two fundamental control-flows: *if-else* and *while*. If we are to implement CSP, we need the following: - -1. a new data type: *channel* and operators *send* and *recv*, -1. *goroutine* or thread, and -1. a new control-flow: select. - -We also need Python wrappers for the above components. - -The type *channel* is conceptually the blocking queue. In Go, its implemented is a [blocking circular queue](https://github.com/golang/go/blob/68ce117cf17b8debf5754bfd476345779b5b6616/src/runtime/chan.go#L31-L50), which supports send and recv. - -The `select` operation has been in OS kernels long before Go language. All Unix kernels implement system calls *poll* and *select*. They monitor multiple file descriptors to see if I/O is possible on any of them. This takes O(N) time. Since Linux 2.6, a new system call, *epoll*, can do the same in O(1) time. In BSD systems, there is a similar system call *kqueue*. Go's Linux implementation uses epoll. - -It might be a good idea to implement Fluid's select using epoll too. In this design doc, we start from the O(N) way so that we could focus on Python binding and the syntax. - -### Type Channel - -Fluid supports many data types: - -1. Tensor, -1. Row-sparse Tensor -1. LoD Tensor, -1. Tensor array, etc - -Each data type is registered in the [`framework.proto`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto#L117-L127) as an enum value. To add a new type channel, we need to add a new type enum. - -To expose a C++ type to Python, we need to edit the [`pybind.cc`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/pybind/pybind.cc) file. [Here](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/pybind/pybind.cc#L120-L164) is an example how we expose C++ class LoDTensor. - -## Syntax Design - -### Create Channel - -In Go, we create a channel by specifying the element type and buffer size: - -```go -ch := make(chan int) // a channel without buffer -ch1 := make(chan int, 100) // a channel that can buffer 100 ints. -``` - -In Fluid, we should be able to do the same: - -```python -ch = fluid.make_channel(dtype=INT) -ch1 = fluid.make_channel(dtype=INT, 100) -``` - -In addition to that, we want channels that can hold more complex element types, e.g., Tensors of float16: - -```python -ch = fluid.make_channel(dtype=Tensor, etype=float16) -``` - -or Tensors of Tensors of float16 etc. - -The point here is that we need a consistent way to compose types, like in C++ we can have `Tensor...> >`. - -### Send and Recv - -Go's CSP implementation depends on data type *channel*. There are two types of channels: - -1. The unblocked channel, or buffered channel, is a blocking queue with a non-zero sized buffer. The sending to buffered channel blocks if the buffer is full, and the receive operation blocks if the buffer is empty. -1. blocked channel, or unbuffered channel, is a blocking queue with no buffer. Both sending and receiving block with unbuffered channels. - -There are four types of actions with a channel: - -1. Create a channel - - ```go - ch := make(chan int) // this is an unbuffered channel - ch := make(chan int, 100) // this is a buffered channel of 100 ints. - ``` - -1. Send - - ```go - ch <- 111 - ``` - -1. Recv - - ```go - y, ok <- ch - ``` - -1. Close - - ```go - close(ch) - ``` - - Please be aware that a closed channel is not a nil channel, which is `var ch chan int`. - -There are some [axioms with channels](https://dave.cheney.net/2014/03/19/channel-axioms): - -1. A send to a nil channel blocks forever - -1. A receive from a nil channel blocks forever - -1. A send to a closed channel panics - -1. A receive from a closed channel returns the residual values and then zeros. - -In Fluid, we have [buffered channels](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/details/buffered_channel.h) and [unbuffered channels](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/details/unbuffered_channel.h) - -The following program illustrates the Python syntax for accessing Fluid buffers. - -```python -import fluid - -buffer_size = 10 -ch = fluid.make_channel(dtype=INT, buffer_size) - -# Now write three elements to the channel -with fluid.while(steps=buffer_size): - fluid.send(ch, step) - -fluid.close_channel(ch) - -with fluid.while(steps=buffer_size): - fluid.print(fluid.recv(ch)) -``` - -The following example shows that to avoid the always-blocking behavior of unbuffered channels, we need to use Fluid's goroutines. - -```python -import fluid - -ch = fluid.make_channel(dtype=INT) - -with fluid.go(): - fluid.send(ch) - -y = fluid.recv(ch) - -fluid.close_channel(ch) -``` - -### Select - -In Go, the `select` statement lets a goroutine wait on multiple communication operations. A `select` blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready. - -```go - -ch1 := make(chan int) -ch2 := make(chan int, 100) - -x := 0 - -for { - select { - case ch1 <- x: - x := x + 1 - case y <- ch2: - fmt.Println("Received on channel") - default: - fmt.Println("Default") - } - } - -``` - -In Fluid, we should be able to do the same: - -```python -ch1 = fluid.make_chan(dtype=INT) -ch2 = fluid.make_chan(dtype=INT, 100) - -sel = fluid.select() - -with sel.case(ch1, 'w', X): - fluid.layers.increment(X) - -with sel.case(ch2, 'r', Y): - fluid.print("Received on Channel") - -with sel.default(): - fluid.print("Default") - -``` - -In the above code snippet, `X` and `Y` are variables. Now let us look at each of these statements one by one. - -- `sel.case(ch1, 'w', X)` : This specifies that we are writing to `ch1` and we want to write the integer in variable `X` to the channel. The character `w` is used here to make the syntax familiar to write syntax in Python I/O. - -- `sel.case(ch2, 'r', Y)` : This specifies that we would like to read the result from `ch2` into variable `Y`. The character `r` is used here to make the syntax familiar to read syntax in Python I/O. - -- `sel.default()` : This is equivalent to the default in Go `select`. If none of the channels are ready for read or write, then the fluid code in the default block will be executed. - -## Example Programs - -### 1. RPC between Trainers and Parameter Servers - -### 2. Concurrent Minibatch Loading diff --git a/develop/doc_cn/_sources/design/dist_refactor/distributed_architecture.md.txt b/develop/doc_cn/_sources/design/dist_refactor/distributed_architecture.md.txt deleted file mode 100644 index 9368c5780dc..00000000000 --- a/develop/doc_cn/_sources/design/dist_refactor/distributed_architecture.md.txt +++ /dev/null @@ -1,197 +0,0 @@ -# Design Doc: Distributed Training Architecture - -## Abstract - -PaddlePaddle version 0.10.0 uses the "trainer-parameter server" architecture. We run multiple instances of trainers (where each trainer runs the same model) and parameter servers for distributed training. This architecture serves well, but has few limitations: - -1. There is a need to write special code that handles tasks which should only be run on a single trainer. E.g., initializing the model, saving the model etc. - -2. Model parallelism is hard: It would need all the if-else branches conditioned on the trainer ID to partition the model onto the trainers, and eventually manually writing out the inter-model-shard communication code to communicate between different trainers. - -3. The user can not directly specify the parameter update rule: This would need to modify the parameter server code and compile a new binary. This makes things more complicated for researchers: A lot of extra effort is required to make this work. Besides, the training job submission program may not allow running arbitrary binaries. - -This design doc discusses PaddlePaddle's new distributed training architecture that addresses the above mentioned limitations. - -## Analysis - -The assumption is that the user writes the trainer program in either Python or C++. - -### Limitation 1 - -There are two basic functionalities in the trainer program: - -1. The training logic such as loading / saving the model and printing out the logs. -2. The neural network definition such as the definition of the data layer, the fully connected layer, the cost function and the - optimizer. - -When we train using PaddlePaddle v0.10.0 in a distributed fashion, multiple instances of the same Python code are run on different nodes, hence both: the -training logic as well as the neural network computation logic, is replicated. - -The tasks that only need to be run once belong to the training logic. Hence if we only replicate the neural network computation part, and do **not** -replicate the training logic, the limitation mentioned above can be avoided. - -### Limitation 2 - -Model parallelism means that a single model is partitioned into different components and each node runs one of the component separately. This comes at the extra cost of managing the -inter-model-shard communication between nodes. - -PaddlePaddle should ideally be able to modify the neural network computation and figure out the support for model parallelism automatically. However, the -computation is only specified in Python code which sits outside of PaddlePaddle, hence PaddlePaddle can not support the feature in this setup. - -Similar to how a compiler uses an intermediate representation (IR) so that the programmer does not need to manually optimize their code for most of the cases, we can have an intermediate representation in PaddlePaddle as well. The compiler optimizes the IR as follows: - - - -PaddlePaddle can support model parallelism by converting the IR so that the user no longer needs to manually perform the computation and operations in the Python component: - - - -The IR for PaddlePaddle after refactoring is called a `Block`, it specifies the computation dependency graph and the variables used in the computation. - -### Limitation 3 - -The user can not directly specify the parameter update rule for the parameter server in the Python module, since the parameter server does not use the same computation definition as the trainer. Instead, the update rule is baked inside the parameter server. The user can not specify the update rule explicitly. - -This could be fixed by making the parameter server also run an IR, which can be different to the trainer side -For a detailed explanation, refer to this document - -[Design Doc: Parameter Server](./parameter_server.md) - -## Distributed Training Architecture - -The revamped distributed training architecture can address the above discussed limitations. Below is the illustration of how it does so: - - - -The major components are: *Python API*, *Distribute Transpiler* and *Remote Executor*. - -### Python API - -Python API is the Python library that user's Python code invokes, to read the data, build the neural network topology, and start training, etc. - -```Python -images = fluid.layers.data(name='pixel', shape=[1, 28, 28], dtype='float32') -label = fluid.layers.data(name='label', shape=[1], dtype='int64') -... -predict = fluid.layers.fc(input=conv_pool_2, size=10, act="softmax") -cost = fluid.layers.cross_entropy(input=predict, label=label) -avg_cost = fluid.layers.mean(x=cost) -optimizer = fluid.optimizer.Adam(learning_rate=0.01) -optimizer.minimize(avg_cost) - -train_reader = paddle.batch( - paddle.reader.shuffle( - paddle.dataset.mnist.train(), buf_size=500), - batch_size=BATCH_SIZE) - -place = fluid.CPUPlace() -exe = fluid.Executor(place) - -for pass_id in range(10): - for data in train_reader(): - loss, acc = exe.run(trainer_prog, - feed=feeder.feed(data), - fetch_list=[avg_cost]) -``` - -The code above is a typical local training program, the "Training Program" is built using helper functions such as -`fluid.layer.fc`. The training is done by calling `Executor.run` -iteratively. - -For more details, the implementation of IR is [Program](../program.md), and `ProgramDesc` is the protobuf type. - -[Executor](../executor.md) simply runs the `ProgramDesc`. For local training you generally use -`Executor` to run the program locally. For any kind of distributed training, you can use -`RemoteExecutor` to specify desired distributed training method with some optional arguments. - -### Distributed Transpiler - -The Distributed Transpiler automatically converts the IR (in protobuf format) to partitioned IRs. Then -the Remote Executor dispatches the new IRs to Remote Executors across the cluster. -Below are the steps that are followed : - -1. User only need to change `Executor` to `RemoteExecutor` to change local program to distributed program. -1. `RemoteExecutor` calls `Distributed Transpiler` to "transpile" user's program to several IRs representing a - distributed training program: - 1. Parse configurations from `RemoteExecutor`. - 1. Determine the type of distributed program, can be DataParallelism, ModelParallelism or Streaming. - 1. Partition the `ProgramDesc` according to type and add `send` / `recv` OP pair on the boundaries. Take - DataParallelism type for example, it removes the optimization operators and add a `send` OP to the - "trainer" role, then add the optimization operators to the parameter server role within the `recv` OP. -1. Dispatch the partitioned graph to different `RemoteExecutor` in the cluster. -1. `RemoteExecutor` on each node run the received `ProgramDesc` utill the end. - - -### RemoteExecutor - -As shown in the graph, `RemoteExecutor.run` sends the IR to the cluster for Execution. -You can also use parameter `fetch_list` to interactively fetch variable back to local for -log printing. - -The Python `RemoteExecutor` is derived from `Executor` class. - -```python -exe = RemoteExecutor( - feed=feeder.feed(data), - fetch_list=[avg_cost], - job_desc=JobDesc( - jobname, - num_trainer, - num_pserver, - cpu_per_trainer, - gpu_per_trainer, - mem_per_trainer, - cpu_per_pserver, - mem_per_pserver - )) -for data in train_reader(): - loss, acc = exe.run(trainer_prog, - feed=feeder.feed(data), - fetch_list=[avg_cost]) -``` - -`JobDesc` object describe the distributed job resource specification to run on -Cluster environment. - - - -`RemoteExecutor.run` sends the `ProgramDesc` and -[TrainingJob](https://github.com/PaddlePaddle/cloud/blob/develop/doc/autoscale/README.md#training-job-resource) -to a server in the cluster which executes `RemoteExecutor.listen`. This server is responsible -to start the final Kubernetes Jobs to run the different role of `ProgramDesc` from `ConfigMap`. - - -### Placement Algorithm - -Our first implementation will only support "trainer-parameter server" placement: the parameters, initializers, and optimizers are all placed on the PaddlePaddle runtimes with the parameter server role. Everything else will be placed on the PaddlePaddle runtimes with the trainer role. This has the same functionality as the "trainer-parameter server" architecture of PaddlePaddle v0.10.0, but is more generic and flexible. - -In the future, a more general placement algorithm should be implemented, which makes placements according to the input IR, and a model of device computation time and device communication time. Model parallelism requires the generic placement algorithm. - - -### Local Training Architecture - -The local training architecture will be the same as the distributed training architecture, the difference is that everything runs locally, and there is just one PaddlePaddle runtime: - - - - -### Training Data - -In PaddlePaddle v0.10.0, training data is typically read -with [data reader](../reader/README.md) from Python. This approach is -no longer efficient when training distributedly since the Python -process no longer runs on the same node with the trainer processes, -the Python reader will need to read from the distributed filesystem -(assuming it has the access) and send to the trainers, doubling the -network traffic. - -When doing distributed training, the user can still use Python data -reader: the training data are sent with `Executor.run`. However, should -be used for debugging purpose only. The users are encouraged to use -the read data OPs. - - -## References: - -[1] [TensorFlow: Large-Scale Machine Learning on Heterogeneous Distributed Systems](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45166.pdf) - -[2] [TensorFlow: A System for Large-Scale Machine Learning](https://www.usenix.org/system/files/conference/osdi16/osdi16-abadi.pdf) diff --git a/develop/doc_cn/_sources/design/dist_refactor/multi_cpu.md.txt b/develop/doc_cn/_sources/design/dist_refactor/multi_cpu.md.txt deleted file mode 100644 index a8d8ee0422a..00000000000 --- a/develop/doc_cn/_sources/design/dist_refactor/multi_cpu.md.txt +++ /dev/null @@ -1,43 +0,0 @@ -# Design Doc: Execute the Program with Multi CPU - -## Abstract - -This Design Doc propose an approach to make the user-defined Op graph -running with multi-CPU, we will use an auto transpiler to convert the user-defined -Op graph to a multi-CPU Op graph, and run `ParallelDo` Op to run the graph. - -## Transpiler - - - -After converted: - - - -## Implement - -- `Multi-CPU Transpiler` will convert the graph to a multi-CPU graph - which would be executed with multi-threads. -- `BlockingCounter` will `Init/Decrement` an atomic counter, and Blocking `Wait` - for the atomic counter become `0`: - ```cpp - BlockingCounter bc(thread_count); - for (int i = 0; i < thread_count; ++i) { - thread_pool->Start([&bc] {bc.DecrementCount(); }) - } - bc.Wait(); - ``` -- `ParallelDo` Operator - - Initialize a thread pool which is a Singleton. - - Use a block id as the input, and create run the specify Block on independent scope - with multi-threads. - - Initialize a `BlockingCounter` instance and wait until all threads are done. -- `Split` Operator will split the Input Tensor into a TensorArray. -- `Merge` merge all the gradients which calculated in different threads - with `mean/sum/max/min...` method, and then run the Optimizer Op to optimize `W`. - -## TODO - -- Improve the optimizer stage with multi-threads, since we could - assign the parameters to the different threads and execute - optimizer with multi-threads. diff --git a/develop/doc_cn/_sources/design/dist_refactor/parameter_server.md.txt b/develop/doc_cn/_sources/design/dist_refactor/parameter_server.md.txt deleted file mode 100644 index 805dd13048d..00000000000 --- a/develop/doc_cn/_sources/design/dist_refactor/parameter_server.md.txt +++ /dev/null @@ -1,96 +0,0 @@ -# Design Doc: Parameter Server - -## Abstract - -We propose an approach to implement the parameter server. In this -approach, there is no fundamental difference between the trainer and -the parameter server: they both run subgraphs, but subgraphs of -different purposes. - -## Background - -The previous implementations of the parameter server do not run a -fluid sub-program. Parameter initialization, optimizer computation, network -communication and checkpointing are implemented twice on both the -trainer as well as the parameter server. - -It would be great if we can write code once and use them on both: the -trainer and the parameter server, since this reduces code duplication and -improves extensibility. Given that after the current refactoring, we are -representing everything as a computation graph on the -trainer. Representing everything as a computation graph on the parameter -server becomes a natural extension. - -## Design - -### Distributed Transpiler - -The *Distributed Transpiler* converts the user-defined fluid program -into sub-programs to be scheduled on different nodes with the following -steps: - -1. OP placement: the OPs will be placed on different nodes according - to a heuristic that minimizes the estimated total computation - time. Currently we will use a simple heuristic that puts parameter - variable on parameter server workers and everything else on trainer - workers. -1. Add communication OPs to enable the communication between nodes. - -We will need these OPs: *Send*, *Recv*, *Enqueue*, *Dequeue*. - -Below is an example of converting the user defined graph to the -subgraphs for the trainer and the parameter server: - - - -After converting: - - - -1. The parameter variable W and its optimizer program are placed on the parameter server. -1. Operators are added to the program. - - *Send* sends data to the connected *Recv* operator. The - scheduler on the receive node will only schedule *Recv* operator - to run when the *Send* operator has ran (the *Send* OP will mark - the *Recv* OP runnable automatically). - - *Enqueue* enqueues the input variable, it can block until space - become available in the queue. - - *Dequeue* outputs configurable numbers of tensors from the - queue. It will block until the queue has the required number of - tensors. - - -### Benefits - -- Model parallelism becomes easier to implement: it is an extension to - the trainer - parameter server approach. We can have several "Transpilers" - to achieve different goals. -- User-defined optimizer is easier to add - user can now express it as - a sub-program. -- No more duplication logic inside the trainer and the parameter - server mentioned in the background section. - -### Challenges - -- It is important to balance the parameter shards on multiple - parameter servers. If a single parameter is very big (for example: some - word-embedding, fully connected, softmax layer), we need to - automatically partition the single parameter onto different - parameter servers when possible (only element-wise optimizer depends - on the parameter variable). -- In the "Async SGD" figure, the "W" variable on the parameter server - could be read and written concurrently. See - [here](https://github.com/PaddlePaddle/Paddle/pull/6394) for more - details about concurrent program in Fluid. - -### Discussion - -- Can the Enqueue OP be implemented under our current tensor design - (put the input tensor into the queue tensor)? -- *Dequeue* OP will have variable numbers of output (depending on the - `min_count` attribute), does our current design support it? (similar - question for the *Add* OP) - - -### References: -[1] [TensorFlow: Large-Scale Machine Learning on Heterogeneous Distributed Systems](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45166.pdf) diff --git a/develop/doc_cn/_sources/design/error_clip.md.txt b/develop/doc_cn/_sources/design/error_clip.md.txt deleted file mode 100644 index 58aa73b8cd3..00000000000 --- a/develop/doc_cn/_sources/design/error_clip.md.txt +++ /dev/null @@ -1,92 +0,0 @@ -# Error Clip - -## Overview - -Error clip is widely used in model training to prevent gradient exploding. It takes some specific rules to adjust variables' gradients and prevent them from being too large. With it, values of a gradient will be checked before they are taken by the next `grad_op` and be shrunk if necessary. -## Usage - -Users are allowed to assign different error clip methods or attributes to different `Variable`s. Users can specify it as a parameter of `Variable`'s constructor: - -```python -var = framework.Variable(..., error_clip=myErrorClip, ...) -``` - -The default value of `error_clip` is `None`, which means no error clip is employed. When it's not `None`, it should take an object of `BaseErrorClipAttr`'s derived class. So far, `BaseErrorClipAttr` has only one derived class: `ErrorClipByValue`, whose constructor is: - -```python -ErrorClipByValue(max, min=None) -``` - -`max` and `min` represent the maximal and minimal clip threshold respectively. In backward pass, all values of `var`'s gradient greater than `max` or less than `min` will be clipped to `max` and `min` respectively. When the `min` is None, the minimal threshold will be assigned with `-max` automatically. - -So we can enable the error clip with threshold `[-5.0, 5.0]` for variable `var` by: - -```python -var = framework.Variable(..., error_clip=ErrorClipByValue(max=5.0), ...) -``` - -## Implementation - -The `BaseErrorClipAttr` and its derived class `ErrorClipByValue` are defined in *clip.py*. - -```python -class BaseErrorClipAttr(object): - def append_clip_op(self, block, grad_name): - raise NotImplementedError() - - -class ErrorClipByValue(BaseErrorClipAttr): - def __init__(self, max, min=None): - max = float(max) - if min is None: - min = -max - else: - min = float(min) - self.max = max - self.min = min - - def append_clip_op(self, block, grad_name): - clip_op_desc = block.desc.append_op() - clip_op_desc.set_type("clip") - clip_op_desc.set_input("X", [grad_name]) - clip_op_desc.set_output("Out", [grad_name]) - clip_op_desc.set_attr("min", self.min) - clip_op_desc.set_attr("max", self.max) -``` - -The `BaseErrorClipAttr` have one main member functions: `append_clip_op(self, block, grad_name)`. - -This function is used to create a `clip_op` and append it to the end of given `block`. For different error clip algorithm require different `clip_op`, the function is defined as virtual in the base class. All derived classes must implement their own versions of this function. - -These `clip_op`s should be inserted after `grad_op`s whose output gradients need to be clipped. It is equivalent to appending some `clip_op`s to the end of the target block every time a new `grad_op` is added. - -```python -for op_desc in grad_op_descs: - new_op_desc = target_block.desc.append_op() - new_op_desc.copy_from(op_desc) - callback(block=target_block, context=grad_to_var) -``` - -Here we employ a callback function to complete this kind of jobs. In `_append_backward_ops_` function, each time after a `grad_op` is added to the `target_block`, a callback function is invoked. The logic of `clip_op` appending can be implemented inside the callback function. - -The callback function for `clip_op` appending is defined in *clip.py*: - -```python -def error_clip_callback(block, context): - # the context is a grad_to_var map - grad_to_var = context - op_desc = block.desc.op(block.desc.op_size() - 1) - for grad_n in filter(lambda n: grad_to_var.has_key(n), - op_desc.output_arg_names()): - fwd_var = block.var_recursive(grad_to_var[grad_n]) - error_clip = getattr(fwd_var, "error_clip", None) - if not (error_clip is None or isinstance(error_clip, - BaseErrorClipAttr)): - raise TypeError( - "Variable's error_clip should be an instance of BaseErrorClipAttr or None." - ) - if error_clip is not None: - error_clip.append_clip_op(block, grad_n) -``` - -This function takes a `block` and a `context`(which is actually a grad\_to\_var map) as inputs. It checks each output of the last `OpDesc` in the `block`. Notice that the last `OpDesc` of the `block` must be a `grad_op` and its outputs must be some forward variables' gradients. If an output gradient's corresponding forward variable has an attribute of `error_clip`, `error_clip_callback` will call the `error_clip`'s `append_clip_op` function to append the required `clip_op` into the `block`. diff --git a/develop/doc_cn/_sources/design/evaluator.md.txt b/develop/doc_cn/_sources/design/evaluator.md.txt deleted file mode 100644 index 11cc129d569..00000000000 --- a/develop/doc_cn/_sources/design/evaluator.md.txt +++ /dev/null @@ -1,58 +0,0 @@ -## Evaluator Design - -### Problem Statement - -During training or inference, we provide an evaluation function to measure the model performance, for example, accuracy, precision, etc. In the operator based framework design, the data passes through the network pipeline batch by batch. As a result, inside the operator, we only calculate the metrics for one minibatch. Thus, we need to provide a mechanism to calculate the metrics for each N pass/batch the user wants. - -### Evaluator Design -Currently, every operation is expressed in the graph. We divide the evaluator process into three steps. - -1. Initialize the metric state and add it into the block. - -2. Calculate the concerned metrics for every mini-batch. The single evaluator operator is only responsible for calculating the necessary statistics for one mini-batch. For example, the accuracy operator only calculates the accuracy for a minibatch data if run once. - - -3. Merge the mini-batch statistics to form the evaluation result for multiple mini-batches. When it comes to distributed training/Multi-GPU training, aggregate the value from different devices. - -### Implementation -This design is shown in the Python API. -Each metric operator needs to caculate the metric statistic and return the batch-aware states. Python side is responsible for accumulating the states for each pass. - - -```python -class Evaluator(object): - """ - Evaluator Base class. - """ - def __init__(self, name, **kwargs): - """ - Different evaluator may has different metric states. E.g, Accuracy need two variables, total and right sample counts. - Auc need four variables, `true_positives`, - `true_negatives`, `false_positives` and `false_negatives`. So every evaluator should create its needed variables and append to main_program - - The initialization of Evaluator should be responsible for: - create metric states and append to the main_program - """ - pass - - def _update_ops(self, input, label, **kwargs) - """ - Add mini-batch evaluator caculate operators to the main_program. - Add increment operator to accumulate the metric states. - """ - - - def reset(self, executor, reset_program=None): - """ - Reset metric states at the begin of each pass/user specified batch number. - Execute the reset_program to reset the states. - """ - - - def eval(self, executor, eval_program=None): - """ - Merge the mini-batch statistics to form the evaluation result for multiple mini-batches. - Execute the eval_program and return the result. - """ - return eval_result -``` diff --git a/develop/doc_cn/_sources/design/executor.md.txt b/develop/doc_cn/_sources/design/executor.md.txt deleted file mode 100644 index 2d4b371cc56..00000000000 --- a/develop/doc_cn/_sources/design/executor.md.txt +++ /dev/null @@ -1,29 +0,0 @@ -# Executor Design Doc - -## Motivation -In [fluid](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/fluid.md), we encourage the user to use deep learning programming paradigms to describe the training process. When the user-written Python program is executed, it will first create a protobuf message -[`ProgramDesc`](https://github.com/PaddlePaddle/Paddle/blob/a91efdde6910ce92a78e3aa7157412c4c88d9ee8/paddle/framework/framework.proto#L145) that describes the process and is conceptually like an [abstract syntax tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree). - -The executor runs the `ProgramDesc` like an interpreter. `ProgramDesc` contains the intrinsics (operators in this case) and variables which will be used, executor explicitly executes the stored precompiled code. - -## Overview - -An executor takes a `ProgramDesc`, a `block_id` and a `Scope`. The `ProgramDesc` is a list of blocks and each block contains the protobuf definition of all the parameters and operators in the block. The `block_id` specifies the entrance block. And the `Scope` is the container of all the variable instances, which is persistent throughout different runs. - -## Executor - -The `Executor` explicitly executes all the intrinsics (operators here) in the `block_id`th block of a `ProgramDesc`. Essentially, it instantiates Variables and Operators, then runs all the operators in sequence one-by-one. -It is very similar to how a push stack frame works when entering a block, following which it cleans up all the temporary variables when a mini-batch is finished. It does not however, have the stack frame pop process. - -### The interface -```c++ - Executor(places); -``` -A executor does not own any computing resources, a user can only construct an executor using the specified places. - -### Running an Executor - -``` - void Run(ProgramDesc, Scope, block_id, create_local_scope); -``` -An `Executor` only provides a unified way to execute `ProgramDesc`. `ProgramDesc` is the target that will be executed, the `Scope` specifies the variable container, the `block_id` indicates the entrance block and `create_local_scope` is a boolean that states whether it will destroy the temporary variables after the execution is finished. diff --git a/develop/doc_cn/_sources/design/file_manager/README.md.txt b/develop/doc_cn/_sources/design/file_manager/README.md.txt deleted file mode 100644 index 3df10d801e5..00000000000 --- a/develop/doc_cn/_sources/design/file_manager/README.md.txt +++ /dev/null @@ -1,87 +0,0 @@ -# FileManager设计文档 -## 目标 -在本文档中,我们设计说明了名为FileManager系统,方便用户上传自己的训练数据以进行分布式训练 - -主要功能包括: - -- 提供常用的命令行管理命令管理文件和目录 -- 支持大文件的断点上传、下载 - -## 名词解释 -- PFS:是`Paddlepaddle cloud File System`的缩写,是对用户文件存储空间的抽象,与之相对的是local filesystem。目前我们用CephFS来搭建。 -- [CephFS](http://docs.ceph.com/docs/master/cephfs/):一个POSIX兼容的文件系统。 -- Chunk:逻辑划上文件分块的单位。 - -## 模块 -### 架构图 - - -### PFSClient -- 功能: 详细设计[link](./pfs/pfsclient.md) - - 提供用户管理文件的命令 - - 需要可以跨平台执行 - -- 双向验证 - PFSClient需要和Ingress之间做双向验证[tls](#tls),所以用户需要首先在`cloud.paddlepaddle.org`上注册一下,申请用户空间,并且把系统生成的CA(certificate authority)、Key、CRT(CA signed certificate)下载到本地,然后才能使用PFSClient。 - -### [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) -- 功能: - 提供七层协议的反向代理、基于粘性会话的负载均衡功能。 - -- 透传用户身份的办法 - Ingress需要把PFSClient的身份信息传给PFSServer,配置的方法参考[link](http://www.integralist.co.uk/posts/clientcertauth.html#3) - -### PFSServer -PFSServer提供RESTful API接口,接收处理PFSClient端的文件管理请求,并且把结果返回PFSClient端。 - -RESTful API - -- /api/v1/files - - `GET /api/v1/files`: Get metadata of files or directories. - - `POST /api/v1/files`: Create files or directories. - - `PATCH /api/v1/files`: Update files or directories. - - `DELETE /api/v1/files`: Delete files or directories. - -- /api/v1/file/chunks - - `GET /api/v1/storage/file/chunks`: Get chunks's metadata of a file. - -- /api/v1/storage/files - - `GET /api/v1/storage/files`: Download files or directories. - - `POST /api/v1/storage/files`: Upload files or directories. - -- /api/v1/storage/file/chunks - - `GET /api/v1/storage/file/chunks`: Download chunks's data. - - `POST /api/v1/storage/file/chunks`: Upload chunks's data. - -## 文件传输优化 - -### 分块文件传输 -用户文件可能是比较大的,上传到Cloud或者下载到本地的时间可能比较长,而且在传输的过程中也可能出现网络不稳定的情况。为了应对以上的问题,我们提出了Chunk的概念,一个Chunk由所在的文件偏移、数据、数据长度及校验值组成。文件的上传和下载都是通过对Chunk的操作来实现的。由于Chunk比较小(默认256K),完成一个传输动作完成的时间也比较短,不容易出错。PFSClient需要在传输完毕最后一个Chunk的时候检查destination文件的MD5值是否和source文件一致。 - -一个典型的Chunk如下所示: - -``` -type Chunk struct { - fileOffset int64 - checksum uint32 - len uint32 - data []byte -} -``` - -### 生成sparse文件 -当destination文件不存在或者大小和source文件不一致时,可以用[Fallocate](https://Go.org/pkg/syscall/#Fallocate)生成sparse文件,然后就可以并发写入多个Chunk。 - -### 覆盖不一致的部分 -文件传输的的关键在于需要PFSClient端对比source和destination的文件Chunks的checksum是否保持一致,不一致的由PFSClient下载或者传输Chunk完成。这样已经传输成功的部分就不用重新传输了。 - -## 用户使用流程 -参考[link](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/cluster_train/data_dispatch.md) - -## 框架生成 -用[swagger](https://github.com/swagger-api/swagger-codegen)生成PFSClient和PFSServer的框架部分,以便我们可以把更多的精力放到逻辑本身上。 - -## 参考文档 --
                                [TLS complete guide](https://github.com/k8sp/tls/blob/master/tls.md) -- [aws.s3](http://docs.aws.amazon.com/cli/latest/reference/s3/) -- [linux man document](https://linux.die.net/man/) diff --git a/develop/doc_cn/_sources/design/file_manager/pfs/pfsclient.md.txt b/develop/doc_cn/_sources/design/file_manager/pfs/pfsclient.md.txt deleted file mode 100644 index 56bc70c54bb..00000000000 --- a/develop/doc_cn/_sources/design/file_manager/pfs/pfsclient.md.txt +++ /dev/null @@ -1,129 +0,0 @@ -# PFSClient - -## Description -The `pfs` command is a Command Line Interface to manage your files on PaddlePaddle Cloud - -## Synopsis -``` -paddle [options] pfs [parameters] -``` - -## Options -``` ---profile (string) - Use a specific profile from your credential file. - ---help (string) - Display more information about command - ---version - Output version information and exit - ---debug - Show detailed debugging log - ---only-show-errors (boolean) - Only errors and warnings are displayed. All other output is suppressed. -``` - -## Path Arguments -When using a command, we need to specify path arguments. There are two path argument type: `localpath` and `pfspath`. - -A `pfspath` begin with `/pfs`, eg: `/pfs/$DATACENTER/home/$USER/folder`. - -[Here](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/cluster_train/data_dispatch.md#上传训练文件) is how to config datacenters. - -## order of Path Arguments -Commonly, if there are two path arguments, the first is the source, and the second is the destination. - -## Subcommonds -- rm - remove files or directories - -``` -Synopsis: - rm [-r] [-v] ... - -Options: - -r - Remove directories and their contents recursively - -v - Cause rm to be verbose, showing files after they are removed. - -Examples: - paddle pfs rm /pfs/$DATACENTER/home/$USER/file - paddle pfs rm -r /pfs/$DATACENTER/home/$USER/folder -``` -- mv - move (rename) files - -``` -Synopsis: - mv [-f | -n] [-v] - mv [-f | -n] [-v] ... - mv [-f | -n] [-v] - mv [-f | -n] [-v] ... - mv [-f | -n] [-v] - mv [-f | -n] [-v] ... - -Options: - -f - Do not prompt for confirmation before overwriting the destination path. (The -f option overrides previous -n options.) - -n - Do not overwrite an existing file. (The -n option overrides previous -f options.) - -v - Cause mv to be verbose, showing files after they are moved. - -Examples: - paddle pfs mv ./text1.txt /pfs/$DATACENTER/home/$USER/text1.txt -``` -- cp - copy files or directories - -``` -Synopsis: - cp [-r] [-f | -n] [-v] [--preserve--links] - cp [-r] [-f | -n] [-v] [--preserve--links] ... - cp [-r] [-f | -n] [-v] [--preserve--links] - cp [-r] [-f | -n] [-v] [--preserve--links] ... - cp [-r] [-f | -n] [-v] [--preserve--links] - cp [-r] [-f | -n] [-v] [--preserve--links] ... - -Options: - -r - Copy directories recursively - -f - Do not prompt for confirmation before overwriting the destination path. (The -f option overrides previous -n options.) - -n - Do not overwrite an existing file. (The -n option overrides previous -f options.) - -v - Cause cp to be verbose, showing files after they are copied. - --preserve--links - Reserve links when copy links - -Examples: - paddle pfs cp ./file /pfs/$DATACENTER/home/$USER/file - paddle pfs cp /pfs/$DATACENTER/home/$USER/file ./file -``` -- ls- list files - -``` -Synopsis: - ls [-r] ... - -Options: - -R - List directory(ies) recursively - -Examples: - paddle pfs ls /pfs/$DATACENTER/home/$USER/file - paddle pfs ls /pfs/$DATACENTER/home/$USER/folder -``` - -- mkdir - mkdir directory(ies) -Create intermediate directory(ies) as required. - -``` -Synopsis: - mkdir ... - -Examples: - paddle pfs mkdir /pfs/$DATACENTER/home/$USER/folder -``` diff --git a/develop/doc_cn/_sources/design/float16.md.txt b/develop/doc_cn/_sources/design/float16.md.txt deleted file mode 100644 index 1ea95ed6b5d..00000000000 --- a/develop/doc_cn/_sources/design/float16.md.txt +++ /dev/null @@ -1,105 +0,0 @@ -# Design Doc: float16 - -## Why float16 -Half precision (float16) is a binary floating-point format that occupies 16 bits in memory. float16 is half the size of traditional 32-bit single precision format (float) and has lower precision and smaller range. - -When high precision computation is not required, using float16 data type could potentially - -- reduce storage space, memory bandwidth, and power usages; -- increase the chance of data fitting into a smaller cache of lower latency; -- provide arithmetic speed up if supported by hardware. - -## Survey of current float16 support -A brief survey of float16 support on different compilers, hardwares, and libraries can be found below. Interested readers can refer to [link1](https://github.com/PaddlePaddle/Paddle/issues/4853) and [link2](https://github.com/Xreki/Xreki.github.io/blob/master/multi_data_types_in_dl_framework/ppt/float16_and_quantized_type.md) for more info. - -The goal of float16 is to serve as a key for the executor to find and run the correct version of compute method specialized for float16 in operator kernel. It should be compatible with various natively supported float16 implementations including `__half` for cuda, `float16_t` for ARM, and `Eigen::half` for Eigen to make writing customized float16 kernels easier. - -### Compiler -- nvcc supports `__half` data type after CUDA 7.5. -- `__fp16` or `float16_t` is supported as storage type for gcc >= 6.1 and clang >= 3.4. -- `__fp16` or `float16_t` is supported as arithmetic type for gcc >= 7.1 and clang >= 3.9. - -### Hardware -- `__half` is supported on GPU with compute capability >= 5.3. -- `__fp16` is supported as storage type for ARMv7-A, ARMv8-A, and above. -- `__fp16` is supported as arithmetic type after ARMv8.2-A (currently, the only microarchitecture implementing ARMv8.2-A is ARM Cortex-A75, which is announced in May 2017. There seems to be no application processors currently available on market that adopts this architecture. It is reported that Qualcomm Snapdragon 845 uses Cortex-A75 design and will be available in mobile devices in early 2018). - -### Libraries -- [Eigen](https://github.com/RLovelett/eigen) >= 3.3 supports float16 calculation on both GPU and CPU using the `Eigen::half` class. It is mostly useful for Nvidia GPUs because of the overloaded arithmetic operators using cuda intrinsics. It falls back to using software emulation on CPU for calculation and there is no special treatment to ARM processors. -- [ARM compute library](https://github.com/ARM-software/ComputeLibrary) >= 17.02.01 supports NEON FP16 kernels (requires ARMv8.2-A CPU). - -### CUDA version issue -There are currently three versions of CUDA that supports `__half` data type, namely, CUDA 7.5, 8.0, and 9.0. -CUDA 7.5 and 8.0 define `__half` as a simple struct that has a `uint16_t` data (see [`cuda_fp16.h`](https://github.com/ptillet/isaac/blob/9212ab5a3ddbe48f30ef373f9c1fb546804c7a8c/include/isaac/external/CUDA/cuda_fp16.h)) as follows: -``` -typedef struct __align__(2) { - unsigned short x; -} __half; - -typedef __half half; -``` -This struct does not define any overloaded arithmetic operators. So you have to directly use `__hadd` instead of `+` to correctly add two half types: -``` -__global__ void Add() { - half a, b, c; - c = __hadd(a, b); // correct - c = a + b; // compiler error: no operator "+" matches these operands -} -``` -CUDA 9.0 provides a major update to the half data type. The related code can be found in the updated [`cuda_fp16.h`](https://github.com/ptillet/isaac/blob/master/include/isaac/external/CUDA/cuda_fp16.h) and the newly added [`cuda_fp16.hpp`](https://github.com/ptillet/isaac/blob/master/include/isaac/external/CUDA/cuda_fp16.hpp). - -Essentially, CUDA 9.0 renames the original `__half` type in 7.5 and 8.0 as `__half_raw`, and defines a new `__half` class type that has constructors, conversion operators, and also provides overloaded arithmetic operators such as follows: -``` -typedef struct __CUDA_ALIGN__(2) { - unsigned short x; -} __half_raw; - - -struct __CUDA_ALIGN__(2) __half { -protected: - unsigned short __x; -public: - // constructors and conversion operators from/to - // __half_raw and other built-in data types -} - -typedef __half half; - -__device__ __forceinline__ -__half operator+(const __half &lh, const __half &rh) { - return __hadd(lh, rh); -} - -// Other overloaded operators -``` -This new design makes `c = a + b` work correctly for CUDA half data type. - -## Implementation -The float16 class holds a 16-bit `uint16_t` data internally. -``` -struct float16 { - uint16_t x; -}; -``` - -float16 supports the following features: - - constructors / assignment operators that take input from primitive data types including bool, integers of various length, float, and double. - - constructors / assignment operators that take input from `__half` on cuda, `float16_t` on ARM, and `Eigen::half` on Eigen. - - conversion operators to primitive data types and half precision data types on cuda, ARM and Eigen. - - overloaded arithmetic operators for cuda, arm, and non-arm cpu, respectively. These operators will take advantage of the cuda and ARM intrinsics on the corresponding hardware. - -To support the above features, two fundamental conversion functions are provided: -``` -float16 float_to_half_rn(float f); // convert to half precision in round-to-nearest-even mode -float half_to_float(float16 h); -``` -which provides one-to-one conversion between float32 and float16. These twos functions will do different conversion routines based on the current hardware. CUDA/ARM instrinsics will be used when the corresonding hardware is available. If the hardware or compiler level does not support float32 to float16 conversion, software emulation will be performed to do the conversion. - -## To do -After float16 class is available, some of the future items are below: - -- Update pybind/tensor_py.h to bind c++ float16 with numpy float16. - -- Modify `GetKernelType()` method in `framework/operator.h` to make it compatible with float16. - -- Create a type-casting operator that can convert the data type in tensor between float16 and other types. diff --git a/develop/doc_cn/_sources/design/fluid.md.txt b/develop/doc_cn/_sources/design/fluid.md.txt deleted file mode 100644 index f78fa8c1914..00000000000 --- a/develop/doc_cn/_sources/design/fluid.md.txt +++ /dev/null @@ -1,114 +0,0 @@ -# Design Doc: PaddlePaddle Fluid - -## Why Fluid - -When Baidu developed PaddlePaddle in 2013, the only well-known open source deep learning system at the time was Caffe. However, when PaddlePaddle was open-sourced in 2016, many other choices were available. There was a challenge -- what is the need for open sourcing yet another deep learning framework? - -Fluid is the answer. Fluid is similar to PyTorch and TensorFlow Eager Execution, which describes the "process" of training or inference using the concept of a model. In fact in PyTorch, TensorFlow Eager Execution and Fluid, there is no concept of a model at all. The details are covered in the sections below. Fluid is currently more extreme in the above mentioned idea than PyTorch and Eager Execution, and we are trying to push Fluid towards the directions of a compiler and a new programming language for deep learning. - -## The Evolution of Deep Learning Systems - -Deep learning infrastructure is one of the fastest evolving technologies. Within four years, there have already been three generations of technologies invented. - -| Existed since | model as sequence of layers | model as graph of operators | No model | -|--|--|--|--| -| 2013 | Caffe, Theano, Torch, PaddlePaddle | | | -| 2015 | | TensorFlow, MxNet, Caffe2, ONNX, n-graph | | -| 2016 | | | PyTorch, TensorFlow Eager Execution, PaddlePaddle Fluid | - -From the above table, we see that the deep learning technology is evolving towards getting rid of the concept of a model. To understand the reasons behind this direction, a comparison of the *programming paradigms* or the ways to program deep learning applications using these systems, would be helpful. The following section goes over these. - -## Deep Learning Programming Paradigms - -With the systems listed as the first or second generation, e.g., Caffe or TensorFlow, an AI application training program looks like the following: - -```python -x = layer.data("image") -l = layer.data("label") -f = layer.fc(x, W) -s = layer.softmax(f) -c = layer.mse(l, s) - -for i in xrange(1000): # train for 1000 iterations - m = read_minibatch() - forward({input=x, data=m}, minimize=c) - backward(...) - -print W # print the trained model parameters. -``` - -The above program includes two parts: - -1. The first part describes the model, and -2. The second part describes the training process (or inference process) for the model. - -This paradigm has a well-known problem that limits the productivity of programmers. If the programmer made a mistake in configuring the model, the error messages wouldn't show up until the second part is executed and `forward` and `backward` propagations are performed. This makes it difficult for the programmer to debug and locate a mistake that is located blocks away from the actual error prompt. - -This problem of being hard to debug and re-iterate fast on a program is the primary reason that programmers, in general, prefer PyTorch over the older systems. Using PyTorch, we would write the above program as following: - -```python -W = tensor(...) - -for i in xrange(1000): # train for 1000 iterations - m = read_minibatch() - x = m["image"] - l = m["label"] - f = layer.fc(x, W) - s = layer.softmax(f) - c = layer.mse(l, s) - backward() - -print W # print the trained model parameters. -``` - -We can see that the main difference is the moving the model configuration part (the first step) into the training loop. This change would allow the mistakes in model configuration to be reported where they actually appear in the programming block. This change also represents the model better, or its forward pass, by keeping the configuration process in the training loop. - -## Describe Arbitrary Models for the Future - -Describing the process instead of the model also brings Fluid, the flexibility to define different non-standard models that haven't been invented yet. - -As we write out the program for the process, we can write an RNN as a loop, instead of an RNN as a layer or as an operator. A PyTorch example would look like the following: - -```python -for i in xrange(1000): - m = read_minibatch() - x = m["sentence"] - for t in xrange x.len(): - h[t] = the_step(x[t]) -``` - -With Fluid, the training loop and the RNN in the above program are not really Python loops, but just a "loop structure" provided by Fluid and implemented in C++ as the following: - -```python -train_loop = layers.While(cond) -with train_loop.block(): - m = read_minibatch() - x = m["sentence"] - rnn = layers.While(...) - with rnn.block(): - h[t] = the_step(input[t]) -``` - -An actual Fluid example is described [here](https://github.com/PaddlePaddle/Paddle/blob/bde090a97564b9c61a6aaa38b72ccc4889d102d9/python/paddle/fluid/tests/unittests/test_while_op.py#L50-L58). - -From the example, the Fluid programs look very similar to their PyTorch equivalent programs, except that Fluid's loop structure, wrapped with Python's `with` statement, could run much faster than just a Python loop. - -We have more examples of the [`if-then-else`](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/if_else_op.md) structure of Fluid. - -## Turing Completeness - -In computability theory, a system of data-manipulation rules, such as a programming language, is said to be Turing complete if it can be used to simulate any Turing machine. For a programming language, if it provides if-then-else and loop, it is Turing complete. From the above examples, Fluid seems to be Turing complete; however, it is noteworthy to notice that there is a slight difference between the `if-then-else` of Fluid and that of a programming language. The difference being that the former runs both of its branches and splits the input mini-batch into two -- one for the True condition and another for the False condition. This hasn't been researched in depth if this is equivalent to the `if-then-else` in programming languages that makes them Turing-complete. Based on a conversation with [Yuang Yu](https://research.google.com/pubs/104812.html), it seems to be the case but this needs to be looked into in-depth. - -## The Execution of a Fluid Program - -There are two ways to execute a Fluid program. When a program is executed, it creates a protobuf message [`ProgramDesc`](https://github.com/PaddlePaddle/Paddle/blob/a91efdde6910ce92a78e3aa7157412c4c88d9ee8/paddle/framework/framework.proto#L145) that describes the process and is conceptually like an [abstract syntax tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree). - -There is a C++ class [`Executor`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/executor.h), which runs a `ProgramDesc`, similar to how an interpreter runs a Python program. - -Fluid is moving towards the direction of a compiler, which is explain in [fluid_compiler.md](fluid_compiler.md). - -## Backward Compatibility of Fluid - -Given all the advantages from the removal of the concept of a *model*, hardware manufacturers might still prefer the existence of the concept of a model, so it would be easier for them to support multiple frameworks all at once and could run a trained model during inference. For example, Nervana, a startup company acquired by Intel, has been working on an XPU that reads the models in the format known as [n-graph](https://github.com/NervanaSystems/ngraph). Similarly, [Movidius](https://www.movidius.com/) is producing a mobile deep learning chip that reads and runs graphs of operators. The well-known [ONNX](https://github.com/onnx/onnx) is also a file format of graphs of operators. - -For Fluid, we can write a converter that extracts the parts in the `ProgramDesc` protobuf message, converts them into a graph of operators, and exports the graph into the ONNX or n-graph format. diff --git a/develop/doc_cn/_sources/design/fluid_compiler.md.txt b/develop/doc_cn/_sources/design/fluid_compiler.md.txt deleted file mode 100644 index 2a6beafc52e..00000000000 --- a/develop/doc_cn/_sources/design/fluid_compiler.md.txt +++ /dev/null @@ -1,110 +0,0 @@ -# PaddlePaddle Fluid: Towards a Compiled Programming Language - -As described in [fluid.md](fluid.md), when a Fluid application program -runs, it generates a `ProgramDesc` protobuf message as an intermediate -representation of itself. The C++ class `Executor` can run this -protobuf message as an interpreter. This article describes the Fluid -compiler. - -![](fluid-compiler.png) - -## ProgramDesc - -Before we go deeper into the idea of compiled language, let us take a -look at a simple example Fluid application. - -```python -import "fluid" - -func paddlepaddle() { - X = fluid.read(...) - W = fluid.Tensor(...) - Y = fluid.mult(X, W) -} -``` - -This program consists of a [block](block.md) of three operators -- -`read`, `assign`, and `mult`. Its `ProgramDesc` message looks like -the following - -```protobuf -message ProgramDesc { - block[0] = Block { - vars = [X, W, Y], - ops = [ - read(output = X) - assign(input = ..., output = W) - mult(input = {X, W}, output = Y) - ], - } -} -``` - -## Transpilers - -We can write a transpiler program that takes a `ProgramDesc`, e.g., -the above one, and outputs another `ProgramDesc`. Let us take some -examples: - -1. *Memory optimization transpiler*: We can write a transpiler that - inserts some `FreeMemoryOp`s in the above example `ProgramDesc` so - to free memory early, before the end of an iteration, so to keep a - small memory footprint. - -1. *Distributed training transpiler*: We can write a transpiler that - converts a`ProgramDesc` into its distributed version of two - `ProgramDesc`s -- one for running by the trainer processes and the - other for the parameter server. - -In the rest of this article, we talk about a special kind of -transpiler, *Native code generator*, which takes a `ProgramDesc` and -generates a `.cu` (or `.cc`) file, which could be built by C++ -compilers (gcc, nvcc, icc) into binaries. - -## Native Code Generator - -For the above example, the native code generator transpiler, say, the -CUDA code generator, should generate a `main` function: - -```c++ -void main() { - auto X = fluid_cuda_read(...); - auto W = fluid_cuda_create_tensor(...); - auto Y = fluid_cuda_mult(X, W); -} -``` - -and the definitions of functions `fluid_cuda_read`, -`fluid_cuda_create_tensor`, and `fluid_cuda_mult`. Please be aware -that each function could just define a C++ instance of an operator and -run it. For example - -```c++ -paddle::Tensor fluid_cuda_read(...) { - paddle::Tensor t; - paddle::operator::Read r(&t, ...); - r.Run(); - return t; -} -``` - -For computational operators that have multiple *kernels*, each for a -specific hardware platform, for example, the `mult` operator, the -generated code should call its CUDA kernel: - -```c++ -paddle::Tensor fluid_cuda_mult(const paddle::Tensor& a, - const paddle::Tensor& b) { - paddle::Tensor t; - paddle::operator::Mult m(a, b, ...); - Mult.Run(cuda_context); -} -``` - -where `cuda_context` could be a global variable of type -`paddle::CUDADeviceContext`. - -## Multi-Block Code Generation - -Most Fluid application programs may have more than one blocks. To -execute them, we need to trace [scopes](scope.md). diff --git a/develop/doc_cn/_sources/design/functions_operators_layers.md.txt b/develop/doc_cn/_sources/design/functions_operators_layers.md.txt deleted file mode 100644 index 984b59f4c69..00000000000 --- a/develop/doc_cn/_sources/design/functions_operators_layers.md.txt +++ /dev/null @@ -1,100 +0,0 @@ -# Design Doc: Functions, Operators, and Layers - -In a DL system, we can compose one or more fine grained operators into a coarse grained one. For example, the FC layer can be composed of a multiplication operator and an add operator. - -Historically, some fine grained operations are known as operators, and some coarse level ones are known as layers. But we need a well-defined separation. - -In general, operators are those very fine grained operations, e.g., mul and add. In the implementation, we can write them as C++ functions: - -```c++ -template T add(T x, T y) { return x + y; } -template T mul(T x, T y) { return x * y; } -``` - -Then we can wrap them into operators which are C++ classes and can be created from Python bindings by name. A C macro can do this. For example, the following macro invocation - -```c++ -#define MAKE_FUNCTION_OPERATOR(mul); -``` - -generates - -```c++ -template class mulOp : public OperatorBase {...}; -REGISTER_OP(mulOp, "mul"); -``` - -so that in Python we can create operator mul by: - -```python -X1 = Var() -X2 = Var() -Y = Var() -paddle.cpp.create_operator("mul", input=[X1, X2], output=Y) -``` - -Also, at the same time, we can compose a coarse level C++ operator class by composing functions `mul` and `add`: - -```c++ -template -class FCOp : public OperatorBase { - public: - void Run(...) { - add(mul(Input("X"), Input("W")), Input("b"); - } -}; -REGISTER_OP(FCOp, "fc"); -``` - -We need to support such composition in Python as well. To do so, we need a higher level Python wrapping of operator creation than `paddle.cpp.create_operator`. This higher level operator API should be compatible with the layer API. - -Let's explain using an example. Suppose that we are going to compose the FC using mul and add in Python, we'd like to have Python functions `mul` and `add` defined in module `operator`: - -```python -def operator.mul(X1, X2): - O = Var() - paddle.cpp.create_operator("mul", input={X1, Y1}, output=O) - return O - -def operator.add(X1, X2): - O = Var() - paddle.cpp.create_operator("add", input={X1, X2}, output=O) - return O -``` - -Above code snippets are automatically generated. Given them, users can define - -```python -def layer.fc(X): - W = Var() - b = Var() - return operator.add(operator.mul(X, W), b) -``` - -If we don't have `operator.mul` and `operator.add`, the definiton of `layer.fc` would be complicated: - -```python -def layer.fc(X): - W = Var() - b = Var() - O1 = Var() - paddle.cpp.create_operator("mul", input=[X, W], output=O1) - O2 = Var() - paddle.cpp.create_operator("add", input=[O1, b], output=O2) - return O2 -``` - -We'd like to have Python bindings to operators in package `paddle.operator`, and Python compositions of operators in package `paddle.layer`. So we have the following concepts in above illustrative example: - - -| C++ functions/functors | mul | add | | | -|------------------------|--------------|--------------|-------------|----------| -| C++ operator class | mulOp | addOp | FCOp | | -| Python binding | operator.mul | operator.add | operator.fc | | -| Python function | | | | layer.fc | - - -This is how we differentiate layer and operators in PaddlePaddle: - -- those defined in C++ and have a lightweighted Python wrapper in module `operators` are operators; whereas -- those who don't have C++ implementations but a Python implementation that compose C++ operators are known as layers. diff --git a/develop/doc_cn/_sources/design/gan_api.md.txt b/develop/doc_cn/_sources/design/gan_api.md.txt deleted file mode 100644 index fb41df8615f..00000000000 --- a/develop/doc_cn/_sources/design/gan_api.md.txt +++ /dev/null @@ -1,253 +0,0 @@ -# Design for GAN - -GAN (General Adversarial Net [https://arxiv.org/abs/1406.2661]) is an important model for unsupervised learning and widely used in many areas. - -It applies several important concepts in machine learning system design, including building and running subgraphs, dependency tracing, different optimizers in one executor and so forth. - -In our GAN design, we wrap it as a user-friendly easily customized python API to design different models. We take the conditional DC-GAN (Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks [https://arxiv.org/abs/1511.06434]) as an example due to its good performance on image generation. - -

                                -
                                -Figure 1. The overall running logic of GAN. The black solid arrows indicate the forward pass; the green dashed arrows indicate the backward pass of generator training; the red dashed arrows indicate the backward pass of the discriminator training. The BP pass of the green (red) arrow should only update the parameters in the green (red) boxes. The diamonds indicate the data providers. d\_loss and g\_loss marked in red and green are the two targets we would like to run. -

                                - -The operators, layers and functions required/optional to build a GAN demo is summarized in https://github.com/PaddlePaddle/Paddle/issues/4563. - -

                                -
                                -Figure 2. Photo borrowed from the original DC-GAN paper. -

                                - -## The Conditional-GAN might be a class. -This design we adopt the popular open source design in https://github.com/carpedm20/DCGAN-tensorflow and https://github.com/rajathkmp/DCGAN. It contains following data structure: - -- DCGAN(object): which contains everything required to build a GAN model. It provides following member functions methods as API: - -- __init__(...): Initialize hyper-parameters (like conv dimension and so forth), and declare model parameters of discriminator and generator as well. - -- generator(z, y=None): Generate a fake image from input noise z. If the label y is provided, the conditional GAN model will be chosen. -Returns a generated image. - -- discriminator(image): -Given an image, decide if it is from a real source or a fake one. -Returns a 0/1 binary label. - -- build_model(self): -build the whole GAN model, define training loss for both generator and discrimator. - -## Discussion on Engine Functions required to build GAN -- Trace the tensor and variable dependency in the engine executor. (Very critical, otherwise GAN can'be be trained correctly) -- Different optimizers responsible for optimizing different loss. - -To be more detailed, we introduce our design of DCGAN as following: - -### Class member Function: Initializer -- Set up hyper-parameters, including condtional dimension, noise dimension, batch size and so forth. -- Declare and define all the model variables. All the discriminator parameters are included in the list self.theta_D and all the generator parameters are included in the list self.theta_G. -```python -class DCGAN(object): - def __init__(self, y_dim=None): - - # hyper parameters - self.y_dim = y_dim # conditional gan or not - self.batch_size = 100 - self.z_dim = z_dim # input noise dimension - - # define parameters of discriminators - self.D_W0 = pd.Variable(shape=[3,3, 1, 128], data=pd.gaussian_normal_randomizer()) - self.D_b0 = pd.Variable(np.zeros(128)) # variable also support initialization using a numpy data - self.D_W1 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer()) - self.D_b1 = pd.Variable(np.zeros(128)) # variable also support initialization using a numpy data - self.D_W2 = pd.Varialble(np.random.rand(128, 1)) - self.D_b2 = pd.Variable(np.zeros(128)) - self.theta_D = [self.D_W0, self.D_b0, self.D_W1, self.D_b1, self.D_W2, self.D_b2] - - # define parameters of generators - self.G_W0 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer()) - self.G_b0 = pd.Variable(np.zeros(128)) # variable also support initialization using a numpy data - self.G_W1 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer()) - self.G_b1 = pd.Variable(np.zeros(128)) # variable also support initialization using a numpy data - self.G_W2 = pd.Varialble(np.random.rand(128, 1)) - self.G_b2 = pd.Variable(np.zeros(128)) - self.theta_G = [self.G_W0, self.G_b0, self.G_W1, self.G_b1, self.G_W2, self.G_b2] -``` - -### Class member Function: Generator -- Given a noisy input z, returns a fake image. -- Concatenation, batch-norm, FC operations required; -- Deconv layer required, which is missing now... -```python -class DCGAN(object): - def generator(self, z, y = None): - # input z: the random noise - # input y: input data label (optional) - # output G_im: generated fake images - - if not self.y_dim: - z = pd.layer.concat(1, [z, y]) - - G_h0 = pd.layer.fc(z, self.G_w0, self.G_b0) - G_h0_bn = pd.layer.batch_norm(G_h0) - G_h0_relu = pd.layer.relu(G_h0_bn) - - G_h1 = pd.layer.deconv(G_h0_relu, self.G_w1, self.G_b1) - G_h1_bn = pd.layer.batch_norm(G_h1) - G_h1_relu = pd.layer.relu(G_h1_bn) - - G_h2 = pd.layer.deconv(G_h1_relu, self.G_W2, self.G_b2)) - G_im = pd.layer.tanh(G_im) - return G_im -``` - -### Class member function: Discriminator -- Given a noisy input z, returns a fake image. -- Concatenation, Convolution, batch-norm, FC, Leaky-ReLU operations required; -```python -class DCGAN(object): - def discriminator(self, image): - # input image: either generated images or real ones - # output D_h2: binary logit of the label - - D_h0 = pd.layer.conv2d(image, w=self.D_w0, b=self.D_b0) - D_h0_bn = pd.layer.batchnorm(h0) - D_h0_relu = pd.layer.lrelu(h0_bn) - - D_h1 = pd.layer.conv2d(D_h0_relu, w=self.D_w1, b=self.D_b1) - D_h1_bn = pd.layer.batchnorm(D_h1) - D_h1_relu = pd.layer.lrelu(D_h1_bn) - - D_h2 = pd.layer.fc(D_h1_relu, w=self.D_w2, b=self.D_b2) - return D_h2 -``` - -### Class member function: Build the model -- Define data readers as placeholders to hold the data; -- Build generator and discriminators; -- Define two training losses for discriminator and generator, respectively. -If we have execution dependency engine to back-trace all tensors, the module building our GAN model will be like this: -```python -class DCGAN(object): - def build_model(self): - if self.y_dim: - self.y = pd.data(pd.float32, [self.batch_size, self.y_dim]) - self.images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size]) - self.faked_images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size]) - self.z = pd.data(tf.float32, [None, self.z_size]) - - # step 1: generate images by generator, classify real/fake images with discriminator - if self.y_dim: # if conditional GAN, includes label - self.G = self.generator(self.z, self.y) - self.D_t = self.discriminator(self.images) - # generated fake images - self.sampled = self.sampler(self.z, self.y) - self.D_f = self.discriminator(self.G) - else: # original version of GAN - self.G = self.generator(self.z) - self.D_t = self.discriminator(self.images) - # generate fake images - self.sampled = self.sampler(self.z) - self.D_f = self.discriminator(self.images) - - # step 2: define the two losses - self.d_loss_real = pd.reduce_mean(pd.cross_entropy(self.D_t, np.ones(self.batch_size)) - self.d_loss_fake = pd.reduce_mean(pd.cross_entropy(self.D_f, np.zeros(self.batch_size)) - self.d_loss = self.d_loss_real + self.d_loss_fake - - self.g_loss = pd.reduce_mean(pd.cross_entropy(self.D_f, np.ones(self.batch_szie)) -``` - -If we do not have dependency engine but blocks, the module building our GAN model will be like this: -```python -class DCGAN(object): - def build_model(self, default_block): - # input data in the default block - if self.y_dim: - self.y = pd.data(pd.float32, [self.batch_size, self.y_dim]) - self.images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size]) - # self.faked_images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size]) - self.z = pd.data(tf.float32, [None, self.z_size]) - - # step 1: generate images by generator, classify real/fake images with discriminator - with pd.default_block().g_block(): - if self.y_dim: # if conditional GAN, includes label - self.G = self.generator(self.z, self.y) - self.D_g = self.discriminator(self.G, self.y) - else: # original version of GAN - self.G = self.generator(self.z) - self.D_g = self.discriminator(self.G, self.y) - self.g_loss = pd.reduce_mean(pd.cross_entropy(self.D_g, np.ones(self.batch_szie)) - - with pd.default_block().d_block(): - if self.y_dim: # if conditional GAN, includes label - self.D_t = self.discriminator(self.images, self.y) - self.D_f = self.discriminator(self.G, self.y) - else: # original version of GAN - self.D_t = self.discriminator(self.images) - self.D_f = self.discriminator(self.G) - - # step 2: define the two losses - self.d_loss_real = pd.reduce_mean(pd.cross_entropy(self.D_t, np.ones(self.batch_size)) - self.d_loss_fake = pd.reduce_mean(pd.cross_entropy(self.D_f, np.zeros(self.batch_size)) - self.d_loss = self.d_loss_real + self.d_loss_fake -``` -Some small confusion and problems with this design: -- D\_g and D\_f are actually the same thing, but has to be written twice; i.e., if we want to run two sub-graphs conceptually, the same codes have to be written twice if they are shared by the graph. -- Requires ability to create a block anytime, rather than in if-else or rnn only; - -## Main function for the demo: -Generally, the user of GAN just need to the following things: -- Define an object as DCGAN class; -- Build the DCGAN model; -- Specify two optimizers for two different losses with respect to different parameters. -```python -# pd for short, should be more concise. -from paddle.v2 as pd -import numpy as np -import logging - -if __name__ == "__main__": - # dcgan class in the default graph/block - # if we use dependency engine as tensorflow - # the codes, will be slightly different like: - # dcgan = DCGAN() - # dcgan.build_model() - with pd.block() as def_block: - dcgan = DCGAN() - dcgan.build_model(def_block) - - # load mnist data - data_X, data_y = self.load_mnist() - - # Two subgraphs required!!! - with pd.block().d_block(): - d_optim = pd.train.Adam(lr = .001, beta= .1) - d_step = d_optim.minimize(dcgan.d_loss, dcgan.theta_D) - with pd.block.g_block(): - g_optim = pd.train.Adam(lr = .001, beta= .1) - g_step = pd.minimize(dcgan.g_loss, dcgan.theta_G) - - # executor - sess = pd.executor() - - # training - for epoch in xrange(10000): - for batch_id in range(N / batch_size): - idx = ... - # sample a batch - batch_im, batch_label = data_X[idx:idx+batch_size], data_y[idx:idx+batch_size] - # sample z - batch_z = np.random.uniform(-1., 1., [batch_size, z_dim]) - - if batch_id % 2 == 0: - sess.run(d_step, - feed_dict = {dcgan.images: batch_im, - dcgan.y: batch_label, - dcgan.z: batch_z}) - else: - sess.run(g_step, - feed_dict = {dcgan.z: batch_z}) -``` - -# More thinking about dependency engine v.s. block design: -- What if we just want to run an intermediate result? Do we need to run the whole block/graph? -- Should we call eval() to get the fake images in the first stage? And then train the discriminator in the second stage? diff --git a/develop/doc_cn/_sources/design/graph.md.txt b/develop/doc_cn/_sources/design/graph.md.txt deleted file mode 100644 index 7519a65df83..00000000000 --- a/develop/doc_cn/_sources/design/graph.md.txt +++ /dev/null @@ -1,70 +0,0 @@ -# Design Doc: Computations as a Graph - -A primary goal of the refactorization of PaddlePaddle is a more flexible representation of deep learning computation, in particular, a graph of operators and variables, instead of sequences of layers as before. - -This document explains that the construction of a graph as three steps: - -- construct the forward part -- construct the backward part -- construct the optimization part - -## The Construction of a Graph - -Let us take the problem of image classification as a simple example. The application program that trains the model looks like: - -```python -x = layer.data("images") -l = layer.data("label") -y = layer.fc(x) -cost = layer.mse(y, l) -optimize(cost) -train(cost, reader=mnist.train()) -``` - -### Forward Part - -The first four lines of above program build the forward part of the graph. - -![](images/graph_construction_example_forward_only.png) - -In particular, the first line `x = layer.data("images")` creates variable x and a Feed operator that copies a column from the minibatch to x. `y = layer.fc(x)` creates not only the FC operator and output variable y, but also two parameters, W and b, and the initialization operators. - -Initialization operators are kind of "run-once" operators -- the `Run` method increments a class data member counter so to run at most once. By doing so, a parameter wouldn't be initialized repeatedly, say, in every minibatch. - -In this example, all operators are created as `OpDesc` protobuf messages, and all variables are `VarDesc`. These protobuf messages are saved in a `BlockDesc` protobuf message. - -### Backward Part - -The fifth line `optimize(cost)` calls two functions, `ConstructBackwardGraph` and `ConstructOptimizationGraph`. - -`ConstructBackwardGraph` traverses the forward graph in the `BlockDesc` protobuf message and builds the backward part. - -![](images/graph_construction_example_forward_backward.png) - -According to the chain rule of gradient computation, `ConstructBackwardGraph` would - -1. create a gradient operator G for each operator F, -1. make all inputs, outputs, and outputs' gradient of F as inputs of G, -1. create gradients for all inputs of F, except for those who don't have gradients, like x and l, and -1. make all these gradients as outputs of G. - -### Optimization Part - -For each parameter, like W and b created by `layer.fc`, marked as double circles in above graphs, `ConstructOptimizationGraph` creates an optimization operator to apply its gradient. Here results in the complete graph: - -![](images/graph_construction_example_all.png) - -## Block and Graph - -The word block and graph are interchangable in the desgin of PaddlePaddle. A [Block](https://github.com/PaddlePaddle/Paddle/pull/3708) is a metaphore of the code and local variables in a pair of curly braces in programming languages, where operators are like statements or instructions. A graph of operators and variables is a representation of the block. - -A Block keeps operators in an array `BlockDesc::ops` - -```protobuf -message BlockDesc { - repeated OpDesc ops = 1; - repeated VarDesc vars = 2; -} -``` - -in the order that they appear in user programs, like the Python program at the beginning of this article. We can imagine that in `ops`, we have some forward operators, followed by some gradient operators, and then some optimization operators. diff --git a/develop/doc_cn/_sources/design/graph_survey.md.txt b/develop/doc_cn/_sources/design/graph_survey.md.txt deleted file mode 100644 index 6c6db08f463..00000000000 --- a/develop/doc_cn/_sources/design/graph_survey.md.txt +++ /dev/null @@ -1,232 +0,0 @@ -## Survey on Graph - -Neural network framework often provides symbolic API for users to write network topology conveniently. This doc manily focus on symbolic API in most popular neural network frameworks, and try to find out how to parse symbolic configuration to a portable file, such as protobuf or json. - -### Mxnet - -The core concept of symbolic API is `Symbol`. Mxnet implements `Symbol` class in C++, and export to Python using C-API. Please refer to the comments in Mxnet: - - -`Symbol` is help class used to represent the operator node in Graph. -`Symbol` acts as an interface for building graphs from different components like Variable, Functor and Group. `Symbol` is also exported to python front-end (while Graph is not) to enable quick test and deployment. Conceptually, symbol is the final operation of a graph and thus including all the information required (the graph) to evaluate its output value. - - -A simple network topology wrote by Symbol is as follows: - -```python -def get_symbol(num_classes=10, **kwargs): - data = mx.symbol.Variable('data') - data = mx.symbol.Flatten(data=data) - fc1 = mx.symbol.FullyConnected(data = data, name='fc1', num_hidden=128) - act1 = mx.symbol.Activation(data = fc1, name='relu1', act_type="relu") - fc2 = mx.symbol.FullyConnected(data = act1, name = 'fc2', num_hidden = 64) - act2 = mx.symbol.Activation(data = fc2, name='relu2', act_type="relu") - fc3 = mx.symbol.FullyConnected(data = act2, name='fc3', num_hidden=num_classes) - mlp = mx.symbol.SoftmaxOutput(data = fc3, name = 'softmax') - return mlp -``` - - - -Varible here is actually a Symbol. Every basic Symbol will correspond to one Node, and every Node has its own NodeAttr. There is a op field in NodeAttr class, when a Symbol represents Variable(often input data), the op field is null. - -Symbol contains a data member, std::vector outputs, and NodeEntry cantains a poniter to Node. We can follow the Node pointer to get all the Graph. - -And Symbol can be saved to a Json file. - -Here is a detailed example: - -``` ->>> import mxnet as mx ->>> data = mx.symbol.Variable('data') ->>> print data.debug_str() -Variable:data - ->>> data = mx.symbol.Flatten(data=data) ->>> print data.debug_str() -Symbol Outputs: - output[0]=flatten0(0) -Variable:data --------------------- -Op:Flatten, Name=flatten0 -Inputs: - arg[0]=data(0) version=0 - ->>> fc1 = mx.symbol.FullyConnected(data = data, name='fc1', num_hidden=128) ->>> print fc1.debug_str() -Symbol Outputs: - output[0]=fc1(0) -Variable:data --------------------- -Op:Flatten, Name=flatten0 -Inputs: - arg[0]=data(0) version=0 -Variable:fc1_weight -Variable:fc1_bias --------------------- -Op:FullyConnected, Name=fc1 -Inputs: - arg[0]=flatten0(0) - arg[1]=fc1_weight(0) version=0 - arg[2]=fc1_bias(0) version=0 -Attrs: - num_hidden=128 - -``` - - -### TensorFlow - - -The core concept of symbolic API is `Tensor`. Tensorflow defines `Tensor` in Python. Please refer to the comments in TensorFlow: - -A `Tensor` is a symbolic handle to one of the outputs of an `Operation`. It does not hold the values of that operation's output, but instead provides a means of computing those values in a TensorFlow [Session](https://www.tensorflow.org/api_docs/python/tf/Session). - -A simple example is as follows: - -```python - # Build a dataflow graph. - c = tf.constant([[1.0, 2.0], [3.0, 4.0]]) - d = tf.constant([[1.0, 1.0], [0.0, 1.0]]) - e = tf.matmul(c, d) - - # Construct a `Session` to execute the graph. - sess = tf.Session() - - # Execute the graph and store the value that `e` represents in `result`. - result = sess.run(e) -``` - - -The main method of `Tensor` is as follows: - - -```python -@property -def op(self): - """The `Operation` that produces this tensor as an output.""" - return self._op - -@property -def dtype(self): - """The `DType` of elements in this tensor.""" - return self._dtype - -@property -def graph(self): - """The `Graph` that contains this tensor.""" - return self._op.graph - -@property -def name(self): - """The string name of this tensor.""" - if not self._op.name: - raise ValueError("Operation was not named: %s" % self._op) - return "%s:%d" % (self._op.name, self._value_index) - -@property -def device(self): - """The name of the device on which this tensor will be produced, or None.""" - return self._op.device -``` - - -Tensor can be taken as target to run by session. Tensor contains all the information of Graph, and tracks data dependency. - - -Here is a detailed example: - - -``` ->>> import tensorflow as tf ->>> c = tf.constant([[1.0, 2.0], [3.0, 4.0]]) ->>> print c.graph - ->>> d = tf.constant([[1.0, 1.0], [0.0, 1.0]]) ->>> print d.graph - ->>> e = tf.matmul(c, d) ->>> print e.graph - -``` - -### Dynet - - -The core concept of symbolic API is `Expression`, and Dynet defines `Expression` class in C++. - - -A simple example is as follows: - -```cpp -ComputationGraph cg; -Expression W = parameter(cg, pW); - -Expression in = input(cg, xs[i]); -Expression label = input(cg, ys[i]); -Expression pred = W * in; -Expression loss = square(pred - label); -``` - -The input data and parameter are also represented by Expression. Every basci Expression corresponds to a Node. And input data is also a Node. - -Expression has a data member ComputationGraph, and ComputationGraph will be modified in users' configuring process. Expression can be a running target, beacuse Expression contains all dependency. - - -Here is a detailed example: - -write topology in C++ - -``` -ComputationGraph cg; -Expression W = parameter(cg, pW); -cg.print_graphviz(); - -Expression pred = W * xs[i]; -cg.print_graphviz(); - -Expression loss = square(pred - ys[i]); -cg.print_graphviz(); -``` - -compile and print - -``` -# first print -digraph G { - rankdir=LR; - nodesep=.05; - N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"]; -} -# second print -digraph G { - rankdir=LR; - nodesep=.05; - N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"]; - N1 [label="v1 = v0 * -0.98"]; - N0 -> N1; -} -# third print -digraph G { - rankdir=LR; - nodesep=.05; - N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"]; - N1 [label="v1 = v0 * -0.98"]; - N0 -> N1; - N2 [label="v2 = -1.88387 - v1"]; - N1 -> N2; - N3 [label="v3 = -v2"]; - N2 -> N3; - N4 [label="v4 = square(v3)"]; - N3 -> N4; -} -``` - -### Conclusion - - -Actually, Symbol/Tensor/Expression in Mxnet/TensorFlow/Dynet are the same level concepts. We use a unified name Expression here, this level concept has following features: - -- Users wirte topoloy with symbolic API, and all return value is Expression, including input data and parameter. -- Expression corresponds with a global Graph, and Expression can also be composed. -- Expression tracks all dependency and can be taken as a run target diff --git a/develop/doc_cn/_sources/design/if_else_op.md.txt b/develop/doc_cn/_sources/design/if_else_op.md.txt deleted file mode 100644 index 26d140f06db..00000000000 --- a/develop/doc_cn/_sources/design/if_else_op.md.txt +++ /dev/null @@ -1,51 +0,0 @@ -# The `IfElse` Operator - -PaddlePaddle's `IfElse` operator differs from TensorFlow's: - -- the TensorFlow version takes a scalar boolean value as the condition so that the whole mini-batch goes to either the true or the false branch, whereas -- the PaddlePaddle version takes a vector of boolean value as the condition, and instances corresponding to true values go to the true branch, those corresponding to false values go to the false branch. - -## Example - -The following PaddlePaddle program shows the usage of the IfElse operator: - -```python -import paddle as pd - -x = minibatch([10, 20, 30]) # shape=[None, 1] -y = var(1) # shape=[1], value=1 -z = minibatch([10, 20, 30]) # shape=[None, 1] -cond = larger_than(x, 15) # [false, true, true] - -ie = pd.ifelse() -with ie.true_block(): - d = pd.layer.add(x, y) - ie.output(d, pd.layer.softmax(d)) -with ie.false_block(): - d = pd.layer.fc(z) - ie.output(d, d+1) -o1, o2 = ie(cond) -``` - -A challenge to implement the `IfElse` operator is to infer those variables to be split, or, say, to identify the variable of the mini-batch or those derived from the mini-batch. - -An equivalent C++ program is as follows: - -```c++ -namespace pd = paddle; - -int x = 10; -int y = 1; -int z = 10; -bool cond = false; -int o1, o2; -if (cond) { - int d = x + y; - o1 = z; - o2 = pd::layer::softmax(z); -} else { - int d = pd::layer::fc(z); - o1 = d; - o2 = d+1; -} -``` diff --git a/develop/doc_cn/_sources/design/infer_var_type.md.txt b/develop/doc_cn/_sources/design/infer_var_type.md.txt deleted file mode 100644 index d9d5397becb..00000000000 --- a/develop/doc_cn/_sources/design/infer_var_type.md.txt +++ /dev/null @@ -1,78 +0,0 @@ -# Design Doc: InferVarType - -## The Problem Posed - -The variable in our design can hold variant types. Such as `LoDTensor` and `SelectedRows`. An operator should be able to inference the variable types of its output. - -For example, a `lookup table` operator takes two `LoDTensor`; one is a float tensor as the embedding table, the other is an int tensor as word ID. The gradient operator of `lookup table` will generate a `SelectedRows` as its output. A `sum` operator can take both `LoDTensor` and `SelectedRows` as its inputs and will generate a `LoDTensor` if any of its inputs is `LoDTensor`, otherwise, the `sum` operator will generate `SelectedRows` as its output. - -The variable type will be constant at runtime. Every variable's type can either be set by the user (input data and parameter) or be inferred by the operator in compile time. - -## Proposed Solution - -The `InferVarType` is a compile-time function which is registered to each operator. The inferface of that function is: - - -```c++ -using InferVarTypeFN = std::function< - void (const OpDescBind& /*op_desc*/, BlockDescBind* /*block*/)>; -``` - -It takes an operator description as its input and will write the output variable type and store them in block description. - -The `InferVarTypeFN` will be registered in `OpInfo`, to replace `infer_var_type_` field. The `OpInfo` should be - -```cpp -struct OpInfo { - InferVarTypeFN infer_var_type_; - ... -}; -``` - -The default `InferVarType` will set output type as `LoDTensor`. It can be done by `GetInferVarType()`. - -```cpp -void DefaultInferVarType(const OpDescBind& op_desc, BlockDescBind* block) { - // set the output type of variable as `LoDTensor`. - // ... -} - -struct OpInfo { - InferVarTypeFN infer_var_type_; - InferVarTypeFN GetInferVarType() const { - if (infer_var_type_) { - return infer_var_type_; - } else { - return DefaultInferVarType; - } - } -}; -``` - -## Register InferVarType - -We provide a thin base class for registering an `InferVarTypeFN`. To use a base class will ease the implementation of registry since we can detect the registry entry is an `InferVarTypeFN` or not. - -```cpp -class VarTypeInferer { -public: - virtual void operator()(const OpDescBind& op_desc, BlockDescBind* block) const = 0; -} -``` - -Operator developers can write the specialize `VarTypeInferer` as follow. - -```cpp -class SpecialVarTypeInferer : public VarTypeInferer { -public: - virtual void operator()(const OpDescBind& op_desc, BlockDescBind* block) const { - // .. own logic - } -} -``` - -Then user can register the `InferVarType` just like `GradOpDescMaker` and `OpInfoMaker`. - -``` -REGISTER_OPERATOR(some_op, OpType, SpecialVarTypeInferer, ...); -``` diff --git a/develop/doc_cn/_sources/design/kernel_hint_design.md.txt b/develop/doc_cn/_sources/design/kernel_hint_design.md.txt deleted file mode 100644 index a54b7da045e..00000000000 --- a/develop/doc_cn/_sources/design/kernel_hint_design.md.txt +++ /dev/null @@ -1,57 +0,0 @@ -## Problem -In PaddlePaddle's [Design](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/switch_kernel.md), one Operator may have multiple kernels. Users may have some personal preference to choose a certain type of kernel for an operator, such as `force_cpu` to choose a CPU kernel, `use_cudnn` to choose a CUDNN kernel, we need to provide a way for users to do this. - -In the current design, we use KernelType to describe one kernel. - -```cpp -struct KernelType { - Place place_; - DataType data_type_; - LayoutType layout_; -}; -``` - `place_` `data_type_` and `layout_` can be got from the input tensors of the operator, `GetActualKernelType(inputs)` use inputs to infer the proper kernel key that fit the incoming data, but users can not directly configure it. - -The [design](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/switch_kernel.md) also provides a virtual method `GetExpectedKernelType` that user can overload and use to choose the KernelType they want to use. - -So we should send the information user defined in proto to `GetExpectedKernelType` for choosing a kernel. - -The problem is, how should we define and send the information for `GetExpectedKernelType` to use? - -## Solution - -### Potential choice -1. Do nothing, let the user add the information they want to operator‘s attribute and get them inside `GetExpectedKernelType`, this can work properly. But there is a little problem that users may define many kinds of hints for the same purpose, such as `force_cpu`, `use_cpu`, `cpu_kernel` to choose CPU kernel, and `use_cudnn`, `force_cudnn`, `cudnn_kernel` to choose CUDNN kernel. - -2. Pre-define all the needed option and use a single attr key such as `kernel_hint` for the user, this is not so flexible if the user wants to define some more kind of hint. - -### Final choice -To provide enough flexibility while avoiding confusion definition, we can define some global constants for these attribute names, such as `force_cpu`, `use_cudnn`, `use_mkldnn` for a user to choose. - -In C++ - -```cpp -const std::string kForceCPU = "force_cpu"; -const std::string kUseCUDNN = "use_cudnn"; -const std::string kUseMKLDNN = "use_mkldnn"; - -KernelType GetExpectedKernelType() { - if (Attr(kForceCPU)) { - return KernelType(CPUPlace, ...) - } else { - ... - } -} -``` - -In Python code - -```python -FORCE_CPU = core.kForceCPU() - -def xx_layer(..., force_cpu=false): - layer_helper = LayerHelper(...) - layer_helper.append_op( - type="xx", - attr={FORCE_CPU: force_cpu}) -``` diff --git a/develop/doc_cn/_sources/design/kernel_selection.md.txt b/develop/doc_cn/_sources/design/kernel_selection.md.txt deleted file mode 100644 index 9719e031c70..00000000000 --- a/develop/doc_cn/_sources/design/kernel_selection.md.txt +++ /dev/null @@ -1,99 +0,0 @@ -## Background -Every operator has many kernels because there are multiple data types, places, data layout, library type that Fluid supports. We use the `OpKernelType ` to describe kernel types that operators can hold. - -The `OpKernelType ` is as follows: - -```cpp -struct OpKernelType { - Place place_; - DataType data_type_; - DataLayout data_layout_; - LibraryType library_type_; -}; -``` - -- The `place_` is a descriptor of the device, e.g., CPUPlace, CUDAPlace. - -- The `data_type_` is the data type that this kernel performs on, e.g., `FP32`, `INT64`. Note that one kernel may have inputs with different data types. However, it will be a major `data_type`. For example, the `cross_entropy` takes `int64` as it label, and `double`/`float` as its input logit and output cost. The major `data_type` of `cross_entropy` is `float` or `double`. - -- The `data_layout_ ` is useful for some computational library. One example is that MKLDNN uses many kinds of layout, such as `nChw8c`. Each kind of layout will invoke the different kernel. - -- The `library_type_` describes the computational library, e.g., `MKLDNN`, `CUDNN`. - -## Problem - -We register a kernel for every operator and every kernel type ideally. However, it is impracticable for the following situations. - -1. Some operators, like CRF, are complicated and inefficient to be implemented on GPU. The CRF operator will only have a CPU kernel. -2. Some operators will take too many memory. It is better to force them into CPU. However, the rest of operators in this neural network will be performed on GPU, i.e., model parallel problem. -3. Some layout and place are particular. One example is that MKLDNN uses `nChw8` and there is no other library uses `nChw8c`. - -Take one situation to give a detailed explanation, if we have two Operators: OP1 and OP2, OP1 has one output `op1_to_op2`, and `op1_to_op2` is the input of OP2. - -If OP1 and OP2 run on the same place(for example CPUPlace), then `op1_2_op2` can be used directly by OP2. - -``` -OP1(CPUPlace) - | - op1_2_op2 - | -OP2(CPUPlace) -``` - -If OP1 and OP2 run one different place, then OP2 cannot `use op1_2_op2` directly. - -Problems under these situations are similar. We can formalize this problem as follow. - -We register kernels with types $KT = \{kt_1, kt_2, kt_3, ...\}$ for one operator. The inputs of this operator should be run on kernel type $kt_{?}$, which the $kt_{?} \notin KT$. How to cast the input of this operator from $kt_{?}$ to any of kernel type in $KT$. - -## Solution: data transform - -It is clear that transforming inputs of an operator to adapt another kernel type is not related to the particular operator. So we should register these transformation methods as global methods. - -We can infer kernel type for each input of an operator. We let this kernel type as `actual kernel type for var`, which means this kernel type is the kernel type that can process this input variable. - -We can get a kernel type by 1) The configuration of operator description. (Users may want to force use `MKL` for `conv` operator). 2) The place of the current executor. (Executor is running on GPU). This kernel type is what we expect the operator will be performed on. We let this kernel type as `expect kernel type`. - -We transform the input data from `actual` to `expect` if the actual kernel type is not as same as expect kernel type. - -The algorithm is described as following - -```cpp -void OperatorWithKernel::Run( - const Scope& scope, - const platform::Place& place) const { - ExecutionContext ctx(...); - auto expected_kernel_key = this->GetExpectedKernelType(ctx); - - Scope& new_scope = scope.NewScope(); - - for (auto& var_name : this->Inputs()) { - auto* tensor_in = GetTensor(var_name); - auto kernel_type_for_var = this->GetKernelTypeForVar(...); - if (kernel_type_for_var.place_ != expected_kernel_key.place_) { - auto* trans_var = new_scope.Var(var_name); - auto* out = DataTransform(expected_kernel_key, - kernel_type_for_var, - *tensor_in); - CopyVariableWithTensor(...); - } - } - - auto kernel = kernels.find(expected_kernel_key); - kernel->Compute(ExecutionContext(...)); -} -``` - -then the actual process for the multi-device above will be: - -``` -OP1(CPUPlace) - | -op1_2_op2(on CPU) - | -[transform](from CPU to GPU) - | -op1_2_op2(on GPU) - | -OP2(CUDAPlace) -``` diff --git a/develop/doc_cn/_sources/design/memory_optimization.md.txt b/develop/doc_cn/_sources/design/memory_optimization.md.txt deleted file mode 100644 index 285464ada72..00000000000 --- a/develop/doc_cn/_sources/design/memory_optimization.md.txt +++ /dev/null @@ -1,217 +0,0 @@ -# Memory Optimization - - -## Problem - -In a lecture from Andrew Ng, he attributes the recent sucess of AI due to a combination of these: - -- Availability of Big Data -- Supercomputing power to process this Big Data over very large neural networks -- Modern algorithms - -Following graph shows the details: - -![](images/deep_learning.png) - -Larger model usually bring better performance. However, GPU memory is limited. For example, the memory size of a GTX TITAN X is only 12GB. To train complex and large models, we have to take care of memory usage. Besides, memory optimization is also necessary in both online/mobile inference. - -## Solution - -### Basic Strategy - -There are some basic strategies to improve memory usage, including in-place operations and memory sharing. - -#### In-place Operation -In a relu activation operator: - -$y = \max(x, 0)$ - -If the variable x is not used in any other operator, we can make an in-place operation. In other words, the memory block of variable y and variable x will be the same. In-place operations will save 50% memory occupancy immediately. - -#### Memory Sharing - -Not all operators support in-place operations. Memory sharing is a more general strategy. - -Following is an example: - -``` -a = op1(b, c); -d = op2(a) -e = op3(d, f) -``` - -In this case, variable a is no longer used, and op2 does not support in-place operation. After op2 finishes, we can put the memory of variable a to a memory pool. Then, variable e can share the memory of variable a from the pool. - - -### Live Variable Analysis - -It's not enough to only have some basic strategies. The pre-requisite of memory optimization is to know if a variable is still "live" after an operation. - -In our design, the neural network topology is defined as a program. Luckily, [live variable analysis](https://en.wikipedia.org/wiki/Live_variable_analysis) is a classic problem in compilers which can be used in many stages, such as register allocation. - -In compilers, the front end of the compiler translates programs into an intermediate language with an unbounded number of temporary variables. This program must run on a machine with a bounded number of registers. Two temporary variables a and b can fit into the same register, if a and b are never "in use" at the same time. Thus, many temporary variables can fit in few registers; if they don't all fit, the excess tempory variables can be kept in memory. - -Therefore, the compiler needs to analyze the intermediate-representation program to determine which temporary variables are in use at the same time. We say a variable is "live" if it holds a value that may be needed in the future, so this analysis is called liveness analysis. - -We can leran these techniques from compilers. There are mainly two stages to make live variable analysis: - -- construct a control flow graph -- solve the dataflow equations - - -#### Control Flow Graph -To perform analysis on a program, it is often useful to make a control flow graph. A [control flow graph](https://en.wikipedia.org/wiki/Control_flow_graph) (CFG) in computer science is a representation, using graph notation, of all paths that might be traversed through a program during its execution. Each statement in the program is a node in the flow graph; if statemment x can be followed by statement y, there is an egde from x to y. - -Following is the flow graph for a simple loop. - -![](images/control_flow_graph.png) - -#### Dataflow Analysis - -Liveness of variable "flows" around the edges of the control flow graph; determining the live range of each variable is an example of a dataflow problem. [Dataflow analysis](https://en.wikipedia.org/wiki/Data-flow_analysis) is a technique for gathering information about the possible set of values calculated at various points in a computer program. - -A simple way to perform data-flow analysis of programs is to set up dataflow equations for each node of the control flow graph and solve them by repeatedly calculating the output from the input locally at each node until the whole system stabilizes. - -- Flow Graph Terminology - -A flow graph node has out-edges that lead to sucessor nodes, and in-edges that come from predecessor nodes. The set *pred[n]* is all the predecessors of node n, and *succ[n]* is the set of sucessors. -In former control flow graph, the out-edges of node 5 are 5 --> 6 and 5 --> 2, and *succ[5]* = {2, 6}. The in-edges of 2 are 5 --> 2 and 1 --> 2, and *pred[2]* = {1, 5}. - -- Uses and Defs - -An assignmemt to a variable or temporary defines that variable. An occurence of a variable on the right-hand side of an assginment(or in other expressions) uses the variable. We can define the *def* of a variable as the set of graph nodes that define it; or the *def* of a graph node as the set of variables that it defines; and the similarly for the *use* of a variable or graph node. In former control flow graph, *def(3)* = {c}, *use(3)* = {b, c}. - -- Liveness - -A variable is *live* on an edge if there is a directed path from that edge to a *use* of the variable that does not go through any *def*. A variable is *live-in* at a node if it is live on any of the in-edges of that node; it is *live-out* at a node if it is live on any of the out-edges of the node. - - -The calcution of liveness can be solved by iteration until a fixed pointer is reached. Following is the recursive formula: - -![](images/dataflow_equations.png) - -### Memory optimization transpiler - -At last, we take basic strategy and liveness analysis techniques learning from compilers to implement our memory optimization transpiler. - -#### add in-place attribute - -In-place is a built-in attribute of an operator. Since we treat in-place and other operators differently, we have to add an in-place attribute for every operator. - - -#### contruct control flow graph - -Following is the ProgramDesc protobuf of [machine translation](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/tests/book/test_machine_translation.py) example. - -- Block0: - -``` -lookup_table -mul -... -while(sub-block idx 1) -... -array_to_lod_tensor -cross_entropy -... -while_grad(sub-block idx 2) -read_from_array -array_to_lod_tensor -... -``` - -- Block1 - -``` -read_from_array -read_from_array -... -write_to_array -increment -write_to_array -less_than -``` - -- Block2 - -``` -read_from_array -increment -... -write_to_array -write_to_array -``` - -We can transfer all the operators and variables in ProgramDesc to build a control flow graph. - -```python -class ControlFlowGraph(object): - def __init__(self, Program): - self._sucessors = defaultdict(set) - self._presucessors = defaultdict(set) - self._uses = defaultdict(set) - self._defs = defaultdict(set) - self._live_in = defaultdict(set) - self._live_out = defaultdict(set) - self._program = Program - - def build(self): - pass - - def dataflow_analysis(self): - pass - - def memory_optimization(self): - pass - - def get_program(self): - return self._program -``` - -#### Make dataflow analysis - -We follow the guide from compilers and try to solve the dataflow equation to get liveness of every variable. If the live-in of an operator node is different from the live-out, then we can make memory sharing. - -For example: - -``` -a = op1(b, c); -d = op2(a) -e = op3(d, f) -``` - -The dataflow analysis result is: - -``` -live_in(op1) = {b, c, f} -live_out(op1) = {a, f} - -live_in(op2) = {a, f} -live_out(op2) = {d, f} - -live_in(op3) = {d, f} -live_out(op3) = {} -``` - -After op1, we can process variable b and variable c; After op2, we can process variable a. After op3, we can process variable d and variable f. - -#### memory sharing policy - -A memory pool will be mantained in the stage of memory optimization. Each operator node will be scanned to determine memory optimization is done or not. If an operator satifies the requirement, following policy will be taken to handle input/output variables. - -``` -if op.support_inplace(): - i --> pool - pool --> o -else: - pool --> o - i --> pool -``` - - - -## Reference - -- [Lecture Notes From Artificial Intelligence Is The New Electricity By Andrew Ng](https://manavsehgal.com/lecture-notes-from-artificial-intelligence-is-the-new-electricity-by-andrew-ng-4712dcbf26e5) -- Modern compiler implementation in ML, by Andrew W. Appel -- [Optimizing Memory Consumption in Deep learning](https://mxnet.incubator.apache.org/architecture/note_memory.html) diff --git a/develop/doc_cn/_sources/design/mkl/mkl_packed.md.txt b/develop/doc_cn/_sources/design/mkl/mkl_packed.md.txt deleted file mode 100644 index 0123315ad43..00000000000 --- a/develop/doc_cn/_sources/design/mkl/mkl_packed.md.txt +++ /dev/null @@ -1,108 +0,0 @@ -# Intel® MKL Packed on PaddlePaddle: Design Doc - - -## Contents - -- [Overview](#overview) -- [Key Points](#key-points) - - [Background](#background) - - [Solution](#solution) -- [Actions](#actions) - - [CMake](#cmake) - - [Layers](#layers) - - [Unit Tests](#unit-tests) - - [Python API](#python-api) - - [Benchmarking](#benchmarking) - - -## Overview -我们计划将 Intel® MKL 中引入的 GEMM Packed APIs\[[1](#references)\] 集成到 PaddlePaddle 中,充分发挥英特尔平台的优势,有效提升PaddlePaddle在英特尔架构上的性能。 -现阶段的优化主要针对 Recurrent Neural Network(以下简称RNN)相关层(包括`RecurrentLayer`, `GatedRecurrentLayer`和`LstmLayer`), 以及 PaddlePaddle V1 API。 - -## Key Points - -### Background -目前PaddlePaddle采用了 Intel® MKL库的[cblas_?gemm](https://software.intel.com/en-us/mkl-developer-reference-c-cblas-gemm)函数,这个函数本身会在计算前将原数据转换为更适合英特尔平台的内部格式。 - -1. 转换耗时 \ -这一数据格式的转换操作(Packing),在问题本身的计算量比较小的时候,显得相对来说较为耗时。例如在DeepSpeech2 \[[2](#references)\] 的Vanilla RNN部分中,矩阵大小是`batch_size * 2048`。 -2. 转换冗余 \ -由于在现有的某些情况下(例如RNN),多次调用 cblas_?gemm 会使用相同的原数据,因此,每次调用时对原数据的重复Packing便成为了冗余。 - -为了最大程度减少多次调用 cblas_?gemm 在Packing上的耗时,Intel® MKL 引入了以下四个API: - * [cblas_?gemm_alloc](https://software.intel.com/en-us/mkl-developer-reference-c-cblas-gemm-alloc) - * [cblas_?gemm_pack](https://software.intel.com/en-us/mkl-developer-reference-c-cblas-gemm-pack) - * [cblas_?gemm_compute](https://software.intel.com/en-us/mkl-developer-reference-c-cblas-gemm-compute) - * [cblas_?gemm_free](https://software.intel.com/en-us/mkl-developer-reference-c-cblas-gemm-free) - -通过使用这些API,我们可以先完成对原数据的Packing操作,再把已转换为Packed格式的数据传递给那些复用同一数据的gemm_compute函数,从而避免了Packing冗余。 - -### Solution -在RNN的情况下,同一次前向、后向(forward/backward)过程中所有时间步(time step)共享同一个权重(weight)。当只做推断(inference)时,各次前向之间也都使用了相同的权重,没有必要在每次前向中每个时间步的计算时对权重进行重复的Packing操作。 - -我们通过使用新引入的GEMM Packed APIs,在层初始化的时候,先完成对权重的Packing操作,然后在前向,后向时复用已经转换过的权重,并在每次权重更新后,对新的权重进行转换用于下次迭代。 - -* 优化前,对于序列长度(sequence length)为`T`的网络模型(model), `N`次迭代执行的转换次数为: - - `inference`: `N * T` - - `training`: `2 * N * T` -* 优化后,对于同样设置的网络模型,其转换次数减少至: - - `inference`: `1` - - `training`: `2 * N` - -## Actions - -添加的相关文件和目录结构如下: - -```txt -PaddlePaddle/Paddle -├── ... -└── paddle/ - ├── ... - └── gserver/ - ├── ... - ├── layers/ - │ ├── ... - │ ├── MKLPackedRecurrentLayer.* - | ├── MKLPackedGatedRecurrentLayer.* - | ├── MKLPackedLstmLayer.* - | └── MKLPackedGemm.h - └── tests/ - ├── ... - └── test_MKLPacked.cpp -``` - -### CMake -在对应的`CMakeLists.txt`中根据`WITH_MKL`是否打开,来决定是否开启MKL Packed相关功能。 - -### Layers -所有的`MKLPacked*Layer`都继承于PaddlePaddle的基类`Layer`, 并添加头文件 `MKLPackedGemm.h`,该文件对相关GEMM Packed APIs做了封装。 - -### Unit Tests -我们会添加`test_MKLPacked.cpp`用于MKL Packed优化后layer的测试。 -对于每一个新加的RNN layer,我们会对比如下2个方面: -1. 对比优化后layer自身,sequence mode(`rnn_use_batch=false`)与batch mode(`rnn_use_batch=true`)的结果。 -2. 对比优化后layer与相对应的PaddlePaddle原有layer, 在batch mode下的结果。 - -### Python API -计划在`paddle/utils.Flags`中添加`use_mkl_packed`的flag,用于选择是否使用相关功能,并且当编译时`WITH_MKL=ON`的情况下,默认设置为`true`。 - -同时,在`python/paddle/trainer/config_parser.py`中对应的layer处,添加`use_mkl_packed`这个选择,方便用户在Python端选择是否启用这个功能。 - -具体实现方式比如: - -```python -use_mkl_packed = bool(int(g_command_config_args.get("use_mkl_packed", 0))) -if use_mkl_packed: - self.layer_type = mkl_packed_* -``` - -所有相关的`layer_type`会以*mkl_packed_*开头,这些会在`MKLPacked*Layer`注册layer的时候保证,以示区分。 - - -### Benchmarking -会添加相应的脚本用于测试和对比在使用MKL Packed recurrent layers 前后的网络性能。 - -## References -1. [Introducing the new Packed APIs for GEMM](https://software.intel.com/en-us/articles/introducing-the-new-packed-apis-for-gemm) -2. [DeepSpeech2 on PaddlePaddle](https://github.com/PaddlePaddle/DeepSpeech#deepspeech2-on-paddlepaddle) - diff --git a/develop/doc_cn/_sources/design/mkl/mkldnn.md.txt b/develop/doc_cn/_sources/design/mkl/mkldnn.md.txt deleted file mode 100644 index e2fe1e6b26f..00000000000 --- a/develop/doc_cn/_sources/design/mkl/mkldnn.md.txt +++ /dev/null @@ -1,210 +0,0 @@ -# Intel® MKL-DNN on PaddlePaddle: Design Doc - -我们计划将英特尔深度神经网络数学库[Intel MKL-DNN](https://github.com/01org/mkl-dnn) -(Intel Math Kernel Library for Deep Neural Networks)集成到PaddlePaddle, -充分展现英特尔平台的优势,有效提升PaddlePaddle在英特尔架构上的性能。 - -
                                -
                                -Figure 1. PaddlePaddle on IA -
                                - -近期目标 - -- 完成常用Layer的MKL-DNN实现。 -- 完成常见深度神经网络VGG,GoogLeNet 和 ResNet的MKL-DNN实现。 - -目前的优化,主要针对PaddlePaddle在重构之前的代码框架以及V1的API。 -具体的完成状态可以参见[这里](https://github.com/PaddlePaddle/Paddle/projects/21)。 - -## Contents - -- [Overview](#overview) -- [Actions](#actions) - - [CMake](#cmake) - - [Matrix](#matrix) - - [Layers](#layers) - - [Activations](#activations) - - [Parameters](#parameters) - - [Gradients](#gradients) - - [Unit Tests](#unit-tests) - - [Python API](#python-api) - - [Benchmarking](#benchmarking) - - [Others](#others) -- [Design Concerns](#design-concerns) - -## Overview - -我们会把MKL-DNN会作为第三方库集成进PaddlePaddle,与其他第三方库一样,会在编译PaddlePaddle的时候下载并编译MKL-DNN。 - -同时,为了进一步提升PaddlePaddle在基本数学运算的计算速度,我们也将MKLML即(MKL small library\[[1](#references)\]) -作为另一个第三方库集成进PaddlePaddle,它只会包括生成好的动态库和头文件。 - -MKL,MKLML以及MKL-DNN三者关系如下表: - -| Name | Open Source | License | Descriptions | -| :---------- | :--------------- | :---------- | :------------ | -| MKL | No | Proprietary | Accelerate math processing routines | -| MKLML | No | Proprietary | Small package of MKL, especially for Machine Learning | -| MKL-DNN | Yes | Apache 2.0 | Accelerate primitives processing routines especially for Deep Neural Networks | - -MKLML可以与MKL-DNN共同使用,以此达到最好的性能。 - -
                                -
                                -Figure 2. PaddlePaddle with MKL Engines -
                                - -## Actions - -添加的相关文件和目录结构如下: - -```txt -PaddlePaddle/Paddle -├── ... -├── cmake/ -│ ├── external/ -│ │ ├── ... -│ │ ├── mkldnn.cmake -│ │ └── mklml.cmake -└── paddle/ - ├── ... - ├── math/ - │ ├── ... - │ └── MKLDNNMatrix.* - └── gserver/ - ├── ... - ├── layers/ - │ ├── ... - │ └── MKLDNN*Layer.* - ├── activations/ - │ ├── ... - │ └── MKLDNNActivations.* - └── tests/ - ├── ... - ├── MKLDNNTester.* - └── test_MKLDNN.cpp -``` - -### CMake -在`CMakeLists.txt`中提供一个与MKL有关的总开关:`WITH_MKL`,它负责决定编译时是否使用MKLML和MKL-DNN - -- `WITH_MKLML` 控制是否使用MKLML库。 -当打开`WITH_MKL`时,会自动使用MKLML库作为PaddlePaddle的CBLAS和LAPACK库,同时会开启Intel OpenMP用于提高MKLML的性能。 -编译时会把对应的头文件和库放在`build/third_party/install/mklml/*`目录下对应的地方。 -MKLML的库目前都是动态库,主要包括`libiomp5.so`和`libmklml_intel.so`。 -- `WITH_MKLDNN` 控制是否使用MKL-DNN。 -当开启`WITH_MKL`时,会自动根据硬件配置[[2](#references)]选择是否编译MKL-DNN。 -编译时会把对应的头文件和库放在`build/third_party/install/mkldnn/*`目录下对应的地方。 -MKL-DNN的库目前只有动态库`libmkldnn.so`。 - -### Matrix -目前在PaddlePaddle中数据都是以`NCHW`的格式存储,但是在MKL-DNN中的排列方式不止这一种。 -所以我们定义了一个`MKLDNNMatrix`用于管理MKL-DNN数据的不同格式以及相互之间的转换。 - -
                                -
                                -Figure 3. MKLDNNMatrix -
                                - -### Layers -所有MKL-DNN的Layers都会继承于`MKLDNNLayer`,该类继承于PaddlePaddle的基类`Layer`。 -在`MKLDNNLayer`中会提供一些必要的接口和函数,并且会写好`forward`和`backward`的基本逻辑, -子类只需要使用定义好的接口,实现具体的函数功能即可。 - -
                                -
                                -Figure 4. MKLDNNLayer -
                                - -每个MKLDNNLayer都包含用于内部存储和外部存储的一系列MKLDNNMatrix: - -- 内部存储(internel memory):`inVal_`,`inGrad_`,`outVal_`和`outGrad_`,分别代表输入数据,输入梯度,输出数据和输出梯度。 -- 外部存储(external memory):都是以ext开头,比如`extInVal_`和`extInGrad_`,它们主要是用于, -当数据格式与PaddlePaddle默认的`NCHW`格式不匹配时,转换内存的工作。 -需要注意的是,PaddlePaddle的activation会直接使用`output_.value`和`output_.grad`, -所以`extOutVal_`和`extOutGrad_`必须分别与`output_.value`和`output_.grad`共享内存, -如果不需要外部存储用于转换,那么对应的内部存储也会与它们共享内存。 -- 转换函数(resetXXX): 包括`resetInValue`,`resetInGrad`,`resetOutValue`和`resetOutGrad`, -表示对输入数据,输入梯度,输出数据和输出梯度的转换。 -这些函数会根据输入参数重新设置内部和外部存储,当然这两者也可以相等,即表示不需要转换。 - -注意:每个`MKLDNNlayer`的子类只需要使用内部存储就可以了,所有外部的转换工作都会在reset系列函数中都准备好。 - -### Activations -在重构前的PaddlePaddle中,激活函数是独立于`Layer`的概念,并且输入输出都是共用一块内存, -所以添加了对应的`MKLDNNActivation`来实现,方式类似于`MKLDNNLayer`。 - -### Parameters -对于有参数的层,我们会保证`MKLDNNLayer`使用的参数与PaddlePaddle申请的buffer共用一块内存。 -如果存在数据排列格式不一样的情况时,我们会在网络训练之前把格式转换为MKL-DNN希望的格式, -在训练结束的时候再保存为PaddlePaddle的格式,但是整个训练过程中不需要任何转换。 -这样既使得最终保存的参数格式与PaddlePaddle一致,又可以避免不必要的转换。 - -### Gradients -由于MKL-DNN的操作都是直接覆盖的形式,也就是说输出的结果不会在原来的数据上累加, -这样带来的好处就是不需要一直清空memory,节省了不必要的操作。 -但是注意的是,当网络出现分支且在`backward`的时候,需要累加不同Layer传过来的梯度。 -所以在`MKLDNNlayer`中实现了一个merge的方法,此时每个小分支的`Input Gradient` -会先临时保存在`MKLDNNMatrix`中,由分支处的Layer负责求和,并把结果放到当前层的`output_.grad`中。 -所以整体上,在实现每个子类的时候就不需要关心分支的事情了。 - -
                                -
                                -Figure 5. Merge Gradients -
                                - -### Unit Tests -我们会添加`test_MKLDNN.cpp`和`MKLDNNTester.*`用于MKL-DNN的测试。 -测试分为每个Layer(或Activation)的单元测试和简单网络的整体测试。 -每个测试会对比PaddlePaddle中CPU算出的结果与MKL-DNN的结果,小于某个比较小的阈值认为通过。 - -### Python API -目前只考虑**v1 API**。 - -计划在`python/paddle/trainer/config_parser.py`里面添加`use_mkldnn`这个选择,方便用户选择使用MKL-DNN的layers。 - -具体实现方式比如: - -```python -use_mkldnn = bool(int(g_command_config_args.get("use_mkldnn", 0))) -if use_mkldnn - self.layer_type = mkldnn_* -``` - -所有MKL-DNN的`layer_type`会以*mkldnn_*开头,这些会在`MKLDNN*Layer`注册layer的时候保证,以示区分。 - -同时,会在`paddle/utils.Flags`中添加一个`use_mkldnn`的flag,用于选择是否使用MKL-DNN的相关功能。 - -### Benchmarking -会添加相应的脚本在[这里](https://github.com/PaddlePaddle/Paddle/tree/develop/benchmark/paddle/image),用于测试和对比在使用MKL-DNN前后的CNN网络性能。 -测试的性能对比结果会在[IntelOptimizedPaddle.md](https://github.com/PaddlePaddle/Paddle/blob/develop/benchmark/IntelOptimizedPaddle.md) - -### Others -1. 如果在使用MKL-DNN的情况下,会把CPU的Buffer对齐为4096,具体可以参考MKL-DNN中的[memory](https://github.com/01org/mkl-dnn/blob/master/include/mkldnn.hpp#L673)。 -2. 深入PaddlePaddle,寻找有没有其他可以优化的可能,进一步优化。比如可能会用OpenMP改进SGD的更新性能。 - -## Design Concerns - -为了更好的符合PaddlePaddle的代码风格\[[3](#references)\],同时又尽可能少的牺牲MKL-DNN的性能\[[4](#references)\]。 - -我们总结出一些特别需要注意的点: - -1. 使用**deviceId_**。为了尽可能少的在父类Layer中添加变量或者函数, -我们决定使用已有的`deviceId_`变量来区分layer的属性,定义`-2`为`MKLDNNLayer`特有的设备ID。 -2. 重写父类Layer的**init**函数,修改`deviceId_`为`-2`,代表这个layer是用于跑在MKL-DNN的环境下。 -3. 创建`MKLDNNBase`,定义一些除了layer和memory相关的类和函数。 -包括MKL-DNN会用到`MKLDNNStream`和`CPUEngine`,和未来可能还会用到`FPGAEngine`等。 -4. 如果MKL-DNN layer的后面接有cpu device,那么就会使`output_.value`与`extOutVal_`共享内存, -同时数据格式就是`NCHW`,这样下一个cpu device就能拿到正确的数据。 -在有普通的CPU layer时, `extOutVal_`和`extOutGrad_`的格式始终是`NCHW`或者`NC`。 - -## References -1. [MKL small library](https://github.com/01org/mkl-dnn#linking-your-application)是[Intel MKL](https://software.intel.com/en-us/mkl)的一个子集。 -主要包括了深度学习相关的数学原语与操作,一般由MKL-DNN在发布[新版本](https://github.com/01org/mkl-dnn/releases)时一起更新。 -2. [MKL-DNN System Requirements](https://github.com/01org/mkl-dnn#system-requirements)。 -目前在PaddlePaddle中,仅会在支持AVX2指令集及以上的机器才使用MKL-DNN。 -3. [原来的方案](https://github.com/PaddlePaddle/Paddle/pull/3096)会引入**nextLayer**的信息。 -但是在PaddlePaddle中,无论是重构前的layer还是重构后的op,都不会想要知道next layer/op的信息。 -4. MKL-DNN的高性能格式与PaddlePaddle原有的`NCHW`不同(PaddlePaddle中的cuDNN部分使用的也是`NCHW`,所以不存在这个问题)。 -所以需要引入一个转换方法,并且只需要在必要的时候转换这种格式,才能更好的发挥MKL-DNN的性能。 diff --git a/develop/doc_cn/_sources/design/mkl/mkldnn_fluid.md.txt b/develop/doc_cn/_sources/design/mkl/mkldnn_fluid.md.txt deleted file mode 100644 index bef126f3f05..00000000000 --- a/develop/doc_cn/_sources/design/mkl/mkldnn_fluid.md.txt +++ /dev/null @@ -1,149 +0,0 @@ -# Design Doc: Add MKLDNN Kernel in Fluid Operator - -## Principles - -First of all, we should follow some basical principles like: -1. [How to write a new operator](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/dev/new_op_en.md). We are trying to add a new kind of kernel into operators, so basically we should follow this doc. -2. [Supporting new Device/Library](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/support_new_device.md). Since MKLDNN is a new library to fluid, we should add `MKLDNNDeviceContext` and maybe `mkldnn_helper.h`, just like [cudnn_helper.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/cudnn_helper.h). -3. [Switch Kernel](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/switch_kernel.md). Another important point is that we should ensure the data synchronization between different kernel types, which is this [topic](https://github.com/PaddlePaddle/Paddle/issues/6549). So basically we should override `GetExpectedKernelType` and `trans` functions to support switching kernels. -4. [The Keys of Operator Kernel Type](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/operator_kernel_type.md). Kernel Type is a pivotal conception which can record the `Place`, `Library`, `DataType` and `Layout`. - -## Sulution - -In general, there are four parts we should follow to run a MKL-DNN primitive. -- Create a primitive descriptor that describe this operator -- Create a primitive itself by primitive descriptor and the engine -- Create all memory buffers that primitive needed -- Launch a stream to execute the primitive created -More details can refer to [here](http://01org.github.io/mkl-dnn). - -It's better to avoid reinitialization of primitives and memory handles in the first three stages in every iteration. \ -So we plan to create a map to record all the `primitive` and `memory`, which should not take too much memories as discussed [here](https://github.com/PaddlePaddle/Paddle/issues/6822). - -It's assumed that following three conditions should be satisfied. -1. there is a unique key for each operator instance. May be the actual name of `Output Tensor`. -2. the `Input Tensor` inside `Compute` function is the one after converted. -3. we can get the phase(eg. `is_test`) inside `Compute` function, otherwise we need to expose this attribue to user. - -### Compute -The algorithm of `Compute` would be described as follow, let's take conv like an example. - -```c++ - - PADDLE_ENFORCE(platform::is_cpu_place(ctx.GetPlace()), "It must use CPUPlace."); - PADDLE_ENFORCE(platform::is_mkldnn_library(ctx.GetLibrary()), "It must use MKLDNN Library."); - - auto& dev_ctx = ctx.template device_context(); - - // find primitive by unique key from mkldnn context - // the op_key should be a unique name of this op instance - auto& p = dev_ctx.findPrimitive(op_key + "_fwd"); - - // assuming the input tensor inside this compute function is the one after converted - // this point should be guarantee by another mechanism - auto& i = dev_ctx.findMemory(op_key + "_input"); - - if (p == nullptr || i == nullptr || inputSizeChanged(p, i)) { - auto fwd_primitive_desc = createPrimitiveDesc(ctx); - auto* input = ctx.Input("Input"); - auto* filter = ctx.Input("Filter"); - auto* output = ctx.Output("Output"); - shared_ptr in(new mkldnn::memory(fwd_primitive_desc->src_primitive_desc(), input->data())); - shared_ptr wgt(new mkldnn::memory(fwd_primitive_desc->weights_primitive_desc(), filter->data())); - shared_ptr out(new mkldnn::memory(fwd_primitive_desc->dst_primitive_desc(), output->mutable_data(ctx.GetPlace()))); - shared_ptr fwd_primitive(new mkldnn::conv_fwd(*fwd_primitive_desc, *in, *wgt, *out)); - - dev_ctx.addMemory(op_key+"_input", in); - dev_ctx.addMemory(op_key+"_output", out); - dev_ctx.addMemory(op_key+"_filer", wgt); - dev_ctx.addPrimitive(op_key+"_fwd", fwd_primitive); - dev_ctx.addPrimitiveDesc(op_key+"_fwd_PD", fwd_primitive_desc); - } - - p = dev_ctx.findPrimitive(op_key + "_fwd"); - - PADDLE_ENFORCE(p, "Should have forward Primitive"); - PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_input"), "Should have input memory"); - PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_output"), "Should have output memory"); - PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_filter"), "Should have filter memory"); - PADDLE_ENFORCE(dev_ctx.findPrimitiveDesc(op_unique_key+"_fwd_PD"), "Should have forward PrimitiveDesc"); - dev_ctx.submit(p); - dev_ctx.execute(); // the convert primitive should have already contained. - -``` - -The `createPrimitiveDesc` returns the primitive descripotor of this operator, would be like this: -```c++ - auto* input = ctx.Input("Input"); - auto* filter = ctx.Input("Filter"); - auto* output = ctx.Output("Output"); - std::vector strides = ctx.Attr>("strides"); - std::vector paddings = ctx.Attr>("paddings"); - std::vector dilations = ctx.Attr>("dilations"); - int groups = ctx.Attr("groups"); - algorithm algo = static_cast(ctx.Attr("convolution_algorithm_option")); - prop_kind pk = ctx.Attr("is_test") ? prop_kind::forward_inference : prop_kind::forward_training; - - auto fwd_desc = mkldnn::conv_fwd::desc(/* all the setting above*/); - shared_ptr fwd_primitive_desc(new mkldnn::conv_fwd::primitive_desc(fwd_desc, ctx.getEngine())); - - return fwd_primitive_desc; - } -``` - -### MKLDNNDeviceContext -`MKLDNNDeviceContext`, which is very straightforward, should contain some base information like: `stream`, `engine` and the map needed. - - -### mkldnn_helper -Some functions would be put in `paddle/platform/mkldnn_helper.h`. -- create MKLDNN memories -- create MKLDNN primitives -- error check function -- etc - - -### Kernel Switch -We should `reorder` the different Layout from other device or to other device. `GetExpectedKernelType` and `trans` functions can help us to implement it. - -`GetExpectedKernelType` should get the context, and this operator can return the best `KernelType`. -`trans` would be like this: - -```c++ -void trans(inputs, ctx) override { - if (NoNeedTrans()) { - return; - } - // find reorder primitive by op_key from context - auto& dev_ctx = ctx.template device_context(); - auto& p = dev_ctx.findPrimitive(op_key + "_reorder_input"); - auto& i = dev_ctx.findMemory(op_key + "_src_input"); - - if (p == nullptr || i == nullptr || changeSized(i, input)) { - auto prim = createPrimitiveDesc(ctx); - auto src = createMemory(memoryDesc(input->dims(), actual_layout), input->data); - auto newbuffer = paddle::memory::Alloc(ctx.GetPlace(), input->size_in_bytes()); - auto dst = createMemory(p->expected_desc(), newbuffer->data); - auto reorder_primitive(new mkldnn::reorder(src, dst)); - - dev_ctx.addMemory(op_key+"_src_input", src); - dev_ctx.addMemory(op_key+"_input", dst); - dev_ctx.addPrimitive(op_key+"_reorder_input", reorder_primitive); - } - - p = dev_ctx.findPrimitive(op_key + "_reorder_input"); - PADDLE_ENFORCE(p, "Should have Reorder Primitive"); - dev_ctx.submit(p); - if (! this->isMKLDNNKernel()) { - // execute immediately only if this is not mkldnn kernel function. - // otherwise, it can be executed with the operator primitive in Compute - dev_ctx.stream(); - } - // after submit, the input tensor in ExecutionContext should be changed as the converted one - // there should be another mechanism to ensure this -} -``` - -### Unit Test -All the functions should be tested corresponding. -TBD diff --git a/develop/doc_cn/_sources/design/model_format.md.txt b/develop/doc_cn/_sources/design/model_format.md.txt deleted file mode 100644 index e29129fddf7..00000000000 --- a/develop/doc_cn/_sources/design/model_format.md.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Design Doc: Model Format - -## Motivation - -A model is an output of the training process. One complete model consists of two parts, the **topology** and the **parameters**. In order to support industrial deployment, the model format must be self-complete and must not expose any training source code. - -As a result, In PaddlePaddle, the **topology** is represented as a [ProgramDesc](https://github.com/PaddlePaddle/Paddle/blob/1c0a4c901c9fc881d120249c703b15d1c50dae7d/doc/design/program.md), which describes the model structure. The **parameters** contain all the trainable weights in the model. We must support large size parameters and efficient serialization/deserialization of parameters. - -## Implementation - -The topology is saved as a plain text in a detailed self-contain protobuf file. - -The parameters are saved as a binary file. As we all know, the protobuf message has a limit of [64M size](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.io.coded_stream#CodedInputStream.SetTotalBytesLimit.details). We have done a [benchmark experiment](https://github.com/PaddlePaddle/Paddle/pull/4610), which shows that protobuf is not fit for the task. - -As a result, we design a particular format for tensor serialization. By default, an arbitrary tensor in Paddle is a [LoDTensor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/lod_tensor.md), and has a description information proto of [LoDTensorDesc](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto#L99). We save the DescProto as the byte string header. It contains all the necessary information, such as the `dims`, and the `LoD` information in [LoDTensor](https://github.com/PaddlePaddle/Paddle/blob/1c0a4c901c9fc881d120249c703b15d1c50dae7d/paddle/framework/lod_tensor.md). A tensor stores values in a continuous memory buffer. For speed we dump the raw memory to disk and save it as the byte string content. So, the binary format of one tensor is, - -The table below shows a tensor's byte view in detail. Note that all the signed values are written in the little-endian format. - -|field name | type | description | -| --- | --- | --- | -| version | uint32_t | Version of saved file. Always 0 now. | -| tensor desc length | uint32_t | TensorDesc(Protobuf message) length in bytes. | -| tensor desc | void* | TensorDesc protobuf binary message | -| tensor data | void* | Tensor's data in binary format. The length of `tensor_data` is decided by `TensorDesc.dims()` and `TensorDesc.data_type()` | -| lod_level | uint64_t | Level of LoD | -| length of lod[0] | uint64_t | [Optional] length of lod[0] in bytes. | -| data of lod[0] | uint64_t* | [Optional] lod[0].data() | -| ... | ... | ... | - - - -## Summary - -- We introduce a model format. -- The model represented by its forward-pass computation procedure is saved in a **ProgramDesc** protobuf message. -- A bunch of specified format binary tensors describe the **parameters**. diff --git a/develop/doc_cn/_sources/design/multi_language_interface/00.why_plain_c.md.txt b/develop/doc_cn/_sources/design/multi_language_interface/00.why_plain_c.md.txt deleted file mode 100644 index a1443093342..00000000000 --- a/develop/doc_cn/_sources/design/multi_language_interface/00.why_plain_c.md.txt +++ /dev/null @@ -1,118 +0,0 @@ -# Paddle多语言接口实现 -## 背景 - -Paddle需要一个多语言接口,这个接口需要做到: - -* 有标准的,良好的文档 - * 例如Python可以使用[Sphinx](http://www.sphinx-doc.org/en/stable/)生成API文档,golang可以使用[GoDoc](https://godoc.org/golang.org/x/tools/cmd/godoc)生成文档。这都需要这个接口按照约定俗成的规则来注释完备。 -* 不同语言的接口适应不同语言的特性 - * 例如Java与Python的错误处理是直接扔出来Exception,而对于golang错误处理应该使用返回值。 - -## 基本要求 - -Paddle的多语言接口实现包括一下几个方面: - -* 我们使用动态库来分发Paddle。在这个动态库中不嵌入任何其他语言的解释器,也不使用其他动态库。 -* 这个动态库使用C99标准的头文件导出一些函数,不使用/导出C++符号。 -* 不导出Paddle内部的结构体、类,仅仅使用`void*`指针作为类型的句柄(handler)。 -* 不使用SWIG这种代码生成器,而是手写多语言绑定。 - - -## 原因 - -### 使用动态库来分发Paddle - -* Paddle的链接方式比较复杂 - * 如果用户要把Paddle的静态库(libpaddle.a)链接到自己的程序里,得使用 `--whole-archive` (for GCC) 或者 `--force_load` (for Clang) 参数,来确保把 libpaddle.a 里所有的符号都写入自己的程序的二进制文件里。这是因为 Paddle 的源码里使用了[object factory design pattern](http://stackoverflow.com/a/1310326/724872)。 -* 编译型语言,例如C/C++使用静态库和动态库难度差不多。但是解释性语言,例如[Python](http://stackoverflow.com/questions/19560594/how-to-import-static-library-in-python)或者[Java](http://stackoverflow.com/questions/24493337/linking-static-library-with-jni),只能调用Paddle的动态库,否则得把Paddle静态库链接到解释器里。 - * 解释性语言实际运行的二进制是解释器本身,如果调用静态库只能将静态库与解释器链接。例如对于Java来说,便是将静态库加入JVM中。这对于通常的Java的开发者来说,是不常见的做法。 - -### 动态库中不嵌入任何其他语言的解释器 - -* 目前Paddle的进程模型是C++内部驱动Python解释器进行模型配置解析和数据读取 -* 我们最终的动态库中不嵌入Python或者其他任何语言的解释器。模型配置解析,数据读取均交由其他语言完成 - -现阶段Paddle有一个问题是,Paddle内嵌的Python解释器和外部使用的Python如果版本不同,会直接报错退出。 - -### Paddle动态库中,不引用其他动态库 - -* 即这个动态库是不依赖于其他任何文件的,可以在任何机器上执行的。 - -### 这个动态库使用C99标准的头文件导出一些函数,不使用/导出C++符号 - -* 由于C++编译器没有[名字修饰](https://en.wikipedia.org/wiki/Name_mangling#C.2B.2B)的规范,不同版本的编译器之间,对于同一段C++代码生成的符号可能不一致。而多语言接口需要直接读取生成的二进制(动态库),需要有稳定的导出符号。 -* C语言是有导出符号的标准的,并且在常见的平台上,都是ABI调用标准的。 -* 大多数语言都支持使用C语言API -* 使用C99而不使用C89,是因为C99支持[Fixed-width integer types](https://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types)和[Boolean type](https://en.wikipedia.org/wiki/C_data_types#Boolean_type)。 -* 使用C99而不使用C11的原因是,[C11](https://en.wikipedia.org/wiki/C11_(C_standard_revision))并没有Paddle特别需要的特性,且C99相对于C11使用更加广泛。 - -### 不导出Paddle内部的结构体、类,仅仅使用`void*`指针作为类型的句柄(handler) - -* Paddle内部的类为C++书写,直接导出到C的接口比较困难。 -* 在C-API中使用`void*`来表示Paddle内部类。再在每一个API中自己检查类型。 - -在C的头文件 `paddle_matrix.h` 中: - -```C -typedef void* paddle_matrix; -typedef int paddle_error; - -extern "C" -paddle_error paddle_matrix_get_shape(paddle_matrix matrix, - uint64_t* width, - uint64_t* height); -``` -而在CPP里面实现这个C的接口,文件 `paddle_matrix.cpp` - -```cpp -#include "paddle/math/matrix.h" -extern "C" -paddle_error paddle_matrix_shape(paddle_matrix matrix, - uint64_t *width, - uint64_t *height) { - auto m = (paddle::capi::CMatrix*)(matrix); - *width = m->width(); - *height = m->height(); -} -``` - -其中`paddle/capi/CMatrix.hpp`文件内容为: - -```cpp -namespace paddle { -namespace math { - -class CMatrix { - std::shared_ptr mat; -}; - -} // namespace math -} // namespace paddle -``` - -### 不使用SWIG这种代码生成器,而是手写多语言绑定 - -* [SWIG](http://www.swig.org/)是一个多语言接口的代码生成器。他的目标是使用C/C++写代码,SWIG直接读取C/C++的头文件,生成各种语言的绑定代码。 - * 对于多语言接口,SWIG需要写一个interface文件。这个文件具有独特的语法,学习成本高。且增加一个第三方语言,就需要对这个第三方语言增加一些定义。有的时候,interface文件的写法非常[tricky](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/api/Paddle.swig#L36)。社区贡献代码学习成本高。 - * SWIG暴露的接口保留了C++的接口样式,很难保证多语言代码风格的一致性。(函数命名,错误处理) - * 因为SWIG在第三方语言中暴露的函数名,类名和C++中完全一致。C++的命名风格并不能适应其他第三方语言。如果使用SWIG我们需要将在interface文件里,将大量的`SomeCppClass`重命名成`some_python_class`,或者`SomeGoTypes`。 - * 对于不同语言,错误处理的方式也不尽相同。例如对于Java或者Python,最常见的错误处理方式是Exception,而对于Golang,错误处理方式是返回值。而SWIG只能简单的暴露C++接口,无法做到对于各种语言错误处理方式的适配。 - * 对于大多数语言,直接使用C语言的.h并不困难。例如Python的[cffi](https://cffi.readthedocs.io/en/latest/overview.html#simple-example-abi-level-in-line)或者[Cython](http://cython.org/), golang的[cgo](https://golang.org/cmd/cgo/)。 - * SWIG支持的语言或者解释器有局限。例如对于Python,使用SWIG只支持CPython解释器,而不支持PyPy解释器。 - - -## 原因列表 - -| 结论 | 对比 | 原因 | -|---| --- | --- | -| 使用动态库 | 不使用静态库 | 解释型语言只能调用动态库,Paddle静态库链接复杂 | -| 不嵌入其他语言解释器 | 不嵌入Python解释器 | Paddle C++目前嵌入Python解释器,会导致不同版本Python在一个进程里的bug | -| 不引用其他动态库 | | Paddle一个动态库可以在任何Linux系统上运行 | -| 使用C99做接口 | 不使用C++做接口 | C有标准的ABI,C99是目前C最广泛的使用标准,且C99支持bool类型和定长整数(uint64_t等)类型 | -| 使用void*作为类句柄 | 不显示的写每个类具体包含什么| 实现简单,并且让接口脱离实现细节 | -| 手写多语言绑定 | 不使用SWIG | 使用SWIG需要多语言绑定的开发人员熟练掌握SWIG配置,社区参与困难。SWIG生成的代码不能保证多语言代码风格的一致性 | - - -## 实现 - -参考[Inference implementation](01.inference_implementation.md) diff --git a/develop/doc_cn/_sources/design/multi_language_interface/01.inference_implementation.md.txt b/develop/doc_cn/_sources/design/multi_language_interface/01.inference_implementation.md.txt deleted file mode 100644 index 98202845232..00000000000 --- a/develop/doc_cn/_sources/design/multi_language_interface/01.inference_implementation.md.txt +++ /dev/null @@ -1,131 +0,0 @@ -# C-API 模型推断实现文档 - -本文档描述Paddle C-API的实现细节。Paddle C-API是多语言API的基础部分。Paddle需要暴露的API很多。先实现模型推断的API,通过模型推断API的实现作为一个样例,来进行讨论。至于为什么需要C-API,请参考[Why Plain C](./00.why_plain_c.md)。 - -## Table of Contents - * [C-API 模型推断实现文档](#c-api-模型推断实现文档) - * [暴露接口原则](#暴露接口原则) - * [目录结构](#目录结构) - * [实现方式](#实现方式) - * [capi.h](#capih) - * [具体某种类型的头文件](#具体某种类型的头文件) - * [capi_private.h](#capi_privateh) - * [具体某种类型的实现文件](#具体某种类型的实现文件) - * [libpaddle_capi_shared.{so, dylib}](#libpaddle_capi_sharedso-dylib) - * [libpaddle_capi_whole.a](#libpaddle_capi_wholea) - * [examples](#examples) - * [编译选项](#编译选项) - - -## 暴露接口原则 - -1. 所有的接口均为C接口。即使用`extern "C"` -2. 除构造某种类型的函数(`paddle_matrix_create`等),其他函数均返回`paddle_error`。且调用时不能抛出异常或出现运行时错误。 -3. 所有类型名为`paddle_类型名`,所有与类型相关的函数,函数名为`paddle_类型名_函数名` -4. 如果某一个Paddle Core概念(GradientMachine/Matrix)需要被暴露到其他语言,那么 - * 为了暴露的接口尽量简单。只暴露概念的接口,而不暴露概念的实现。即暴露`GradientMachine`或者`Matrix`但不暴露`RecurrentGradientMachine`和`CpuSparseMatrix`。 - * 暴露这个概念必要函数。`必要`是指,即完成某一个任务的最少函数。 -5. 不在`capi`接口层做过多封装。 - * 如果某一个Paddle概念必须要暴露,但是又过于琐碎。不在`capi`这一层进行封装,而是直接修改Paddle Core。让Paddle核心中,这一概念不再琐碎。 - - -## 目录结构 - -```text -Paddle - `-- paddle - `-- capi - `-- examples # The example project for C-API. - `-- tests # unittests for C-API - `-- capi.h # C-API header file. - `-- capi_private.h # The shared header file between implementation sources. - `-- matrix.{h, cpp} - `-- gradient_machine.{h, cpp} - `-- ... -``` - - -Paddle的C-API目录结构如上图表所示。这个目录中除了`capi_private.h`之外的所有头文件,均会被安装到include/paddle路径下。C-API生成的二进制文件会被安装到`lib`目录下。即,安装后的目录结构为 - -```text -`-- include - `-- paddle - `-- capi.h - `-- matrix.h - `-- gradient_machine.h - `-- ... -`-- lib - `-- libpaddle_capi_shared.{so, dylib} # In mac, dynamic libary's file name extention is `dylib` - `-- libpaddle_capi_whole.a # static library for all symbols of Paddle. -``` - -## 实现方式 - -下面分别介绍某一类文件的实现方式。 - -### capi.h - -`capi.h`是用户使用C-API时所唯一需要引入的头文件。在`capi.h`中,引入了类型的头文件,`matrix.h`, `gradient_machine.h`。在引入其他类型的头文件时,使用相对路径的引用方式。即`#include "matrix.h"` - -### 具体某种类型的头文件 - -具体某种类型的头文件,即例如`matrix.h`,`gradient_machine.h`等。在这些头文件中,包含了某种类型的类型定义和暴露的全部函数。 - -这个头文件不假设其他文件的引用顺序,即使用户直接引用某种类型的头文件,也不应该报错(虽然不鼓励这样)。如果某一个类型需要引用另一个类型,例如`gradient_machine`需要引用`matrix`,则直接引入另一种类型的头文件,即`#include "matrix.h"`。 - -### capi_private.h - -`capi_prviate.h`是各个实现中共享的头文件,他主要包含了实际暴露的类型结构。在用户使用C-API时,Paddle的类型全部退化成`void *`,即`typedef paddle_matrix void*`。但,对于每种C-API暴露的类型,均是在`capi_private.h`中实现的结构体。 - -```cpp -struct CMatrix { - int type = MatrixType; - std::shared_ptr mat; -}; -``` - -通常,这个结构体包含两个项目。 - -* `type`是一个类型的标志。对于每种类型,type字段均不尽相同。这样,即使C-API接受的类型全是`void *`,我们也可以确定每一个参数的类型。 - - ```cpp - void some_c_api_function(void* some_instance) { - int* type = (int *) some_instance; - switch (*type) { - case MatrixType: - CMatrix* mat = (CMatrix *) some_instance; - ... - ... - } - } - ``` -* 这个结构体中的另一个项目是,Paddle Core中这一类型接口的智能指针(shared_ptr)。 - * 使用智能指针的原因是: 用户可以安全的释放某个C-API的实例,而不必在意Paddle Core是否还在使用这个实例。 - * 例如,用户通过C-API获得了神经网络的参数实例。当用户使用完这个参数后,直接删除这个参数即可。即便Paddle Core中的模型还在使用这个参数,这个参数也不会一并删除。 - -### 具体某种类型的实现文件 - -具体某种类型的实现文件,即`matrix.cpp`, `gradient_machine.cpp`等文件。在这些文件中,使用C++ 11实现了C-API的接口,并且使用`extern "C"`导出这些接口。在实现过程中,对输入参数的安全性进行了必要的判断,并将C-API接口的参数转发给`Paddle Core`。 - -### libpaddle\_capi_shared.{so, dylib} - -`libpaddle_capi_shared`是C-API导出的动态库。这个动态库的连接参数与Paddle的其他二进制(例如`paddle_trainer`)类似。用户可以直接使用这个动态库来引入Paddle C-API。具体使用方法为`-lpaddle_capi_shared`。 - -### libpaddle\_capi_whole.a - -`libpaddle_capi_whole`是C-API导出的静态库。这个静态库包含了Paddle的全部符号。他是将`libpaddle_gserver.a`, `libpaddle_math.a`, `libpaddle_capi.a`等全部静态库中的目标文件全部打包后产生的文件。具体使用方法为`--whole-archive -lpaddle_capi_whole --no-whole-archive`。 - - -### examples - -在样例中,使用`C99`开发了模型预测的样例代码。具体请参考[example/README.md](../../../paddle/capi/examples/README.md)。 - -## 编译选项 - -C-API的编译选项默认关闭,打开这个编译选项,需要在cmake的时候,设置 - -```bash -cmake ${YOUR_SOURCE_ROOT} -DWITH_C_API=ON -DWITH_PYTHON=OFF -DWITH_SWIG_PY=OFF -``` - -编译C-API的时候推荐Paddle不嵌入Python解释器,也不生成`SWIG`接口,具体原因参考[Why Plain C](./00.why_plain_c.md)。 diff --git a/develop/doc_cn/_sources/design/operator_kernel_type.md.txt b/develop/doc_cn/_sources/design/operator_kernel_type.md.txt deleted file mode 100644 index f86e6b7a564..00000000000 --- a/develop/doc_cn/_sources/design/operator_kernel_type.md.txt +++ /dev/null @@ -1,91 +0,0 @@ -# Design Doc: The Keys of Operator Kernel Type -## Problem -An operator can have different kernel implementations, and each operator will have a map to store the related kernels. Fluid uses `OpKernelType` as a key to identify a unique kernel. Before an operator runs, a certain type of kernel must be chosen via a key of `OpKernelType`. Currently, `OpKernelType` is defined as follows: - -```cpp -struct OpKernelType { - platform::Place place_; - proto::DataType data_type_; -}; -``` -For more details, please refer to [codes](https://github.com/PaddlePaddle/Paddle/blob/2d5ec16bc8a09fb8e0f62c89b116b0cd1d333907/paddle/framework/operator.h#L348-L374) in github. - -It contains two keys, `Place` and `DataType`. And these two keys will be hashed to a unique key to represent a certain type of kernel. However, these two keys do not provide enough information. We need a more complete representation of `OpKernelType`. - -We often implement a kernel of an operator with some computing library on certain device(place). Please note that computing library and device do not have a one-to-one correspondence. A device can have a lot of computing libraries and a computing library can also support different devices. - -For example, Eigen library supports Nvidia GPU/AMD GPU/CPU and MKLDNN library supports Intel CPU/Intel FPGA. Both `Place` and `Library` should be a key of `OpKernelType`. - -Different DataTypes, such as fp64/fp32/int8, will obviously have different kernels. But different data layout of a Tensor will also lead to different implementations. Please refer to the batch norm operator [kernels](https://github.com/PaddlePaddle/Paddle/blob/a948fac4d0ad7e0412d373b8aabeb711c2899563/paddle/operators/batch_norm_op.cc#L180-L209) as an example. Data layout should also be taken into consideration. - -## Solution - -There are four keys to determine a kernel type of an operator: `Place`/`Library`/`DataType`/`Layout`. - -```cpp -struct OpKernelType { - platform::Place place_; - platform::Library library_; - proto::DataType data_type_; - framework::Layout layout_; -}; -``` - -The details are as follows: - -### Place - -`Place` is defined as: - -```cpp -typedef boost::variant Place; -``` - -`Place` represents the device memory where data is located. - - -### Library - -One operator kernel is usually implemented based on one library. `Library` is defined as a enum variable: - -```cpp -enum Library { Plain, MKLDNN, CUDNN }; -``` - -We use `Plain` enumerator to represent default library. Since most operators in Fluid are implemented based on the `Eigen` library, we take `Eigen` library as the `Plain` enumerator. -A library usually has a corresponding `DeviceContext` which contains some handles needed for computation. Fluid now has two default DeviceContexts for CPU and CUDA, namely, `CPUDeviceContext` and `CUDADeviceContext`. `CPUDeviceContext` contains an Eigen library handle and `CDUADeviceContext` contains an Eigen library handle and a cuBLAS handle. - -If we want to support new library, a new enumerator need to be added to `Library` and a corresponding new `LibraryDeviceContext` need to be created. - - -### DataType - - -`DataType` is defined in [framework.proto](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto). Currently, int32/int64/fp32/fp64 are supported. - -### Layout - -Actually, a Tensor is a view of a block of memory. Besides a pointer to the memory, we also have to get some other descriptions of this block of memory, such as shape(ddim), stride, and layout. - -Different layout leads to different implementation of the operator kernel. There are mainly 4 principles we have to follow to support layout in our Fluid framework. - -- We take layout as a data member of Tensor. Layout is actually a enum variable. If Fluid is built with MKLDNN, then the memory format in MKLDNN will also be added into this enum variable. - -- Users have to set layout for input data. And some operators like fill_constant/random, also have to set layout for generating data. Of course, we can have some default layout, like NCHW. - -- The inference of Layout is at run-time, not at compile-time. - -- Every operator has to implement different kernels for different layouts. Let's take MKLDNN as an example. If we want to implement an MKLDNN convolution operator, we have to implement all the kernels for different layouts, which are listed [here](http://01org.github.io/mkl-dnn/structmkldnn_1_1memory.html). And we will have a special macro to register kernels for MKLDNN operators. - -`Layout` is also defined as a enum variable: - -```cpp -enum Layout { - kNCHW, - kNHWC, -#ifdef PADDLE_WITH_MKLDNN - knChw8c - ... -#endif -}; -``` diff --git a/develop/doc_cn/_sources/design/ops/rnn.md.txt b/develop/doc_cn/_sources/design/ops/rnn.md.txt deleted file mode 100644 index 2f4854793fa..00000000000 --- a/develop/doc_cn/_sources/design/ops/rnn.md.txt +++ /dev/null @@ -1,153 +0,0 @@ -# RNNOp design - -This document describes the RNN (Recurrent Neural Network) operator and how it is implemented in PaddlePaddle. The RNN op requires that all instances in a mini-batch have the same length. We will have a more flexible dynamic RNN operator in the future. - -## RNN Algorithm Implementation - -

                                - -

                                - -The above diagram shows an RNN unrolled into a full network. - -There are several important concepts here: - -- *step-net*: the sub-graph that runs at each step. -- *memory*, $h_t$, the state of the current step. -- *ex-memory*, $h_{t-1}$, the state of the previous step. -- *initial memory value*, the memory of the first (initial) step. - -### Step-scope - -There could be local variables defined in each step-net. PaddlePaddle runtime realizes these variables in *step-scopes* which are created for each step. - -

                                -
                                -Figure 2 illustrates the RNN's data flow -

                                - -Please be aware that every step runs the same step-net. Each step does the following: - -1. Creates the step-scope. -2. Initializes the local variables including step-outputs, in the step-scope. -3. Runs the step-net, which uses the above mentioned variables. - -The RNN operator will compose its output from step outputs in each of the step scopes. - -### Memory and Ex-memory - -Let's give more details about memory and ex-memory using a simple example: - -$$ -h_t = U h_{t-1} + W x_t -$$, - -where $h_t$ and $h_{t-1}$ are the memory and ex-memory (previous memory) of step $t$ respectively. - -In the implementation, we can make an ex-memory variable either "refer to" the memory variable of the previous step, -or copy the memory value of the previous step to the current ex-memory variable. - -### Usage in Python - -For more information on Block, please refer to the [design doc](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/block.md). - -We can define an RNN's step-net using a Block: - -```python -import paddle as pd - -X = some_op() # x is some operator's output and is a LoDTensor -a = some_op() - -# declare parameters -W = pd.Variable(shape=[20, 30]) -U = pd.Variable(shape=[20, 30]) - -rnn = pd.create_rnn_op(output_num=1) -with rnn.stepnet(): - x = rnn.add_input(X) - # declare a memory (rnn's step) - h = rnn.add_memory(init=a) - # h.pre_state(), the previous memory of rnn - new_state = pd.add_two( pd.matmul(W, x) + pd.matmul(U, h.pre_state())) - # update current memory - h.update(new_state) - # indicate that h variables in all step scopes should be merged - rnn.add_outputs(h) - -out = rnn() -``` - -Python API functions in above example: - -- `rnn.add_input`: indicates that the parameter is a variable that will be segmented into step-inputs. -- `rnn.add_memory`: creates a variable used as the memory. -- `rnn.add_outputs`: marks the variables that will be concatenated across steps into the RNN output. - -### Nested RNN and LoDTensor - -An RNN whose step-net includes other RNN operators is known as an *nested RNN*. - -For example, we could have a 2-level RNN, where the top level corresponds to paragraphs, and the lower level corresponds to sentences. Each step of the higher level RNN also receives an input from the corresponding step of the lower level, and additionally the output from the previous time step at the same level. - -The following figure illustrates feeding in text into the lower level, one sentence at a step, and the feeding in step outputs to the top level. The final top level output is about the whole text. - -

                                - -

                                - -```python -import paddle as pd - -W = pd.Variable(shape=[20, 30]) -U = pd.Variable(shape=[20, 30]) - -W0 = pd.Variable(shape=[20, 30]) -U0 = pd.Variable(shape=[20, 30]) - -# a is output of some op -a = some_op() - -# chapter_data is a set of 128-dim word vectors -# the first level of LoD is sentence -# the second level of LoD is a chapter -chapter_data = pd.Variable(shape=[None, 128], type=pd.lod_tensor, level=2) - -def lower_level_rnn(paragraph): - ''' - x: the input - ''' - rnn = pd.create_rnn_op(output_num=1) - with rnn.stepnet(): - sentence = rnn.add_input(paragraph, level=0) - h = rnn.add_memory(shape=[20, 30]) - h.update( - pd.matmul(W, sentence) + pd.matmul(U, h.pre_state())) - # get the last state as sentence's info - rnn.add_outputs(h) - return rnn - -top_level_rnn = pd.create_rnn_op(output_num=1) -with top_level_rnn.stepnet(): - paragraph_data = rnn.add_input(chapter_data, level=1) - low_rnn = lower_level_rnn(paragraph_data) - paragraph_out = low_rnn() - - h = rnn.add_memory(init=a) - h.update( - pd.matmul(W0, paragraph_data) + pd.matmul(U0, h.pre_state())) - top_level_rnn.add_outputs(h) - -# output the last step -chapter_out = top_level_rnn(output_all_steps=False) -``` - -In the above example, the construction of the `top_level_rnn` calls `lower_level_rnn`. The input is an LoD Tensor. The top level RNN segments input text data into paragraphs, and the lower level RNN segments each paragraph into sentences. - -By default, the `RNNOp` will concatenate the outputs from all the time steps. -If the `output_all_steps` is set to False, it will only output the final time step. - - -

                                - -

                                diff --git a/develop/doc_cn/_sources/design/ops/sequence_decoder.md.txt b/develop/doc_cn/_sources/design/ops/sequence_decoder.md.txt deleted file mode 100644 index c4a9bbeeefc..00000000000 --- a/develop/doc_cn/_sources/design/ops/sequence_decoder.md.txt +++ /dev/null @@ -1,229 +0,0 @@ -# Design: Sequence Decoder Generating LoDTensors -In tasks such as machine translation and visual captioning, -a [sequence decoder](https://github.com/PaddlePaddle/book/blob/develop/08.machine_translation/README.md) is necessary to generate sequences, one word at a time. - -This documentation describes how to implement the sequence decoder as an operator. - -## Beam Search based Decoder -The [beam search algorithm](https://en.wikipedia.org/wiki/Beam_search) is necessary when generating sequences. It is a heuristic search algorithm that explores the paths by expanding the most promising node in a limited set. - -In the old version of PaddlePaddle, the C++ class `RecurrentGradientMachine` implements the general sequence decoder based on beam search, due to the complexity involved, the implementation relies on a lot of special data structures that are quite trivial and hard to be customized by users. - -There are a lot of heuristic tricks in the sequence generation tasks, so the flexibility of sequence decoder is very important to users. - -During the refactoring of PaddlePaddle, some new concepts are proposed such as: [LoDTensor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/lod_tensor.md) and [TensorArray](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/tensor_array.md) that can better support the sequence usage, and they can also help make the implementation of beam search based sequence decoder **more transparent and modular** . - -For example, the RNN states, candidates IDs and probabilities of beam search can be represented all as `LoDTensors`; -the selected candidate's IDs in each time step can be stored in a `TensorArray`, and `Packed` to the sentences translated. - -## Changing LoD's absolute offset to relative offsets -The current `LoDTensor` is designed to store levels of variable-length sequences. It stores several arrays of integers where each represents a level. - -The integers in each level represent the begin and end (not inclusive) offset of a sequence **in the underlying tensor**, -let's call this format the **absolute-offset LoD** for clarity. - -The absolute-offset LoD can retrieve any sequence very quickly but fails to represent empty sequences, for example, a two-level LoD is as follows -```python -[[0, 3, 9] - [0, 2, 3, 3, 3, 9]] -``` -The first level tells that there are two sequences: -- the first's offset is `[0, 3)` -- the second's offset is `[3, 9)` - -while on the second level, there are several empty sequences that both begin and end at `3`. -It is impossible to tell how many empty second-level sequences exist in the first-level sequences. - -There are many scenarios that rely on empty sequence representation, for example in machine translation or visual captioning, one instance has no translation or the empty candidate set for a prefix. - -So let's introduce another format of LoD, -it stores **the offsets of the lower level sequences** and is called **relative-offset** LoD. - -For example, to represent the same sequences of the above data - -```python -[[0, 3, 6] - [0, 2, 3, 3, 3, 9]] -``` - -the first level represents that there are two sequences, -their offsets in the second-level LoD is `[0, 3)` and `[3, 5)`. - -The second level is the same with the relative offset example because the lower level is a tensor. -It is easy to find out the second sequence in the first-level LoD has two empty sequences. - -The following examples are based on relative-offset LoD. - -## Usage in a simple machine translation model -Let's start from a simple machine translation model that is simplified from the [machine translation chapter](https://github.com/PaddlePaddle/book/tree/develop/08.machine_translation) to draw a blueprint of what a sequence decoder can do and how to use it. - -The model has an encoder that learns the semantic vector from a sequence, and a decoder which uses the sequence encoder to generate new sentences. - -**Encoder** -```python -import paddle as pd - -dict_size = 8000 -source_dict_size = dict_size -target_dict_size = dict_size -word_vector_dim = 128 -encoder_dim = 128 -decoder_dim = 128 -beam_size = 5 -max_length = 120 - -# encoder -src_word_id = pd.data( - name='source_language_word', - type=pd.data.integer_value_sequence(source_dict_dim)) -src_embedding = pd.embedding(size=source_dict_size, size=word_vector_dim) - -src_word_vec = pd.lookup(src_embedding, src_word_id) - -encoder_out_seq = pd.gru(input=src_word_vec, size=encoder_dim) - -encoder_ctx = pd.last_seq(encoder_out_seq) -# encoder_ctx_proj is the learned semantic vector -encoder_ctx_proj = pd.fc( - encoder_ctx, size=decoder_dim, act=pd.activation.Tanh(), bias=None) -``` - -**Decoder** - -```python -def generate(): - decoder = pd.while_loop() - with decoder.step(): - decoder_mem = decoder.memory(init=encoder_ctx) # mark the memory - generated_ids = decoder.memory() # TODO init to batch_size s - generated_scores = decoder.memory() # TODO init to batch_size 1s or 0s - - target_word = pd.lookup(trg_embedding, gendrated_ids) - # expand encoder_ctx's batch to fit target_word's lod - # for example - # decoder_mem.lod is - # [[0 1 3], - # [0 1 3 6]] - # its tensor content is [a1 a2 a3 a4 a5] - # which means there are 2 sentences to translate - # - the first sentence has 1 translation prefixes, the offsets are [0, 1) - # - the second sentence has 2 translation prefixes, the offsets are [1, 3) and [3, 6) - # the target_word.lod is - # [[0, 1, 6] - # [0, 2, 4, 7, 9 12]] - # which means 2 sentences to translate, each has 1 and 5 prefixes - # the first prefix has 2 candidates - # the following has 2, 3, 2, 3 candidates - # the encoder_ctx_expanded's content will be - # [a1 a1 a2 a2 a3 a3 a3 a4 a4 a5 a5 a5] - encoder_ctx_expanded = pd.lod_expand(encoder_ctx, target_word) - decoder_input = pd.fc( - act=pd.activation.Linear(), - input=[target_word, encoder_ctx_expanded], - size=3 * decoder_dim) - gru_out, cur_mem = pd.gru_step( - decoder_input, mem=decoder_mem, size=decoder_dim) - scores = pd.fc( - gru_out, - size=trg_dic_size, - bias=None, - act=pd.activation.Softmax()) - # K is an config - topk_scores, topk_ids = pd.top_k(scores, K) - topk_generated_scores = pd.add_scalar(topk_scores, generated_scores) - - selected_ids, selected_generation_scores = decoder.beam_search( - topk_ids, topk_generated_scores) - - # update the states - decoder_mem.update(cur_mem) # tells how to update state - generated_ids.update(selected_ids) - generated_scores.update(selected_generation_scores) - - decoder.output(selected_ids) - decoder.output(selected_generation_scores) - -translation_ids, translation_scores = decoder() -``` -The `decoder.beam_search` is an operator that, given the candidates and the scores of translations including the candidates, -returns the result of the beam search algorithm. - -In this way, users can customize anything on the input or output of beam search, for example: - -1. Make the corresponding elements in `topk_generated_scores` zero or some small values, beam_search will discard this candidate. -2. Remove some specific candidate in `selected_ids`. -3. Get the final `translation_ids`, remove the translation sequence in it. - -The implementation of sequence decoder can reuse the C++ class: [RNNAlgorithm](https://github.com/Superjom/Paddle/blob/68cac3c0f8451fe62a4cdf156747d6dc0ee000b3/paddle/operators/dynamic_recurrent_op.h#L30), -so the python syntax is quite similar to that of an [RNN](https://github.com/Superjom/Paddle/blob/68cac3c0f8451fe62a4cdf156747d6dc0ee000b3/doc/design/block.md#blocks-with-for-and-rnnop). - -Both of them are two-level `LoDTensors`: - -- The first level represents `batch_size` of (source) sentences. -- The second level represents the candidate ID sets for translation prefix. - -For example, 3 source sentences to translate, and has 2, 3, 1 candidates. - -Unlike an RNN, in sequence decoder, the previous state and the current state have different LoD and shape, and an `lod_expand` operator is used to expand the LoD of the previous state to fit the current state. - -For example, the previous state: - -* LoD is `[0, 1, 3][0, 2, 5, 6]` -* content of tensor is `a1 a2 b1 b2 b3 c1` - -the current state is stored in `encoder_ctx_expanded`: - -* LoD is `[0, 2, 7][0 3 5 8 9 11 11]` -* the content is - - a1 a1 a1 (a1 has 3 candidates, so the state should be copied 3 times for each candidates) - - a2 a2 - - b1 b1 b1 - - b2 - - b3 b3 - - None (c1 has 0 candidates, so c1 is dropped) - -The benefit from the relative offset LoD is that the empty candidate set can be represented naturally. - -The status in each time step can be stored in `TensorArray`, and `Pack`ed to a final LoDTensor. The corresponding syntax is: - -```python -decoder.output(selected_ids) -decoder.output(selected_generation_scores) -``` - -The `selected_ids` are the candidate ids for the prefixes, and will be `Packed` by `TensorArray` to a two-level `LoDTensor`, where the first level represents the source sequences and the second level represents generated sequences. - -Packing the `selected_scores` will get a `LoDTensor` that stores scores of each translation candidate. - -Packing the `selected_generation_scores` will get a `LoDTensor`, and each tail is the probability of the translation. - -## LoD and shape changes during decoding -

                                - -

                                - -According to the image above, the only phase that changes the LoD is beam search. - -## Beam search design -The beam search algorithm will be implemented as one method of the sequence decoder and has 3 inputs: - -1. `topk_ids`, the top K candidate ids for each prefix. -2. `topk_scores`, the corresponding scores for `topk_ids` -3. `generated_scores`, the score of the prefixes. - -All of these are LoDTensors, so that the sequence affiliation is clear. Beam search will keep a beam for each prefix and select a smaller candidate set for each prefix. - -It will return three variables: - -1. `selected_ids`, the final candidate beam search function selected for the next step. -2. `selected_scores`, the scores for the candidates. -3. `generated_scores`, the updated scores for each prefix (with the new candidates appended). - -## Introducing the LoD-based `Pack` and `Unpack` methods in `TensorArray` -The `selected_ids`, `selected_scores` and `generated_scores` are LoDTensors that exist at each time step, -so it is natural to store them in arrays. - -Currently, PaddlePaddle has a module called `TensorArray` which can store an array of tensors. It is better to store the results of beam search in a `TensorArray`. - -The `Pack` and `UnPack` in `TensorArray` are used to pack tensors in the array to an `LoDTensor` or split the `LoDTensor` to an array of tensors. -It needs some extensions to support the packing or unpacking an array of `LoDTensors`. diff --git a/develop/doc_cn/_sources/design/optimizer.md.txt b/develop/doc_cn/_sources/design/optimizer.md.txt deleted file mode 100644 index 691081c268b..00000000000 --- a/develop/doc_cn/_sources/design/optimizer.md.txt +++ /dev/null @@ -1,91 +0,0 @@ -## Optimizer Design - -### The Problem - -A PaddlePaddle program, or a block, is a sequence of operators operating variables. A training program needs to do three kinds of works: - -1. the forward pass, which computes intermediate results and the cost(s), -1. the backward pass, which derives gradients from intermediate results and costs, and -1. the optimization pass, which update model parameters to optimize the cost(s). - -These works rely on three kinds of operators: - -1. forward operators, -1. gradient operators, and -1. optimization operators. - -It's true that users should be able to create all these operators manually by calling some low-level API, but it would be much more convenient if they could only describe the forward pass and let PaddlePaddle create the backward and optimization operators automatically. - -In this design, we propose a high-level API that automatically derives the optimisation pass and operators from the forward pass. - - -### High-level Python API to describe the training process - -1. User write code to describe the network: - - ```python - images = layer.data("images") - labels = layer.data("labels") - w1 = pd.var("w1") - b1 = pd.var("b1") - hidden = layer.fc(images, w=w1, b=b1) - cost = layer.mse(hidden, labels) - ``` - - The above code snippet will create forward operators in [Block](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/block.md). - - -2. Users create a certain kind of Optimizer with some argument. - - ```python - optimizer = AdagradOptimizer(learing_rate=0.001) - ``` - -3. Users use the optimizer to `minimize` a certain `cost` through updating parameters in parameter_list. - - ```python - opt_op_list = optimizer.minimize(cost, parameter_list=[w1, b1]) - ``` - The above code snippet will create gradient and optimization operators in Block. The return value of `minimize()` is list of optimization operators that will be run by session. - -4. Users use Session/Executor to run this opt_op_list as target to do training. - - ```python - sess.run(target= opt_op_list, ...) - ``` - -#### Optimizer Python interface: - -```python -class Optimizer(object): - """Optimizer Base class. - - """ - - def __init__(self): - pass - - def create_optimization_pass(self, parameters_and_grads): - """Add optimization operators to update gradients to variables. - - Args: - parameters_and_grads: a list of (variable, gradient) pair to update. - - Returns: - optmization_op_list: a list of optimization operator that will update parameter using gradient. - """ - return None - - def minimize(self, loss, parameter_list): - """Add operations to minimize `loss` by updating `parameter_list`. - - This method combines interface `append_backward()` and - `create_optimization_pass()` into one. - """ - params_grads = self.create_backward_pass(loss, parameter_list) - update_ops = self.create_optimization_pass(params_grads) - return update_ops - -``` - -Users can inherit the Optimizer above to create their own Optimizer with some special logic, such as AdagradOptimizer. diff --git a/develop/doc_cn/_sources/design/paddle_nccl.md.txt b/develop/doc_cn/_sources/design/paddle_nccl.md.txt deleted file mode 100644 index c7dac70998a..00000000000 --- a/develop/doc_cn/_sources/design/paddle_nccl.md.txt +++ /dev/null @@ -1,65 +0,0 @@ -# Design Doc: NCCL support in Paddle Fluid - -## Abstract - -This Design Doc refers to the NCCL feature in paddle. We propose an approach to support NCCL library both on a single machine and multiple machines. We wrapper the NCCL primitives `Broadcast`, `Allreduce`, `Reduce` as operators to utilize Multi-GPU powers in one script. - - -## Motivation - -[NCCL](https://developer.nvidia.com/nccl) is a NVIDIA library support Multi-GPU communicating and optimized for NVIDIA GPUs, it provides routines such as all-gather, all-reduce, broadcast, reduce, reduce-scatter, that can achieve high bandwidth over PCIe and NVLink high-speed interconnect. With NCCL library, we can easily accelerate the training in parallel. - -- Pros -1. easily plug-in with [NCCL2](https://developer.nvidia.com/nccl) library. -1. high performance in NVIDIA GPUs. -1. MPI like primitives, which have low learning cost for users. - -- Cons -1. Only design for NVIDIA GPUs, not a general multi-device solution. -1. Although NCCL1 is opensourced under BSD license, but NCCL2 is not opensourced anymore. - -At the beginning of training, the framework needs to distribute the same parameters to every GPU, and merge the gradients at any time user interests. - -As a result, during training, we need the operations of peer to peer copy between different GPUs, aggregating gradients/parameters from GPUs, and broadcasting parameters to GPUs. Every GPU only need to run the operator with correct place information. - -Besides, it needs interfaces to synchronize model update with each different GPU Cards. - -## Implementation - -As mentioned above, we wrap the NCCL routines as several kinds of operators. Need to note that NCCL need to create Communicator between gpu at the beginning, so there is a NCCLInit operator created. - -### Transpiler - -To be compatible with [parameter server design doc](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/ops/dist_train.md), the transpiler compiles the user defined operation graph into sub-graphs to be executed on different devices. - -1. The user-defined model will be a single device program - -2. Broadcast/Reduce operators between GPUs will be inserted into the program, even for the multi-node, may insert the `Send`, `Recv` operator. - - *Broadcast, AllReduce in a single machine. And Broadcast, AllReduce, [Send, Recv](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/ops/dist_train.md#graph-converter) in multiple machines* - - - -After compiling, the graph as shows - - - -Operators are added to the sub-graphs. Every GPU assigned a role of `rank0`, `rank1` etc. - -- **Broadcast**. Broadcast operator distribute initialized parameter to all the GPUs from the GPU who owns it. e.g. from`rank0` GPU. -- **AllReduce**. AllReduce operator synchronizes parameters/gradients between GPUs. AllReduce implemented in the Ring-Based communicating method, avoid of the bottle neck in a single GPU. - -Need to notice that AllReduce operator force GPUs synchronized at that point. The whole training process in asynchronous or synchronous mode depends on the AllReduce point in the graph. - -As it shown in the picture, when each GPU compute the gradient of `W`, followed with a `AllReduce` operator, accumulate the `dW` to full batch of data, then run the optimize process individually and apply the gradient to its `W`. - -- **AllReduce** - Need to note that our AllReduce operator is a ring-base AllReduce implementation. If we use the NCCL2 AllReduce primitive, every GPU optimized full batch of data, wasted (n-1) GPU compute resources. In addition, NCCL2 built-in AllReduce will only utilize the communicating resource during synchronization, then update the gradient will be a subsequent phase. In fact, we can amortize the update gradient time cost into the communicating phase. The process is -1. Every parameter has its root card. That card will responsible for aggregating the gradients from GPUs. -2. The whole model's parameter will be hashed to different root card, ensure the load balance between GPUs. -3. Logically neighberhood card will start send parameter to the next one. After one round, the parameter main card will aggregate the full gradients. -4. Then the root card will optimize the parameter. -5. This parameter card will send its optimized result to its neighberhood, then the neighberhood will send parameter to its next one. -6. Finish the sychronization round. - -The total time cost will be 2 * (n-1) * per-parameter-send-time, we reach the goal of amortize the upgrade time into communicating phase. diff --git a/develop/doc_cn/_sources/design/parallel_do.md.txt b/develop/doc_cn/_sources/design/parallel_do.md.txt deleted file mode 100644 index 42bd136f825..00000000000 --- a/develop/doc_cn/_sources/design/parallel_do.md.txt +++ /dev/null @@ -1,163 +0,0 @@ -# Design Doc: Parallel_Do in PaddlePaddle - -In PaddlePaddle, we use parallel_do primitive to represent multithread data parallel processing. - -## Design overview - -The definition of a parallel_do op looks like the following - -```c++ -AddInput(kInputs, "Inputs needed to be split onto different devices").AsDuplicable(); -AddInput(kParameters, "Parameters are duplicated over different devices") - .AsDuplicable(); -AddInput(kPlaces, "Devices used for parallel processing"); -AddOutput(kOutputs, "Outputs needed to be merged from different devices").AsDuplicable(); -AddOutput(kParallelScopes, - "Scopes for all local variables in forward pass. One scope for each device"); -AddAttr(kParallelBlock, - "List of operaters to be executed in parallel"); -``` - -A vanilla implementation of parallel_do can be shown as the following (`|` means single thread and -`||||` means multiple threads) - -``` -In the forward pass - | Split input onto different devices - | Copy parameter onto different devices - |||| Compute forward pass in parallel - | Merge output from different devices - -In the backward pass - | Split output@grad onto different devices - |||| Compute backward pass in parallel - | accumulate param@grad from different devices to the first device - | Merge input@grad from different devices -  | Copy param@grad to the place of parallel_do_op -``` - -This implementation allows to write mixed device program like this - -```python -W1 = fluid.tensor(size=[100,20], parameter=true) -W2 = fluid.tensor(size=[20,15], parameter=true) - -data = layers.data() - -gpu_places = layers.get_place(use_gpu=True) -# parallel processing on multiple GPUs -pd = ParallelDo(gpu_places) -with pd.do(input=data): - prediction = softmax(fc(fc(data, W1), W2)) - write_output(prediction) -prediction = pd() -loss = cross_entropy(prediction, label) -``` - -And the programDesc are like the following - -``` -# start_program will be run by executor(CPUPlace), all w1, w2 will be allocated on CPU -start_program -{ - vars: w1, w2 - ops: init(w1), init(w2) -} - -main_program -{ -block0 { - vars: data, places, w1, w2, w1_grad, w2_grad, - ops: data, get_place, parallel_do(block1), - parallel_do_grad(block2), - sgd(w2, w2_grad), - sgd(w1, w1_grad) -} -block1 { # the forward pass - parent_block: 0 - vars: data, h1, h2, loss - ops: fc, fc, softmax -} -block2 { # the backward pass - parent_block: 1 - vars: data_grad, h1_grad, h2_grad, loss_gard, local_w1_grad, local_w2_grad - ops: softmax_grad, - fc_grad - fc_grad -} -} -``` - -## Performance Imporvement - -There are serial places we can make this parallel_do faster. - -### forward: split input onto different devices - -If the input of the parallel_do is independent from any prior opeartors, we can avoid this step by -prefetching the input onto different devices in a seperate background thread. And the python code -looks like this. -```python -pd = ParallelDo(gpu_places) -with pd.do(): -    feature = get_data_from_prefetch_queue(gpu_places) - prediction = my_net(feature) - write_output(activation) -``` - -### forward: Copy parameter to onto different devices - -We can avoid this step by making each device have a copy of the parameter. This requires: - -1. `fluid.default_start_up_program()` to be run on all devices -1. In the backward, allreduce param@grad at different devices, this requires - 1. `backward.py` add `allreduce` operators at parallel_do_grad - 1. `allreduce` operators need to be called in async mode to achieve maximum throughput -1. apply gradients related op(i.e. cliping, normalization, decay, sgd) on different devices in parallel - -By doing so, we also avoided "backward: accumulate param@grad from different devices to the first device". -And the ProgramDesc looks like the following - -``` -# w1, w2 will be allocated on all GPUs -start_program -{ -block0 { - parallel_do(block1) -} -block1 { - parent_block: 0 - vars: w1, w2 - ops: init(w1), init(w2) -} -} - -main_program -{ -block0 { - vars: data, places, w1, w2 - ops: data, get_place, parallel_do(block1), - parallel_do_grad(block2), # append_backward - parallel_do(block3) # append_optimization - -} -block1 { - parent_block: 0 - vars: data, h1, h2, loss - ops: fc, fc, softmax -} -block2 { - parent_block: 1 - vars: data_grad, h1_grad, h2_grad, loss_gard, w1_grad, w2_grad - ops: softmax_grad, - fc_grad, allreduce(places, scopes, w1_grad), - fc_grad, allreduce(places, scopes, w2_grad) -} -block3 { - parent_block: 0 - vars: lr - ops: sgd(w2, w2_grad), - sgd(w1, w1_grad) -} -} -``` diff --git a/develop/doc_cn/_sources/design/parameter_average.md.txt b/develop/doc_cn/_sources/design/parameter_average.md.txt deleted file mode 100644 index 2c4edee9fe3..00000000000 --- a/develop/doc_cn/_sources/design/parameter_average.md.txt +++ /dev/null @@ -1,72 +0,0 @@ -# Averaging Parameter in PaddlePaddle - -## Why Averaging -In a large scale machine learning setup where the size of the training data is huge, it could take us a large number of iterations over the training data before we can achieve the optimal values of parameters of our model. Looking at the problem setup, it is desirable if we can obtain the optimal values of parameters by going through the data in as few passes as we can. - -Polyak and Juditsky (1992) showed that the test performance of simple average of parameters obtained by Stochastic Gradient Descent (SGD) is as good as that of parameter values that are obtained by training the model over and over again, over the training dataset. - -Hence, to accelerate the speed of Stochastic Gradient Descent, Averaged Stochastic Gradient Descent (ASGD) was proposed in Polyak and Juditsky (1992). For ASGD, the running average of parameters obtained by SGD, is used as the estimator for
                                . The averaging is done as follows: - -
                                - -We propose averaging for any optimizer similar to how ASGD performs it, as mentioned above. - -### How to perform Parameter Averaging in PaddlePaddle - -Parameter Averaging in PaddlePaddle works in the following way during training : -1. It will take in an instance of a normal optimizer as an input, e.g. RMSPropOptimizer -2. The optimizer itself is responsible for updating the parameters. -3. The ParameterAverageOptimizer maintains a separate copy of the parameters for itself: - 1. In concept, the values of this copy are the average of the values of the parameters in the most recent N batches. - 2. However, saving all the N instances of the parameters in memory is not feasible. - 3. Therefore, an approximation algorithm is used. - -Hence, overall we have have two copies of the parameters: one for the optimizer itself, and one for the ParameterAverageOptimizer. The former should be used in back propagation, while the latter should be used during testing and should be saved. - -During the testing/ saving the model phase, we perform the following steps: -1. Perform the delayed operations. -2. Save current values of the parameters to a temporary variable. -3. Replace the values of the parameters with the averaged values. -4. Perform testing and/or save the parameters. -5. Restore the values of the parameters once done. - -### How to implement Averaging of Parameter in PaddlePaddle - -We can add the ParameterAverageOptimizer op to the graph through Python API. Using this approach, we manually add this op to the graph and direct the output of the optimizer op to this op during training. - - **Advantages**: - - Allows for greater flexibility to the users of PaddlePaddle. Using this approach, the users can plug different optimizers into ParameterAverageOptimizer by passing in the optimizer to the op. - - Makes it easy for the users to customize and extend the framework. - - **Disadvantages**: - - Implementation requires re-writing the averaging methodology in Python. - -### Low-Level implementation - -In the new design, we propose to create a new operation for averaging parameter updates (ParameterAverageOptimizer). For now, we can add an op that takes in the following as input: -- the optimizer -- the window_size to keep the updates - -The ParameterAverageOptimizer op can be like any other operator with its own CPU/GPU implementation either using Eigen or separate CPU and GPU kernels. As the initial implementation, we can implement the kernel using Eigen following the abstraction pattern implemented for [Operators](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/rmsprop_op.h). We also want to support the case when the Trainer/Optimizer runs on the GPU while ParameterAverageOptimizer runs on a CPU. - -The idea of building an op for averaging is in sync with the refactored PaddlePaddle philosophy of using operators to represent any computation unit. The way the op will be added to the computation graph will be decided by the [layer functions](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md#layer-function) in Python API. - -### Python API implementation for ParameterAverageOptimizer - -Based on Polyak and Juditsky (1992), we can generalize the averaging of updates to any optimizer. The input to the op would be the following: -- Any optimizer (RMSProp , AdaGrad etc.) -- A window size. The op keeps accumulating updated parameter values over a window of N batches and takes an average. Move the averaged value to a buffer when window is full to avoid loss of precision. - -Using the ParameterAverageOptimizer op, any user can add the operation to their computation graphs. However, this will require a lot of lines of code and we should design Python APIs that support averaging. As per the PaddlePaddle [Python API design](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md), the layer functions are responsible for creating operators, operator parameters and variables. Since ParameterAverageOptimizer will be an operator, it makes sense to create it in the layer functions. -We will have a wrapper written in Python that will support the functionality and implement the actual core computation in C++ core as we have done for other [Optimizers](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/rmsprop_op.cc) - -#### Creation of the ParameterAverageOptimizer operator -There are two ways for creating the ParameterAverageOptimizer op: -1. We create the op immediately while building the computation graph. -2. We add the op in a lazy manner, just before the backward pass, similar to the way the optimization ops are added. - -The proposal is to add the op immediately while building the computation graph. - -#### High-level API - -In PaddlePaddle Python API, users will primarily rely on [layer functions](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md#layer-function) to create neural network layers. Hence, we also need to provide parameter average functionality in layer functions. diff --git a/develop/doc_cn/_sources/design/parameters_in_cpp.md.txt b/develop/doc_cn/_sources/design/parameters_in_cpp.md.txt deleted file mode 100644 index a7ac3f17c44..00000000000 --- a/develop/doc_cn/_sources/design/parameters_in_cpp.md.txt +++ /dev/null @@ -1,41 +0,0 @@ -# Design Doc: The C++ Class `Parameters` - -`Parameters` is a concept we designed in PaddlePaddle V2 API. `Parameters` is a container of parameters, which makes PaddlePaddle capable of sharing parameter between topologies. We described usages of `Parameter` in [api.md](./api.md). - -We used Python to implement Parameters when designing V2 API before. There are several defects for the current implementation: -* We just use `memcpy` to share Parameters between topologies, but this is very inefficient. -* We did not support sharing Parameters while training. We just trigger `memcpy` when start training. - -It is necessary that we implement Parameters in CPP side. However, it could result a code refactoring for PaddlePaddle, because PaddlePaddle was designed for training only one topology before, i.e., each GradientMachine contains its Parameter as a data member. In current PaddlePaddle implementation, there are three concepts associated with `Parameters`: - -1. `paddle::Parameter`. A `Parameters` is a container for `paddle::Parameter`. -It is evident that we should use `paddle::Parameter` when developing `Parameters`. -However, the `Parameter` class contains many functions and does not have a clear interface. -It contains `create/store Parameter`, `serialize/deserialize`, `optimize(i.e SGD)`, `randomize/zero`. -When we developing `Parameters`, we only use `create/store Parameter` functionality. -We should extract functionalities of Parameter into many classes to clean PaddlePaddle CPP implementation. - -2. `paddle::GradientMachine` and its sub-classes, e.g., `paddle::MultiGradientMachine`, `paddle::NeuralNetwork`. -We should pass `Parameters` to `paddle::GradientMachine` when `forward/backward` to avoid `memcpy` between topologies. -Also, we should handle multi-GPU/CPU training, because `forward` and `backward` would perform on multi-GPUs and multi-CPUs. -`Parameters` should dispatch the parameter value to each device, and gather the parameter gradient from each device. - -3. `paddle::ParameterUpdater`. The ParameterUpdater is used to update parameters in Paddle. -So `Parameters` should be used by `paddle::ParameterUpdater`, and `paddle::ParameterUpdater` should optimize `Parameters` (by SGD). - - -The step by step approach for implementation Parameters in PaddlePaddle C++ core is listed below. Each step should be a PR and could be merged into PaddlePaddle one by one. - -1. Clean `paddle::Parameter` interface. Extract the functionalities of `paddle::Parameter` to prepare for the implementation of Parameters. - -2. Implementation a `Parameters` class. It just stores the `paddle::Parameter` inside. Make `GradientMachine` uses `Parameters` as a class member. - -3. Make `Parameters` support Multi-CPU and Multi-GPU training to prepare for sharing `Parameter` between topologies. -Because we need share `Parameters` between topologies, it is `Parameters`'s response to exchange Parameters between GPUs. -`GradientMachine` should not handle how to exchange Parameters because `GradientMachine` only used to train one topology and we need to support train many topologies in Paddle, i.e., there could be many GradientMachines use one `Parameters`. - * We should use a global function to exchange Parameters between GPUs, not a member function in `Parameters`. The `MultiGradientMachine` invoke this function, which uses `Parameters` as this function inputs. - * The MultiGradientMachine contains many functionalities. Extracting the Parameters exchanging logic could make MultiGradientMachine clearer and simpler. - -4. Make `Parameters` as an argument for `forward/backward` function, not a data member for `GradientMachine`. For example, `forward` could be `forward(const Parameters& params, ...)` and `backward` could be `backward(Parameters* params, ...)`. After this step, Paddle could share `Parameters` between topologies. - -5. `ParameterUpdater` is invoked by `GradientMachine` and `Trainer`, but it updates `Parameters`. In the end of this code refactoring, we could change `ParameterUpdater` directly uses `Parameters` to make `ParameterUpdater`'s implementation clear. diff --git a/develop/doc_cn/_sources/design/profiler.md.txt b/develop/doc_cn/_sources/design/profiler.md.txt deleted file mode 100644 index b20b5efdc1f..00000000000 --- a/develop/doc_cn/_sources/design/profiler.md.txt +++ /dev/null @@ -1,97 +0,0 @@ -## Introduction - -There are many performance analysis tools for [different programming languages and different software frameworks](https://en.wikipedia.org/wiki/List_of_performance_analysis_tools). For most popular deep learning frameworks, they use several programming languages and adapt to heterogeneous platforms. Similar to most of the deep learning frameworks, PaddlePaddle also uses C++, CUDA and Python as the basic programming languages to adapt to run on CPU and GPU devices. The [`nvprof` tools](http://docs.nvidia.com/cuda/profiler-users-guide/index.html#nvprof-overview) is usually used to analyse the CUDA program. We have [a document](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/optimization/cpu_profiling.md) to profile CPU and Python program by [yep](https://pypi.python.org/pypi/yep) and [Google's perftools](https://github.com/google/pprof) to profile only the CPU and Python program. But for [PaddlePaddle fluid](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/fluid.md), the operator is the basic computing unit. The developers usually want to collect the time of each operator and locate bottlenecks. The `nvprof` usually collect the timeline of CUDA-related activities on both CPU and GPU, including kernel execution, memory transfers, memory set and CUDA API calls and events or metrics for CUDA kernels. And the `yep` and `Google's perftools` can't collect the timeline for CUDA program. All these tools can't collect time in the operator level. So we design this profiling tool. - -## Architecture - -The work flow for most task is as follows. Each operator will run many times in the all iterations. So the profiler must collect the total time of each operator during the iteration. For more, sometimes, the developers may want to collect more detailed time span inside the operator or record time span for elsewhere, this requires that the profiler must support to record the nested time span. And in order to speedup training, all the deep learning frameworks support parallel computing, including multiple threads on CPU and multiple GPUs. So the profiler must be able to collect the timeline for each thread. In addition, the profiler also occupies certain resources. It must can be easily to be enabled or disabled by the developers. At last, the profiler should present a human-readable report. - -```python -for i in xrange(M): # M is the iteration number - for op in operator_lists: # The `operator_lists` contains all the operators in the network. - op.run(); -``` - -In summary, the proflier should have following features: - -- records time span in loop. -- supports nested time span. -- supports multiple threads/multiple GPUs. -- supports to be enabled and disabled by users. - -But how to record the time for the mixed C++ and CUDA program? There many C++ APIs to get the current calendar time in host program. But for GPU, the CUDA kernels may be executed concurrently if they are in different [streams](http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#streams) and the CUDA kernels is asynchronous with the host program if there is no the synchronous aftern the CUDA kernels. CUDA provides [event](http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#events) to monitor the device and perform accurate timing. Inspired by PyTorch and CUDA event, we also design and apply the events to record the timeline. Then summarize and present statistics based on these events. - -The overall flow is shown as the following figure. - -
                                - -### Event - -In above work flow, a pair of events are needed before and after the piece of code to collect time. So the event has a flag to mark whether it is a starting event or an ending event. Except this two kinds of event, sometime, a only marker with a text message is needed, for example, a marker to specify the profiling start or end. There are three kinds of event: - -```c++ -enum EventKind { - kMark, - kPushRange, - kPopRange}; -``` -- kMark: only a marker without time range. -- kPushRange: mark the starting event for time range. -- kPopRange: mark the ending event for time range. - -For the CPU code, the events only need to record the current time. For the CUDA code, the [event management functions of CUDA](http://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__EVENT.html#group__CUDART__EVENT) are used. For many pieces of code, an event lists are used to record each piece. - -```c++ -class Event { - public: - // The DeviceContext is used to get current CUDA stream. - Event(EventKind kind, std::string name, uint32_t thread_id, - const platform::DeviceContext* dev_ctx = nullptr); - double CpuElapsedUs(const Event& e) const; - double CudaElapsedUs(const Event& e) const; - - private: - EventKind kind_; - std::string name_; - uint32_t thread_id_; - int64_t cpu_ns_; -#ifdef PADDLE_WITH_CUDA - cudaEvent_t event_ = nullptr; - int device_ = -1; -#endif -}; - -struct EventList { - std::forward_list> event_blocks; -}; -``` - -As mentioned above, there is no need to record the timeline when disabling the profiler. So there is a global state to enable or disable the profiler. - -```c++ -enum ProfilerState { - kDisabled, - kCPU, - kCUDA -}; -ProfilerState g_state; -``` -- kDisabled: the disabled state. -- kCPU: CPU profiling state. -- kCUDA: GPU profiling state. - -A pair of starting and ending events are pushed to event lists in constructor and destructor of `RecordEvent`. So the timeline is recorded for the code in the lifecycle of an object of `RecordEvent`. - -```c++ -struct RecordEvent { - explicit RecordEvent(const std::string name, - platform::DeviceContext* dev_ctx = nullptr) { - if (kState == ProfilerState::kDisabled) return; - // push the starting event to the event lists. - } - ~RecordEvent() { - if (kState == ProfilerState::kDisabled) return; - // push the ending event to the event lists. - } -}; -``` diff --git a/develop/doc_cn/_sources/design/program.md.txt b/develop/doc_cn/_sources/design/program.md.txt deleted file mode 100644 index bd2456787c4..00000000000 --- a/develop/doc_cn/_sources/design/program.md.txt +++ /dev/null @@ -1,139 +0,0 @@ -# Design Doc: PaddlePaddle Programs - -## Compile and Execution - -A PaddlePaddle program consists of two parts -- the first generates a `ProgramDesc` protobuf message that describes the program, and the second runs this message using a C++ class `Executor`. - -A simple example PaddlePaddle program can be found in [graph.md](./graph.md): - -```python -x = layer.data("images") -l = layer.data("label") -y = layer.fc(x) -cost = layer.mse(y, l) -optimize(cost) -train(cost, reader=mnist.train()) -``` - -The first five lines of the following PaddlePaddle program generates, or, compiles, the `ProgramDesc` message. The last line runs it. - -## Programs and Blocks - -The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program. - -- program: some nested blocks -- [block](./block.md): - - some local variable definitions, and - - a sequence of operators - -The concept of block comes from usual programs. For example, the following C++ program has three blocks: - -```c++ -int main() { // block 0 - int i = 0; - if (i < 10) { // block 1 - for (int j = 0; j < 10; j++) { // block 2 - } - } - return 0; -} -``` - -The following PaddlePaddle program has three blocks: - -```python -import paddle as pd // block 0 - -x = minibatch([10, 20, 30]) # shape=[None, 1] -y = var(1) # shape=[1], value=1 -z = minibatch([10, 20, 30]) # shape=[None, 1] -cond = larger_than(x, 15) # [false, true, true] - -ie = pd.ifelse() -with ie.true_block(): // block 1 - d = pd.layer.add_scalar(x, y) - ie.output(d, pd.layer.softmax(d)) -with ie.false_block(): // block 2 - d = pd.layer.fc(z) - ie.output(d, d+1) -o1, o2 = ie(cond) -``` - -## `BlockDesc` and `ProgramDesc` - -All protobuf messages are defined in `framework.proto`. - -`BlockDesc` is straight-forward -- it includes local variable definitions, `vars`, and a sequence of operators, `ops`. - -```protobuf -message BlockDesc { - required int32 parent = 1; - repeated VarDesc vars = 2; - repeated OpDesc ops = 3; -} -``` - -The parent ID indicates the parent block so that operators in a block can refer to variables defined locally and also those defined in their ancestor blocks. - -All hierarchical blocks in a program are flattened and stored in an array. The block ID is the index of the block in this array. - -```protobuf -message ProgramDesc { - repeated BlockDesc blocks = 1; -} -``` - - -### Global Block - -The global block is the first one in the above array. - -## Operators that Use Blocks - -In the above example, the operator `IfElseOp` has two blocks -- the true branch and the false branch. - -The definition of `OpDesc` shows that an operator could have some attributes: - -```protobuf -message OpDesc { - AttrDesc attrs = 1; - ... -} -``` - -and an attribute could be of type block, which is, in fact, a block ID as described above: - -``` -message AttrDesc { - required string name = 1; - - enum AttrType { - INT = 1, - STRING = 2, - ... - BLOCK = ... - } - required AttrType type = 2; - - optional int32 block = 10; // when type == BLOCK - ... -} -``` - -## InferShape - -With this design, the InferShape function should take the following parameters: - -```c++ -void InferShape(int current_block, - int current_operator, - ProgramDesc* program // might change VarDesc values. - ) { - ... -} -``` - -where - -- `current_block` indices into `ProgramDesc::blocks`, -- `current_operator` indices into `BlockDesc::ops`. diff --git a/develop/doc_cn/_sources/design/prune.md.txt b/develop/doc_cn/_sources/design/prune.md.txt deleted file mode 100644 index 4a5cf10c79a..00000000000 --- a/develop/doc_cn/_sources/design/prune.md.txt +++ /dev/null @@ -1,63 +0,0 @@ -# Prune - -## Motivation - -We want to support running inference, training and checkpointing in one `ProgramDesc`. We implement -`void Prune(const ProgramDesc* input, ProgramDesc* output)` function, which takes a `ProgramDesc` -and generate a pruned `ProgramDesc`. - -## Challenge - -Pruning need to support both variables and operators being evaluation targets. Consider the following -different situations. - -```python -# Case 1: run foward pass. -cost_np = session.run(target=cost) -# Case 2: run backward passing. -opts_np, _ = session.run(target=[cost, opt]) -# Case 3: run checkpointing -_ = session.run(target=checkpoint) -``` - -## Solution - -To support evaluation of operators, we add `is_target` field in the `OpDesc`. - -```c++ -message OpDesc { - required string type = 3; - repeated Var inputs = 1; - repeated Var outputs = 2; - repeated Attr attrs = 4; - optional bool is_target = 5 [ default = false ]; -}; -``` - -To support evaluation of variables, we add [fetch_op](https://github.com/PaddlePaddle/Paddle/pull/4599). -For each variable in the `target`, we insert a `fetch_op` into the `ProgramDesc` with `variable` being -`fetch_op`'s input. Then we also set `fetch_op` is a target. - -### Algorithm - -If an operator needs to be run, it must fall into one of the following cases: - -1. It is the target. -2. It is depended by some other ops, meaning its output is some other op's input. - -The first case can be checked by `op_desc.is_traget()` . The second case can be implement as - -```c++ -bool HasDependentVar(const OpDesc& op_desc, const std::set& dependent_vars) { - for (auto& var : op_desc.outputs()) { - for (auto& argu : var.arguments()) { - if (dependent_vars.count(argu) != 0) { - return true; - } - } - } - return false; -} -``` - -Then the whole algorithm can be implemented as the following [code](https://github.com/tonyyang-svail/Paddle/blob/prune_impl/paddle/framework/prune.cc). diff --git a/develop/doc_cn/_sources/design/python_api.md.txt b/develop/doc_cn/_sources/design/python_api.md.txt deleted file mode 100644 index 73f6d7b90c7..00000000000 --- a/develop/doc_cn/_sources/design/python_api.md.txt +++ /dev/null @@ -1,304 +0,0 @@ -# Design Doc: Python API - -Due to the refactorization of the PaddlePaddle core, we need Python classes to construct corresponding protobuf messages that describe a DL program. - -| Python classes | Protobuf messages | -| --- | --- | -| Program | ProgramDesc | -| Block | BlockDesc | -| Operator | OpDesc | -| Variable | VarDesc | - -Please be aware that these Python classes need to maintain some construction-time information, which are not part of the protobuf messages. - -## Core Concepts - -### Program - -A `ProgramDesc` describes a [DL program](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/program.md), which is composed of an array of `BlockDesc`s. The `BlockDesc`s in a `ProgramDesc` can have a tree-like hierarchical structure. However, the `ProgramDesc` onlys stores a flattened array of `BlockDesc`s. A `BlockDesc` refers to its parent block by its index in the array. For example, operators in the step block of an RNN operator need to be able to access variables in its ancestor blocks. - -Whenever we create a block, we need to set its parent block to the current block, hence the Python class `Program` needs to maintain a data member `current_block`. - -```python -class Program(objects): - def __init__(self): - self.desc = core.NewProgram() # a C++ ProgramDesc pointer. - self.blocks = vector() - self.blocks.append(Block(self, -1)) # the global block - self.current_block = 0 # initialized to the global block - - def global_block(): - return self.blocks[0] - - def current_block(): - return self.get_block(self.current_block) - - def rollback(): - self.current_block = self.current_block().parent_idx - - def create_block(): - new_block_idx = len(self.block) - self.blocks.append(Block(self, self.current_block)) - self.current_block = new_block_idx - return current_block() -``` - -`Program` is an accessor to the protobuf message `ProgramDesc`, which is created in C++ space, because the InferShape function is in C++, which manipulates `VarDesc` messages, which are in turn members of `BlockDesc`, which is a member of `ProgramDesc`. - -`Program` creates the first block as the global block in its constructor. All parameters and their initializer operators are in the global block. - -### Block - -A [Block](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/block.md) includes - -1. a map from variable names to an instance of the Python `Variable` class, and -1. a list of `Operator` instances. - -```python -class Block(objects): - def __init__(self, program, parent_idx): - self.desc = core.NewBlock(program.desc) - self.program = program - self.vars = map() - self.ops = vector() - self.parent_idx = parent_idx - - def create_var(self, ...): - return Variable(self, ...) - - def _create_global_var(self, ...): - program.global_block().create_var(...) - - def create_parameter(self, name, ...): - # Parameter is a subclass of variable. See Parameter section for details. - self.vars[name] = Parameter(self._create_global_var(...), ...) - return self.vars[name] - - def append_operator(self, ...): - self.ops.append(Operator(self, ...)) - - def prepend_operator(self, ...): # Parameter's ctor prepands initialize operators. - self.ops.prepend(Operator(self, ...)) -``` - -`create_parameter` is necessary because parameters are global variables, defined in the global block, but can be created in some sub-blocks. For example, an FC layer in the step block of an RNN operator. - -`prepend_operator` is necessary because the constructor of `Parameter` needs to create the initialize (or load) operator of the parameter, and would like to put it in the *preamble* of the global block. - -### Operator - -The `Operator` class fills in the `OpDesc` message and calls the C++ function `InferShape` to infer the output shapes from the input shapes. - -```python -class Operator(object): - def __init__(self, - block, # Block - type, # string - inputs, # dict - outputs,# dict - attrs # dict - ): - self.desc = core.NewOpDesc(block.desc, type, inputs, outputs, attrs) - core.infer_shape(self.desc, inputs, outputs) - - def type(self): - return self.desc.type() -``` - -`Operator` creates the `OpDesc` message in C++ space, so that it can call the `InferShape` function, which is in C++. - -### Variable - -Operators take Variables as its inputs and outputs. - -```python -class Variable(object): - def __init__(self, - block=None, # Block - name=None, # string - shape, # tuple - dtype="float32", # string - lod_level=None # int - ): - if name is None: - name = unique_name_generator() - self.name = name - self.block = block - self.desc = core.NewVarDesc(block.desc, name, shape, lod_level) - self.writer = None -``` - -Please be aware of `self.writer`, that tracks operator who creates the variable. It possible that there are more than one operators who write a variable, but in Python space, each write to a variable is represented by a Variable class. This is guaranteed by the fact that **`core.NewVarDesc` must NOT create a new `VarDesc` message if its name already exists in the specified block**. - -### Parameter - -A parameter is a global variable with an initializer (or load) operator. - -```python -class Parameter(Variable): - def __init__(self, - block=None, # Block - name=None, # string - shape, # tuple - dtype="float32", # string - lod_level=None # int - trainable, # bool - initialize_op_attrs, - optimize_op_attrs): - super(Parameter, self).__init__(block, name, shape, dtype, lod_level) - self.trainable = trainable - self.optimize_op_attrs = optimize_op_attrs - block.prepend(Operator(block, # Block - initialize_op_attrs['type'], # string - None, # no inputs - self, # output is the parameter - initialize_op_attrs) -``` - -When users create a parameter, they can call - -```python -program.create_parameter( - ..., - init_attr={ - type: "uniform_random", - min: -1.0, - max: 1.0, - }) -) -``` - -In above example, `init_attr.type` names an initialize operator. It can also name the load operator - -```python -init_attr={ - type: "load", - filename: "something.numpy", -} -``` - -`optimize_op_attrs` is not in the `VarDesc` message, but kept in the Python instance, as it will be used in the Python space when creating the optimize operator's `OpDesc`, and will be in the `OpDesc` message. - -## Layer Function - -A layer is a Python function that creates some operators and variables. Layers simplify the work of application programmers. - -Layer functions take `Variable` and configuration parameters as its input and return the output variable(s). - -For example, `FullyConnected` take one or more variable as its input. The input could be input data or another layer's output. There are many configuration options for a `FullyConnected` layer, such as layer size, activation, parameter names, initialization strategies of parameters, and so on. The `FullyConnected` layer will return an output variable. - - -### Necessity for reusing code between layer functions - -There are a lot of code that can be reused. Such as - -* Give the default value of configuration. e.g., default initialize strategy for parameters is uniform random with `min = -1.0`, `max = 1.0`. and default initialize strategy for bias is to fill zero. -* Append the activation operator. -* Create a temporary variable. -* Create parameter. -* Generate a unique name. -* Add a bias. -* ... - -A mechanism to reuse code between layer functions is necessary. It will be around [150 lines of code](https://github.com/PaddlePaddle/Paddle/pull/4724/files#diff-823b27e07e93914ada859232ae23f846R12) if we write a `FullyConnected` layer without any helper functions. - - - -### Comparision between global functions and helper class - -The `FullyConnected` layer will be as follow when we provide global functions: - -```python -def fc_layer(input, size, param_attr=None, bias_attr=None, act=None, name=None): - if name is None: - name = unique_name("fc") - input = multiple_input(input) - param_attr = default_param_attr(param_attr) - param_attr = multiple_param_attr(param_attr, len(input)) - - # mul - mul_results = [] - for ipt, attr in zip(input, param_attr): - shape = ipt.shape[1:] + [size] - w = g_program.global_block().create_parameter(shape, ipt.dtype, name, attr) - tmp = create_tmp_var(name) - g_program.current_block().append_op("mul", {ipt, w}, {tmp}) - mul_results.append(tmp) - - # add sum - ... - # add bias - ... - # add activation - ... - return out -``` - -We can provide many helpers functions for layer developers. However, there are several disadvantages for global helper functions: - -1. We need a namespace for these methods, then layer developers can quickly figure out what method they can use. -2. Global functions will force layer developers to pass its parameter time by time. - -So we provide a helper class, `LayerHelper`, to share code between layer functions. The `FullyConnected` Layer will be as follow. - -```python -def fc_layer(input, size, param_attr=None, bias_attr=None, act=None, name=None): - helper = LayerHelper(locals()) # pass all parameter to LayerHelper - - mul_results = [] - for ipt, param in helper.iter_multiple_input_and_param(): - w = helper.create_parameter(shape=ipt.shape[1:] + [size], dtype = ipt.dtype) - tmp = helper.create_tmp_variable() - helper.append_op('mul', {ipt, w}, {tmp}) - mul_results.append(tmp) - - pre_bias = helper.add_sum(mul_results) - pre_activation = helper.add_bias(pre_bias) - return helper.add_activation(pre_activation) -``` - -We not only use the fewer lines of code to write `fc_layer` but also make the code clearer to understand. At the same time, layer developers can figure out what function they can invoke by typing `helper.` in a python editor. - - -### Implementation of layer helper - -We just keep all parameters of a layer function as a dictionary in layer helper as a private data member. Every method of layer helper will look up the dictionary after it is invoked. In that way, we can implement a layer helper for all layer functions even some layer does not contain some operator. For example, The `activation` is used by the FullyConnected layer or convolution layers, but a cross-entropy layer does not use it. The example code of `add_activation` are: - -```python -class LayerHelper(object): - def __init__(self, **kwargs): # kwargs is short for `keyword arguments` - self.kwargs = kwargs - - def add_activation(self, input_var): - act = self.kwargs.get("act", None) # default value is None - if act is None: # do nothing if no act - return input_var - - tmp = self.create_tmp_var(self) - self.append_op(type=act, input=input_var, output=tmp) - return tmp -``` - -### Return value of layer functions - -The layer will return a Variable, which is also the output of an operator. However, outputs of a layer function have more attributes than an operator. There are parameter variables, and their gradient variables need to return. To return them is useful. For example, - -1. Users can debug the network by printing parameter gradients. -2. Users can append attributes to a parameter, such as, `param.stop_gradient=True` will make a parameter stop generate the gradient. We can fix the parameter value during training by using this attribute. - -However, it is good to return a Variable for layers, since all layers and operators use Variables as their parameters. We can just append a `param` field and a `grad` field for layer function since the Python is dynamic typing. - -The sample usage is - -```python -data = fluid.layers.data(...) -hidden = fluid.layers.fc(data, ...) -... - -executor.run(fetch_list=[hidden.param, hidden.param.grad], ...) -``` - - -## Optimizer - -[Optimizer Design Doc](./optimizer.md) diff --git a/develop/doc_cn/_sources/design/reader/README.md.txt b/develop/doc_cn/_sources/design/reader/README.md.txt deleted file mode 100644 index 2cd4b6225b6..00000000000 --- a/develop/doc_cn/_sources/design/reader/README.md.txt +++ /dev/null @@ -1,206 +0,0 @@ -# Python Data Reader Design Doc - -During the training and testing phases, PaddlePaddle programs need to read data. To help the users write code that performs reading input data, we define the following: - -- A *reader*: A function that reads data (from file, network, random number generator, etc) and yields the data items. -- A *reader creator*: A function that returns a reader function. -- A *reader decorator*: A function, which takes in one or more readers, and returns a reader. -- A *batch reader*: A function that reads data (from *reader*, file, network, random number generator, etc) and yields a batch of data items. - -and also provide a function which can convert a reader to a batch reader, frequently used reader creators and reader decorators. - -## Data Reader Interface - -*Data reader* doesn't have to be a function that reads and yields data items. It can just be any function without any parameters that creates an iterable (anything can be used in `for x in iterable`) as follows: - -``` -iterable = data_reader() -``` - -The item produced from the iterable should be a **single** entry of data and **not** a mini batch. The entry of data could be a single item or a tuple of items. Item should be of one of the [supported types](http://www.paddlepaddle.org/doc/ui/data_provider/pydataprovider2.html?highlight=dense_vector#input-types) (e.g., numpy 1d array of float32, int, list of int etc.) - -An example implementation for single item data reader creator is as follows: - -```python -def reader_creator_random_image(width, height): - def reader(): - while True: - yield numpy.random.uniform(-1, 1, size=width*height) - return reader -``` - -An example implementation for multiple item data reader creator is as follows: -```python -def reader_creator_random_image_and_label(width, height, label): - def reader(): - while True: - yield numpy.random.uniform(-1, 1, size=width*height), label - return reader -``` - -## Batch Reader Interface - -*Batch reader* can be any function without any parameters that creates an iterable (anything can be used in `for x in iterable`). The output of the iterable should be a batch (list) of data items. Each item inside the list should be a tuple. - -Here are some valid outputs: - -```python -# a mini batch of three data items. Each data item consist three columns of data, each of which is 1. -[(1, 1, 1), -(2, 2, 2), -(3, 3, 3)] - -# a mini batch of three data items, each data item is a list (single column). -[([1,1,1],), -([2,2,2],), -([3,3,3],)] -``` - -Please note that each item inside the list must be a tuple, below is an invalid output: -```python - # wrong, [1,1,1] needs to be inside a tuple: ([1,1,1],). - # Otherwise it is ambiguous whether [1,1,1] means a single column of data [1, 1, 1], - # or three columns of data, each of which is 1. -[[1,1,1], -[2,2,2], -[3,3,3]] -``` - -It is easy to convert from a reader to a batch reader: - -```python -mnist_train = paddle.dataset.mnist.train() -mnist_train_batch_reader = paddle.batch(mnist_train, 128) -``` - -It is also straight forward to create a custom batch reader: - -```python -def custom_batch_reader(): - while True: - batch = [] - for i in xrange(128): - batch.append((numpy.random.uniform(-1, 1, 28*28),)) # note that it's a tuple being appended. - yield batch - -mnist_random_image_batch_reader = custom_batch_reader -``` - -## Usage - -Following is how we can use the reader with PaddlePaddle: -The batch reader, a mapping from item(s) to data layer, the batch size and the number of total passes will be passed into `paddle.train` as follows: - -```python -# two data layer is created: -image_layer = paddle.layer.data("image", ...) -label_layer = paddle.layer.data("label", ...) - -# ... -batch_reader = paddle.batch(paddle.dataset.mnist.train(), 128) -paddle.train(batch_reader, {"image":0, "label":1}, 128, 10, ...) -``` - -## Data Reader Decorator - -The *Data reader decorator* takes in a single reader or multiple data readers and returns a new data reader. It is similar to a [python decorator](https://wiki.python.org/moin/PythonDecorators), but it does not use `@` in the syntax. - -Since we have a strict interface for data readers (no parameters and return a single data item), a data reader can be used in a flexible way using data reader decorators. Following are a few examples: - -### Prefetch Data - -Since reading data may take some time and training can not proceed without data, it is generally a good idea to prefetch the data. - -Use `paddle.reader.buffered` to prefetch data: - -```python -buffered_reader = paddle.reader.buffered(paddle.dataset.mnist.train(), 100) -``` - -`buffered_reader` will try to buffer (prefetch) `100` data entries. - -### Compose Multiple Data Readers - -For example, if we want to use a source of real images (say reusing mnist dataset), and a source of random images as input for [Generative Adversarial Networks](https://arxiv.org/abs/1406.2661). - -We can do the following : - -```python -def reader_creator_random_image(width, height): - def reader(): - while True: - yield numpy.random.uniform(-1, 1, size=width*height) - return reader - -def reader_creator_bool(t): - def reader: - while True: - yield t - return reader - -true_reader = reader_creator_bool(True) -false_reader = reader_creator_bool(False) - -reader = paddle.reader.compose(paddle.dataset.mnist.train(), data_reader_creator_random_image(20, 20), true_reader, false_reader) -# Skipped 1 because paddle.dataset.mnist.train() produces two items per data entry. -# And we don't care about the second item at this time. -paddle.train(paddle.batch(reader, 128), {"true_image":0, "fake_image": 2, "true_label": 3, "false_label": 4}, ...) -``` - -### Shuffle - -Given the shuffle buffer size `n`, `paddle.reader.shuffle` returns a data reader that buffers `n` data entries and shuffles them before a data entry is read. - -Example: -```python -reader = paddle.reader.shuffle(paddle.dataset.mnist.train(), 512) -``` - -## Q & A - -### Why does a reader return only a single entry, and not a mini batch? - -Returning a single entry makes reusing existing data readers much easier (for example, if an existing reader returns 3 entries instead if a single entry, the training code will be more complicated because it need to handle cases like a batch size 2). - -We provide a function: `paddle.batch` to turn (a single entry) reader into a batch reader. - -### Why do we need a batch reader, isn't is sufficient to give the reader and batch_size as arguments during training ? - -In most of the cases, it would be sufficient to give the reader and batch_size as arguments to the train method. However sometimes the user wants to customize the order of data entries inside a mini batch, or even change the batch size dynamically. For these cases using a batch reader is very efficient and helpful. - -### Why use a dictionary instead of a list to provide mapping? - -Using a dictionary (`{"image":0, "label":1}`) instead of a list (`["image", "label"]`) gives the advantage that the user can easily reuse the items (e.g., using `{"image_a":0, "image_b":0, "label":1}`) or even skip an item (e.g., using `{"image_a":0, "label":2}`). - -### How to create a custom data reader creator ? - -```python -def image_reader_creator(image_path, label_path, n): - def reader(): - f = open(image_path) - l = open(label_path) - images = numpy.fromfile( - f, 'ubyte', count=n * 28 * 28).reshape((n, 28 * 28)).astype('float32') - images = images / 255.0 * 2.0 - 1.0 - labels = numpy.fromfile(l, 'ubyte', count=n).astype("int") - for i in xrange(n): - yield images[i, :], labels[i] # a single entry of data is created each time - f.close() - l.close() - return reader - -# images_reader_creator creates a reader -reader = image_reader_creator("/path/to/image_file", "/path/to/label_file", 1024) -paddle.train(paddle.batch(reader, 128), {"image":0, "label":1}, ...) -``` - -### How is `paddle.train` implemented - -An example implementation of paddle.train is: - -```python -def train(batch_reader, mapping, batch_size, total_pass): - for pass_idx in range(total_pass): - for mini_batch in batch_reader(): # this loop will never end in online learning. - do_forward_backward(mini_batch, mapping) -``` diff --git a/develop/doc_cn/_sources/design/refactorization.md.txt b/develop/doc_cn/_sources/design/refactorization.md.txt deleted file mode 100644 index f93d6155e17..00000000000 --- a/develop/doc_cn/_sources/design/refactorization.md.txt +++ /dev/null @@ -1,249 +0,0 @@ -# Design Doc: Refactorization Overview - -The goals of refactoring include: - -1. Making it easy for external contributors to write new elementary computation operations. -1. Making the codebase clean and readable. -1. Designing a new computation representation -- a computation graph of operators and variables. -1. Implementing auto-scalability and auto fault recoverable distributed computing with the help of computation graphs. - -## Computation Graphs - -1. PaddlePaddle represents the computation, training and inference of Deep Learning models, by computation graphs. - - 1. Please refer to [computation graphs](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/graph.md) for a concrete example. - -1. Users write Python programs to describe the graphs and run them (locally or remotely). - -1. A graph is composed of *variables* and *operators*. - -1. The description of graphs must be serializable/deserializable, so that: - - 1. It can be sent to the cloud for distributed execution, and - 1. It can be sent to clients for mobile or enterprise deployment. - -1. The Python program does two things - - 1. *Compilation* runs a Python program to generate a protobuf message representation of the graph and send it to - 1. the C++ library `libpaddle.so` for local execution, - 1. the master process of a distributed training job for training, or - 1. the server process of a Kubernetes serving job for distributed serving. - 1. *Execution* executes the graph by constructing instances of class [`Variable`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/variable.h#L24) and [`OperatorBase`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/operator.h#L70), according to the protobuf message. - -## Description and Realization of Computation Graph - -At compile time, the Python program generates a protobuf message representation of the graph, or a description of the graph. - -At runtime, the C++ program realizes the graph and runs it. - -| | Representation (protobuf messages) | Realization (C++ class objects) | -|---|---|---| -|Data|[VarDesc](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto#L107)|[Variable](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/variable.h#L24)| -|Operation|[OpDesc](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto#L35)|[Operator](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/operator.h#L64)| -|Block|BlockDesc|Block| - -The word *graph* is interchangeable with *block* in this document. A graph consists of computation steps and local variables similar to a C++/Java program block, or a pair of parentheses(`{` and `}`). - -## Compilation and Execution - -1. Run a Python program to describe the graph. In particular, the Python application program does the following: - - 1. Create `VarDesc` to represent local/intermediate variables, - 1. Create operators and set attributes, - 1. Validate attribute values, - 1. Infer the type and the shape of variables, - 1. Plan memory-reuse for variables, - 1. Generate the backward graph - 1. Add optimization operators to the computation graph. - 1. Optionally, split the graph for distributed training. - -1. The invocation of `train` or [`infer`](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/v2/inference.py#L108) methods in the Python program does the following: - - 1. Create a new Scope instance in the [scope hierarchy](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/scope.md) for each run of a block, - 1. realize local variables defined in the BlockDesc message in the new scope, - 1. a scope is similar to the stack frame in programming languages, - - 1. Create an instance of class `Block`, in which, - 1. realize operators in the BlockDesc message, - - 1. Run the Block by calling - 1. `Block::Eval(vector* targets)` for forward and backward computations, or - 1. `Block::Eval(vector* targets)` for optimization. - - -## Intermediate Representation (IR) - -```text -Compile Time -> IR -> Runtime -``` - -### Benefits of IR - -- Optimization - ```text - Compile Time -> IR -> Optimized IR -> Runtime - ``` -- Automatically send partitioned IR to different nodes. - - Automatic Data Parallelism - ```text - Compile Time - |-> Single GPU IR - |-> [trainer-IR-0, trainer-IR-1, pserver-IR] - |-> Node-0 (runs trainer-IR-0) - |-> Node-1 (runs trainer-IR-1) - |-> Node-2 (runs pserver-IR) - ``` - - Automatic Model Parallelism (planned for future) - ---- - -# Operator/OpWithKernel/OpKernel - -![class_diagram](http://api.paddlepaddle.org/graphviz?dot=https://gist.githubusercontent.com/reyoung/53df507f6749762675dff3e7ce53372f/raw/49caf1fb70820fb4a6c217634317c9306f361f36/op_op_with_kern_class_diagram.dot) - ---- - -# Operator -![class_diagram](http://api.paddlepaddle.org/graphviz?dot=https://gist.githubusercontent.com/reyoung/53df507f6749762675dff3e7ce53372f/raw/dd598e8f1976f5759f58af5e5ef94738a6b2e661/op.dot) - -* `Operator` is the fundamental building block of the user interface. - * Operator stores input/output variable names and attributes. - * The `InferShape` interface is used to infer the shape of the output variables based on the shapes of the input variables. - * Use `Run` to compute the `output` variables from the `input` variables. - ---- - -# OpWithKernel/Kernel - -![class_diagram](http://api.paddlepaddle.org/graphviz?dot=https://gist.githubusercontent.com/reyoung/53df507f6749762675dff3e7ce53372f/raw/9d7f4eba185cf41c8e2fbfb40ae21890dbddcd39/op_with_kernel.dot) - -* `OpWithKernel` inherits `Operator`. -* `OpWithKernel` contains a Kernel map. - * `OpWithKernel::Run` get device's kernel, and invoke `OpKernel::Compute`. - * `OpKernelKey` is the map key. Only device place now, but may be data type later. - ---- - -# Why separate Kernel and Operator - -* Separate GPU and CPU code. - * Make Paddle capable of running without GPU. -* Make one operator (which is a user interface) and create many implementations. - * For example, same multiplication op can have different implementations kernels such as FP16 kernel, FP32 kernel, MKL, eigen kernel. ---- - -# Libraries for Kernel development - -* `Eigen::Tensor` contains basic math and element-wise functions. - * Note that `Eigen::Tensor` has broadcast implementation. - * Limit the number of `tensor.device(dev) = ` in your code. -* `thrust::transform` and `std::transform`. - * `thrust` has the same API as C++ standard library. Using `transform`, one can quickly implement customized element-wise kernels. - * `thrust`, in addition, supports more complex APIs, like `scan`, `reduce`, `reduce_by_key`. -* Hand-writing `GPUKernel` and `CPU` code - * Do not write in header (`.h`) files. CPU Kernel should be in cpp source (`.cc`) and GPU kernels should be in cuda (`.cu`) files. (GCC cannot compile GPU code.) ---- -# Operator Registration - -## Why is registration necessary? -We need a method to build mappings between Op type names and Op classes. - -## How is registration implemented? -Maintaining a map, whose key is the type name and the value is the corresponding Op constructor. - ---- -# The Registry Map - -### `OpInfoMap` - -`op_type(string)` -> `OpInfo` - -`OpInfo`: - -- **`creator`**: The Op constructor. -- **`grad_op_type`**: The type of the gradient Op. -- **`proto`**: The Op's Protobuf, including inputs, outputs and required attributes. -- **`checker`**: Used to check attributes. - ---- -# Related Concepts - -### Op_Maker -It's constructor takes `proto` and `checker`. They are completed during Op_Maker's construction. ([ScaleOpMaker](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/scale_op.cc#L37)) - -### Register Macros -```cpp -REGISTER_OP(op_type, op_class, op_maker_class, grad_op_type, grad_op_class) -REGISTER_OP_WITHOUT_GRADIENT(op_type, op_class, op_maker_class) -``` - ---- -# Registration Process -1. Write an Op class and its gradient Op class, if required. -2. Write an Op maker class. In the constructor of this class, describe the inputs, outputs and attributes of the operator. -3. Invoke the macro `REGISTER_OP`. This macro will - 1. Call maker class to complete `proto` and `checker` - 2. Using the completed `proto` and `checker`, it will add a new key-value pair to the `OpInfoMap` - ---- -# Backward Module (1/2) -### Create Backward Operator -- Mapping from forward Op to backward Op -![backward](https://gist.githubusercontent.com/dzhwinter/a6fbd4623ee76c459f7f94591fd1abf0/raw/61026ab6e518e66bde66a889bc42557a1fccff33/backward.png) - ---- -# Backward Module (2/2) -### Build Backward Network -- **Input**: a graph of forward operators -- **Output**: a graph of backward operators -- **Corner cases in construction** - - Shared Variables => insert an `Add` operator to combine gradients - - No Gradient => insert a `fill_zero_grad` operator - - Recursive NetOp => call `Backward` recursively - - RNN Op => recursively call `Backward` on stepnet - - RNN Op => recursively call `Backward` on stepnet - - ---- -# Scope, Variable, Tensor - -* `Tensor` is an n-dimension array with type. - * Only dims and data pointers are stored in `Tensor`. - * All operations on `Tensor` are written in `Operator` or global functions. - * Variable length Tensor design [LoDTensor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/lod_tensor.md) -* `Variable` instances are the inputs and the outputs of an operator, not just `Tensor`. - * `step_scopes` in RNN is a variable and not a tensor. -* `Scope` is where variables are stored. - * map - * `Scope` has a hierarchical structure. The local scope can get variables from its parent scope. - ---- -# Block (in design) -## the difference between original RNNOp and Block -- As an operator is more intuitive than `RNNOp`, -- Offers a new interface `Eval(targets)` to deduce the minimal block to `Run`, -- Fits the compile-time/ runtime separation design paradigm. - - During the compilation, `SymbolTable` stores `VarDesc`s and `OpDesc`s and serialize to a `BlockDesc` - - When graph executes, a Block with `BlockDesc` is passed. It then creates `Op` and `Var` instances and then invokes `Run`. - ---- -# Milestone -- Take Paddle/books as the main line, the requirement of the models motivates framework refactoring, -- Model migration - - Framework development gives **priority support** to model migration, for example, - - the MNIST demo needs a Python interface, - - the RNN models require the framework to support `LoDTensor`. - - Determine some timelines, - - Frequently used Ops need to be migrated first, - - Different models can be migrated in parallel. -- Improve the framework at the same time -- Accept imperfection, concentrate on solving the specific problem at the right price. - ---- -# Control the migration quality -- Compare the performance of migrated models with old ones. -- Follow the google C++ style guide. -- Build the automatic workflow of generating Python/C++ documentations. - - The documentation of layers and ops should be written inside the code. - - Take the documentation quality into account when submitting pull requests. - - Preview the documentations, read and improve them from a user's perspective. diff --git a/develop/doc_cn/_sources/design/register_grad_op.md.txt b/develop/doc_cn/_sources/design/register_grad_op.md.txt deleted file mode 100644 index 8d973eb5317..00000000000 --- a/develop/doc_cn/_sources/design/register_grad_op.md.txt +++ /dev/null @@ -1,92 +0,0 @@ -# Design Doc: Gradient Operators Registration - - -## The Problem Posed - -Currently, for each C++ operator class definition, a *gradient operator creator* function is registered, which takes as input a C++ operator instance and returns the corresponding gradient operator instance. - -However, we noticed two problems with the current design: - -1. As we decided to separate the *compilation* and the *execution* phases, we need to change the creator to take an `OpDesc` protobuf message in a `ProgramDesc` and inserts corresponding `OpDesc` messages into the `ProgramDesc` message. - -1. For some operators, the gradient computation can be written in terms of existing operators. For example, the gradient of *minus* operator consists of two operators -- an *identity* operator followed by a *scale* operator. Hence the registration mechanism needs to support mapping from an operator to a set of operators for the gradient computation. - -## The Current Implementation - -Instances of the C++ class `OpInfo` are stored an associative map whose key is the operator type. The `grad_op_type` indicates the associated gradient operator type. An operator can create the gradient operator by invoking `OpInfo::creator_` of the gradient operator. The pseudo code is as follows - -```cpp -struct OpInfo { - std::function creator_; - std::string grad_op_type_; - ... -}; - -map OpInfoMap; - -OperatorBase* CreateGradientOperator(const OperatorBase& op) { - return OpInfoMap.at(op.Type()).creator_(...); -} -``` - -## Proposed Solution - -The mapping relationship between an operator and its gradient operators is a function. The interface of this function is: - -```cpp -// (OpDesc) --> vector -std::function(const OpDescBind&)>; -``` - -The function takes an `OpDescBind` of the forward operator and returns one or many gradient operator descriptions. `OpDescBind` is a C++ wrapper for the protobuf message `OpDesc` for rapid manipulation of `OpDesc`. - -The `GradOpDescMaker` will be registered in `OpInfo` and will replace the `grad_op_type_` field. The `OpInfo` should look like - -```cpp -struct OpInfo { - std::function>(const OpDescBind&)> grad_op_maker_; - ... -}; -``` - -The `grad_op_maker_ ` is a `nullptr` if the operator does not have any associated gradient operators. - -We propose a base class called `GradOpDescMakerBase` to let operator developers generate `Gradient Operators` easily. The public interface of that class is - -```cpp -class GradOpDescMakerBase { -public: - GradOpDescMakerBase(const OpDescBind& ); - virtual std::vector> operator()()const = 0; -}; -``` - -We can convert `GradOpDescMakerBase` to `std::function>(const OpDescBind&)>` by - -```cpp -using GradOpMaker = ...; -std::function(const OpDescBind&)> func; -func = [] (const OpDescBind& fwd_op) { - GradOpMaker maker(fwd_op); - return maker(); -}; -``` - -We can write many helper functions since the `GradOpDescMakerBase` is a class now. The basic helper functions get the variables of `Input`, `Output`, `InputGradient` and `OutputGradient` in the forwarding operator. - -We should change register macros at the same time. In the current solution, there is no difference between forwarding operators and backward operators. So `REGISTER_OP` just register one operator. If the `REGISTER_OPERATOR ` contains `OpProtoAndCheckerMaker` and `GradOpDescMaker`, we just list them in the same macro. It can be done by a macro contains `__VA_ARGS__`. - -The user interface should be - -```cpp -vector MinusOpGradMaker(OpDesc) {...} -REGISTER_OPERATOR(minus, MinusOp, MinusOpProtoAndCheckerMaker, SumOpGradMaker); -// Developers can still manually implement gradient operator. -REGISTER_OPERATOR(minus_grad, MinusGradOp); -``` - -The interface of current `REGISTER_OP` macro could not be changed. In `REGISTER_OP`, it will invoke `REGISTER_OPERATOR` two times and generate GradOpDescMaker inside. - -```cpp -REGISTER_OP(minus, MinusOp, MinusOpProtoAndCheckerMaker, minus_grad, MinusGradOp); -``` diff --git a/develop/doc_cn/_sources/design/regularization.md.txt b/develop/doc_cn/_sources/design/regularization.md.txt deleted file mode 100644 index 21280ac898f..00000000000 --- a/develop/doc_cn/_sources/design/regularization.md.txt +++ /dev/null @@ -1,72 +0,0 @@ -# Regularization in PaddlePaddle - -## Introduction to Regularization -A central problem in machine learning is how to design an algorithm that will perform well not just on the training data, but also on new data. A frequently faced problem is the problem of **overfitting**, where the model does not make reliable predictions on new unseen data. **Regularization** is the process of introducing additional information in order to prevent overfitting. This is usually done by adding extra penalties to the loss function that restricts the parameter spaces that an optimization algorithm can explore. - -### Parameter Norm Penalties -Most common regularization approaches in deep learning are based on limiting the capacity of the models by adding a parameter norm penalty to the objective function `J`. This is given as follows: - -
                                - -The parameter `alpha` is a hyperparameter that weights the relative contribution of the norm penalty term, `omega`, relative to the standard objective function `J`. - -The most commonly used norm penalties are the L2 norm penalty and the L1 norm penalty. These are given as follows: - -##### L2 Regularization: -
                                - -##### L1 Regularization -
                                - -A much more detailed mathematical background of regularization can be found [here](http://www.deeplearningbook.org/contents/regularization.html). - -## Regularization Survey - -A detailed survey of regularization in various deep learning frameworks can be found [here](https://github.com/PaddlePaddle/Paddle/wiki/Regularization-Survey). - -## Proposal for Regularization in PaddlePaddle - -### Low-Level implementation - -In the new design, we propose to create new operations for regularization. For now, we can add 2 ops that correspond to the most frequently used regularizations: -- L2_regularization_op -- L1_regularization_op - -These ops can be like any other ops with their own CPU/GPU implementations either using Eigen or separate CPU and GPU kernels. As the initial implementation, we can implement their kernels using Eigen following the abstraction pattern implemented for [Activation Ops](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/accuracy_op.h). This abstraction pattern can make it very easy to implement new regularization schemes other than L1 and L2 norm penalties. - -The idea of building ops for regularization is in sync with the refactored Paddle philosophy of using operators to represent any computation unit. The way these ops will be added to the computation graph, will be decided by the [layer functions](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md#layer-function) in Python API. - -### Computation Graph - -Below is an example of a really simple feed forward neural network. - -
                                - -The Python API will modify this computation graph to add regularization operators. The modified computation graph will look as follows: - -
                                -    -### Python API implementation for Regularization - -Using the low level ops, `L2_regularization_op` and `L1_regularization_op`, any user can add regularization to their computation graphs. However, this will require a lot of lines of code and we should design Python APIs that support regularization. An example of such an API can be seen in [Keras](https://keras.io/regularizers/). As per the PaddlePaddle [Python API design](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md), the layer functions are responsible for creating operators, operator parameters and variables. Since regularization is a property of parameters, it makes sense to create these in the layer functions. - -#### Creation of Regularization ops -There are two possibilities for creating the regularization ops: -1. We create these ops immediately while building the computation graph. -2. We add these ops in a lazy manner, just before the backward, similar to the way the optimization ops are added. - -The proposal is to add these ops in a lazy manner just before the backward pass. - -#### Storage of Regularization attributes - -Since we want to create the regularization ops in a lazy manner, the regularization attributes (type of regularization and weight of regularization penalty) can be stored as attributes of the [`Parameter`](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/v2/framework/framework.py#L421) class. This is because regularization is a property of the parameters and storing regularization properties with Parameters also allows for shared parameters. - -#### High-level API - -In PaddlePaddle Python API, users will primarily rely on [layer functions](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/python_api.md#layer-function) to create neural network layers. Hence, we also need to provide regularization functionality in layer functions. The design of these APIs can be postponed for later right now. A good reference for these APIs can be found in [Keras](https://keras.io/regularizers/) and also by looking at Tensorflow in [`tf.contrib.layers`](https://www.tensorflow.org/api_guides/python/contrib.layers). - - - - - - diff --git a/develop/doc_cn/_sources/design/releasing_process.md.txt b/develop/doc_cn/_sources/design/releasing_process.md.txt deleted file mode 100644 index b9787261092..00000000000 --- a/develop/doc_cn/_sources/design/releasing_process.md.txt +++ /dev/null @@ -1,90 +0,0 @@ -# PaddlePaddle发行规范 - -PaddlePaddle使用git-flow branching model做分支管理,使用[Semantic Versioning](http://semver.org/)标准表示PaddlePaddle版本号。 - -PaddlePaddle每次发新的版本,遵循以下流程: - -1. 从`develop`分支派生出新的分支,分支名为`release/版本号`。例如,`release/0.10.0` -1. 将新分支的版本打上tag,tag为`版本号rc.Patch号`。第一个tag为`0.10.0rc1`,第二个为`0.10.0rc2`,依次类推。 -1. 对这个版本的提交,做如下几个操作: - * 使用Regression Test List作为检查列表,测试本次release的正确性。 - * 如果失败,记录下所有失败的例子,在这个`release/版本号`分支中,修复所有bug后,Patch号加一,到第二步 - * 修改`python/setup.py.in`中的版本信息,并将`istaged`字段设为`True`。 - * 编译这个版本的python wheel包,并发布到pypi。 - * 由于pypi.python.org目前遵循[严格的命名规范PEP 513](https://www.python.org/dev/peps/pep-0513),在使用twine上传之前,需要重命名wheel包中platform相关的后缀,比如将`linux_x86_64`修改成`manylinux1_x86_64`。 - * pypi上的package名称为paddlepaddle和paddlepaddle_gpu,如果要上传GPU版本的包,需要修改build/python/setup.py中,name: "paddlepaddle_gpu"并重新打包wheel包:`python setup.py bdist_wheel`。 - * 上传方法: - ``` - cd build/python - pip install twine - twine upload dist/[package to upload] - ``` - * 编译这个版本的Docker发行镜像,发布到dockerhub。如果失败,修复Docker编译镜像问题,Patch号加一,返回第二步 -1. 第三步完成后,将`release/版本号`分支合入master分支,并删除`release/版本号`分支。将master分支的合入commit打上tag,tag为`版本号`。同时再将`master`分支合入`develop`分支。最后删除`release/版本号`分支。 -1. 协同完成Release Note的书写 - - -需要注意的是: - -* `release/版本号`分支一旦建立,一般不允许再从`develop`分支合入`release/版本号`。这样保证`release/版本号`分支功能的封闭,方便测试人员测试PaddlePaddle的行为。 -* 在`release/版本号`分支存在的时候,如果有bugfix的行为,需要将bugfix的分支同时merge到`master`, `develop`和`release/版本号`这三个分支。 - -## 发布wheel包到pypi - -使用[PaddlePaddle CI](https://paddleci.ngrok.io/project.html?projectId=Manylinux1&tab=projectOverview) -完成自动化二进制编译,参考下图,选择需要发布的版本(通常包含一个CPU版本和一个GPU版本),点击"run"右侧的"..."按钮,可以 -弹出下面的选择框,在第二个tab (Changes)里选择需要发布的分支,这里选择0.11.0,然后点击"Run Build"按钮。等待编译完成后 -可以在此页面的"Artifacts"下拉框中找到生成的3个二进制文件,分别对应CAPI,`cp27m`和`cp27mu`的版本。然后按照上述的方法 -使用`twine`工具上传即可。 - - - -* 注:CI环境使用 https://github.com/PaddlePaddle/buildtools 这里的DockerImage作为编译环境以支持更多的Linux - 发型版,如果需要手动编译,也可以使用这些镜像。这些镜像也可以从 https://hub.docker.com/r/paddlepaddle/paddle_manylinux_devel/tags/ 下载得到。 -* pypi不支持覆盖上传,所以一个版本号的wheel包发布之后,不可以更改。下一个wheel包需要更新版本号才可以上传。 - -## 发布Docker镜像 - -上述PaddlePaddle CI编译wheel完成后会自动将Docker镜像push到DockerHub,所以,发布Docker镜像只需要对自动push的镜像打上 -版本号对应的tag即可: - -1. 进入 https://hub.docker.com/r/paddlepaddle/paddle/tags/ 查看latest tag的更新时间是否在上述编译wheel包完成后是否最新。 -1. 执行 `docker pull paddlepaddle/paddle:[latest tag]`,latest tag可以是latest或latest-gpu等。 -1. 执行 `docker tag paddlepaddle/paddle:[latest tag] paddlepaddle/paddle:[version]` -1. 执行 `docker push paddlepaddle/paddle:[version]` - -## PaddlePaddle 分支规范 - -PaddlePaddle开发过程使用[git-flow](http://nvie.com/posts/a-successful-git-branching-model/)分支规范,并适应github的特性做了一些区别。 - -* PaddlePaddle的主版本库遵循[git-flow](http://nvie.com/posts/a-successful-git-branching-model/)分支规范。其中: - * `master`分支为稳定(stable branch)版本分支。每一个`master`分支的版本都是经过单元测试和回归测试的版本。 - * `develop`分支为开发(develop branch)版本分支。每一个`develop`分支的版本都经过单元测试,但并没有经过回归测试。 - * `release/版本号`分支为每一次Release时建立的临时分支。在这个阶段的代码正在经历回归测试。 - -* 其他用户的fork版本库并不需要严格遵守[git-flow](http://nvie.com/posts/a-successful-git-branching-model/)分支规范,但所有fork的版本库的所有分支都相当于特性分支。 - * 建议,开发者fork的版本库使用`develop`分支同步主版本库的`develop`分支 - * 建议,开发者fork的版本库中,再基于`develop`版本fork出自己的功能分支。 - * 当功能分支开发完毕后,向PaddlePaddle的主版本库提交`Pull Reuqest`,进而进行代码评审。 - * 在评审过程中,开发者修改自己的代码,可以继续在自己的功能分支提交代码。 - -* BugFix分支也是在开发者自己的fork版本库维护,与功能分支不同的是,BugFix分支需要分别给主版本库的`master`、`develop`与可能有的`release/版本号`分支,同时提起`Pull Request`。 - -## PaddlePaddle回归测试列表 - -本列表说明PaddlePaddle发版之前需要测试的功能点。 - -### PaddlePaddle Book中所有章节 - -PaddlePaddle每次发版本首先要保证PaddlePaddle Book中所有章节功能的正确性。功能的正确性包括验证PaddlePaddle目前的`paddle_trainer`训练和纯使用`Python`训练模型正确性。 - -| | 新手入门章节 | 识别数字 | 图像分类 | 词向量 | 情感分析 | 语意角色标注 | 机器翻译 | 个性化推荐 | -| --- | --- | --- | --- | --- | --- | --- | --- | --- | -| API.V2 + Docker + GPU | | | | | | | | | -| API.V2 + Docker + CPU | | | | | | | | | -| `paddle_trainer` + Docker + GPU | | | | | | | | | -| `paddle_trainer` + Docker + CPU | | | | | | | | | -| API.V2 + Ubuntu + GPU | | | | | | | | | -| API.V2 + Ubuntu + CPU | | | | | | | | | -| `paddle_trainer` + Ubuntu + GPU | | | | | | | | | -| `paddle_trainer` + Ubuntu + CPU | | | | | | | | | diff --git a/develop/doc_cn/_sources/design/scope.md.txt b/develop/doc_cn/_sources/design/scope.md.txt deleted file mode 100644 index 4da76eebb74..00000000000 --- a/develop/doc_cn/_sources/design/scope.md.txt +++ /dev/null @@ -1,124 +0,0 @@ -# Design of Scope in Paddle - -## Overview - -Scope is an important concept in programming languages, which defines a program region that a set of bindings between names and entities applies. In a specific scope, a valid name is uniquely associated with an entity, such as a variable. And in another scope, this name may refer to other entity or nothing at all. It clearly restricts the visibility and validity of names in a program. Hence **Scope** is introduced to PaddlePaddle to manage variables in context. But different from the original abstract concept, Scope now becomes an object with two important attributes: - -- Scope is an association of a name to variable. -- Variables in a parent scope can be retrieved from local scope. - -A detailed explanation of these two attributes goes as following. - - -## Scope is an association of a name to variable. - -Scope is an association of a name to variable. All variables belong to `Scope`. You need to specify a scope to run a Net, i.e., `net.Run(&scope)`. One net can run in different scopes and update different variable in the scope. - - -1. Scope only contains a map of a name to variable. - - All parameters, data, states in a Net should be variables and stored inside a scope. Each op should get inputs and outputs to do computation from a scope, such as data buffer, state (momentum) etc. - -1. Variable can only be created by Scope and a variable can only be got from Scope. User cannot create or get a variable outside a scope. This is a constraints of our framework, and will keep our framework simple and clear. - -1. Scope only contains methods that are used to Create and Get Variables. Scope do not contain Operators and have no information to run them. - `Net` is designed to drive the computation and Scope only contains a map of variables. There is no computation logic inside a `Scope`. Scope just handles the lifetime management of variables. - - `Create` is used to create a Variable by its name and add the mapping relation. - - `Get` is used to find a Variable by name. - -1. Every variable only belongs to one certain Scope. - - Variable can not belong to many scopes. If you want to use variables from parent scope, you can use `parent scope`. - -1. Scope should destruct all Variables inside it when itself is destructed. User can never store `Variable` pointer somewhere else. - - Because Variable can only be got from Scope. When destroying Scope, we also need to destroy all the Variables in it. If user store `Variable` pointer to private data member or some global variable, the pointer will be an invalid pointer when associated `Scope` is destroyed. - -```cpp -class Scope { - public: - Variable* Var(const std::string& name); - const Variable* FindVar(const std::string& name) const; - - private: - std::unordered_map> vars_; -}; -``` - - -## Parent scope and local scope - -Just like [scope](https://en.wikipedia.org/wiki/Scope_(computer_science)) in programming languages, `Scope` in the neural network can also be a local scope. There are two attributes about local scope. - -1. We can create local variables in a local scope. When that local scope is destroyed, all local variables should also be destroyed. -2. Variables in a parent scope can be retrieved from local scopes of that parent scope, i.e., when user get a variable from a scope, it will try to search this variable in current scope. If there is no such variable in the local scope, `scope` will keep searching from its parent, until the variable is found or there is no parent. - -```cpp -class Scope { - public: - Scope(const std::shared_ptr& scope): parent_(scope) {} - - Variable* FindVar(const std::string& name) const { - auto it = vars_.find(name); - if (it != vars_.end()) { - return it->second.get(); - } else if (parent_ != nullptr) { - return parent_->FindVar(name); - } else { - return nullptr; - } - } - - private: - std::shared_ptr parent_ {nullptr}; -}; -``` - -In `Scope` class, there is a private data member called `parent_`. `parent_` is a smart pointer to its parent scope. When user `Get` a variable by its `name`, the `name` will be searched inside the current scope. If the variable cannot be found locally and parent scope is not a `nullptr`, the variable will be searched inside that parent scope. `parent_` pointer's default value is `nullptr`. It means that the scope is a global scope when `parent_` is nullptr. - -A local scope is very useful when we implement Recurrent Neural Network. Each timestep of an RNN should be a `Net`. Each `Net` of timestep (`StepNet` for short) should use an independent local scope. Just like variables in a while loop is inside a local scope in programming languages. By using a single `StepNet` and changing local scope, we can implement an RNN easily. - -# Interface Design - -```cpp -class Variable { - private: - Variable() = default; - friend class Scope; -}; - -class Scope { - private: - Scope(const std::shared_ptr& parent = nullptr); - - public: - static std::shared_ptr Create(const std::shared_ptr& parent = nullptr); - - // return nullptr if not found. - Variable* FindVar(const std::string& name) const; - - // return if already contains same name variable. - Variable* Var(const std::string& name); - - private: - std::shared_ptr parent_; - std::unordered_map> vars_; -}; -``` -## Only scope can create a variable - -To ensure `only scope can create a variable`, we should mark `Variable`'s constructor as a private member function, and Scope is a friend class of Variable. And then only `Var` can construct `Variable`. - -## When scope destroyed, all variables inside this scope should be destroyed together - -The scope hold unique pointers for all variables. User can `FindVar` from scope, but he should not hold this pointer as a member variable. Because when scope is destroyed, all variables inside this scope will be destroyed together. - -## Sharing a parent scope - -Local scope contains a `parent_` pointer. It is a linked-list for scopes. Using a `shared_ptr` because when a local scope is using, its parents cannot be destroyed. - -Also, as the parent scope is a `shared_ptr`, we can only `Create()` a scope shared pointer. We cannot construct a scope variable, because it cannot be passed to other scope as `parent` pointer. - -## Orthogonal interface - -`FindVar` will return `nullptr` when `name` is not found. It can be used as `Contains` method. `Var` will return an `Error` when there is a name conflict locally. Combine `FindVar` and `Var`, we can implement `Var` easily. diff --git a/develop/doc_cn/_sources/design/selected_rows.md.txt b/develop/doc_cn/_sources/design/selected_rows.md.txt deleted file mode 100644 index 1a98839a957..00000000000 --- a/develop/doc_cn/_sources/design/selected_rows.md.txt +++ /dev/null @@ -1,74 +0,0 @@ -# Design Doc: Selected Rows - -`SelectedRows` is a type of sparse tensor data type, which is designed to support `embedding` operators. The gradient of embedding table is a sparse tensor. Only a few rows are non-zero values in this tensor. It is straight-forward to represent a sparse tensor by the following sparse tensor data structure: - -```cpp -class SelectedRows { - private: - vector rows_; - Tensor value_; - int height_; -}; -``` - -The field `height_` is the first dimension of `SelectedRows`. The `rows` are the indices of the non-zero rows of `SelectedRows`. The `value_` field is an N-dim tensor of shape `[rows.size() /* NUM_ROWS */, ...]`, which supplies values for each row. The dimension of `SelectedRows` satisfies `[height_] + value_.shape[1:]`. - -Suppose that a SelectedRows-typed variable `x` has many rows, but only two of them have values -- row 73 is `[1, 2]` and row 84 is `[3, 4]`, the `SelectedRows` representation would be: - -``` -x = SelectedRow { - rows = [73, 84], - value = [[1, 2], [3,4]] -} -``` - - -## SelectedRows in Protobuf - -`SelectedRows` is a type of `Variable`. `VarDesc` in protobuf should describe the `SelectedRows` information. Only the tensor dimension of a `SelectedRows` will be described in compile-time because the `rows_` and `value_` are dependent on the training data. -So we use `TensorDesc` to unify `data_type` and `dims`. A LodTensorDesc contains a `TensorDesc` and `lod_level`. The description of `SelectedRows` is a Tensor description. - -```proto -message TensorDesc { - required DataType data_type = 1; - repeated int64 dims = 2; // [UNK, 640, 480] is saved as [-1, 640, 480] -} - -message LodTensorDesc { - required TensorDesc tensor = 1; - optional int lod_level = 2; -} - -message VarDesc { - required string name = 1; - enum VarType { - LOD_TENSOR = 0; - SELECTED_ROWS = 1; - } - required VarType type = 2; - optional LodTensorDesc lod_desc = 3; - optional TensorDesc selected_rows_desc = 4; - optional bool persistable = 5 [ default = false ]; -} -``` - -## InferShape for Selected Rows - -Just like `LoD` information, `InferShape` method will infer the output tensor type as well. The operator should decide whether its output is a `SelectedRows` or `Dense` tensor. - -For example, the gradient operator of `TableLookup` will always generate `SelectedRows`. Its `InferShape` method should be like following - -```cpp -void TableLookupGrad::InferShape(context) { - ... - context.SetDataType("Embedding.Grad", kSelectedRows); -} -``` - - -## Sparse Operators - -There are several operators that need to be written to support `SelectedRows`. These are: - -1. Operators which generate `SelectedRows` gradient. e.g. Gradient of `TableLookupOp`. -2. Optimize operators which support `SelectedRows` gradient. e.g. `SGD` or `AdaGrad` for `SelectedRows`. However, there should be only one `SGD` operator. `OpWithKernel::Run` should select a suitable kernel for both `dense` tensor or `SelectedRows`. diff --git a/develop/doc_cn/_sources/design/simple_op_design.md.txt b/develop/doc_cn/_sources/design/simple_op_design.md.txt deleted file mode 100644 index c7aeed7f9b4..00000000000 --- a/develop/doc_cn/_sources/design/simple_op_design.md.txt +++ /dev/null @@ -1,202 +0,0 @@ -## Interaction between C++ and Python - -Users employ API in Python to describe their own network, however, the network construction actually happens in C++. so Protobuf is introduced to send the message between Python and C++. - -The Interaction between Python and C++ can be simplified as two steps: - -1. C++ tells Python how many Ops there are, and what parameter do users need to offer to initialize a new Op. Python then builds API for each Op at compile time. - -2. Users invoke APIs built by Python and provide necessary parameters. These parameters will be sent to C++ for finishing the Op construction task. - -### Message from C++ to Python - -We define a Protobuf message class `OpProto` to hold message needed in the first step. What should an `OpProto` contain? This question is equivalent to “What message do we need to offer, to build a Python API which is legal and user oriented and can use to describe a whole Op.” - -Following message are necessary: - -1. Op's name, and its simple comment. -2. Input and output variable number; each variable's name, type, and comment. -3. Op's attributes; each attribute includes name, type, comment, **default value** and **value range**. - -So `OpProto` can be defined as follows: - -```proto -enum AttrType { - INT = 1; - FLOAT = 2; - STRING = 3; - INTS = 4; - FLOATS = 5; - STRINGS = 6; -}; - -message AttrValue { - AttrType type = 1; - optional int iv = 2; - optional float fv = 3; - optional string sv = 4; - repeated int ivs = 5; - repeated float fvs = 6; - repeated string svs = 7; -}; - -message AttrProto { - required string name = 1; - required string comment = 2; - required AttrType type = 3; -}; - -message VarProto { - required string name = 1; - required string comment = 2; - required bool is_tensor = 3; -}; - -message OpProto { - repeated VarProto inputs = 1; - repeated VarProto outputs = 2; - repeated AttrProto attrs = 3; - required string type = 4; - required string comment = 5; -}; -``` - -To generate Python code automatically: - -```python -def create_python_ops_creatation_functions(): - op_protos = paddle.framework.OpRegistry.get_all_op_proto() - for type_name in op_protos: - op_proto = op_protos[type_name] - def __impl__(**kwargs): # User must use key word args in Paddle API - inputs = [kwargs.get(ipt.name, "") for ipt in op_proto.inputs] - outputs = [kwargs.get(opt.name, "") for opt in op_proto.outputs] - attrs = [cast_to_op_attr(attr, kwargs.get(attr.name, None)) for attr in op_proto.attrs] - opdesc = (input, outputs, type_name, attrs) - return paddle.framework.OpRegistry.CreateOp(opdesc) - __impl__.__doc__ = create_doc_string(op_proto) - globals()[type_name] = __impl__ - -create_python_ops_creatation_functions() -``` - -### Message from Python to C++ - -To hold message needed in the above second step, we define Protobuf message class `OpDesc`. It is used to hold user-specified parameters in Op describing. - -```proto -message OpDesc { - required string type = 1; - repeated string inputs = 2; - repeated string outputs = 3; - map attrs = 4; -}; -``` - -## OpProto Register - -Every Op has its own `OpProto`. For using convenience, we need to register them and record all their messages. For each `Op` class, we define a corresponding `OpMaker` class, in whose constructor we implement the `OpProto`'s building process. `OpMaker`'s constructor will be invoked by another function `OpRegistry::RegisterOp()`. - -```cpp -class OpProtoMaker { -public: - OpProtoMaker(OpProto* proto): proto_(proto) {} -protected: - OpProto* proto_; - void AddInput(const std::string& name, const std::string& desc) {...} - void AddAttr(const std::string& name, const std::string& desc, TypeId type) {...} - void AddComment(const std::string& comment) { ... } -}; - -class OpRegistry { -public: - using OpCreator = std::function; - - template - static void RegisterOp(const std::string& name) { - gCreators_[name] = [](const OpDesc& desc) { - return new OpType(desc); - }; - OpProto& opProto = gProtos_[name]; - OpMaker()(&opProto); - } - - static map gCreators_; - static map gProtos_; -}; - -template -class OpRegister { - public: - OpRegister(std::string type) { - OpRegistry::RegisterOp(type); - } -}; - -#define REGISTER_OP(op_class, op_maker_class, type_name) \ - class op_class##Register { \ - private: \ - const static OpRegister<#op_class, #op_maker_class> reg; \ - }; \ - const Register op_class##Register::reg(#type_name); - -class CosineOp { -// ... -} - -struct CosineOpProtoMaker : public OpProtoMaker { - CosineOpProtoMaker(OpProto* proto) : OpProtoMaker(proto) { - AddInput("input", "input of cosine op"); - AddAttr("scale", "scale of cosine op", float).Default(1.0).GreaterThan(0.0); - AddType("cos"); - AddComment("This is cos op"); - } -} - -REGISTER_OP(CosineOp, CosineOpProtoMaker, cos); -``` - -In `REGISTER_OP(CosineOp, CosineOpProtoMaker, cos)`, we register not only `CosineOp` but also `CosineOpProto`. As fields of `CosineOpProto`, the default value and value range of `scale` are also registered here. - -## Python API - -Python APIs are divided into two types, high-level API and low-level API. - -### High-Level API - -High-level API is called by users directly, so it should keep its style consistent with existing V2 APIs. - -Here is a sample about how a define a fc layer: - -```python -hd = fc_layer(input=data, size=56, with_bias=True, activation="sigmoid"); -``` - -`hd` is the output of `fc_layer` and it's a `variable`. It can be further sent into other layers as input. - -The definition of `fc_layer()`: - -```python -def fc_layer(input, size, with_bias, activation): - attr_map = {"size":size} - check_attrs(attr_map) - w = make_variable('w') - if with_bias: - b = make_variable('b') - else: - b = None - fc_output = make_variable('fc_output'); - fc_op(input, w, b, fc_output, attr_map) - act_output = make_variable('sigmod_output'); - if activation == "sigmod": - sigmod_op(fc_output, act_output); - elif: - # ... - return act_output; -``` - -### Low Leval API - -In above sample, `fc_op` and `sigmod_op` are low-level API. They build `OpDesc` and invoke corresponding C++ code. - -*TODO* diff --git a/develop/doc_cn/_sources/design/speech/deep_speech_2.md.txt b/develop/doc_cn/_sources/design/speech/deep_speech_2.md.txt deleted file mode 100644 index cfdc4d6df04..00000000000 --- a/develop/doc_cn/_sources/design/speech/deep_speech_2.md.txt +++ /dev/null @@ -1,168 +0,0 @@ -# DeepSpeech2 on PaddlePaddle: Design Doc - -We are planning to build Deep Speech 2 (DS2) \[[1](#references)\], a powerful Automatic Speech Recognition (ASR) engine, on PaddlePaddle. For the first-stage plan, we have the following short-term goals: - -- Release a basic distributed implementation of DS2 on PaddlePaddle. -- Contribute a chapter of Deep Speech to PaddlePaddle Book. - -Intensive system optimization and low-latency inference library (details in \[[1](#references)\]) are not yet covered in this first-stage plan. - -## Table of Contents - -- [Tasks](#tasks) -- [Task Dependency](#task-dependency) -- [Design Details](#design-details) - - [Overview](#overview) - - [Row Convolution](#row-convolution) - - [Beam Search With CTC and LM](#beam-search-with-ctc-and-lm) -- [Future Work](#future-work) -- [References](#references) - -## Tasks - -We roughly break down the project into 14 tasks: - -1. Develop an **audio data provider**: - - Json filelist generator. - - Audio file format transformer. - - Spectrogram feature extraction, power normalization etc. - - Batch data reader with SortaGrad. - - Data augmentation (optional). - - Prepare (one or more) public English data sets & baseline. -2. Create a **simplified DS2 model configuration**: - - With only fixed-length (by padding) audio sequences (otherwise need *Task 3*). - - With only bidirectional-GRU (otherwise need *Task 4*). - - With only greedy decoder (otherwise need *Task 5, 6*). -3. Develop to support **variable-shaped** dense-vector (image) batches of input data. - - Update `DenseScanner` in `dataprovider_converter.py`, etc. -4. Develop a new **lookahead-row-convolution layer** (See \[[1](#references)\] for details): - - Lookahead convolution windows. - - Within-row convolution, without kernels shared across rows. -5. Build KenLM **language model** (5-gram) for beam search decoder: - - Use KenLM toolkit. - - Prepare the corpus & train the model. - - Create infererence interfaces (for Task 6). -6. Develop a **beam search decoder** with CTC + LM + WORDCOUNT: - - Beam search with CTC. - - Beam search with external custom scorer (e.g. LM). - - Try to design a more general beam search interface. -7. Develop a **Word Error Rate evaluator**: - - update `ctc_error_evaluator`(CER) to support WER. -8. Prepare internal dataset for Mandarin (optional): - - Dataset, baseline, evaluation details. - - Particular data preprocessing for Mandarin. - - Might need cooperating with the Speech Department. -9. Create **standard DS2 model configuration**: - - With variable-length audio sequences (need *Task 3*). - - With unidirectional-GRU + row-convolution (need *Task 4*). - - With CTC-LM beam search decoder (need *Task 5, 6*). -10. Make it run perfectly on **clusters**. -11. Experiments and **benchmarking** (for accuracy, not efficiency): - - With public English dataset. - - With internal (Baidu) Mandarin dataset (optional). -12. Time **profiling** and optimization. -13. Prepare **docs**. -14. Prepare PaddlePaddle **Book** chapter with a simplified version. - -## Task Dependency - -Tasks parallelizable within phases: - -Roadmap | Description | Parallelizable Tasks ------------ | :------------------------------------ | :-------------------- -Phase I | Simplified model & components | *Task 1* ~ *Task 8* -Phase II | Standard model & benchmarking & profiling | *Task 9* ~ *Task 12* -Phase III | Documentations | *Task13* ~ *Task14* - -Issue for each task will be created later. Contributions, discussions and comments are all highly appreciated and welcomed! - -## Design Details - -### Overview - -Traditional **ASR** (Automatic Speech Recognition) pipelines require great human efforts devoted to elaborately tuning multiple hand-engineered components (e.g. audio feature design, accoustic model, pronuncation model and language model etc.). **Deep Speech 2** (**DS2**) \[[1](#references)\], however, trains such ASR models in an end-to-end manner, replacing most intermediate modules with only a single deep network architecture. With scaling up both the data and model sizes, DS2 achieves a very significant performance boost. - -Please read Deep Speech 2 \[[1](#references),[2](#references)\] paper for more background knowledge. - -The classical DS2 network contains 15 layers (from bottom to top): - -- **Two** data layers (audio spectrogram, transcription text) -- **Three** 2D convolution layers -- **Seven** uni-directional simple-RNN layers -- **One** lookahead row convolution layers -- **One** fully-connected layers -- **One** CTC-loss layer - -
                                -
                                -Figure 1. Archetecture of Deep Speech 2 Network. -
                                - -We don't have to persist on this 2-3-7-1-1-1 depth \[[2](#references)\]. Similar networks with different depths might also work well. As in \[[1](#references)\], authors use a different depth (e.g. 2-2-3-1-1-1) for final experiments. - -Key ingredients about the layers: - -- **Data Layers**: - - Frame sequences data of audio **spectrogram** (with FFT). - - Token sequences data of **transcription** text (labels). - - These two type of sequences do not have the same lengthes, thus a CTC-loss layer is required. -- **2D Convolution Layers**: - - Not only temporal convolution, but also **frequency convolution**. Like a 2D image convolution, but with a variable dimension (i.e. temporal dimension). - - With striding for only the first convlution layer. - - No pooling for all convolution layers. -- **Uni-directional RNNs** - - Uni-directional + row convolution: for low-latency inference. - - Bi-direcitional + without row convolution: if we don't care about the inference latency. -- **Row convolution**: - - For looking only a few steps ahead into the feature, instead of looking into a whole sequence in bi-directional RNNs. - - Not nessesary if with bi-direcitional RNNs. - - "**Row**" means convolutions are done within each frequency dimension (row), and no convolution kernels shared across. -- **Batch Normalization Layers**: - - Added to all above layers (except for data and loss layer). - - Sequence-wise normalization for RNNs: BatchNorm only performed on input-state projection and not state-state projection, for efficiency consideration. - - -Required Components | PaddlePaddle Support | Need to Develop -:------------------------------------- | :-------------------------------------- | :----------------------- -Data Layer I (Spectrogram) | Not supported yet. | TBD (Task 3) -Data Layer II (Transcription) | `paddle.data_type.integer_value_sequence` | - -2D Convolution Layer | `paddle.layer.image_conv_layer` | - -DataType Converter (vec2seq) | `paddle.layer.block_expand` | - -Bi-/Uni-directional RNNs | `paddle.layer.recurrent_group` | - -Row Convolution Layer | Not supported yet. | TBD (Task 4) -CTC-loss Layer | `paddle.layer.warp_ctc` | - -Batch Normalization Layer | `paddle.layer.batch_norm` | - -CTC-Beam search | Not supported yet. | TBD (Task 6) - -### Row Convolution - -TODO by Assignees - -### Beam Search with CTC and LM - -
                                -
                                -Figure 2. Algorithm for CTC Beam Search Decoder. -
                                - -- The **Beam Search Decoder** for DS2 CTC-trained network follows the similar approach in \[[3](#references)\] as shown in Figure 2, with two important modifications for the ambiguous parts: - - 1) in the iterative computation of probabilities, the assignment operation is changed to accumulation for one prefix may comes from different paths; - - 2) the if condition ```if l^+ not in A_prev then``` after probabilities' computation is deprecated for it is hard to understand and seems unnecessary. -- An **external scorer** would be passed into the decoder to evaluate a candidate prefix during decoding whenever a white space appended in English decoding and any character appended in Mandarin decoding. -- Such external scorer consists of language model, word count or any other custom scorers. -- The **language model** is built from Task 5, with parameters should be carefully tuned to achieve minimum WER/CER (c.f. Task 7) -- This decoder needs to perform with **high efficiency** for the convenience of parameters tuning and speech recognition in reality. - - -## Future Work - -- Efficiency Improvement -- Accuracy Improvement -- Low-latency Inference Library -- Large-scale benchmarking - -## References - -1. Dario Amodei, etc., [Deep Speech 2 : End-to-End Speech Recognition in English and Mandarin](http://proceedings.mlr.press/v48/amodei16.pdf). ICML 2016. -2. Dario Amodei, etc., [Deep Speech 2 : End-to-End Speech Recognition in English and Mandarin](https://arxiv.org/abs/1512.02595). arXiv:1512.02595. -3. Awni Y. Hannun, etc. [First-Pass Large Vocabulary Continuous Speech Recognition using Bi-Directional Recurrent DNNs](https://arxiv.org/abs/1408.2873). arXiv:1408.2873 diff --git a/develop/doc_cn/_sources/design/support_new_device.md.txt b/develop/doc_cn/_sources/design/support_new_device.md.txt deleted file mode 100644 index 8983df90046..00000000000 --- a/develop/doc_cn/_sources/design/support_new_device.md.txt +++ /dev/null @@ -1,240 +0,0 @@ -# Design Doc: Supporting new Device/Library - -## Background - -Deep learning has a high demand for computing resources. New high-performance devices and computing libraries are appearing very frequently. Deep learning frameworks have to integrate these high-performance devices and computing libraries in a flexible and efficient manner. - -On one hand, hardware and computing libraries usually do not have a one-to-one correspondence. For example, Intel CPUs support Eigen and MKL computing libraries while Nvidia GPUs support Eigen and cuDNN computing libraries. We have to implement operator specific kernels for each computing library. - -On the other hand, users usually do not want to care about the low-level hardware and computing libraries when writing a neural network configuration. In Fluid, `Layer` is exposed in `Python`, and `Operator` is exposed in `C++`. Both `Layer` and `Operator` are hardware independent. - -So, how to support a new Device/Library in Fluid becomes a challenge. - - -## Basic: Integrate A New Device/Library - -For a general overview of fluid, please refer to the [overview doc](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/read_source.md). - -There are mainly three parts that we have to consider while integrating a new device/library: - -- Place and DeviceContext: indicate the device id and manage hardware resources - -- Memory and Tensor: malloc/free data on certain device - -- Math Functor and OpKernel: implement computing unit on certain devices/libraries - -### Place and DeviceContext - -Please note that device and computing library are not one-to-one corresponding. A device can have a lot of computing libraries and a computing library can also support several devices. - -#### Place -Fluid uses class [Place](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/place.h#L55) to represent the device memory where data is located. If we add another device, we have to add the corresponding `DevicePlace`. - -``` - | CPUPlace -Place --| CUDAPlace - | FPGAPlace -``` - -And `Place` is defined as follows: - -``` -typedef boost::variant Place; -``` - -#### DeviceContext - -Fluid uses class [DeviceContext](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/device_context.h#L30) to manage the resources in different libraries, such as CUDA stream in `CDUADeviceContext`. There are also inheritance relationships between different kinds of `DeviceContext`. - - -``` - /-> CPUDeviceContext -DeviceContext ----> CUDADeviceContext - \-> FPGADeviceContext -``` - -An example of Nvidia GPU is as follows: - -- DeviceContext - - -``` -class DeviceContext { - virtual Place GetPlace() const = 0; -}; -``` - - -- CUDADeviceContext - - -``` -class CUDADeviceContext : public DeviceContext { - Place GetPlace() const override { return place_; } -private: - CUDAPlace place_; - cudaStream_t stream_; - cublasHandle_t cublas_handle_; - std::unique_ptr eigen_device_; // binds with stream_ -}; -``` - -### Memory and Tensor - - -#### memory module - -Fluid provides the following [memory interfaces](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/memory/memory.h#L36): - -``` -template -void* Alloc(Place place, size_t size); - -template -void Free(Place place, void* ptr); - -template -size_t Used(Place place); -``` - -To implement these interfaces, we have to implement MemoryAllocator for different Devices. - - -#### Tensor - -[Tensor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/tensor.h#L36) holds data with some shape in a specific Place. - -```cpp -class Tensor { - public: - /*! Return a pointer to mutable memory block. */ - template - inline T* data(); - - /** - * @brief Return a pointer to mutable memory block. - * @note If not exist, then allocation. - */ - template - inline T* mutable_data(platform::Place place); - - /** - * @brief Return a pointer to mutable memory block. - * - * @param[in] dims The dimensions of the memory block. - * @param[in] place The place of the memory block. - * - * @note If not exist, then allocation. - */ - template - inline T* mutable_data(DDim dims, platform::Place place); - - /*! Resize the dimensions of the memory block. */ - inline Tensor& Resize(const DDim& dims); - - /*! Return the dimensions of the memory block. */ - inline const DDim& dims() const; - - private: - /*! holds the memory block if allocated. */ - std::shared_ptr holder_; - - /*! points to dimensions of memory block. */ - DDim dim_; -}; -``` - -`Placeholder` is used to delay memory allocation; that is, we can first define a tensor, using `Resize` to configurate its shape, and then call `mutuable_data` to allocate the actual memory. - -```cpp -paddle::framework::Tensor t; -paddle::platform::CPUPlace place; -// set size first -t.Resize({2, 3}); -// allocate memory on CPU later -t.mutable_data(place); -``` - - - -### Math Functor and OpKernel - -Fluid implements computing units based on different DeviceContexts. Some computing units are shared between operators. This common part will be put in operators/math directory as basic Functors. - -Let's take [MaxOutFunctor](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/math/maxouting.h#L27) as an example: - -The interface is defined in the header file. - -``` -template -class MaxOutFunctor { - public: - void operator()(const DeviceContext& context, const framework::Tensor& input, - framework::Tensor* output, int groups); -}; -``` - -CPU implementation is in .cc file - -``` -template -class MaxOutFunctor { - public: - void operator()(const platform::CPUDeviceContext& context, - const framework::Tensor& input, framework::Tensor* output, - int groups) { - ... - } -}; -``` - -CUDA implementation is in .cu file - -``` -template -class MaxOutFunctor { - public: - void operator()(const platform::CUDADeviceContext& context, - const framework::Tensor& input, framework::Tensor* output, - int groups) { - ... - } -}; -``` - - -We first obtain the computing handle from a concrete DeviceContext and then compute on tensors. - -The implementation of `OpKernel` is similar to math functors, the extra thing we need to do is to register the OpKernel in a global map. - -Fluid provides different register interfaces in op_registry.h - - -Let's take [Crop](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/crop_op.cc#L134) operator as an example: - -In .cc file: - -``` -REGISTER_OP_CPU_KERNEL(crop, ops::CropKernel); -REGISTER_OP_CPU_KERNEL( - crop_grad, ops::CropGradKernel); -``` - -In .cu file: - -``` -REGISTER_OP_CUDA_KERNEL(crop, ops::CropKernel); -REGISTER_OP_CUDA_KERNEL( - crop_grad, ops::CropGradKernel); -``` - - -## Advanced topics: How to switch between different Device/Library - -Generally, we will implement OpKernel for all Device/Library of an Operator. We can easily train a Convolutional Neural Network in GPU. However, some OpKernel is not suitable on a specific Device. For example, crf operator can only run on CPU, whereas most other operators can run on GPU. To achieve high performance in such circumstance, we have to switch between different Device/Library. - - -For more details, please refer to following docs: - -- operator kernel type [doc](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/operator_kernel_type.md) -- switch kernel [doc](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/switch_kernel.md) diff --git a/develop/doc_cn/_sources/design/switch.md.txt b/develop/doc_cn/_sources/design/switch.md.txt deleted file mode 100644 index 827d0601c62..00000000000 --- a/develop/doc_cn/_sources/design/switch.md.txt +++ /dev/null @@ -1,31 +0,0 @@ -### Design Doc: Switch - -### Background - -Many programming languages provide `switch` as a generalization of `if-elif-else`. We want to add it to Fluid. - -The following example shows the usage of `fluid.switch`. - -```python -a = fluid.Var(10) -b = fluid.Var(0) - -with switch() as switch: - with switch.case(fluid.less_equal(a, 10)): - fluid.print("Case 1") - with switch.case(fluid.larger(a, 0)): - fluid.print("Case 2") - with switch.default(): - fluid.print("Case 3") -``` - -### The Semantics - -1. A `switch` control-flow checks cases one-by-one. -1. The condition of each case is a boolean value, which is a scalar, and differs from the `fluid.if_else` control-flow, which condition could be a vector of boolean values. -1. It runs the first matched case, or the default case if there is one. -1. Once it matches a case, it runs the corresponding branch and only that branch. It's like there is a C's `break` keyword at the end of each case. - -The above program should print and print only "Case 1". - -The implementation of the backward pass of the `switch` control-flow is easier than the backward of the `if_else`, because `switch` runs at most one branch, whereas `if-else` could run more than one branches. diff --git a/develop/doc_cn/_sources/design/tensor_array.md.txt b/develop/doc_cn/_sources/design/tensor_array.md.txt deleted file mode 100644 index 37e4f7b90f9..00000000000 --- a/develop/doc_cn/_sources/design/tensor_array.md.txt +++ /dev/null @@ -1,271 +0,0 @@ -# Design for TensorArray -This design doc presents the necessity of a new C++ class `TensorArray`. -In addition to the very simple C++ implementation - -```c++ -class TensorArray { - public: - explicit TensorArray(const LoDTensor&); - explicit TensorArray(size_t size); - - private: - vector values_; -}; -``` - -We also need to expose it to PaddlePaddle's Python API, -because users would want to use it with our very flexible operators `WhileLoop`. -An example for a RNN based on dynamic operators is - -```python -input = pd.data(...) -num_steps = Var(12) - -TensorArray states(size=num_steps) -TensorArray step_inputs(unstack_from=input) -TensorArray step_outputs(size=num_steps) - -W = Tensor(...) -U = Tensor(...) -default_state = some_op() - -step = Var(1) - -wloop = paddle.create_whileloop(loop_vars=[step]) -with wloop.frame(): - wloop.break_if(pd.equal(step, num_steps) - pre_state = states.read(step-1, default_state) - step_input = step_inputs.read(step) - state = pd.sigmoid(pd.matmul(U, pre_state) + pd.matmul(W, step_input)) - states.write(step, state) - step_outputs.write(step, state) # output state - step.update(state+1) - -output = step_outputs.stack() -``` - -## Background -Steps are one of the core concepts of RNN. In each time step of RNN, there should be several input segments, states, and output segments; all these components act like arrays, for example, call `states[step_id]` will get the state in `step_id`th time step. - -An RNN can be implemented with the following pseudocode - -```c++ -Array states; -Array input_segments; -Array output_segments; -Parameter W, U; - -step = 1 -seq_len = 12 -while_loop { - if (step == seq_len) break; - states[step] = sigmoid(W * states[step-1] + U * input_segments[step]); - output_segments[step] = states[step] // take state as output - step++; -} -``` -According to the [RNN roadmap](https://github.com/PaddlePaddle/Paddle/issues/4561), there are several different RNNs that PaddlePaddle will eventually support. - -Currently, the basic RNN implementation supported by PaddlePaddle is the `recurrent_op` which takes tensors as input and splits them into `input_segments`. - - -Since a tensor cannot store variable-length sequences directly, PaddlePaddle implements the tensor with level of details (`LoDTensor` for short). -Segmenting the `LoDTensor` is much more complicated than splitting a tensor, that makes it necessary to refactor the `recurrent_op` with `LoDTensor` segmenting support. - -As the next step in RNN support, `dynamic_recurrent_op` should be introduced to handle inputs with variable-length sequences. - -The implementation is similar to `recurrent_op`. -The key difference is the way **the original input `LoDTensors` and outupts are split to get the `input_segments` and the `output_segments`.** - - -Though it can't be built over `recurrent_op` or `dynamic_recurrent_op` directly, -the logic behind splitting a tensor or a LoD tensor into `input_segments` remains the same. - -## Why `TensorArray` -The logic behind splitting the inputs to segments, states and outputs is similar and can be shared in a seperate module. - -The array of `states`, `input_segments` and `output_segments` would be exposed to users when writing a dynamic RNN model similar to the above pseudo codes. - -So there should be an array-like container, which can store the segments of a tensor or LoD tensor. - -**This container can store an array of tensors and provides several methods to split a tensor or a LoD tensor** . -This is where the notion of `TensorArray` comes from. - -## Introduce TensorArray to uniform all the three RNNs -TensorArray as a new concept is borrowed from TensorFlow, -it is meant to be used with dynamic iteration primitives such as `while_loop` and `map_fn`. - -This concept can be used to support our new design of dynamic operations, and help to refactor some existing variant-sentence-related layers, -such as `recurrent_op`, `RecurrentGradientMachine`. - -In [our design for dynamic RNN](https://github.com/PaddlePaddle/Paddle/pull/4401), -`TensorArray` is used to segment inputs and store states in all time steps. -By providing some methods similar to a C++ array, -the definition of some state-based dynamic models such as RNN can be more natural and highly flexible. - -## Dynamic-operations on TensorArray - -`TensorArray` will be used directly when defining dynamic models, so some operators listed below should be implemented - -```python -# several helper operators for TensorArray -def tensor_array_stack(ta, tensor): - ''' - get a tensor array `ta`, return a packed `tensor`. - ''' - pass - -def tensor_array_unstack(tensor, ta): - ''' - get a `tensor`, unstack it and get a tensor array `ta`. - ''' - pass - -def tensor_array_write(ta, index, tensor, data_shared): - ''' - get a `tensor` and a scalar tensor `index`, write `tensor` into index-th - value of the tensor array `ta`. - `data_shared` is an attribute that specifies whether to copy or reference the tensors. - ''' - pass - -def tensor_array_read(ta, index, tensor): - ''' - get a tensor array `ta`, a scalar tensor `index`, read the index-th value of - `ta` and return as the `tensor`. - ''' - pass - -def tensor_array_size(ta, tensor): - ''' - get a tensor array `ta`, return the size of `ta` and return as the scalar `tensor`. - ''' - pass -``` - -It is trivial for users to use so many low-level operators, so some helper methods should be proposed in python wrapper to make `TensorArray` easier to use, -for example - -```python -class TensorArray: - def __init__(self, name): - self.name = name - self.desc = TensorArrayDesc() - - def stack(self, name=None): - ''' - Pack the values in a `TensorArray` into a tensor with rank one higher - than each tensor in `values`. - `stack` can be used to split tensor into time steps for RNN or whileloop. - - @name: str - the name of the variable to output. - ''' - tensor = Var(name) - tensor_array_stack(self.name, tensor) - return tensor - - def unstack(self, input): - ''' - Unpacks the given dimension of a rank-`R` tensor into rank-`(R-1)` tensors. - `unstack` can be used to concatenate all the time steps for RNN or whileloop. - - @input: str - the name of input tensor - ''' - tensor_array_unstack(tensor, self.name) - - def write(self, index, value, data_shared=True): - ''' - Write value into index of the TensorArray. - If `data_shared` is set to True, than the index-th value in TensorArray will - be shared with the tensor passed in. - - @index: str - name of a scalar tensor - @value: str - name of a tensor - @data_shared: bool - ''' - tensor_array_write(self.name, index, value, data_shared) - - def read(self, index, output): - ''' - Read the value at location `index` in the `TensorArray`. - - @index: str - name of a scalar tensor - @output: - name of a output variable - ''' - tensor_array_read(self.name, index, output) - - - def size(self, output): - ''' - Return the number of values. - - @output: str - name of a scalar tensor - ''' - tensor_array_size(self.name, output) -``` - -## LoDTensor-related Supports -The `RecurrentGradientMachine` in Paddle serves as a flexible RNN layer; it takes varience-length sequences as input, and output sequences too. - -Since each step of RNN can only take a tensor-represented batch of data as input, -some preprocess should be taken on the inputs such as sorting the sentences by their length in descending order and cut each word and pack to new batches. - -Such cut-like operations can be embedded into `TensorArray` as general methods called `unpack` and `pack`, -these two operations are similar to `stack` and `unstack` except that they operate on variable-length sequences formated as a LoD tensor rather than a tensor. - -Some definitions are like - -```python -def unpack(level): - ''' - Split LodTensor in some `level` and generate batches, if set `sort_by_length`, - will sort by length. - - Returns: - - a new `TensorArray`, whose values are LodTensors and represents batches - of data. - - an int32 Tensor, which stores the map from the new batch's indices to - original LoDTensor - ''' - pass - -def pack(level, indices_map): - ''' - Recover the original LoD-arranged LoDTensor with the values in a `TensorArray` - and `level` and `indices_map`. - ''' - pass -``` - -With these two methods, a varience-length sentence supported RNN can be implemented like - -```c++ -// input is the varient-length data -LodTensor sentence_input(xxx); -TensorArray ta; -Tensor indice_map; -Tensor boot_state = xxx; // to initialize rnn's first state -TensorArray::unpack(input, 1/*level*/, true/*sort_by_length*/, &ta, &indice_map); -TessorArray step_outputs; -TensorArray states; - -for (int step = 0; step = ta.size(); step++) { - auto state = states.read(step); - // rnnstep is a function which acts like a step of RNN - auto step_input = ta.read(step); - auto step_output = rnnstep(step_input, state); - step_outputs.write(step_output, true/*data_shared*/); -} - -// rnn_output is the final output of an rnn -LoDTensor rnn_output = ta.pack(ta, indice_map); -``` -the code above shows that by embedding the LoDTensor-related preprocess operations into `TensorArray`, -the implementation of a RNN that supports varient-length sentences is far more concise than `RecurrentGradientMachine` because the latter mixes all the codes together, hard to read and extend. diff --git a/develop/doc_cn/_sources/design/var_desc.md.txt b/develop/doc_cn/_sources/design/var_desc.md.txt deleted file mode 100644 index 6a45af19954..00000000000 --- a/develop/doc_cn/_sources/design/var_desc.md.txt +++ /dev/null @@ -1,81 +0,0 @@ -## Background -PaddlePaddle divides the description of neural network computation into two stages: compile time and runtime. At compile time, the neural network computation is described as a `ProgramDesc` whereas at runtime an `Executor` interprets the `ProgramDesc` to compute the operations. - -PaddlePaddle uses proto message to describe compile time program because : - -1. The computation program description must be serializable and saved in a file. -1. During distributed training, the serialized program will be sent to multiple workers. It should also be possible to break the program into different components, each of which can be executed on a different worker. - -The computation `Program` consists of nested `Blocks`. Each `Block` will consist of data(i.e. `Variable`) and `Operations`. The concept to represent them is in the table below. - -| |compile time|runtime| -|---|---|---| -|Data|VarDesc(proto)|Variable(cpp)| -|Operation|OpDesc(proto)|Operator(cpp)| - - -## Definition of VarType - -A VarDesc should have a name, type and whether or not it is persistable. The are different kinds of variable types supported in PaddlePaddle, apart from the POD_Types like: `LOD_TENSOR`, `SELECTED_ROWS`, `FEED_MINIBATCH`, `FETCH_LIST`, `STEP_SCOPES`, `LOD_RANK_TABLE`, `LOD_TENSOR_ARRAY`, `PLACE_LIST`, `READER` and `CHANNEL`. These are declared inside `VarType`. A `VarDesc` then looks as the following: - -```proto -message VarDesc { - required string name = 1; - required VarType type = 2; - optional bool persistable = 3 [ default = false ]; -} -``` - -## Definition of TensorDesc - -```proto -message TensorDesc { - // Should only be PODType. Is enforced in C++ - required Type data_type = 1; - repeated int64 dims = 2; // [UNK, 640, 480] is saved as [-1, 640, 480] -} -``` - -The `Type` here comes from the enum defined inside of `VarType` : - -```proto -enum Type { - // Pod Types - BOOL = 0; - INT16 = 1; - INT32 = 2; - INT64 = 3; - FP16 = 4; - FP32 = 5; - FP64 = 6; - - // Other types that may need additional descriptions - LOD_TENSOR = 7; - SELECTED_ROWS = 8; - FEED_MINIBATCH = 9; - FETCH_LIST = 10; - STEP_SCOPES = 11; - LOD_RANK_TABLE = 12; - LOD_TENSOR_ARRAY = 13; - PLACE_LIST = 14; - READER = 15; - CHANNEL = 16; -} -``` - -A TensorDesc describes `SelectedRows` and `LoDTensor`. For details of `SelectedRows`, please reference [`SelectedRows`](./selected_rows.md). - -## Definition of LodTensorDesc - -```proto -message LoDTensorDesc { - required TensorDesc tensor = 1; - optional int32 lod_level = 2 [ default = 0 ]; -} -``` - -A LoDTensorDesc contains a tensor and a lod_level. - -## Definition of Variable in Python - -For Variable in Python, please reference [`Python API`](./python_api.md). diff --git a/develop/doc_cn/_sources/dev/index_cn.rst.txt b/develop/doc_cn/_sources/dev/index_cn.rst.txt index 487db868bb2..c488191b817 100644 --- a/develop/doc_cn/_sources/dev/index_cn.rst.txt +++ b/develop/doc_cn/_sources/dev/index_cn.rst.txt @@ -6,3 +6,4 @@ contribute_to_paddle_cn.md write_docs_cn.rst + new_layer_cn.rst diff --git a/develop/doc_cn/_sources/dev/new_layer_cn.rst.txt b/develop/doc_cn/_sources/dev/new_layer_cn.rst.txt index 75037e693b3..0ded1c262ad 100644 --- a/develop/doc_cn/_sources/dev/new_layer_cn.rst.txt +++ b/develop/doc_cn/_sources/dev/new_layer_cn.rst.txt @@ -1,6 +1,6 @@ -================ -实现新的网络层 -================ +================== +如何实现新的网络层 +================== 这份教程展示了如何在PaddlePaddle中实现一个自定义的网络层。在这里我们使用全连接层作为例子来展示实现新网络层所需要的四个步骤。 diff --git a/develop/doc_cn/_sources/dev/new_op_cn.md.txt b/develop/doc_cn/_sources/dev/new_op_cn.md.txt deleted file mode 100644 index 92996585674..00000000000 --- a/develop/doc_cn/_sources/dev/new_op_cn.md.txt +++ /dev/null @@ -1,318 +0,0 @@ -# 如何写新的Operator - - - [概念简介](#概念简介) - - [实现C++类](#实现c类) - - [定义ProtoMaker类](#定义protomaker类) - - [定义Operator类](#定义operator类) - - [定义OpKernel类](#定义opkernel类) - - [注册Operator](#注册operator) - - [编译](#编译) - - [绑定Python](#绑定python) - - [实现单元测试](#实现单元测试) - - [前向Operator单测](#前向operator单测) - - [反向Operator单测](#反向operator单测) - - [编译和执行](#编译和执行) - - [注意事项](#注意事项) - - -## 概念简介 - -简单介绍需要用到基类,详细介绍请参考设计文档。 - -- `framework::OperatorBase`: Operator(简写,Op)基类。 -- `framework::OpKernel`: Op计算函数的基类,称作Kernel。 -- `framework::OperatorWithKernel`:继承自OperatorBase,Op有计算函数,称作有Kernel。 -- `class OpProtoAndCheckerMaker`:描述该Op的输入、输出、属性、注释,主要用于Python API接口生成 - -依据是否包含kernel,可以将Op分为两种:包含Kernel的Op和不包含kernel的Op,前者Op的定义继承自`OperatorWithKernel`,后者继承自`OperatorBase`。本教程主要介绍带Kernel的Op如何写,简单总结Op需要包含的内容如下: - - - 内容 | 定义位置 --------------- | :---------------------- -OpProtoMake定义 | `.cc`文件,Backward Op不需要定义OpProtoMake -Op定义 | `.cc`文件 -Kernel实现 | CPU、CUDA共享Kernel实现在`.h`文件中,否则,CPU 实现在`.cc`文件中,CUDA 实现在`.cu`文件中。 -注册Op | Op注册实现在`.cc`文件;Kernel注册CPU实现在`.cc`文件中,CUDA实现在`.cu`文件中 - - -实现新的op都添加至目录[paddle/operators](https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/operators)下,文件命名以`*_op.h`(如有) 、 `*_op.cc` 、`*_op.cu`(如有)结尾。**系统会根据文件名自动构建op和其对应的Python扩展。** - - -下面以矩阵乘操作,即[MulOp](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/mul_op.cc)为例来介绍如何写带Kernel的Operator。 - - -## 实现C++类 - - -### 定义ProtoMaker类 - -矩阵乘法的公式:$Out = X * Y$, 可见该计算由两个输入,一个输出组成。 - -首先定义`ProtoMaker`来描述该Op的输入、输出,并添加注释: - -```cpp -class MulOpMaker : public framework::OpProtoAndCheckerMaker { - public: - MulOpMaker(OpProto *proto, OpAttrChecker *op_checker) - : OpProtoAndCheckerMaker(proto, op_checker) { - AddInput("X", "(Tensor), 2D tensor of size (M x K)"); - AddInput("Y", "(Tensor), 2D tensor of size (K x N)"); - AddOutput("Out", "(Tensor), 2D tensor of size (M x N)"); - AddComment(R"DOC( -Two Element Mul Operator. -The equation is: Out = X * Y -)DOC"); - } -}; -``` - -[`MulOpMaker`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/mul_op.cc#L43)继承自`framework::OpProtoAndCheckerMaker`,构造函数含有2个参数: - - - `framework::OpProto` : 前者存储Op的输入输出和参数属性,将用于Python API接口的生成。 - - `framework::OpAttrChecker` :后者用于检查参数属性的合法性。 - -构造函数里通过`AddInput`添加输入参数,通过`AddOutput`添加输出参数,通过`AddComment`添加Op的注释。这些函数会将对应内容添加到`OpProto`中。 - -上面的代码在`MulOp`中添加两个输入`X`和`Y`,添加了一个输出`Out`,并解释了各自含义,命名请遵守[命名规范](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/name_convention.md)。 - - -再以[`ScaleOp`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/scale_op.cc#L37)为例: - -```cpp -template -class ScaleOpMaker : public framework::OpProtoAndCheckerMaker { - public: - ScaleOpMaker(OpProto *proto, OpAttrChecker *op_checker) - : OpProtoAndCheckerMaker(proto, op_checker) { - AddInput("X", "The input tensor of scale operator.").NotInGradient(); - AddOutput("Out", "The output tensor of scale operator.").NotInGradient(); - AddComment(R"DOC(Scale operator -The equation is: Out = scale*X -)DOC"); - AddAttr("scale", "scale of scale operator.").SetDefault(1.0); - } -}; -``` - -这个例子有两处不同: - -- `AddInput("X","...").NotInGradient()` : 表示`X`这个输入不参与`ScaleOp`对应的梯度Op计算之中,如果Op的某个输入不参与反向梯度的计算,请显示地调用`.NotInGradient()`进行设置。 - -- `AddAttr("scale", "...").SetDefault(1.0);` : 增加`scale`系数,作为参数属性,并且设置默认值为1.0。 - - -### 定义Operator类 - -下面的点实现了MulOp的定义: - -```cpp -class MulOp : public framework::OperatorWithKernel { - public: - using framework::OperatorWithKernel::OperatorWithKernel; - - protected: - void InferShape(const framework::InferShapeContext &ctx) const override { - auto dim0 = ctx.Input("X")->dims(); - auto dim1 = ctx.Input("Y")->dims(); - PADDLE_ENFORCE_EQ(dim0.size(), 2, - "input X(%s) should be a tensor with 2 dims, a matrix", - ctx.op_.Input("X")); - PADDLE_ENFORCE_EQ(dim1.size(), 2, - "input Y(%s) should be a tensor with 2 dims, a matrix", - ctx.op_.Input("Y")); - PADDLE_ENFORCE_EQ( - dim0[1], dim1[0], - "First matrix's width must be equal with second matrix's height."); - ctx.Output("Out")->Resize({dim0[0], dim1[1]}); - } -}; -``` - -[`MulOp`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/mul_op.cc#L22)继承自`OperatorWithKernel`。`public`成员: - -```cpp -using framework::OperatorWithKernel::OperatorWithKernel; -``` - -这句表示使用基类`OperatorWithKernel`的构造函数,也可写成: - -```cpp -MulOp(const std::string &type, const framework::VariableNameMap &inputs, - const framework::VariableNameMap &outputs, - const framework::AttributeMap &attrs) - : OperatorWithKernel(type, inputs, outputs, attrs) {} -``` - -还需要重写`InferShape`接口。`InferShape`为const函数,不能修改Op的成员变量,参数为`const framework::InferShapeContext &ctx`,通过该参数可获取到输入输出以及属性。它的功能是: - - - 1). 做检查, 尽早报错:检查输入数据维度、类型等是否合法。 - - 2). 设置输出Tensor的形状。 - -通常`OpProtoMaker`和`Op`类的定义写在`.cc`文件中,和下面将要介绍的注册函数一起放在`.cc`中 - -### 定义OpKernel类 - -`MulKernel`继承自`framework::OpKernel`,带有下面两个模板参数: - -- `typename DeviceContext`: 表示设备类型,不同设备(CPU、CUDA)共享同一个Kernel时,需加该模板参数,不共享则不加,一个不共享的例子是[`OnehotCrossEntropyOpKernel`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/cross_entropy_op.h#L43)。 - -- `typename T` : 表示数据类型,如`float`, `double`等。 - -需要为`MulKernel`类重写`Compute`接口。 -- `Compute`接受一个输入参数:`const framework::ExecutionContext& context`。 -- 与`InferShapeContext`相比,`ExecutionContext`增加了设备类型,同样可获取到输入输出和属性参数。 -- `Compute`函数里实现`OpKernel`的具体计算逻辑。 - -下面是 `MulKernel` `Compute`的实现: - - ```cpp - template - class MulKernel : public framework::OpKernel { - public: - void Compute(const framework::ExecutionContext& context) const override { - auto* X = context.Input("X"); - auto* Y = context.Input("Y"); - auto* Z = context.Output("Out"); - Z->mutable_data(context.GetPlace()); - auto& device_context = context.template device_context(); - math::matmul(*X, false, *Y, false, 1, Z, 0, device_context); - } - }; - ``` - -需要注意:**不同设备(CPU、CUDA)共享一个Op定义,是否则共享同一个`OpKernel`,取决于`Compute`调用的函数是否支持不同设备。** - -`MulOp`的CPU、CUDA实现共享同一个`Kernel`。`OpKernel`不共享的例子可以参考:[`OnehotCrossEntropyOpKernel`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/cross_entropy_op.h#L43)。 - -为了使`OpKernel`的计算过程书写更加简单,并且CPU、CUDA的代码可以复用,我们通常借助 Eigen unsupported Tensor模块来实现`Compute`接口。关于在PaddlePaddle中如何使用Eigen库,请参考[使用文档](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/dev/use_eigen_cn.md)。 - - -到此,前向Op实现完成。接下来,需要在`.cc`文件中注册该op和kernel。 -反向Op类的定义,反向OpKernel的定义与前向Op类似,这里不再赘述。**但需注意反向Op没有`ProtoMaker`**。 - -### 注册Operator - -- 在`.cc`文件中注册前向、反向Op类,注册CPU Kernel。 - - ```cpp - namespace ops = paddle::operators; - REGISTER_OP(mul, ops::MulOp, ops::MulOpMaker, mul_grad, ops::MulOpGrad); - REGISTER_OP_CPU_KERNEL(mul, ops::MulKernel); - REGISTER_OP_CPU_KERNEL(mul_grad, - ops::MulGradKernel); - ``` - - 在上面的代码中: - - - `REGISTER_OP` : 注册`ops::MulOp`类,类型名为`mul`,该类的`ProtoMaker`为`ops::MulOpMaker`,注册`ops::MulOpGrad`,类型名为`mul_grad`。 - - `REGISTER_OP_WITHOUT_GRADIENT` : 用于注册没有反向的Op。 - - `REGISTER_OP_CPU_KERNEL` :注册`ops::MulKernel`类,并特化模板参数为`paddle::platform::CPUPlace`和`float`类型,同理,注册`ops::MulGradKernel`类。 - - -- 在 `.cu`文件中注册CUDA Kernel。 - - 请注意,如果CUDA Kernel的实现基于Eigen unsupported模块,那么在 `.cu`的开始请加上宏定义 `#define EIGEN_USE_GPU`,代码示例如下: - - ```cpp - // if use Eigen unsupported module before include head files - #define EIGEN_USE_GPU - - namespace ops = paddle::operators; - REGISTER_OP_CUDA_KERNEL(mul, ops::MulKernel); - REGISTER_OP_CUDA_KERNEL(mul_grad, - ops::MulGradKernel); - ``` - -### 编译 - -运行下面命令可以进行编译: - -``` -make mul_op -``` - -## 绑定Python - -系统会对新增的op自动绑定Python,并链接到生成的lib库中。 - -## 实现单元测试 - -单测包括对比前向Op不同设备(CPU、CUDA)的实现、对比反向OP不同设备(CPU、CUDA)的实现、反向Op的梯度测试。下面介绍介绍[`MulOp`的单元测试](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/v2/framework/tests/test_mul_op.py)。 - -### 前向Operator单测 - -Op单元测试继承自`OpTest`。各项更加具体的单元测试在`TestMulOp`里完成。测试Operator,需要: - -1. 在`setUp`函数定义输入、输出,以及相关的属性参数。 -2. 生成随机的输入数据。 -3. 在Python脚本中实现与前向operator相同的计算逻辑,得到输出值,与operator前向计算的输出进行对比。 -4. 反向计算已经自动集成进测试框架,直接调用相应接口即可。 - - - ```python - import unittest - import numpy as np - from op_test import OpTest - - - class TestMulOp(OpTest): - def setUp(self): - self.op_type = "mul" - self.inputs = { - 'X': np.random.random((32, 84)).astype("float32"), - 'Y': np.random.random((84, 100)).astype("float32") - } - self.outputs = {'Out': np.dot(self.inputs['X'], self.inputs['Y'])} - - def test_check_output(self): - self.check_output() - - def test_check_grad_normal(self): - self.check_grad(['X', 'Y'], 'Out', max_relative_error=0.5) - - def test_check_grad_ingore_x(self): - self.check_grad( - ['Y'], 'Out', max_relative_error=0.5, no_grad_set=set("X")) - - def test_check_grad_ingore_y(self): - self.check_grad( - ['X'], 'Out', max_relative_error=0.5, no_grad_set=set('Y')) - ``` - -上面的代码首先导入依赖的包,下面是对`setUp`函数中操作的重要变量的详细解释: - -- `self.op_type = "mul" ` : 定义类型,与operator注册时注册的类型一致。 -- `self.inputs` : 定义输入,类型为`numpy.array`,并初始化。 -- `self.outputs` : 定义输出,并在Python脚本中完成与operator同样的计算逻辑,返回Python端的计算结果。 - -### 反向operator单测 - -而反向测试中: -- `test_check_grad_normal`中调用`check_grad`使用数值法检测梯度正确性和稳定性。 - - 第一个参数`["X", "Y"]` : 指定对输入变量`X`、`Y`做梯度检测。 - - 第二个参数`"Out"` : 指定前向网络最终的输出目标变量`Out`。 - - 第三个参数`max_relative_error`:指定检测梯度时能容忍的最大错误值。 -- `test_check_grad_ingore_x`和`test_check_grad_ingore_y`分支用来测试只需要计算一个输入梯度的情况。 - - -### 编译和执行 - -`python/paddle/v2/framework/tests` 目录下新增的 `test_*.py` 单元测试会被自动加入工程进行编译。 - -请注意,**不同于Op的编译测试,运行单元测试测时需要编译整个工程**,并且编译时需要打开`WITH_TESTING`, 即`cmake paddle_dir -DWITH_TESTING=ON`。编译成功后,执行下面的命令来运行单元测试: - -```bash -make test ARGS="-R test_mul_op -V" -``` - -或者: - -```bash -ctest -R test_mul_op -``` - -## 注意事项 - -- 为每个Op创建单独的`*_op.h`(如有)、`*_op.cc`和`*_op.cu`(如有)。不允许一个文件中包含多个Op,这将会导致编译出错。 -- 注册Op时的类型名,需要和该Op的名字一样。即不允许在`A_op.cc`里面,注册`REGISTER_OP(B, ...)`等,这将会导致单元测试出错。 -- 如果Op没有实现CUDA Kernel,请不要创建空的`*_op.cu`,这将会导致单元测试出错。 -- 如果多个Op依赖一些共用的函数,可以创建非`*_op.*`格式的文件来存放,如`gather.h`文件。 diff --git a/develop/doc_cn/_sources/dev/use_eigen_cn.md.txt b/develop/doc_cn/_sources/dev/use_eigen_cn.md.txt deleted file mode 100644 index 1367323b712..00000000000 --- a/develop/doc_cn/_sources/dev/use_eigen_cn.md.txt +++ /dev/null @@ -1,146 +0,0 @@ -## 在Paddle中如何使用Eigen - -神经网络本质上是一个计算图,计算需要的数据存放在`Tensor`中,而计算过程是由`Operartor`来描述的。在执行时,`Operator`调用对应`OpKernel`中的`Compute`接口,实现对`Tensor`的操作。 - - -### Eigen Tensor模块 - -Eigen Tensor模块对element-wise计算提供了强大的支持,并且书写一份代码,可以同时在CPU、GPU执行。但Eigen Tensor是一个正在开发中的模块,因此可能测试不够完备,文档较少。 - -关于Eigen Tensor模块的详细介绍请参考[文档1](https://github.com/RLovelett/eigen/blob/master/unsupported/Eigen/CXX11/src/Tensor/README.md) 和[文档2](https://bitbucket.org/eigen/eigen/src/default/unsupported/Eigen/CXX11/src/Tensor/README.md) - - -### paddle::framework::Tensor - -Paddle Tensor定义在framework目录下,其主要接口如下: - -```cpp -class Tensor { - public: - /*! Return a pointer to mutable memory block. */ - template - inline T* data(); - - /** - * @brief Return a pointer to mutable memory block. - * @note If not exist, then allocation. - */ - template - inline T* mutable_data(platform::Place place); - - /** - * @brief Return a pointer to mutable memory block. - * - * @param[in] dims The dimensions of the memory block. - * @param[in] place The place of the memory block. - * - * @note If not exist, then allocation. - */ - template - inline T* mutable_data(DDim dims, platform::Place place); - - /*! Resize the dimensions of the memory block. */ - inline Tensor& Resize(const DDim& dims); - - /*! Return the dimensions of the memory block. */ - inline const DDim& dims() const; - - private: - /*! holds the memory block if allocated. */ - std::shared_ptr holder_; - - /*! points to dimensions of memory block. */ - DDim dim_; -}; -``` - -`Placeholder`的作用是延迟分配内存,即我们可以先定义一个Tensor,然后使用Resize接口设置Tensor的大小,最后再调用mutable_data接口分配实际的内存。 - -```cpp -paddle::framework::Tensor t; -paddle::platform::CPUPlace place; -// set size first -t.Resize({2, 3}); -// allocate memory on CPU later -t.mutable_data(place); -``` - -### paddle::framework::Tensor使用样例 -下面以AddOp为例说明Tensor的使用过程: - -- InferShape - -在运行神经网络计算图时,我们先调用每个`Operator`的`InferShape`接口,根据输入Tensor的大小来设置输出Tensor的大小,`Resize`接口会被调用。 - -```cpp -void InferShape(const framework::InferShapeContext &ctx) const override { - PADDLE_ENFORCE_EQ(ctx.Input("X")->dims(), - ctx.Input("Y")->dims(), - "Two input of Add Op's dimension must be same."); - ctx.Output("Out")->Resize(ctx.Input("X")->dims()); -} -``` - - -- Run - -`Operator`的`Run`接口最终会调用对应`OpKernel`的`Compute`接口,在这时真正的分配内存,`mutable_data`接口会被调用。 - -```cpp -void Compute(const framework::ExecutionContext& context) const override { - auto* input0 = context.Input("X"); - auto* input1 = context.Input("Y"); - auto* output = context.Output("Out"); - - output->mutable_data(context.GetPlace()); - - auto x = EigenVector::Flatten(*input0); - auto y = EigenVector::Flatten(*input1); - auto z = EigenVector::Flatten(*output); - - auto place = context.GetEigenDevice(); - - z.device(place) = x + y; -} -``` - - -### paddle::framework::Tensor到EigenTensor的转换 - -如上一小节所示,在具体的计算中,我们需要先把输入Tensor和输出Tensor转换为Eigen支持的格式。我们在[eigen.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/eigen.h)中提供了一些全局函数用来实现paddle::framework::Tensor到EigenTensor/EigenMatrix/EigenVector/EigenScalar的转换。 - -以EigenTensor为例,做一个介绍 - -```cpp -Tensor t; -float* p = t.mutable_data(make_ddim({1, 2, 3}), platform::CPUPlace()); -for (int i = 0; i < 1 * 2 * 3; i++) { - p[i] = static_cast(i); -} - -EigenTensor::Type et = EigenTensor::From(t); -``` - -From是EigenTensor模板提供的一个接口,可以实现从paddle::framework::Tensor到对EigenTensor的转换。由于Tensor的rank是模板参数,因此在转换时需要显示的指定。 - -在Eigen中,不同rank的Tensor是不同类型,Vector是rank为1的Tensor。需要额外注意的是,EigenVector::From方法是把paddle中的一维Tensor转为Eigen的一维Tensor,在这里用EigenVector来表示;而EigenVector::Flatten方法是把paddle中的一个Tensor进行reshape操作,压扁成为Eigen的一维Tensor,类型仍然为EigenVector。 - -更多的转换方法请参考eigen_test.cc中的[单元测试](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/eigen_test.cc)。 - - - -### 实现计算 - -当需要完成计算时,我们需要等式左边的EigenTensor调用device接口。在这里需要注意的是,这里的EigenTensor之间的运算只是改变了原有Tensor中的数据,而不会改变原有Tensor的shape信息。 - -```cpp -auto x = EigenVector::Flatten(*input0); -auto y = EigenVector::Flatten(*input1); -auto z = EigenVector::Flatten(*output); -auto place = context.GetEigenDevice(); -z.device(place) = x + y; -``` - -在这段代码中,input0/input1/output可以是任意维度的Tensor。我们调用了EigenVector的Flatten接口,把任意维度的Tensor转为了一维的EigenVector。而在计算结束之后,input0/input1/output的原有shape信息不变。如果想改变原有Tensor的shape信息,可以调用Resize接口进行改变。 - -由于Eigen Tensor模块的文档较少,我们可以参考TensorFlow的[kernels](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/core/kernels)模块下的相关`OpKernel`的计算代码。 diff --git a/develop/doc_cn/_sources/howto/optimization/cpu_profiling_cn.md.txt b/develop/doc_cn/_sources/howto/optimization/cpu_profiling_cn.md.txt deleted file mode 100644 index d59be670c2b..00000000000 --- a/develop/doc_cn/_sources/howto/optimization/cpu_profiling_cn.md.txt +++ /dev/null @@ -1,155 +0,0 @@ -此教程会介绍如何使用Python的cProfile包、Python库yep、Google perftools来进行性能分析 (profiling) 与调优(performance tuning)。 - -Profling 指发现性能瓶颈。系统中的瓶颈可能和程序员开发过程中想象的瓶颈相去甚远。Tuning 指消除瓶颈。性能优化的过程通常是不断重复地 profiling 和 tuning。 - -PaddlePaddle 用户一般通过调用 Python API 编写深度学习程序。大部分 Python API 调用用 C++ 写的 libpaddle.so。所以 PaddlePaddle 的性能分析与调优分为两个部分: - -* Python 代码的性能分析 -* Python 与 C++ 混合代码的性能分析 - - -## Python代码的性能分析 - -### 生成性能分析文件 - -Python标准库中提供了性能分析的工具包,[cProfile](https://docs.python.org/2/library/profile.html)。生成Python性能分析的命令如下: - -```bash -python -m cProfile -o profile.out main.py -``` - -其中 `main.py` 是我们要分析的程序,`-o`标识了一个输出的文件名,用来存储本次性能分析的结果。如果不指定这个文件,`cProfile`会打印到标准输出。 - -### 查看性能分析文件 - -`cProfile` 在main.py 运行完毕后输出`profile.out`。我们可以使用[`cprofilev`](https://github.com/ymichael/cprofilev)来查看性能分析结果。`cprofilev`是一个Python的第三方库。使用它会开启一个HTTP服务,将性能分析结果以网页的形式展示出来: - -```bash -cprofilev -a 0.0.0.0 -p 3214 -f profile.out main.py -``` - -其中`-a`标识HTTP服务绑定的IP。使用`0.0.0.0`允许外网访问这个HTTP服务。`-p`标识HTTP服务的端口。`-f`标识性能分析的结果文件。`main.py`标识被性能分析的源文件。 - -用Web浏览器访问对应网址,即可显示性能分析的结果: - -``` - ncalls tottime percall cumtime percall filename:lineno(function) - 1 0.284 0.284 29.514 29.514 main.py:1() - 4696 0.128 0.000 15.748 0.003 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/executor.py:20(run) - 4696 12.040 0.003 12.040 0.003 {built-in method run} - 1 0.144 0.144 6.534 6.534 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/v2/__init__.py:14() -``` - -每一列的含义是: - -| 列名 | 含义 | -| --- | --- | -| ncalls | 函数的调用次数 | -| tottime | 函数实际使用的总时间。该时间去除掉本函数调用其他函数的时间 | -| percall | tottime的每次调用平均时间 | -| cumtime | 函数总时间。包含这个函数调用其他函数的时间 | -| percall | cumtime的每次调用平均时间 | -| filename:lineno(function) | 文件名, 行号,函数名 | - - -### 寻找性能瓶颈 - -通常`tottime`和`cumtime`是寻找瓶颈的关键指标。这两个指标代表了某一个函数真实的运行时间。 - -将性能分析结果按照tottime排序,效果如下: - -```text - 4696 12.040 0.003 12.040 0.003 {built-in method run} - 300005 0.874 0.000 1.681 0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/v2/dataset/mnist.py:38(reader) - 107991 0.676 0.000 1.519 0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:219(__init__) - 4697 0.626 0.000 2.291 0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:428(sync_with_cpp) - 1 0.618 0.618 0.618 0.618 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/__init__.py:1() -``` - -可以看到最耗时的函数是C++端的`run`函数。这需要联合我们第二节`Python`与`C++`混合代码的性能分析来进行调优。而`sync_with_cpp`函数的总共耗时很长,每次调用的耗时也很长。于是我们可以点击`sync_with_cpp`的详细信息,了解其调用关系。 - -```text -Called By: - - Ordered by: internal time - List reduced from 4497 to 2 due to restriction <'sync_with_cpp'> - -Function was called by... - ncalls tottime cumtime -/home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:428(sync_with_cpp) <- 4697 0.626 2.291 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:562(sync_with_cpp) -/home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:562(sync_with_cpp) <- 4696 0.019 2.316 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:487(clone) - 1 0.000 0.001 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:534(append_backward) - - -Called: - - Ordered by: internal time - List reduced from 4497 to 2 due to restriction <'sync_with_cpp'> -``` - -通常观察热点函数间的调用关系,和对应行的代码,就可以了解到问题代码在哪里。当我们做出性能修正后,再次进行性能分析(profiling)即可检查我们调优后的修正是否能够改善程序的性能。 - - - -## Python与C++混合代码的性能分析 - -### 生成性能分析文件 - -C++的性能分析工具非常多。常见的包括`gprof`, `valgrind`, `google-perftools`。但是调试Python中使用的动态链接库与直接调试原始二进制相比增加了很多复杂度。幸而Python的一个第三方库`yep`提供了方便的和`google-perftools`交互的方法。于是这里使用`yep`进行Python与C++混合代码的性能分析 - -使用`yep`前需要安装`google-perftools`与`yep`包。ubuntu下安装命令为 - -```bash -apt update -apt install libgoogle-perftools-dev -pip install yep -``` - -安装完毕后,我们可以通过 - -```bash -python -m yep -v main.py -``` - -生成性能分析文件。生成的性能分析文件为`main.py.prof`。 - -命令行中的`-v`指定在生成性能分析文件之后,在命令行显示分析结果。我们可以在命令行中简单的看一下生成效果。因为C++与Python不同,编译时可能会去掉调试信息,运行时也可能因为多线程产生混乱不可读的性能分析结果。为了生成更可读的性能分析结果,可以采取下面几点措施: - -1. 编译时指定`-g`生成调试信息。使用cmake的话,可以将CMAKE_BUILD_TYPE指定为`RelWithDebInfo`。 -2. 编译时一定要开启优化。单纯的`Debug`编译性能会和`-O2`或者`-O3`有非常大的差别。`Debug`模式下的性能测试是没有意义的。 -3. 运行性能分析的时候,先从单线程开始,再开启多线程,进而多机。毕竟单线程调试更容易。可以设置`OMP_NUM_THREADS=1`这个环境变量关闭openmp优化。 - -### 查看性能分析文件 - -在运行完性能分析后,会生成性能分析结果文件。我们可以使用[`pprof`](https://github.com/google/pprof)来显示性能分析结果。注意,这里使用了用`Go`语言重构后的`pprof`,因为这个工具具有web服务界面,且展示效果更好。 - -安装`pprof`的命令和一般的`Go`程序是一样的,其命令如下: - -```bash -go get github.com/google/pprof -``` - -进而我们可以使用如下命令开启一个HTTP服务: - -```bash -pprof -http=0.0.0.0:3213 `which python` ./main.py.prof -``` - -这行命令中,`-http`指开启HTTP服务。`which python`会产生当前Python二进制的完整路径,进而指定了Python可执行文件的路径。`./main.py.prof`输入了性能分析结果。 - -访问对应的网址,我们可以查看性能分析的结果。结果如下图所示: - -![result](./pprof_1.png) - - -### 寻找性能瓶颈 - -与寻找Python代码的性能瓶颈类似,寻找Python与C++混合代码的性能瓶颈也是要看`tottime`和`cumtime`。而`pprof`展示的调用图也可以帮助我们发现性能中的问题。 - -例如下图中, - -![kernel_perf](./pprof_2.png) - -在一次训练中,乘法和乘法梯度的计算占用2%-4%左右的计算时间。而`MomentumOp`占用了17%左右的计算时间。显然,`MomentumOp`的性能有问题。 - -在`pprof`中,对于性能的关键路径都做出了红色标记。先检查关键路径的性能问题,再检查其他部分的性能问题,可以更有次序的完成性能的优化。 diff --git a/develop/doc_cn/_sources/howto/optimization/gpu_profiling_cn.rst.txt b/develop/doc_cn/_sources/howto/optimization/gpu_profiling_cn.rst.txt index 0239eef4f11..25bcaccb697 100644 --- a/develop/doc_cn/_sources/howto/optimization/gpu_profiling_cn.rst.txt +++ b/develop/doc_cn/_sources/howto/optimization/gpu_profiling_cn.rst.txt @@ -55,7 +55,7 @@ above profilers. :code:`paddle/math/test` 目录中的 :code:`test_GpuProfiler` 就是用于展示上述分析工具的用法。 -.. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp +.. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp :language: c++ :lines: 137-151 :linenos: @@ -83,7 +83,7 @@ program crashes when CPU version of PaddlePaddle invokes them. 1. 加入 :code:`REGISTER_TIMER_INFO` 和 :code:`printAllStatus` 函数(如高亮部分)。 - .. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp + .. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp :language: c++ :lines: 137-151 :emphasize-lines: 8-12,14 @@ -130,7 +130,7 @@ nvprof 工具 1. 将 :code:`REGISTER_GPU_PROFILER` 函数加到代码中(参考强调部分)。 - .. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp + .. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp :language: c++ :lines: 137-151 :emphasize-lines: 6-7 diff --git a/develop/doc_cn/_sources/howto/read_source.md.txt b/develop/doc_cn/_sources/howto/read_source.md.txt deleted file mode 100644 index edf46aff8c6..00000000000 --- a/develop/doc_cn/_sources/howto/read_source.md.txt +++ /dev/null @@ -1,67 +0,0 @@ -# PaddlePaddle Fluid Source Code Overview - -Examples: https://github.com/PaddlePaddle/Paddle/tree/develop/python/paddle/fluid/tests/book - -Core: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/framework - -Operator: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/operators - -Memory: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/memory - -Platform: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/platform - -# Compile Time - -The following **defines** the NN. The definition goes into this [protocol buffer](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/framework.proto). - -```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_cost = fluid.layers.mean(x=cost) - -sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.001) -sgd_optimizer.minimize(avg_cost) -``` - -- Variables: `x`, `y`, `y_predict`, `cost` and `avg_cost`. [Python](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/framework.py#) -- Layers: `fluid.layers.data`, `fluid.layers.fc` and `fluid.layers.mean` are layers. [Python](https://github.com/PaddlePaddle/Paddle/tree/develop/python/paddle/fluid/layers) - - Every Layer has one or more operators and variables/parameters - - All the operators are defined at [`paddle/operators/`](https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/operators). Other worth-looking files: - - Base class: [`paddle/framework/operator.h`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/operator.h) - - Operator Registration: [`paddle/framework/op_registry.h`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/op_registry.h) - - Operator Lookup: [`paddle/framework/op_info.h`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/op_info.h) -- Optimizer: `fluid.optimizer.SGD`. It does the following - - Add backward operators. [[Python](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/backward.py)] - - Add optimizer operators. [[Python](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/optimizer.py)] - -# Run Time - -The following **evaluates** the NN. Instantiates all the variables, operators. - -```python -place = fluid.CPUPlace() -feeder = fluid.DataFeeder(place=place, feed_list=[x, y]) -exe = fluid.Executor(place) - -# Allocate memory. Initialize Parameter. -exe.run(fluid.default_startup_program()) - -# Allocate memory. Do computation. -exe.run(fluid.default_main_program(), - feed=feeder.feed(data), - fetch_list=[avg_cost]) -``` - -- Place: `place`. one of CPU, GPU or FPGA. [C++](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/place.h) - - The device handle are at [paddle/platform/device_context.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/platform/device_context.h) -- Executor: `fluid.Executor(place)`. [[Python](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/executor.py), [C++](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/executor.cc)] - - Feeds the data: `feed=feeder.feed(data)` - - Evaluates all the operators - - Fetches the result: `fetch_list=[avg_cost]` -- Other worth looking files: - - Scope: [paddle/framework/scope.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/scope.h). Where all the variables live - - Variable: [paddle/framework/variable.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/variable.h). Where all the data (most likely tensors) live - - Tensor: [paddle/framework/tensor.h](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/framework/tensor.h). Where we allocate memory through [`paddle/memory/`](https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/memory) diff --git a/develop/doc_cn/_sources/mobile/cross_compiling_for_android_cn.md.txt b/develop/doc_cn/_sources/mobile/cross_compiling_for_android_cn.md.txt deleted file mode 100644 index cdd69172393..00000000000 --- a/develop/doc_cn/_sources/mobile/cross_compiling_for_android_cn.md.txt +++ /dev/null @@ -1,187 +0,0 @@ -# Android平台编译指南 - -用户可通过如下两种方式,交叉编译Android平台上适用的PaddlePaddle库: - -- [基于Docker容器的编译方式](#基于docker容器的编译方式) -- [基于Linux交叉编译环境的编译方式](#基于linux交叉编译环境的编译方式) - -## 基于Docker容器的编译方式 -Docker能在所有主要操作系统(包括Linux,Mac OS X和Windows)上运行,因此,使用基于Docker容器的编译方式,用户可在自己熟悉的开发平台上编译Android平台上适用的PaddlePaddle库。 - -### 构建PaddlePaddle的Android开发镜像 -我们把PaddlePaddle的交叉编译环境打包成一个镜像,称为开发镜像,里面涵盖了交叉编译Android版PaddlePaddle库需要的所有编译工具。 - -```bash -$ git clone https://github.com/PaddlePaddle/Paddle.git -$ cd Paddle -$ docker build -t username/paddle-android:dev . -f Dockerfile.android -``` - -用户也可以使用PaddlePaddle提供的官方开发镜像: - -```bash -$ docker pull paddlepaddle/paddle:latest-dev-android -``` - -对于国内用户,我们提供了加速访问的镜像源: - -```bash -$ docker pull docker.paddlepaddlehub.com/paddle:latest-dev-android -``` - -### 编译PaddlePaddle C-API库 -构建好开发镜像后,即可使用开发镜像来编译Android版PaddlePaddle C-API库。 -Android的Docker开发镜像向用户提供两个可配置的参数: - - -- - - - - - - - - - - - - - - - - - - - - - - -
                                ArgumentOptional ValuesDefault
                                ANDROID_ABIarmeabi-v7a, arm64-v8aarmeabi-v7a
                                ANDROID_API>= 1621
                                - -- 编译`armeabi-v7a`,`Android API 21`的PaddlePaddle库 - -```bash -$ docker run -it --rm -v $PWD:/paddle -e "ANDROID_ABI=armeabi-v7a" -e "ANDROID_API=21" username/paddle-android:dev -``` - -- 编译`arm64-v8a`,`Android API 21`的PaddlePaddle库 - -```bash -$ docker run -it --rm -v $PWD:/paddle -e "ANDROID_ABI=arm64-v8a" -e "ANDROID_API=21" username/paddle-android:dev -``` - -执行上述`docker run`命令时,容器默认执行[paddle/scripts/docker/build_android.sh](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/scripts/docker/build_android.sh)脚本。该脚本中记录了交叉编译Android版PaddlePaddle库常用的CMake配置,并且会根据`ANDROID_ABI`和`ANDROID_API`自动构建独立工具链、进行编译和安装。由于arm64架构要求Android API不小于21。因此当`ANDROID_ABI=arm64-v8a`,`ANDROID_API<21`时,Docker容器中将默认使用`Android API 21`的编译工具链。用户可以参考下文[配置交叉编译参数](#配置交叉编译参数)章节,根据个人的需求修改定制Docker容器所执行的脚本。编译安装结束之后,PaddlePaddle的C-API库将被安装到`$PWD/install_android`目录,所依赖的第三方库同时也被安装到`$PWD/install_android/third_party`目录。 - -## 基于Linux交叉编译环境的编译方式 -本文档将以Linux x86-64平台为例,介绍交叉编译Android平台上适用的PaddlePaddle库的方法和步骤。 - -### 准备交叉编译环境 - -从源码交叉编译PaddlePaddle,用户需要提前准备好交叉编译环境。Android平台上使用的C/C++交叉编译工具链为[Android NDK](https://developer.android.com/ndk/downloads/index.html?hl=zh-cn),用户可自行前往下载预编译好的版本,也可通过以下命令获取: - -```bash -wget -q https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip -unzip -q android-ndk-r14b-linux-x86_64.zip -``` - -Android NDK中包含了所有Android API级别、所有架构(arm/arm64/x86/mips)需要用到的编译工具和系统库。用户可根据自己的编译目标架构、所需支持的最低Android API级别,构建[独立工具链](https://developer.android.google.cn/ndk/guides/standalone_toolchain.html?hl=zh-cn)。 - -- 构建`armeabi-v7a`、 `Android API 21`的独立工具链: - -```bash -your/path/to/android-ndk-r14b-linux-x86_64/build/tools/make-standalone-toolchain.sh \ - --arch=arm --platform=android-21 --install-dir=your/path/to/arm_standalone_toolchain -``` - -此命令将在`your/path/to/arm_standalone_toolchain`目录生成一套独立编译工具链,面向架构为32位ARM架构,支持的最小的Android API级别为21,支持编译器`arm-linux-androideabi-gcc (GCC) 4.9`和`clang 3.8`。 - -- 构建`arm64-v8a`、 `Android API 21`的独立工具链: - -```bash -your/path/to/android-ndk-r14b-linux-x86_64/build/tools/make-standalone-toolchain.sh \ - --arch=arm64 --platform=android-21 --install-dir=your/path/to/arm64_standalone_toolchain -``` - -此命令将在`your/path/to/arm64_standalone_toolchain`目录生成一套独立编译工具链,面向架构为64位ARM64架构,支持的最小Android API级别为21,支持编译器`arm-linux-androideabi-gcc (GCC) 4.9`和`clang 3.8`。 - -### 配置交叉编译参数 - -CMake系统对交叉编译提供了支持[cmake-toolchains](https://cmake.org/cmake/help/v3.0/manual/cmake-toolchains.7.html#cross-compiling)。为了简化cmake配置,PaddlePaddle为交叉编译提供了工具链配置文档[cmake/cross_compiling/android.cmake](https://github.com/PaddlePaddle/Paddle/blob/develop/cmake/cross_compiling/android.cmake),以提供一些默认的编译器和编译参数相关配置。注意,从CMake 3.7版本开始,CMake官方对Android平台的交叉编译提供了通用的支持。PaddlePaddle若检测到用户使用的CMake版本不低于3.7时,将会将用户传进来的配置参数传递CMake系统,交由CMake系统本身来处理。有关参数配置的详细说明见[cmake-toolchains](https://cmake.org/cmake/help/v3.7/manual/cmake-toolchains.7.html#cross-compiling)。 - -交叉编译Android版本的PaddlePaddle库时,有一些必须配置的参数: -- `CMAKE_SYSTEM_NAME`,CMake编译的目标平台,必须设置为`Android`。在设置`CMAKE_SYSTEM_NAME=Android`后,PaddlePaddle的CMake系统才认为是在交叉编译Android系统的版本,并自动编译PaddlePaddle所需的所有第三方库。此外,还会强制设置一些PaddlePaddle参数的值(`WITH_GPU=OFF`、`WITH_AVX=OFF`、`WITH_PYTHON=OFF`、`WITH_RDMA=OFF`、`WITH_MKL=OFF`、`WITH_GOLANG=OFF`)。 -- `WITH_C_API`,必须设置为`ON`。在Android平台上只支持使用C-API来预测。 -- `WITH_SWIG_PY`,必须设置为`OFF`。在Android平台上不支持通过swig调用来训练或者预测。 - -Android平台可选配置参数: - -- `ANDROID_STANDALONE_TOOLCHAIN`,独立工具链所在的绝对路径,或者相对于构建目录的相对路径。PaddlePaddle的CMake系统将根据该值自动推导和设置需要使用的交叉编译器、sysroot、以及Android API级别;否则,用户需要在cmake时手动设置这些值。无默认值。 -- `ANDROID_TOOLCHAIN`,目标工具链。可设置`gcc/clang`,默认值为`clang`。 - - CMake 3.7以上,将会始终使用`clang`工具链;CMake 3.7以下,可设置`ANDROID_TOOLCHAIN=gcc`以使用`gcc`工具链。 - - Android官方提供的`clang`编译器要求系统支持`GLIBC 2.15`以上。 -- `ANDROID_ABI`,目标架构ABI。目前支持`armeabi-v7a`和`arm64-v8a`,默认值为`armeabi-v7a`。 -- `ANDROID_NATIVE_API_LEVEL`,工具链的Android API级别。若没有显式设置,PaddlePaddle将根据`ANDROID_STANDALONE_TOOLCHAIN`的值自动推导得到。 -- `ANROID_ARM_MODE`,是否使用ARM模式。 - - `ANDROID_ABI=armeabi-v7a`时,可设置`ON/OFF`,默认值为`ON`; - - `ANDROID_ABI=arm64-v8a`时,不需要设置。 -- `ANDROID_ARM_NEON`,是否使用NEON指令。 - - `ANDROID_ABI=armeabi-v7a`时,可设置`ON/OFF`,默认值为`ON`; - - `ANDROID_ABI=arm64-v8a`时,不需要设置。 - -其他配置参数: - -- `USE_EIGEN_FOR_BLAS`,是否使用Eigen库进行矩阵计算。可设置`ON/OFF`,默认值为`OFF`。 -- `HOST_C/CXX_COMPILER`,宿主机的C/C++编译器。在编译宿主机版protoc可执行文件和目标机版OpenBLAS库时需要用到。默认设置成环境变量`CC/CXX`的值;若环境变量`CC/CXX`没有设置,则设置成`cc/c++`编译器。 - -常用的cmake配置如下: - -```bash -cmake -DCMAKE_SYSTEM_NAME=Android \ - -DANDROID_STANDALONE_TOOLCHAIN=your/path/to/arm_standalone_toolchain \ - -DANDROID_ABI=armeabi-v7a \ - -DANDROID_ARM_NEON=ON \ - -DANDROID_ARM_MODE=ON \ - -DUSE_EIGEN_FOR_BLAS=ON \ - -DCMAKE_INSTALL_PREFIX=your/path/to/install \ - -DWITH_C_API=ON \ - -DWITH_SWIG_PY=OFF \ - .. -``` - -``` -cmake -DCMAKE_SYSTEM_NAME=Android \ - -DANDROID_STANDALONE_TOOLCHAIN=your/path/to/arm64_standalone_toolchain \ - -DANDROID_ABI=arm64-v8a \ - -DUSE_EIGEN_FOR_BLAS=OFF \ - -DCMAKE_INSTALL_PREFIX=your/path/to/install \ - -DWITH_C_API=ON \ - -DWITH_SWIG_PY=OFF \ - .. -``` - -用户还可根据自己的需求设置其他编译参数。 - -- 设置`CMAKE_BUILD_TYPE`为`MinSizeRel`,最小化生成的库的大小。 -- 设置`CMAKE_BUILD_TYPE`为`Release`,获得最快的执行速度, -- 用户亦可以通过手动设置`CMAKE_C/CXX_FLAGS`来影响PaddlePaddle的编译过程。 - -**性能TIPS**,为了达到最快的计算速度,在CMake参数配置上,有以下建议: - -- 设置`CMAKE_BUILD_TYPE`为`Release` -- 使用`clang`编译工具链 -- `armeabi-v7a`时,设置`USE_EIGEN_BLAS=ON`,使用Eigen进行矩阵计算;`arm64-v8a`时,设置`USE_EIGEN_FOR_BLAS=OFF`,使用OpenBLAS进行矩阵计算 - -### 编译和安装 - -CMake配置完成后,执行以下命令,PaddlePaddle将自动下载和编译所有第三方依赖库、编译和安装PaddlePaddle预测库。 - -```bash -make -make install -``` - -注意:如果你曾经在源码目录下编译过其他平台的PaddlePaddle库,请先使用`rm -rf`命令删除`third_party`目录和`build`目录,以确保所有的第三方依赖库和PaddlePaddle代码都是针对新的CMake配置重新编译的。 - -执行完安装命令后,`your/path/to/install`目录中会包含`include`、`lib`和`third_party`目录,其中`include`中包含C-API的头文件,`lib`中包含若干个不同Android ABI的PaddlePaddle库,`third_party`中包含所依赖的所有第三方库。自此,PaddlePaddle的已经安装完成,用户可将`your/path/to/install`目录下的生成文件用于深度学习相关Android App中,调用方法见C-API文档。 diff --git a/develop/doc_cn/_sources/mobile/cross_compiling_for_ios_cn.md.txt b/develop/doc_cn/_sources/mobile/cross_compiling_for_ios_cn.md.txt deleted file mode 100644 index d5196d9a4c9..00000000000 --- a/develop/doc_cn/_sources/mobile/cross_compiling_for_ios_cn.md.txt +++ /dev/null @@ -1,117 +0,0 @@ -# iOS平台编译指南 -交叉编译iOS平台上适用的PaddlePaddle库,需要在MacOS系统上进行。本文的将介绍在MacOS上,从源码交叉编译iOS平台上适用的PaddlePaddle库。 - -## 准备交叉编译环境 -Apple官方为iOS开发提供了完整的交叉编译工具和集成开发环境,用户从App Store下载安装Xcode即可。也可自行前往官网下载,[Xcode](https://developer.apple.com/cn/xcode/)。安装完成之后,可在命令行执行`xcodebuild -version`,判断是否安装成功。 - -```bash -$ xcodebuild -version -Xcode 9.0 -Build version 9A235 -``` - -## 配置交叉编译参数 - -PaddlePaddle为交叉编译提供了工具链配置文档[cmake/cross_compiling/ios.cmake](https://github.com/PaddlePaddle/Paddle/blob/develop/cmake/cross_compiling/ios.cmake),以提供一些默认的编译器和编译参数配置。 - -交叉编译iOS版本的PaddlePaddle库时,有一些必须配置的参数: - -- `CMAKE_SYSTEM_NAME`,CMake编译的目标平台,必须设置为`iOS`。在设置`CMAKE_SYSTEM_NAME=iOS`后,PaddlePaddle的CMake系统会自动编译所有的第三方依赖库,并且强制设置一些PaddlePaddle参数的值(`WITH_C_API=ON`、`WITH_GPU=OFF`、`WITH_AVX=OFF`、`WITH_PYTHON=OFF`、`WITH_RDMA=OFF`)。 -- `WITH_C_API`,是否编译C-API预测库,必须设置为ON。在iOS平台上只支持使用C-API来预测。 -- `WITH_SWIG_PY`,必须设置为`OFF`。在iOS平台上不支持通过swig调用来训练或者预测。 - -iOS平台可选配置参数: - -- `IOS_PLATFORM`,可设置为`OS`(默认值)或`SIMULATOR`。 - - `OS`,构建目标为`arm`架构的iPhone或者iPad等物理设备。 - - `SIMULATOR`,构建目标为`x86`架构的模拟器平台。 -- `IOS_ARCH`,目标架构。针对不同的`IOS_PLATFORM`,可设置的目标架构如下表所示,默认编译所有架构: - - - - - - - - - - - - - - - - - - - - - - -
                                IOS_PLATFORMIOS_ARCH
                                OSarmv7, armv7s, arm64
                                SIMULATORi386, x86_64
                                - -- `IOS_DEPLOYMENT_TARGET`,最小的iOS部署版本,默认值为`7.0`。 -- `IOS_ENABLE_BITCODE`,是否使能[Bitcode](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/AppThinning/AppThinning.html#//apple_ref/doc/uid/TP40012582-CH35-SW3),可设置`ON/OFF`,默认值为`ON`。 -- `IOS_USE_VECLIB_FOR_BLAS`,是否使用[vecLib](https://developer.apple.com/documentation/accelerate/veclib)框架进行BLAS矩阵计算,可设置`ON/OFF`,默认值为`OFF`。 -- `IOS_DEVELOPMENT_ROOT`,`Developer`目录,可显式指定为`/path/to/platform/Developer`。若未显式指定,PaddlePaddle将会根据`IOS_PLATFORM`自动选择`Xcode`对应`platform`的`Developer`目录。 -- `IOS_SDK_ROOT`,所使用`SDK`的根目录,可显式指定为`/path/to/platform/Developer/SDKs/SDK`。若未显式指定,PaddlePaddle将会自动选择`IOS_DEVELOPMENT_ROOT`目录下最新的`SDK`版本。 - -其他配置参数: - -- `USE_EIGEN_FOR_BLAS`,是否使用Eigen库进行矩阵计算,在`IOS_USE_VECLIB_FOR_BLAS=OFF`时有效。可设置`ON/OFF`,默认值为`OFF`。 -- `HOST_C/CXX_COMPILER`,宿主机的C/C++编译器。默认值为环境变量`CC/CXX`的值;若环境变量`CC/CXX`未设置,则使用`cc/c++`编译器。 - -常用的cmake配置如下: - -```bash -cmake -DCMAKE_SYSTEM_NAME=iOS \ - -DIOS_PLATFORM=OS \ - -DIOS_ARCH="armv7;arm64" \ - -DIOS_ENABLE_BITCODE=ON \ - -DIOS_USE_VECLIB_FOR_BLAS=ON \ - -DCMAKE_INSTALL_PREFIX=your/path/to/install \ - -DWITH_C_API=ON \ - -DWITH_TESTING=OFF \ - -DWITH_SWIG_PY=OFF \ - .. -``` - -```bash -cmake -DCMAKE_SYSTEM_NAME=iOS \ - -DIOS_PLATFORM=SIMULATOR \ - -DIOS_ARCH="x86_64" \ - -DIOS_USE_VECLIB_FOR_BLAS=ON \ - -DCMAKE_INSTALL_PREFIX=your/path/to/install \ - -DWITH_C_API=ON \ - -DWITH_TESTING=OFF \ - -DWITH_SWIG_PY=OFF \ - .. -``` - -用户还可根据自己的需求设置其他编译参数。比如希望最小化生成库的大小,可以设置`CMAKE_BUILD_TYPE`为`MinSizeRel`;若希望得到最快的执行速度,则可设置`CMAKE_BUILD_TYPE`为`Release`。亦可以通过手动设置`CMAKE_C/CXX_FLAGS`来影响PaddlePaddle的编译过程。 - -**性能TIPS**,为了达到最快的计算速度,在CMake参数配置上,有以下建议: - -- 设置`CMAKE_BUILD_TYPE`为`Release` -- 设置`IOS_USE_VECLIB_FOR_BLAS=ON`,调用`vecLib`框架提供的BLAS函数进行矩阵计算。 - -## 编译和安装 - -CMake配置完成后,执行以下命令,PaddlePaddle将自动下载和编译所有第三方依赖库、编译和安装PaddlePaddle预测库。 - -``` -$ make -$ make install -``` - -注意:如果你曾在源码目录下编译过其他平台的PaddlePaddle库,请先使用`rm -rf`命令删除`third_party`目录和`build`目录,以确保所有的第三方依赖库和PaddlePaddle代码都是针对新的CMake配置重新编译的。 - -执行完安装命令后,`your/path/to/install`目录中会包含以下内容: - -- `include`目录,其中包含所有C-API的头文件 -- `lib`目录,其中包含PaddlePaddle的C-API静态库 -- `third_party`目录,其中包含所依赖的所有第三方库 - -注意,如果PaddlePaddle库需要同时支持真机和模拟器,则需要分别编译真机和模拟器版本,然后使用`lipo`工具合并fat库。 - -自此,PaddlePaddle库已经安装完成,用户可将合成的fat库用于深度学习相关的iOS App中,调用方法见C-API文档。 diff --git a/develop/doc_cn/_sources/mobile/cross_compiling_for_raspberry_cn.md.txt b/develop/doc_cn/_sources/mobile/cross_compiling_for_raspberry_cn.md.txt deleted file mode 100644 index f8ef9dc8031..00000000000 --- a/develop/doc_cn/_sources/mobile/cross_compiling_for_raspberry_cn.md.txt +++ /dev/null @@ -1,62 +0,0 @@ -# Raspberry Pi平台编译指南 - -通常有两个方法来构建基于 Rasspberry Pi 的版本: - -1. 通过ssh等方式登录到Raspberry Pi系统上来构建。所需的开发工具和第三方库可以参考 [`/Dockerfile`](https://github.com/PaddlePaddle/Paddle/blob/develop/Dockerfile)。 - -1. 另一个方法是交叉编译。这篇文档介绍在 Linux/x64 上交叉编译Raspberry Pi平台上适用的PaddlePaddle的方法和步骤。 - -## 安装交叉编译器 - -克隆下面 Github repo - -```bash -git clone https://github.com/raspberrypi/tools.git -``` - -即可在 `./tools/tree/master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64` 目录里找到交叉编译器 arm-linux-gnueabihf-gcc 4.8.3。运行该编译工具链需要一台 Linux x64 机器上以及 2.14版本以上的 glibc。 - -## 配置交叉编译参数 - -CMake[支持交叉编译](https://cmake.org/cmake/help/v3.0/manual/cmake-toolchains.7.html#cross-compiling)。PaddlePaddle for Raspberry Pi的配置信息在[cmake/cross_compiling/raspberry_pi.cmake](https://github.com/PaddlePaddle/Paddle/blob/develop/cmake/cross_compiling/raspberry_pi.cmake)。 - -交叉编译Raspberry Pi版本PaddlePaddle库时,有一些必须配置的参数: - -- `CMAKE_SYSTEM_NAME`:CMake编译的目标平台,必须配置为`RPi`。在设置`CMAKE_SYSTEM_NAME=RPi`后,PaddlePaddle的CMake系统才认为在是在交叉编译Raspberry Pi系统的版本,并自动编译宿主机版protoc可执行文件、目标机版protobuf库、以及目标机版OpenBLAS库。 - -- `RPI_TOOLCHAIN`:编译工具链所在的绝对路径,或者相对于构建目录的相对路径。PaddlePaddle的CMake系统将根据该值自动设置需要使用的交叉编译器;否则,用户需要在cmake时手动设置这些值。无默认值。 - -- `RPI_ARM_NEON`:是否使用NEON指令。目前必须设置成`ON`,默认值为`ON`。 - -- `HOST_C/CXX_COMPILER`,宿主机的C/C++编译器。在编译宿主机版protoc可执行文件和目标机版OpenBLAS库时需要用到。默认设置成环境变量`CC`的值;若环境变量`CC`没有设置,则设置成`cc`编译器。 - -一个常用的CMake配置如下: - -``` -cmake -DCMAKE_SYSTEM_NAME=RPi \ - -DRPI_TOOLCHAIN=your/path/to/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64 \ - -DRPI_ARM_NEON=ON \ - -DCMAKE_INSTALL_PREFIX=your/path/to/install \ - -DWITH_GPU=OFF \ - -DWITH_C_API=ON \ - -DWITH_PYTHON=OFF \ - -DWITH_SWIG_PY=OFF \ - .. -``` - -其中`WITH_C_API=ON`表示需要构建推理库。 - -用户还可根据自己的需求设置其他编译参数。比如希望最小化生成的库的大小,可以设置`CMAKE_BUILD_TYPE`为`MinSizeRel`;若希望最快的执行速度,则可设置`CMAKE_BUILD_TYPE`为`Release`。 - -## 编译和安装 - -CMake配置完成后,执行以下命令,PaddlePaddle将自动下载和编译所有第三方依赖库、编译和安装PaddlePaddle。 - -```bash -make -make install -``` - -注意:如果你曾经在源码目录下编译过其他平台的PaddlePaddle库,请先使用`rm -rf`命令删除`third_party`目录和`build`目录,以确保所有的第三方依赖库和PaddlePaddle代码都是针对新的CMake配置重新编译的。 - -执行完安装命令后,`your/path/to/install`目录中会包含`include`和`lib`目录,其中`include`中包含C-API的头文件,`lib`中包含一个Raspberry Pi版本的库。 diff --git a/develop/doc_cn/_sources/survey/cluster_bootstrapping_tools.md.txt b/develop/doc_cn/_sources/survey/cluster_bootstrapping_tools.md.txt deleted file mode 100644 index 1cd9962700b..00000000000 --- a/develop/doc_cn/_sources/survey/cluster_bootstrapping_tools.md.txt +++ /dev/null @@ -1,71 +0,0 @@ -# Cluster bootstrapping tool survey -## Abstract -In order to bring up a cluster from bare metal machine to a fully functional kubernetes cluster for Paddlepaddle to run, we need to utilize some tools. Here we are going to compare [Sextant](https://github.com/k8sp/sextant) and [Tectonic installer](https://github.com/coreos/tectonic-installer) - -## Basic assumptions -Here are some basic assumptions before we move on to details -1. You are an administrator of a bare metal machine cluster, which means: - * you have full control to each of the machines. - * you have full control to the network which machines are connected to. -2. Machines can be booted from network with PEX or iPXE -3. You understand the [general procedure to bring up a cluster](#appendix-general-procedure-to-bring-up-a-cluster) - -if your cluster is able to mark above items with checkmarks, then keep reading. - -## Comparing Sextant and Tectonic installer -### Sextant -Sextant is an end2end solution to bring up a bare metal cluster to a fully functional k8s cluster, it integrates DHCP, name service, PEX, cloud-config-service, docker registry services altogether. - -#### Pros -1. End2End: basically all admin need to do is to config the cluster.yaml and power on the cluster. -2. Offline cluster configuration: Sextant has 2 phases during working with it, config time and deploy time. when admin is configuring, it requires admin's machine has internet connectivity, which will download some images, etc. But in deploy time, it's completely OK to go offline since all dependencies are ready during config time. -3. docker registry integrated. -4. GPU machine took care of. - -### Cons -1. k8s API server is not deployed with high availability in considering by default. -2. No grouping support. -3. No API interface, a one-off service. - - -### Tectonic installer -First of all, Tectonic is not free, it requires coreos.com account as a step of installation, and free user can only create less than 10 nodes. - -Tectonic is a suite of software which wraps around k8s and providing more utility regarding dev ops, ie, -Tectonic installer as it's named, it installs Tectonic to a bare metal cluster which means it's not totally an equivalent of Sextant. At the "booting a cluster" part, it mostly utilizes [Matchbox](https://github.com/coreos/matchbox), which is a general cluster bootstrapper. - -Matchbox's Approach is similar to Sexstant. - -### Pros -1. supports grouping machines. -2. supports running provisioning service in rtk. (not a big deal though). -3. supports http/gRPC API interface. -4. supports multi-template. - -### Cons -1. Not an e2e solution to bring up a cluster, need a lot of extra work and other software. -2. [Not fully supporting](https://github.com/coreos/matchbox/issues/550) centOS deployment yet. - -## Conclusion -Sextant is a better solution overall for paddle cloud deploying to a bare metal cluster. It would be great if Sextant can also 1) deploy k8s api server with high availability by default; 2) not designed as a one-off service. - - - -## Appendix: General procedure to bring up a cluster -It's physically impossible for a cluster admin to manually install OS and applications into cluster nodes one by one, here is what an admin would do in cloud industry: -1. setup a bootstrap machine with static IP in the cluster, which has following services: - * DHCP: assigns ip address for rest of the nodes. - * name service: to map node name to a IP - * PXE related services: the booting related info will be delivered to newly booted machines as their IP is assigned via DHCP service, PXE service will provide further booting and installing info and image with TFTP and http protocol. - * cluster config service: this is for providing cluster node with OS config via http - * optional docker registry: a built-in docker registry makes the whole cluster independent from connecting internet, and speeds up software distribution. -2. New node powers on, it will - * broadcast the request for an IP address - * DHCP server assigns the IP address, and deliver the PXE booting related info to the node. - * cluster node will request config files with booting info delivered with DHCP via the TFTP service, and in most of the cases, the config file will point to a http service for the booting image. - * Since PXE is configured with initrd, it will utilize the cloud config service and do further installations like coreOS or K8s installations. - * then restart the node. - -For further understanding, following 2 links from Matchbox are some good readings: -* [Machine lifecycle](https://github.com/coreos/matchbox/blob/master/Documentation/machine-lifecycle.md) -* [PXE booting](https://github.com/coreos/matchbox/blob/master/Documentation/network-booting.md) diff --git a/develop/doc_cn/build_and_install/build_from_source_cn.html b/develop/doc_cn/build_and_install/build_from_source_cn.html index 827675ce4bc..29fddef0cbe 100644 --- a/develop/doc_cn/build_and_install/build_from_source_cn.html +++ b/develop/doc_cn/build_and_install/build_from_source_cn.html @@ -144,6 +144,7 @@ var _hmt = _hmt || [];
                              • 开发标准
                              • FAQ
                                  diff --git a/develop/doc_cn/build_and_install/docker_install_cn.html b/develop/doc_cn/build_and_install/docker_install_cn.html index ff7ee771be3..40209492708 100644 --- a/develop/doc_cn/build_and_install/docker_install_cn.html +++ b/develop/doc_cn/build_and_install/docker_install_cn.html @@ -144,6 +144,7 @@ var _hmt = _hmt || [];
                                • 开发标准
                                • FAQ
                                    diff --git a/develop/doc_cn/build_and_install/index_cn.html b/develop/doc_cn/build_and_install/index_cn.html index 5df3b9c4bc7..521349742c1 100644 --- a/develop/doc_cn/build_and_install/index_cn.html +++ b/develop/doc_cn/build_and_install/index_cn.html @@ -143,6 +143,7 @@ var _hmt = _hmt || [];
                                  • 开发标准
                                  • FAQ
                                      diff --git a/develop/doc_cn/build_and_install/pip_install_cn.html b/develop/doc_cn/build_and_install/pip_install_cn.html index ca6c358a87d..3968a97ebd0 100644 --- a/develop/doc_cn/build_and_install/pip_install_cn.html +++ b/develop/doc_cn/build_and_install/pip_install_cn.html @@ -144,6 +144,7 @@ var _hmt = _hmt || [];
                                    • 开发标准
                                    • FAQ
                                        diff --git a/develop/doc_cn/design/api.html b/develop/doc_cn/design/api.html deleted file mode 100644 index 5d9afbf68e0..00000000000 --- a/develop/doc_cn/design/api.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - - - - - - - PaddlePaddle Design Doc — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        PaddlePaddle Design Doc

                                        -
                                        -

                                        Ingredients

                                        -

                                        As our design principle is starting from the essence: how could we -allow users to express and solve their problems as neural networks. -Some essential concepts that our API have to provide include:

                                        -
                                          -
                                        1. A topology is an expression of layers.
                                        2. -
                                        3. A layer could be any kind of computation, including cost.
                                        4. -
                                        5. Some layers have parameters, some don’t. Most costs don’t have -parameters.
                                        6. -
                                        7. In some topologies, layers share parameters. For -example, -the network for training a ranking model.
                                        8. -
                                        9. At programming time, users specify topologies and possible sharing -of parameters. PaddlePaddle can figure out and create parameters -required (and possibly shared) by one or more topologies.
                                        10. -
                                        -
                                        -
                                        -

                                        Starting from Examples

                                        -

                                        As a summarization -of -our disucssion, -let us present two examples here:

                                        -
                                        -

                                        Example 1. Sharing Parameters between Layers

                                        -

                                        We use -the -3-branch ranking model -in this example. For your convenience, I copy-a-paste the model’s -topology as follows:

                                        -
                                        A -> f -\
                                        -Q -> f --> cost
                                        -B -> f -/
                                        -
                                        -
                                        -

                                        The following program trains the topology including the cost, and then -use the sub-network in the trained topology in inference:

                                        -
                                        def f(in):
                                        -    e = paddle.layer.embedding(in, parameter_name="embedding")
                                        -    o = paddle.layer.softmax(e, parameter_name="semantic")
                                        -    return o
                                        -
                                        -# Create 3 topologies (subnets), they share parameters because all
                                        -# correspoinding layers have the same parameter names.
                                        -fA = f(paddle.layer.data(input_name="A"))
                                        -fB = f(paddle.layer.data(input_name="B"))
                                        -fQ = f(paddle.layer.data(input_name="Q"))
                                        -
                                        -topology = paddle.layer.less_than(
                                        -               paddle.layer.cross_entropy(fA, fQ),
                                        -               paddle.layer.corss_entropy(fB, fQ))
                                        -
                                        -# Derive parameters required in topology and create them in model.
                                        -parameters = paddle.parameters.create(topology)
                                        -
                                        -# Estimate parameters used in topology from data.
                                        -paddle.train(topology, parameters, reader=read_ranking_model_data)
                                        -
                                        -# Inference using fA (or fB or fC, as they share their parameters).
                                        -[testA, testB, testQ] = read_ranking_model_data()
                                        -print "The sematic-vector of testA: ", paddle.infer(fA, parameters, testA)
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Example 2. Sharing Parameters between “Models”

                                        -

                                        We use GAN in -this example. In the following example program, d0 and d1 -correspond to the two networks in the following figure:

                                        -

                                        -
                                        def G(in):
                                        -    # over-simplified example as G has only one layers:
                                        -    return paddle.layer.fc(in, parameter_name="G")
                                        -
                                        -def D(in);
                                        -    # again, over-simplified:
                                        -    return paddle.layer.fc(in, parameter_name="D")
                                        -
                                        -# Construct the first topology, which contains both D and G.
                                        -# By learning this topology, we update parameters of G.
                                        -d0 = paddle.layer.should_be_false(D(G(paddle.layer.data())))
                                        -
                                        -# Construct a second topology d1, which contains only D. By
                                        -# training this topology, we update parameters of D.  Note
                                        -# that d1 share parameters with d0.
                                        -d1 = paddle.layer.should_be_true(D(paddle.layer.data()))
                                        -
                                        -# Create parameters from a list of multiple topologies (models) for
                                        -# the chance to share parameters between these topologies.
                                        -parameters = paddle.parameters.create([d0, d1])
                                        -
                                        -# Iterative training of GAN.
                                        -for ...:
                                        -    train(d0, parameters, reader=read_from_rng, immutable_parameters={"D"})
                                        -    train(d1, parameters, reader=read_from_realistic_images)
                                        -
                                        -# Use d1 for inference:
                                        -print "D thinks a batch of images are realistic ", infer(d1, parameters, read_mnist_images)
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Summarization

                                        -

                                        Above two programs reveal some important design concerns:

                                        -
                                          -
                                        1. Users describe a topology as an expression of layers. Every layer -has a parameter name. If the users don’t specify it explicitly, it’s automatically generated as a unique name. By -specifying the parameter name, users can specify the sharing of -parameters between layers and even between topologies.
                                        2. -
                                        3. paddle.parameters.create figures out parameters required by one -or more topologies from parameter names of layers. It creates these -parameters and returns a ParameterSet object, which is in essence -a map from parameter names to parameters.
                                        4. -
                                        5. At training and inference time, paddle.train and paddle.infer -requires both a topology and the parameter set that holds the parameters of that topology. There are some reasons:
                                            -
                                          1. This prevents users from forgetting to call -paddle.parameters.create.
                                          2. -
                                          3. paddle.train needs to know which parameter set to update.
                                          4. -
                                          5. Users could load another (pre-trained) parameter set and use it -with a topology in train.infer.
                                          6. -
                                          -
                                        6. -
                                        7. By specifying the immutable_parameters parameter of -paddle.train, we can forbid the update of these parameters.
                                        8. -
                                        -
                                        -
                                        -
                                        -

                                        Reader

                                        -

                                        Not all programming frameworks allow users to define I/O functions. -An example is Google MapReduce, which can only read from text, -SSTable, and RecordIO files. Hadoop MapReduce allows users to define -readers and writers by deriving from base classes Reader and -Writer. The former is less flexible but also less error-prone. We -decide to provide the flexibility to users to define their readers.

                                        -

                                        There are some open questions here:

                                        -
                                          -
                                        1. Should a reader return a Python dictionary?
                                        2. -
                                        3. How to map multiple outputs from a reader to multiple data layers?
                                        4. -
                                        5. How to easily compose some existing readers to read more data and -feed a topology with more data layers?
                                        6. -
                                        -
                                        -
                                        -

                                        Training

                                        -

                                        The recommended way to training a model is to call paddle.train, -which simply calls paddle.trainer.Default, a global variable of -type paddle.trainer.SGD. Equivalently, we can do

                                        -
                                        opt = paddle.trainer.SGD(..., paddle.updater.Adam(...))
                                        -opt.train(topology, parameters, reader=read, ...)
                                        -
                                        -
                                        -
                                        -

                                        Updater

                                        -

                                        Please be aware that a trainer can accept an updater as its data -member, where an updater is a class derived from -paddle.trainer.Updater. This is to make it easier to customize -trainers, as discussed -here.

                                        -
                                        -
                                        -

                                        Event Handler

                                        -

                                        paddle.train and paddle.trainer.XXX.train take an optional -parameter event_handler, which should be either None or a function -that handle some events:

                                        -
                                          -
                                        1. BeginTraining
                                        2. -
                                        3. EndTraining
                                        4. -
                                        5. BeginIteration
                                        6. -
                                        7. EndIteration
                                        8. -
                                        9. BeginPass
                                        10. -
                                        11. EndPass
                                        12. -
                                        -

                                        where EndPass is sent if and only if the reader yields -end_pass=True.

                                        -

                                        An example as follows:

                                        -
                                        def event_handler(event):
                                        -    if ininstance(event, paddle.event.EndIteration):
                                        -        print paddle.test(...)
                                        -
                                        -paddle.train(topology, parameters, reader, event_handler)
                                        -
                                        -
                                        -

                                        If we are writing a PaddlePaddle program in and for iPython/Jypyter, -we can use metaplotlib in the event handler to plot a curve of -cost/error versus iterations, as shown -here.

                                        -
                                        -
                                        -

                                        Distributed Training

                                        -

                                        If users want to do distributed training on a cluster, s/he should -call paddle.dist_train and provides access tokens to the cluster as -a parameter.

                                        -

                                        For example, if the user has a TLS certificate that allows him to -access a Kubernetes cluster, s/he should be able to call

                                        -
                                        paddle.dist_train(model,
                                        -                  trainer=paddle.trainer.SGD(...,
                                        -                                             paddle.updater.Adam(...)),
                                        -                  reader=read,
                                        -                  k8s_user="yi",
                                        -                  k8s_token="kube_cluster_tls.pem",
                                        -                  k8s_job="hello",
                                        -                  num_parameter_servers=15)
                                        -
                                        -
                                        -

                                        The pseudo code of paddle.dist_train is as follows:

                                        -
                                        def dist_train(topology, parameters, trainer, reader, ...):
                                        -    if os.getenv("KUBERNETES_SERVICE_HOST") == None:
                                        -        image_name = k8s_user + '/' + k8s_job
                                        -        docker_build(image_name)
                                        -        docker_push()
                                        -        kube_ctrl_start_job(image_name, k8s_user, k8s_token)
                                        -    else:
                                        -        rank = kube_list_containers_in_job_and_return_current_containers_rank()
                                        -        if rank == 0:
                                        -            master()
                                        -        elif rank < 15:
                                        -            parameter_server()
                                        -        else:
                                        -            trainer.train(model, reader=read)
                                        -
                                        -
                                        -

                                        Please be aware that if a process is running on the Kubernetes -cluster, it will have some environment variables pre-defined.

                                        -

                                        If dist_train doesn’t see these environment variables, it knows -that it’s running on users’ personal computer, and it should work as a -launcher. Otherwise, it knows that it’s running on the cluster and -need to figure out its role as either the master, or a trainer, or a -parameter server.

                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/auto_gradient_check.html b/develop/doc_cn/design/auto_gradient_check.html deleted file mode 100644 index 2be2fd09fa9..00000000000 --- a/develop/doc_cn/design/auto_gradient_check.html +++ /dev/null @@ -1,431 +0,0 @@ - - - - - - - - - - - - - Auto Gradient Check Design — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Auto Gradient Check Design

                                        -
                                        -
                                        -

                                        Background:

                                        -
                                          -
                                        • Generally, it is easy to check whether the forward computation of an Operator is correct or not. However, backpropagation is a notoriously difficult algorithm to debug and get right because of the following challenges:
                                            -
                                          1. The formula for backpropagation formula should be correct according to the forward computation.
                                          2. -
                                          3. The Implementation of the above shoule be correct in CPP.
                                          4. -
                                          5. It is difficult to prepare an unbiased test data.
                                          6. -
                                          -
                                        • -
                                        • Auto gradient checking gets a numerical gradient using forward Operator and uses it as a reference for the backward Operator’s result. It has several advantages:
                                            -
                                          1. Numerical gradient checker only needs the forward operator.
                                          2. -
                                          3. The user only needs to prepare the input data for forward Operator and not worry about the backward Operator.
                                          4. -
                                          -
                                        • -
                                        -
                                        -
                                        -

                                        Mathematical Theory

                                        -

                                        The following documents from Stanford have a detailed explanation of how to compute the numerical gradient and why it is useful.

                                        - -
                                        -
                                        -

                                        Numerical Gradient Implementation

                                        -
                                        -

                                        Python Interface

                                        -
                                        def get_numerical_gradient(op,
                                        -                         input_values,
                                        -                         output_name,
                                        -                         input_to_check,
                                        -                         delta=0.005,
                                        -                         local_scope=None):
                                        -    """
                                        -    Get Numerical Gradient for the input of an operator.
                                        -
                                        -    :param op: C++ operator instance, could be an network.
                                        -    :param input_values: The input variables. Should be an dictionary, whose key is
                                        -    variable name, and value is a numpy array.
                                        -    :param output_name: The final output variable name.
                                        -    :param input_to_check: The input variable with respect to which the gradient has to be computed.
                                        -    :param delta: The perturbation value for numerical gradient method. The
                                        -    smaller the delta, the more accurate the result. But if the delta is too
                                        -    small, it will suffer from the numerical stability problem.
                                        -    :param local_scope: The local scope used for get_numeric_gradient.
                                        -    :return: The gradient array in numpy format.
                                        -    """
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Explanation:

                                        -
                                          -
                                        • Why do we need an output_name
                                            -
                                          • An Operator may have multiple Outputs, one can compute an independent gradient from each Output. So the caller should specify the name of the output variable.
                                          • -
                                          -
                                        • -
                                        • Why do we need input_to_check
                                            -
                                          • One operator can have multiple inputs. Gradient Op can calculate the gradient of these inputs at the same time. But Numerical Gradient needs to calculate them one by one. So get_numeric_gradient is designed to calculate the gradient for one input. If you need to compute multiple inputs, you can call get_numeric_gradient multiple times each with a different input.
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -

                                        Core Algorithm Implementation

                                        -
                                            # we only compute the gradient of one element a time.
                                        -    # we use a for loop to compute the gradient of each element.
                                        -    for i in xrange(tensor_size):
                                        -        # get one input element using the index i.
                                        -        original = tensor_to_check.get_float_element(i)
                                        -
                                        -        # add delta to it, run the forward op and then
                                        -        # get the new value of the result tensor.
                                        -        x_pos = original + delta
                                        -        tensor_to_check.set_float_element(i, x_pos)
                                        -        y_pos = get_output()
                                        -
                                        -        # Subtract delta from this element, run the op again
                                        -        # and get the new value of the result tensor.
                                        -        x_neg = original - delta
                                        -        tensor_to_check.set_float_element(i, x_neg)
                                        -        y_neg = get_output()
                                        -
                                        -        # restore old value
                                        -        tensor_to_check.set_float_element(i, original)
                                        -
                                        -        # compute the gradient of this element and store
                                        -        # it into a numpy array.
                                        -        gradient_flat[i] = (y_pos - y_neg) / delta / 2
                                        -
                                        -    # reshape the gradient result to the shape of the source tensor.
                                        -    return gradient_flat.reshape(tensor_to_check.get_dims())
                                        -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Auto Gradient Check Framework

                                        -

                                        Each Operator Kernel has three kinds of Gradient:

                                        -
                                          -
                                        1. Numerical gradient
                                        2. -
                                        3. CPU kernel gradient
                                        4. -
                                        5. GPU kernel gradient (if supported by the device)
                                        6. -
                                        -

                                        The numerical gradient only relies on the forward Operator, so we use the numerical gradient as the reference value. The gradient checking is performed in the following three steps:

                                        -
                                          -
                                        1. Calculate the numerical gradient
                                        2. -
                                        3. Calculate CPU kernel gradient with the backward Operator and compare it with the numerical gradient.
                                        4. -
                                        5. Calculate GPU kernel gradient with the backward Operator and compare it with the numeric gradient. (if supported)
                                        6. -
                                        -
                                        -

                                        Python Interface

                                        -
                                            def check_grad(self,
                                        -                   forward_op,
                                        -                   input_vars,
                                        -                   inputs_to_check,
                                        -                   output_name,
                                        -                   no_grad_set=None,
                                        -                   only_cpu=False,
                                        -                   max_relative_error=0.005):
                                        -        """
                                        -        :param forward_op: used to create backward_op
                                        -        :param input_vars: numpy value of input variable. The following
                                        -          computation will use these variables.
                                        -        :param inputs_to_check: the input variable with respect to which the
                                        -          gradient will be computed.
                                        -        :param output_name: The final output variable name.
                                        -        :param max_relative_error: The relative tolerance parameter.
                                        -        :param no_grad_set: used to create backward ops
                                        -        :param only_cpu: only compute and check gradient on cpu kernel.
                                        -        :return:
                                        -        """
                                        -
                                        -
                                        -
                                        -
                                        -

                                        How to check if two numpy arrays are close enough?

                                        -

                                        if abs_numerical_grad is nearly zero, then use absolute error for numerical_grad.

                                        -
                                        numerical_grad = ...
                                        -operator_grad = numpy.array(scope.find_var(grad_var_name(name)).get_tensor())
                                        -
                                        -abs_numerical_grad = numpy.abs(numerical_grad)
                                        -# if abs_numerical_grad is nearly zero, then use abs error for
                                        -# numeric_grad, instead of relative error.
                                        -abs_numerical_grad[abs_numerical_grad < 1e-3] = 1
                                        -
                                        -diff_mat = numpy.abs(abs_numerical_grad - operator_grad) / abs_numerical_grad
                                        -max_diff = numpy.max(diff_mat)
                                        -
                                        -
                                        -
                                        -

                                        Notes:

                                        -

                                        The Input data for auto gradient checker should be reasonable to avoid numerical stability problem.

                                        -
                                        - -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/backward.html b/develop/doc_cn/design/backward.html deleted file mode 100644 index 139558ad027..00000000000 --- a/develop/doc_cn/design/backward.html +++ /dev/null @@ -1,402 +0,0 @@ - - - - - - - - - - - - - Backward Building — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Backward Building

                                        -
                                        -

                                        Motivation

                                        -

                                        In Neural Network, most models are solved by the backpropagation algorithm(known as BP) at present. Technically, BP calculates the gradient of the loss function, then propagates it back through the networks following the chain rule. However, when configuring the model structure, users do not need to define the backward part. So a mechanism is required by the framework which can complete the model’s backward part automatically according to the given forward part.

                                        -

                                        When implementing a specific op, the developer is also asked to implement its backward version, called grad_op. A grad_op takes gradients of its corresponding op‘s outputs, and calculate gradients of the op‘s inputs. During the building of a model’s backward part, the framework creates each forward op‘s grad_op, and then string them together in reverse order of forwarding part. In this way, gradients spread from the end to the beginning of the model, in another word, from the loss to parameters.

                                        -
                                        -
                                        -

                                        Challenges

                                        -

                                        The motivation of backward building is apparent. However, implementation it correctly is not so easy. In the Fluid design, a deep learning model is described by Program, Block, Op and Variable. The Block itself can be nested. It means that the ops and variables are scattered across different blocks rather than all be gathered in a single graph. Our backward building algorithm shall visit blocks in recursive order and be able to insert grad_ops and new created variables into the right place.

                                        -
                                        -
                                        -

                                        Usage

                                        -

                                        Although the whole algorithm is comprised of many functions, only one is exposed as API:

                                        -
                                        def append_backward(loss, parameter_list=None, no_grad_set=None):
                                        -    """
                                        -    Append backward part to main_program
                                        -
                                        -    Args:
                                        -        loss(Variable): The variable generated by the cost function.
                                        -        parameter_list(list): Parameters that need to be updated by optimizers.
                                        -            If None, it means all parameters need to be updated.
                                        -
                                        -        no_grad_set(set): Variables that have no gradients in Block 0. 
                                        -            If None, the set will be generated inside the function and 
                                        -            contains all variables with `step_gradient=True` from all blocks.
                                        -        
                                        -    Return:
                                        -        (list[Variable]): list of (parameters, gradients) pair.
                                        -    """
                                        -
                                        -
                                        -

                                        By invoking this API, the framework appends backward part of the program where the loss is. It takes three arguments. loss means the final loss value. It must be a scalar and is usually the output of the loss layer. It is also where the gradient generated and backpropagation starts. parameter_list marks all parameters needs updating. If it’s None, all parameter will be updated by optimizers. no_grad_set marks variables without gradient. if all outputs of some grad_op are in no_grad_set, the grad_op will not be run.

                                        -

                                        This API will be invoked automatically before optimizer building. -As a result, in most cases, users do not need to invoke the API by themselves to append backward part.

                                        -
                                        -
                                        -

                                        Implementation

                                        -

                                        The implementation of backward building algorithm is in backward.py file. The whole algorithm can be divided into two independent parts: creating grad_ops and creating new variables.

                                        -
                                        -

                                        Creating grad_ops

                                        -

                                        The creating of grad_ops is implemented by:

                                        -
                                        def _append_backward_ops_(target,
                                        -                          block,
                                        -                          target_block,
                                        -                          no_grad_dict,
                                        -                          grad_to_var):
                                        -    """
                                        -    Create all grad ops, and insert them into given block
                                        -
                                        -    Args:
                                        -        target(Variable): the target variable of forward pass
                                        -        block(Block): the block where forward ops are
                                        -        target_block(Block): the block which is going to hold new generated grad ops
                                        -        no_grad_dict(dict): 
                                        -            key(int)  block index
                                        -            val(set) a set of varibale names. These varibales have no gradient
                                        -        grad_to_var(dict)(output argument):
                                        -            key(str): grad variable name
                                        -            val(str): corresponding forward variable name
                                        -    """
                                        -
                                        -
                                        -

                                        Given a block, the function will traverses all ops in this block in reverse order, gets corresponding grad_op from the C++ core via core.get_grad_op_desc(), then append it to target_block.

                                        -

                                        However, some specific op(e.g. while_op, if_else_op) can hold its own sub-block. For these sub-blocks contains ops as well, the grad_op creating should be recursive.

                                        -

                                        During the reverse traversal, we check each op whether it has an attribute named sub_block. If so, it means there is a sub-block and we need to deal with it first. After creating a new block whose father is the one in op‘s attribute, we invoke _append_backward_ops_() recursively, assigning the new block to parameter target_block and the one in op‘s attribute to block. The pseudo-code shows this process:

                                        -
                                        ******* pseudo-code ********
                                        -for op in reversed(block.ops):
                                        -    if op has an attribute named 'sub_block':
                                        -        Get the sub-block(`s_block`) from op's attribute.
                                        -        Create a new block(`grad_s_block`), whose father is `s_block`.
                                        -        Invoke _append_backward_ops_(), with `block=s_block` and `target_block=grad_s_block`
                                        -    
                                        -    Invoke `core.get_grad_op_desc()` to get op's grad_op.
                                        -    Insert name correspondings between variables and their gradients of the grad_op to grad_to_var
                                        -    Assign grad_s_block to grad_op as it's 'sub_block' attribute.
                                        -    Append grad_op to current target_block.
                                        -
                                        -
                                        -

                                        The first invoking of _append_backward_ops_() is initiated by append_backward(), in which parameters block and target_block are all assigned with root block(the block with index 0).

                                        -
                                        -
                                        -

                                        Corner Cases of grad_op Creating

                                        -

                                        In the previous section, we show the regular process of grad_op creating. However, in some corner cases, the conventional algorithm is not enough to get the correct result and appending handling is required. These additional processes run after the algorithm mentioned above and do some special adjusts on its output grad_ops.

                                        -
                                        -

                                        Shared Variables

                                        -

                                        If a variable is read by more than one op in the forward pass, its gradient is likely to be written by more than one grad_ops in the next backward pass. To make the gradient result being the sum of all grad_ops’ outputs instead of the last running one, we assign each output with a temporary variable and then add a sum_op to add them up.

                                        -

                                        For the debug convenience, if the final gradient name is w@GRAD, it’s corresponding temporary variables will be named as w@GRAD@RENAME@0, w@GRAD@RENAME@1...

                                        -

                                        See function _addup_repetitive_outputs_ in backward.py for implementation details.

                                        -
                                        -
                                        -

                                        No Gradient Variables

                                        -

                                        In our framework, variables can be marked as no_gradient, it means that the gradient of this variable is unnecessary and can be considered as zero in model training. Apparently, when all the outputs of some grad_op are marked as no_gradient, the grad_op itself can be skipped in backward pass.

                                        -

                                        Another situation is all the gradient inputs of some grad_op are marked as no_gradient, which means all of them can be considered as zeros. For grad_ops are in essence the propagation of gradients, all the outputs are definitely zeros when all gradient inputs are zeros. Therefore the grad_op can also be skipped.

                                        -

                                        It should be noted that all these zero gradients still need to be creating and initialized by something, otherwise following grad_ops who take these gradients as inputs take the risk of using uninitialized memory. In our code, we employ fill_zeros_like_op to initialize them as all zeros.

                                        -

                                        This features are implemented in function _remove_no_grad_branch_. It checks new created grad_ops one-by-one, removes who can be skipped and inserts fill_zeros_like_op when its necessary. We can get the no_grad_set from the _append_backward_ops_ argument no_grad_dict or generate it on the fly by scanning all variables’ no_gradient attribute(True or False).

                                        -
                                        -
                                        -
                                        -

                                        Creating Backward Variables

                                        -

                                        Up to now, we have completed all creating and adjusting jobs of grad_ops. However, backward variables have not been created. Now they are only represented by grad_op‘s input and output arguments. The backward variable creating job will be done by:

                                        -
                                        def _append_backward_vars_(block, 
                                        -                           start_op_idx, 
                                        -                           grad_to_var, 
                                        -                           grad_info_map):
                                        -    """
                                        -    Create new variables required by backward pass.
                                        -
                                        -    Args:
                                        -        block(Block): the block where new variables will be created
                                        -        start_op_idx(int): Only variables required by ops in block.ops[start_op_idx : ] will be created
                                        -        grad_to_var(dict):
                                        -            key(str): grad variable name
                                        -            val(str): corresponding forward variable name
                                        -            In most cases, this dict is generated by _append_backward_ops_()
                                        -        grad_info_map(dict)(output argument):
                                        -            key(str): forward variable name
                                        -            val(tuple): a tuple of (str, int), str is the corresponding grad name, int is the block index
                                        -    """
                                        -
                                        -
                                        -

                                        Given a block, this function traverses all the grad_ops in it(The argument start_op_idx indicates where the grad_op sequence starts.) and creates all the uncreated outputs. The pseudo-code shows this process:

                                        -
                                        for op in block.ops[start_op_idx : ]:
                                        -
                                        -    if op has an attribute named 'sub_block':
                                        -        Get the sub-block(`s_block`) from op's attribute.
                                        -        Invoke _append_backward_vars_(), with `block=s_block`
                                        -        
                                        -    for var_name in op.all_output_names():
                                        -        if block.has_var_recursive(var_name) or var_name is the name of empty variable:
                                        -            continue
                                        -        create a new variable named 'var_name' in block
                                        -        if grad_to_var.has_key(var_name):
                                        -            set grad_info_map[grad_to_var[var_name]] as a tuple of (var_name. block)
                                        -            
                                        -    do op's var type inference
                                        -    do op's shape inference
                                        -
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/block.html b/develop/doc_cn/design/block.html deleted file mode 100644 index 3f75987c529..00000000000 --- a/develop/doc_cn/design/block.html +++ /dev/null @@ -1,567 +0,0 @@ - - - - - - - - - - - - - Design Doc: Block and Scope — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Block and Scope

                                        -
                                        -

                                        The Representation of Computation

                                        -

                                        Both deep learning systems and programming languages help users describe computation procedures. These systems use various representations of computation:

                                        -
                                          -
                                        • Caffe, Torch, and Paddle: sequences of layers.
                                        • -
                                        • TensorFlow, Caffe2, Mxnet: graph of operators.
                                        • -
                                        • PaddlePaddle: nested blocks, like C++ and Java programs.
                                        • -
                                        -
                                        -
                                        -

                                        Block in Programming Languages and Deep Learning

                                        -

                                        In programming languages, a block is a pair of curly braces that includes local variables definitions and a sequence of instructions or operators.

                                        -

                                        Blocks work with control flow structures like if, else, and for, which have equivalents in deep learning:

                                        -

                                        | programming languages | PaddlePaddle | -|———————–|———————–| -| for, while loop | RNN, WhileOp | -| if, if-else, switch | IfElseOp, SwitchOp | -| sequential execution | a sequence of layers |

                                        -

                                        A key difference is that a C++ program describes a one pass computation, whereas a deep learning program describes both the forward and backward passes.

                                        -
                                        -
                                        -

                                        Stack Frames and the Scope Hierarchy

                                        -

                                        The existence of the backward pass makes the execution of a block of PaddlePaddle different from traditional programs:

                                        -

                                        | programming languages | PaddlePaddle | -|———————–|———————————| -| stack | scope hierarchy | -| stack frame | scope | -| push at entering block| push at entering block | -| pop at leaving block | destroy when minibatch completes|

                                        -
                                          -
                                        1. In traditional programs:
                                            -
                                          • When the execution enters the left curly brace of a block, the runtime pushes a frame into the stack, where it realizes local variables.
                                          • -
                                          • After the execution leaves the right curly brace, the runtime pops the frame.
                                          • -
                                          • The maximum number of frames in the stack is the maximum depth of nested blocks.
                                          • -
                                          -
                                        2. -
                                        3. In PaddlePaddle
                                            -
                                          • When the execution enters a block, PaddlePaddle adds a new scope, where it realizes variables.
                                          • -
                                          • PaddlePaddle doesn’t pop a scope after the execution of the block because variables therein are used by the backward pass. So it has a stack forest known as a scope hierarchy.
                                          • -
                                          • The height of the highest tree is the maximum depth of nested blocks.
                                          • -
                                          • After the processing of a minibatch, PaddlePaddle destroys the scope hierarchy.
                                          • -
                                          -
                                        4. -
                                        -
                                        -
                                        -

                                        Use Blocks in C++ and PaddlePaddle Programs

                                        -

                                        Let us consolidate the discussion by presenting some examples.

                                        -
                                        -

                                        Blocks with if-else and IfElseOp

                                        -

                                        The following C++ programs shows how blocks are used with the if-else structure:

                                        -
                                        namespace pd = paddle;
                                        -
                                        -int x = 10;
                                        -int y = 1;
                                        -int z = 10;
                                        -bool cond = false;
                                        -int o1, o2;
                                        -if (cond) {
                                        -  int z = x + y;
                                        -  o1 = z;
                                        -  o2 = pd::layer::softmax(z);
                                        -} else {
                                        -  int d = pd::layer::fc(z);
                                        -  o1 = d;
                                        -  o2 = d+1;
                                        -}
                                        -
                                        -
                                        -

                                        An equivalent PaddlePaddle program from the design doc of the IfElseOp operator is as follows:

                                        -
                                        import paddle as pd
                                        -
                                        -x = minibatch([10, 20, 30]) # shape=[None, 1]
                                        -y = var(1) # shape=[1], value=1
                                        -z = minibatch([10, 20, 30]) # shape=[None, 1]
                                        -cond = larger_than(x, 15) # [false, true, true]
                                        -
                                        -ie = pd.ifelse()
                                        -with ie.true_block():
                                        -    d = pd.layer.add_scalar(x, y)
                                        -    ie.output(d, pd.layer.softmax(d))
                                        -with ie.false_block():
                                        -    d = pd.layer.fc(z)
                                        -    ie.output(d, d+1)
                                        -o1, o2 = ie(cond)
                                        -
                                        -
                                        -

                                        In both examples, the left branch computes x+y and softmax(x+y), the right branch computes fc(x) and x+1 .

                                        -

                                        The difference is that variables in the C++ program contain scalar values, whereas those in the PaddlePaddle programs are mini-batches of instances.

                                        -
                                        -
                                        -

                                        Blocks with for and RNNOp

                                        -

                                        The following RNN model in PaddlePaddle from the RNN design doc :

                                        -
                                        x = sequence([10, 20, 30]) # shape=[None, 1]
                                        -m = var(0) # shape=[1]
                                        -W = var(0.314, param=true) # shape=[1]
                                        -U = var(0.375, param=true) # shape=[1]
                                        -
                                        -rnn = pd.rnn()
                                        -with rnn.step():
                                        -  h = rnn.memory(init = m)
                                        -  h_prev = rnn.previous_memory(h)
                                        -  a = layer.fc(W, x)
                                        -  b = layer.fc(U, h_prev)  
                                        -  s = pd.add(a, b)
                                        -  act = pd.sigmoid(s)
                                        -  rnn.update_memory(h, act)
                                        -  rnn.output(a, b)
                                        -o1, o2 = rnn()
                                        -
                                        -
                                        -

                                        has its equivalent C++ program as follows

                                        -
                                        int* x = {10, 20, 30};
                                        -int* m = {0};
                                        -int* W = {0.314};
                                        -int* U = {0.375};
                                        -
                                        -int mem[sizeof(x) / sizeof(x[0]) + 1];
                                        -int o1[sizeof(x) / sizeof(x[0]) + 1];
                                        -int o2[sizeof(x) / sizeof(x[0]) + 1];
                                        -for (int i = 1; i <= sizeof(x)/sizeof(x[0]); ++i) {
                                        -  int x = x[i-1];
                                        -  if (i == 1) mem[0] = m;
                                        -  int a = W * x;
                                        -  int b = Y * mem[i-1];
                                        -  int s = fc_out + hidden_out;
                                        -  int act = sigmoid(sum);
                                        -  mem[i] = act;
                                        -  o1[i] = act;
                                        -  o2[i] = hidden_out;
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Compilation and Execution

                                        -

                                        Like TensorFlow, a PaddlePaddle program is written in Python. The first part describes a neural network as a protobuf message, and the rest executes the message for training or inference.

                                        -

                                        The generation of this protobuf message is similar to how a compiler generates a binary executable file. The execution of the message is similar to how the OS executes the binary file.

                                        -
                                        -
                                        -

                                        The “Binary Executable File Format”

                                        -

                                        The definition of the protobuf message is as follows:

                                        -
                                        message BlockDesc {
                                        -  repeated VarDesc vars = 1;
                                        -  repeated OpDesc ops = 2;
                                        -}
                                        -
                                        -
                                        -

                                        The step net in above RNN example would look like

                                        -
                                        BlockDesc {
                                        -  vars = {
                                        -    VarDesc {...} // x
                                        -    VarDesc {...} // h
                                        -    VarDesc {...} // fc_out
                                        -    VarDesc {...} // hidden_out
                                        -    VarDesc {...} // sum
                                        -    VarDesc {...} // act
                                        -  }
                                        -  ops = {
                                        -    OpDesc {...} // matmul
                                        -    OpDesc {...} // add_two
                                        -    OpDesc {...} // sigmoid
                                        -  }
                                        -};
                                        -
                                        -
                                        -

                                        Also, the RNN operator in above example is serialized into a protobuf message of type OpDesc and would look like:

                                        -
                                        OpDesc {
                                        -  inputs = {0} // the index of x in vars of BlockDesc above
                                        -  outputs = {5, 3} // indices of act and hidden_out in vars of BlockDesc above
                                        -  attrs {
                                        -    "states" : {1} // the index of h
                                        -    "step_net" : <above step net>
                                        -  }
                                        -};
                                        -
                                        -
                                        -

                                        This OpDesc value is in the ops field of the BlockDesc value representing the global block.

                                        -
                                        -
                                        -

                                        The Compilation of Blocks

                                        -

                                        During the generation of the Protobuf message, the Block should store VarDesc (the Protobuf message which describes Variable) and OpDesc (the Protobuf message which describes Operator).

                                        -

                                        VarDesc in a block should have its name scope to avoid local variables affecting parent block’s name scope. -Child block’s name scopes should inherit the parent’s so that OpDesc in child block can reference a VarDesc that is stored in the parent block. For example:

                                        -
                                        a = pd.Variable(shape=[20, 20])
                                        -b = pd.fc(a, params=["fc.w", "fc.b"])
                                        -
                                        -rnn = pd.create_rnn()
                                        -with rnn.stepnet():
                                        -    x = a.as_step_input()
                                        -    # reuse fc's parameter
                                        -    fc_without_b = pd.get_variable("fc.w")
                                        -    rnn.output(fc_without_b)
                                        -
                                        -out = rnn()
                                        -
                                        -
                                        -

                                        The method pd.get_variable can help retrieve a Variable by the name. The Variable may be stored in a parent block, but might be retrieved in a child block, so block should have a variable scope that supports inheritance.

                                        -

                                        In compiler design, the symbol table is a data structure created and maintained by compilers to store information about the occurrence of various entities such as variable names, function names, classes, etc.

                                        -

                                        To store the definition of variables and operators, we define a C++ class SymbolTable, like the one used in compilers.

                                        -

                                        SymbolTable can do the following:

                                        -
                                          -
                                        • store the definitions (some names and attributes) of variables and operators,
                                        • -
                                        • verify if a variable was declared,
                                        • -
                                        • make it possible to implement type checking (offer Protobuf message pointers to InferShape handlers).
                                        • -
                                        -
                                        // Information in SymbolTable is enough to trace the dependency graph. So maybe
                                        -// the Eval() interface takes a SymbolTable is enough.
                                        -class SymbolTable {
                                        - public:
                                        -  SymbolTable(SymbolTable* parent) : parent_(parent) {}
                                        -
                                        -  OpDesc* NewOp(const string& name="");
                                        -
                                        -  // TODO determine whether name is generated by python or C++.
                                        -  // Currently assume that a unique name will be generated by C++ if the
                                        -  // argument name is left default.
                                        -  VarDesc* Var(const string& name="");
                                        -
                                        -  // find a VarDesc by name, if recursive is true, find parent's SymbolTable
                                        -  // recursively.
                                        -  // this interface is introduced to support InferShape, find protobuf messages
                                        -  // of variables and operators, pass pointers into InferShape.
                                        -  //
                                        -  // NOTE maybe some C++ classes such as VarDescBuilder and OpDescBuilder should
                                        -  // be proposed and embedded into pybind to enable python operation on C++ pointers.
                                        -  VarDesc* FindVar(const string& name, bool recursive=true);
                                        -
                                        -  OpDesc* FindOp(const string& name);
                                        -
                                        -  BlockDesc Compile() const;
                                        -
                                        - private:
                                        -  SymbolTable* parent_;
                                        -
                                        -  map<string, OpDesc> ops_;
                                        -  map<string, VarDesc> vars_;
                                        -};
                                        -
                                        -
                                        -

                                        After all the description of variables and operators is added into SymbolTable, -the block has enough information to run.

                                        -

                                        The Block class takes a BlockDesc as input, and provides Run and InferShape functions.

                                        -
                                        namespace {
                                        -
                                        -class Block : OperatorBase {
                                        -public:
                                        -  Block(const BlockDesc& desc) desc_(desc) {}
                                        -
                                        -  void InferShape(const framework::Scope& scope) const override {
                                        -    if (!symbols_ready_) {
                                        -      CreateVariables(scope);
                                        -      CreateOperators();
                                        -    }
                                        -    // should run InferShape first.
                                        -    for (auto& op : runtime_table_.ops()) {
                                        -      op->InferShape(scope);
                                        -    }
                                        -  }
                                        -
                                        -  void Run(const framework::Scope& scope,
                                        -           const platform::Place& place) const override {
                                        -    PADDLE_ENFORCE(symbols_ready_, "operators and variables should be created first.");
                                        -    for (auto& op : runtime_table_.ops()) {
                                        -      op->Run(scope, place);
                                        -    }
                                        -  }
                                        -
                                        -  void CreateVariables(const framework::Scope& scope);
                                        -  void CreateOperators();
                                        -
                                        -  // some other necessary interfaces of NetOp are listed below
                                        -  // ...
                                        -
                                        -private:
                                        -  BlockDesc desc_;
                                        -  bool symbols_ready_{false};
                                        -};
                                        -
                                        -
                                        -
                                        -
                                        -

                                        The Execution of Blocks

                                        -

                                        Block inherits from OperatorBase, which has a Run method. -Block’s Run method will run its operators sequentially.

                                        -

                                        There is another important interface called Eval, which takes some arguments called targets and generates a minimal graph which treats targets as the end points and creates a new Block. After Run, Eval will get the latest value and return the targets.

                                        -

                                        The definition of Eval is as follows:

                                        -
                                        // clean a block description by targets using the corresponding dependency graph.
                                        -// return a new BlockDesc with minimal number of operators.
                                        -// NOTE: The return type is not a Block but the block's description so that this can be distributed
                                        -// to a cluster.
                                        -BlockDesc Prune(const BlockDesc& desc, vector<string> targets);
                                        -
                                        -void Block::Eval(const vector<string>& targets,
                                        -                 const framework::Scope& scope,
                                        -                 const platform::DeviceContext& dev_ctx) {
                                        -  BlockDesc min_desc = Prune(desc_, targets);
                                        -  Block min_block(min_desc);
                                        -  min_block.Run(scope, dev_ctx);
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/build_system/README.html b/develop/doc_cn/design/build_system/README.html deleted file mode 100644 index a41ff09495a..00000000000 --- a/develop/doc_cn/design/build_system/README.html +++ /dev/null @@ -1,409 +0,0 @@ - - - - - - - - - - - - - Required CMake Function — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -

                                        A few months ago when we were trying to replace CMake with Bazel, @emailweixu suggested that we rewrite those handy Bazel functions using CMake. Now it seems that it’s the right time to get this done, as we are facing problems from the porting of Majel and the development of new the parameter server using Go and C++.

                                        -

                                        Here are some initial thoughts. Your comments are welcome!

                                        -
                                        -

                                        Required CMake Function

                                        -

                                        I think we need only the following few CMake functions to make a project description mean and clean:

                                        -

                                        | C++ | CUDA C++ | Go | -|—|—|—| -| cc_library | nv_library | go_library | -| cc_binary | nv_binary | go_binary | -| cc_test | nv_test | go_test |

                                        -
                                          -
                                        • The _library functions generate .a files from source code.
                                        • -
                                        • The _binary functions generate executable binary files.
                                        • -
                                        • The _test functions generate executable unit test files. They work like _binary but links -lgtest and -lgtest_main.
                                        • -
                                        -

                                        The difference between nv_ functions and cc_ functions is that the former use nvcc instead of the system-default C++ compiler.

                                        -

                                        Both nv_ and cc_ functions enables C++11 (-std=c++11).

                                        -

                                        Also,

                                        -
                                          -
                                        • to describe external dependencies, we need external_library.
                                        • -
                                        • to build shared libraries, we need shared_library.
                                        • -
                                        -
                                        -
                                        -

                                        An Example Project

                                        -

                                        Suppose that we have aforementioned functions defined in our /cmake directory. The following example CMakeLists.txt describes a project including the following source files:

                                        -
                                          -
                                        • tensor.h
                                        • -
                                        • tensor.cc
                                        • -
                                        • tensor_test.cc
                                        • -
                                        • ops.h
                                        • -
                                        • ops.cu
                                        • -
                                        • ops_test.cu
                                        • -
                                        • api.go
                                        • -
                                        • api_test.go
                                        • -
                                        -

                                        Suppose that ops.cu depends on CUDNN.

                                        -
                                        # cc_binary parses tensor.cc and figures out that target also depend
                                        -# on tensor.h.
                                        -cc_binary(tensor
                                        -  SRCS
                                        -  tensor.cc)
                                        -
                                        -# The dependency to target tensor implies that if any of
                                        -# tensor{.h,.cc,_test.cc} is changed, tensor_test need to be re-built.
                                        -cc_test(tensor_test
                                        -  SRCS
                                        -  tensor_test.cc
                                        -  DEPS
                                        -  tensor)
                                        -
                                        -# I don't have a clear idea what parameters external_library need to
                                        -# have.  @gangliao as a CMake expert would have better ideas.
                                        -external_library(cudnn
                                        -  ....)
                                        -
                                        -# Suppose that ops.cu depends on external target CUDNN.  Also, ops.cu
                                        -# include global functions that take Tensor as their parameters, so
                                        -# ops depend on tensor.  This implies that if any of tensor.{h.cc},
                                        -# ops.{h,cu} is changed, ops need to be re-built.
                                        -nv_library(ops
                                        -  SRCS
                                        -  ops.cu
                                        -  DEPS
                                        -  tensor
                                        -  cudnn)  # cudnn is defined later.
                                        -
                                        -nv_test(ops_test
                                        -  SRCS
                                        -  ops_test.cu
                                        -  DEPS
                                        -  ops)
                                        -
                                        -# Because api.go defines a GO wrapper to ops and tensor, it depends on
                                        -# both.  This implies that if any of tensor.{h,cc}, ops.{h,cu}, or
                                        -# api.go is changed, api need to be re-built.
                                        -go_library(api
                                        -  SRCS
                                        -  api.go
                                        -  DEPS
                                        -  tensor # Because ops depend on tensor, this line is optional.
                                        -  ops)
                                        -
                                        -go_test(api_test
                                        -  SRCS
                                        -  api_test.go
                                        -  DEPS
                                        -  api)
                                        -
                                        -
                                        -# This builds libapi.so.  shared_library might use CMake target
                                        -# api_shared so to distinguish it from above target api.
                                        -shared_library(api
                                        -  DEPS
                                        -  api)
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Implementation

                                        -

                                        As above example CMakeLists.txt executes, each function invocation adds “nodes” to a dependency graph. It also use this graph to generate CMake commands including add_executable, add_dependencies, target_link_libraries, and add_test.

                                        -
                                        -
                                        -

                                        Using Package Manager For Go

                                        -

                                        Building Go binaries and libraries need to satisfy their dependencies, generally -we can do go get ./... to download and compile all external dependencies. The -problems are:

                                        -
                                          -
                                        1. go get will always get the latest code from the default branch of the -remote repo, so changes of dependents might break the build. This is very -different with what we already have in cmake/external which download a -specific version or commit id of the dependency.
                                        2. -
                                        3. Some locations can not access external dependencies through the internet, as mentioned -in https://github.com/PaddlePaddle/Paddle/issues/2605. Using package management -tools can package the dependencies as a “vendor” package, which can be mirrored -at many cloud file hosting, so users what to compile paddle by themselves can -download this “vendor” package from a mirror site.
                                        4. -
                                        -
                                        -

                                        Choose A Suitable Tool

                                        -

                                        As mentioned by @wangkuiyi, Here -list dozens of Go package managers. We choose the tool using following principles:

                                        -
                                          -
                                        • Most “active” projects with more stars, more pull requests or commits
                                        • -
                                        • Widely used project
                                        • -
                                        -

                                        After comparing all these projects, we shall choose between the most popular -tools: Godep and Glide.

                                        -

                                        Here’s a brief comparison between Godep and Glide -: https://github.com/Masterminds/glide/wiki/Go-Package-Manager-Comparison. There are -also many complaints about using Godep. There’s also a new “official” pakcage -management tool has been started at: https://github.com/golang/dep to resolve -such problems, but it’s currently at Alpha stage. So the best choice now is -glide obviously.

                                        -
                                        -
                                        -

                                        Manage Go Packages

                                        -
                                          -
                                        • Dependencies: go/glide.yaml will store the dependencies and their versions which -is directly imported by paddle. go/glide.lock will store all dependencies recursively -with their commit id. Builds will “lock” to these packages if we don’t glide up -them
                                        • -
                                        • Vendor package: go/vendor directory will generated when running cmake command. cmake -will download the code corresponding to go/glide.lock. If we put a vendor folder -under go/, cmake will just check the commit id to the packages under the folder, -if commit id matches, there will be no download at all.
                                        • -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/cluster_train/README.html b/develop/doc_cn/design/cluster_train/README.html deleted file mode 100644 index 1ead3a4dc3c..00000000000 --- a/develop/doc_cn/design/cluster_train/README.html +++ /dev/null @@ -1,438 +0,0 @@ - - - - - - - - - - - - - Design Doc: Distributed Training — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Distributed Training

                                        -
                                        -

                                        Objective

                                        -

                                        In this slides, we explained that we’d like PaddlePaddle running on general-purpose clusters like those managed by Kubernetes, so to address demands for AI from both Internet and non-Internet industries.

                                        -

                                        This poses technical challenges to PaddlePaddle:

                                        -
                                          -
                                        1. Support fault-recovery.
                                        2. -
                                        3. Support both offline and online training.
                                        4. -
                                        5. Serverless computing of distributed training.
                                        6. -
                                        -
                                        -
                                        -

                                        Training Job

                                        -

                                        A training job will be created once user asks Paddle cloud to train a model. The training job is made up of different processes that collaboratively consume data and produce a trained model. There are three kinds of processes:

                                        -
                                          -
                                        1. the master server process, which dispatches tasks to
                                        2. -
                                        3. one or more trainer processes, which run distributed training and synchronize gradients/models via
                                        4. -
                                        5. one or more parameter server processes, where each holds a shard of the global model, and receive the uploaded gradients from every trainer process, so they can run the optimize functions to update their parameters.
                                        6. -
                                        -

                                        Their relation is illustrated in the following graph:

                                        -

                                        -

                                        By coordinating these processes, PaddlePaddle supports use both Synchronize Stochastic Gradient Descent (sync SGD) and Asynchronous Stochastic Gradient Descent (async SGD) to train user-defined neural network topologies.

                                        -

                                        When training with sync SGD, parameter servers wait for all trainers to finish gradients update and then send the updated parameters to trainers, training can not proceed until the trainer received the updated parameters. This creates a synchronization point between trainers. When training with async SGD, each trainer upload gradient and download new parameters individually, without the synchronization with other trainers. Using asyc SGD will be faster in terms of time per pass, but have more noise in gradient since trainers are likely to have a stale model.

                                        -
                                        -

                                        Master Server Process

                                        -

                                        The master server process will:

                                        -
                                          -
                                        • Partition a dataset into tasks and dispatch tasks to trainers.
                                        • -
                                        • Keep track of training progress on the dataset with task queue. A training job will iterate on the dataset for a full pass until it goes into next pass.
                                        • -
                                        -
                                        -

                                        Task

                                        -

                                        A task is a data shard to be trained. The total number of tasks will be much bigger than the total number of trainers. The number of data instances inside a task will be much bigger than the mini-batch size.

                                        -
                                        -
                                        -

                                        Task Queue

                                        -

                                        The master server has three task queues to track training progress. As illustrated in the graph below, Job A and Job B both have one master server. Each master server process has three task queues.

                                        -

                                        -
                                          -
                                        • The todo queue holds tasks to be dispatched. When a job starts, the master server fills in the todo queue with all tasks.
                                        • -
                                        • The pending queue holds tasks that are currently training by trainers.
                                        • -
                                        • the done queue holds tasks that are already trained.
                                        • -
                                        -

                                        The life cycle of a single task is illustrated below:

                                        -

                                        -
                                          -
                                        1. When a new pass of training starts, all tasks will be placed in the todo queue.
                                        2. -
                                        3. Upon trainer requests for new task, the master server will dispatch a task from todo queue to it, put the task in the pending queue and wait for completion.
                                        4. -
                                        5. The trainer will work on its task and tell the master server once the task is completed and ask for new task. The master server will dispatch a new task to that trainer.
                                        6. -
                                        7. If a task fails for any reason in trainer, or takes longer than a specific period of time, the master server will move the task back to the todo queue. The timeout count for that task will increase by one. If the timeout count is above a threshold, the task is likely to cause a trainer to crash, then it will be discarded.
                                        8. -
                                        9. The master server will move completed task to the done queue. When the todo queue is empty, the master server will start a new pass by moving all tasks in the done queue to todo queue and reset the timeout counter of all tasks to zero.
                                        10. -
                                        -
                                        -
                                        -
                                        -

                                        Trainer Process

                                        -

                                        The trainer process will:

                                        -
                                          -
                                        • Request tasks from the master.
                                        • -
                                        • Work on the tasks
                                        • -
                                        • Upload gradient to parameter servers, and update local model by downloading new parameters from parameter servers.
                                        • -
                                        -
                                        -
                                        -

                                        Parameter Server Process

                                        -

                                        Parameter server processes hold the parameters collaboratively. The parameters are partitioned on different parameter servers.

                                        -

                                        The parameter server will:

                                        -
                                          -
                                        • Receive gradient from the trainers, update its parameters, and give the trainers the latest parameters.
                                        • -
                                        • Periodically save its parameters to distributed file system by overriding the previous save.
                                        • -
                                        -
                                        -
                                        -

                                        Optimization Algorithms

                                        -

                                        The communication pattern between the trainers and the parameter servers depends on the category of optimization algorithm:

                                        -
                                          -
                                        • Synchronous Stochastic Gradient Descent (sync-SGD)

                                          -

                                          Parameter server will wait for all trainer finish n-th mini-batch calculation and send their gradients before broadcasting new parameters to every trainer. Every trainer will wait for the new parameters before starting n+1-th mini-batch.

                                          -
                                        • -
                                        • Asynchronous Stochastic Gradient Descent (async-SGD)

                                          -

                                          There will no synchronization between different trainers, and parameter server updates its parameter as soon as it receives new gradient:

                                          -
                                            -
                                          • Each trainer uploads its accumulated gradient every n mini-batches.
                                          • -
                                          • Every m mini-batches, the trainer downloads new parameters from parameter server.
                                          • -
                                          • n and m do not have to be equal.
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Fault Tolerant

                                        -

                                        The training job will pause if the master server processes is dead, or any of the parameter server process is dead. They will be started by Kubernetes and recover in few minutes. Please refer to fault recovery.

                                        -

                                        The training job will continue to make progress if there is at least one training process running. The strategy depends on the type of optimization algorithm:

                                        -
                                          -
                                        • sync-SGD

                                          -

                                          TODO

                                          -
                                        • -
                                        • async-SGD

                                          -

                                          Since async-SGD does not require synchronization between mini-batches, the system will by definition make process if at least one trainer is running.

                                          -
                                        • -
                                        -
                                        -
                                        -

                                        Fault Recovery

                                        -

                                        PaddlePaddle uses etcd to keep track of the states of processes. Because etcd is a distributed reliable key-value store, the restarted process can recover its states from etcd. The model parameters are periodically saved into distributed file system, so a restarted parameter server can recover its parameters from the saved file.

                                        -

                                        Now we will introduce how each process recovers from a failure, the graph below shows how etcd is used:

                                        -

                                        -
                                        -

                                        Master Server Process

                                        -

                                        When the master is started by the Kubernetes, it executes the following steps at startup:

                                        -
                                          -
                                        1. Grabs a unique master lock in etcd, which prevents concurrent master instantiations.
                                        2. -
                                        3. Recovers the task queues from etcd if they already exist, otherwise, the master will create them.
                                        4. -
                                        5. Write its ip address to /master/addr so that trainers can discover it.
                                        6. -
                                        7. Listens to trainers’ request of task, dispatch one upon request, and updates task queue using an etcd transaction to ensure lock is held during the update.
                                        8. -
                                        -

                                        When the master server process is dead for any reason, Kubernetes will restart it. It will be online again with all states recovered from etcd in few minutes.

                                        -
                                        -
                                        -

                                        Trainer Process

                                        -

                                        When the trainer is started by the Kubernetes, it executes the following steps at startup:

                                        -
                                          -
                                        1. Watches the available parameter server prefix keys /ps/ on etcd and waits until the count of parameter servers reaches the desired count /ps_desired.
                                        2. -
                                        3. Finds and watches /master/addr to get master’s address.
                                        4. -
                                        5. Requests for tasks from the master to start training.
                                        6. -
                                        -

                                        When a trainer fails, Kuberentes would try to restart it. The recovered trainer would fetch tasks from master and go on training.

                                        -
                                        -
                                        -

                                        Parameter Server Process

                                        -

                                        When the parameter server is started by Kubernetes, it executes the following steps at startup:

                                        -
                                          -
                                        1. Read desired total number of parameter servers from etcd /ps_desired

                                          -
                                        2. -
                                        3. Search through etcd keys /ps/<index> (/ps/0, /ps/1, ...) to find the first non-existant key whose index is smaller than the total number of parameter servers. Set the key using a transaction to avoid concurrent writes. The parameter server’s index is inferred from the key name.

                                          -

                                          The desired number of parameter servers is 3:

                                          -

                                          -

                                          The third parameter server joined:

                                          -

                                          -
                                        4. -
                                        5. The parameter server can load parameters if there are already saved parameters in the save path (inferred from its index).

                                          -
                                        6. -
                                        7. Now the parameter server is ready for the trainers’ requests.

                                          -
                                        8. -
                                        -

                                        If the parameter server’s etcd lease expires, the parameter server will kill itself.

                                        -
                                        -
                                        -
                                        -

                                        Parameter Server Checkpointing

                                        -

                                        See here

                                        -
                                        -
                                        -

                                        Store and dispatching trainning data

                                        -

                                        See here

                                        -
                                        -
                                        -

                                        Dynamic Scaling

                                        -
                                        -

                                        Trainer Scaling

                                        -

                                        TODO

                                        -
                                        -
                                        -

                                        Parameter Server Scaling

                                        -

                                        Not planned for v1.

                                        -
                                        -
                                        -
                                        -

                                        Training Dataset Format

                                        -

                                        TODO

                                        -
                                        -
                                        -

                                        User Interface

                                        -

                                        TODO

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/cluster_train/checkpointing.html b/develop/doc_cn/design/cluster_train/checkpointing.html deleted file mode 100644 index 1cb698e6a9c..00000000000 --- a/develop/doc_cn/design/cluster_train/checkpointing.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - - - - - - - - - - 模型参数检查点(Checkpointing) — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        模型参数检查点(Checkpointing)

                                        -

                                        模型数据检查点的实现,可以有效的避免parameter server的单点或多点同时故障。模型参数检查点通过定期向磁盘上保存一份存储在parameter server内存中的模型数据的完整镜像,来保证训练过程可以从中间状态重新启动。在一个不可中断并缺少备份的训练任务中,可以通过阶段性的保存每个parameter server的数据快照(snapshot)到 分布式存储服务 达到容灾的目的,比如每隔10分钟最新的快照,并删除更早的快照。在出现单点故障时,只需要恢复这台节点,或者将这台节点迁移到另一个节点并启动即可恢复训练任务。

                                        -

                                        -
                                        -

                                        快照保存的设计如下:

                                        -

                                        说明:

                                        -
                                          -
                                        • parameter server在集群中启动后,自动挂载分布式存储目录,并把快照保存到这个目录下。
                                        • -
                                        • 注:每个parameter server的检查点各自独立保存,暂时不考虑多个parameter server同步的保存一个特定时间点的全局检查点,因为这样做也没法保证消除随机性。
                                        • -
                                        -

                                        检查点保存程序流程:

                                        -
                                          -
                                        1. 如果满足条件”每隔10分钟”时,parameter server会获取parameters内存的read_lock,启动一个新的线程开始保存检查点。如果已经正在执行保存检查点的线程,则忽略。由于对parameters的更新需要获取parameters内存的write_lock,所以在写入快照的过程中,parameter server会暂停参数更新并等待。
                                        2. -
                                        3. parameter server生成一个UUID,向指定的目录中一个新的文件(文件名为此UUID)写入快照数据。在快照写入完成后,计算这个文件的MD5 sum。然后在etcd的/checkpoints/[pserver_id]中写入json内容:{"uuid": [UUID], "md5", "MD5 sum", "timestamp": xxxx}
                                        4. -
                                        5. 删除磁盘目录中不是当前uuid的快照文件。
                                        6. -
                                        7. 释放对paramters内存的锁定,停止保存检查点的线程。
                                        8. -
                                        -

                                        这里需要用户额外注意,在您的实际环境中,训练任务的运行可能会占满trainer和parameter server之间的网络带宽,如果parameter server此时还需要通过网络访问分布式存储以保存快照,可能会造成网络拥塞,而出现阶段性的运行停滞。

                                        -
                                        -
                                        -

                                        从快照恢复

                                        -

                                        在parameter server第一次启动或任意时间parameter server故障后被Kubernetes重新启动,则需要回滚到上一个检查点:

                                        -
                                          -
                                        1. 从etcd中读取节点:/checkpoints/[pserver_id]获取最新的检查点的文件uuid
                                        2. -
                                        3. 从磁盘文件中加载uuid文件名的检查点快照文件,并加载其中的参数
                                        4. -
                                        5. 如果上面两步出现错误,则使用启动参数定义的初始化方法初始化参数
                                        6. -
                                        7. 开始提供服务
                                        8. -
                                        -
                                        -
                                        -
                                        -

                                        TODO List

                                        -
                                        -

                                        推测执行/加速执行(TODO)

                                        -

                                        在异构集群中,如果存在某些trainer执行速度过慢会影响整体集群的速度(如图中Trainer 1),此时master将负责启动一个新的Trainer(Accelerate Trainer 2),使用同样的训练数据block。哪个trainer先完成block的训练,则把另一个慢速的kill掉。

                                        -
                                        -
                                        -

                                        动态扩容/缩容

                                        -

                                        目前只考虑动态扩容trainer数量,可以减小系统复杂性。

                                        -
                                        -
                                        -
                                        -

                                        术语

                                        -
                                          -
                                        • model: 指深度学习训练之后得到的所有参数,使用这个神经网络可以完成对新数据的预测
                                        • -
                                        • parameters: 神经网络中的参数,包括权重w和偏置b。一个神经网络的模型由大量的参数组成
                                        • -
                                        • shard: 分片,通常指将一个整体拆分成多份的其中的一份。
                                        • -
                                        • model shard: 将一个神经网络参数拆分成多份,每个shard分别存储在其中一台parameter server之上
                                        • -
                                        • parameter block: 多个parameter block构成一个model shard
                                        • -
                                        • 单点故障: 任意时刻只可能同时有一台服务器故障。由于集群中同时存在两台机器故障的概率极低((平均故障率*平均故障修复时间)^2)只对特殊在线系统考虑两台以上同时故障的容灾。
                                        • -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/cluster_train/data_dispatch.html b/develop/doc_cn/design/cluster_train/data_dispatch.html deleted file mode 100644 index f5edd01c514..00000000000 --- a/develop/doc_cn/design/cluster_train/data_dispatch.html +++ /dev/null @@ -1,414 +0,0 @@ - - - - - - - - - - - - - 训练数据的存储和分发 — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        训练数据的存储和分发

                                        -
                                        -

                                        概念解释

                                        -
                                        -
                                        -

                                        流程介绍

                                        -

                                        生产环境中的训练数据集通常体积很大,并被存储在诸如Hadoop HDFS,Ceph,AWS S3之类的分布式存储之上。这些分布式存储服务通常会把数据切割成多个分片分布式的存储在多个节点之上。这样就可以在云端执行多种数据类计算任务,包括:

                                        -
                                          -
                                        • 数据预处理任务
                                        • -
                                        • Paddle训练任务
                                        • -
                                        • 在线模型预测服务
                                        • -
                                        -
                                        - -

                                        在上图中显示了在一个实际生产环境中的应用(人脸识别)的数据流图。生产环境的日志数据会通过实时流的方式(Kafka)和离线数据的方式(HDFS)存储,并在集群中运行多个分布式数据处理任务,比如流式数据处理(online data process),离线批处理(offline data process)完成数据的预处理,提供给paddle作为训练数据。用户也可以上传labeled data到分布式存储补充训练数据。在paddle之上运行的深度学习训练输出的模型会提供给在线人脸识别的应用使用。

                                        -
                                        -
                                        -

                                        训练数据存储

                                        -

                                        我们选择CephFS作为存储系统。

                                        -
                                          -
                                        • 无论是从PFSClient的角度,还是从Pod中运行任务的角度,统一用/pfs/$DATACENTER/home/$USER来访问用户自己的数据。
                                        • -
                                        • /pfs/$DATACENTER/common下存放公共数据集合
                                            -
                                          • 做只读挂载
                                          • -
                                          -
                                        • -
                                        -
                                        - -
                                        -
                                        -

                                        文件预处理

                                        -

                                        在开始训练之前, 数据集需要预先被转换成PaddlePaddle分布式训练使用的存储格RecordIO。我们提供两个转换方式:

                                        -
                                          -
                                        1. 用户在本地转换好再上传
                                        2. -
                                        3. 用户上传数据后,在机群上运行转换程序
                                        4. -
                                        -

                                        转换生成的文件名会是以下格式:

                                        -
                                        name_prefix-aaaaa-of-bbbbb
                                        -
                                        -
                                        -

                                        “aaaaa”和”bbbbb”都是五位的数字,每一个文件是数据集的一个shard,”aaaaa”代表shard的index,”bbbbb”代表这个shard的最大index。

                                        -

                                        比如ImageNet这个数据集可能被分成1000个shard,它们的文件名是:

                                        -
                                        imagenet-00000-of-00999
                                        -imagenet-00001-of-00999
                                        -...
                                        -imagenet-00999-of-00999
                                        -
                                        -
                                        -
                                        -

                                        转换库

                                        -

                                        无论是在本地或是云端转换,我们都提供Python的转换库,接口是:

                                        -
                                        def convert(output_path, reader, num_shards, name_prefix)
                                        -
                                        -
                                        -
                                          -
                                        • output_path: directory in which output files will be saved.
                                        • -
                                        • reader: a data reader, from which the convert program will read data instances.
                                        • -
                                        • num_shards: the number of shards that the dataset will be partitioned into.
                                        • -
                                        • name_prefix: the name prefix of generated files.
                                        • -
                                        -

                                        reader每次输出一个data instance,这个instance可以是单个值,或者用tuple表示的多个值:

                                        -
                                        yield 1 # 单个值
                                        -yield numpy.random.uniform(-1, 1, size=28*28) # 单个值
                                        -yield numpy.random.uniform(-1, 1, size=28*28), 0 # 多个值
                                        -
                                        -
                                        -

                                        每个值的类型可以是整形、浮点型数据、字符串,或者由它们组成的list,以及numpy.ndarray。如果是其它类型,会被Pickle序列化成字符串。

                                        -
                                        -
                                        -
                                        -

                                        示例程序

                                        -
                                        -

                                        使用转换库

                                        -

                                        以下reader_creator生成的reader每次输出一个data instance,每个data instance包涵两个值:numpy.ndarray类型的值和整型的值:

                                        -
                                        def reader_creator():
                                        -    def reader():
                                        -        for i in range(1000):
                                        -            yield numpy.random.uniform(-1, 1, size=28*28), 0 # 多个值
                                        -    return reader
                                        -
                                        -
                                        -

                                        reader_creator生成的reader传入convert函数即可完成转换:

                                        -
                                        convert("./", reader_creator(), 100, random_images)
                                        -
                                        -
                                        -

                                        以上命令会在当前目录下生成100个文件:

                                        -
                                        random_images-00000-of-00099
                                        -random_images-00001-of-00099
                                        -...
                                        -random_images-00099-of-00099
                                        -
                                        -
                                        -
                                        -
                                        -

                                        进行训练

                                        -

                                        PaddlePaddle提供专用的data reader creator,生成给定RecordIO文件对应的data reader。无论在本地还是在云端,reader的使用方式都是一致的

                                        -
                                        # ...
                                        -reader = paddle.reader.creator.RecordIO("/pfs/datacenter_name/home/user_name/random_images-*-of-*")
                                        -batch_reader = paddle.batch(paddle.dataset.mnist.train(), 128)
                                        -trainer.train(batch_reader, ...)
                                        -
                                        -
                                        -

                                        以上代码的reader输出的data instance与生成数据集时,reader输出的data instance是一模一样的。

                                        -
                                        -
                                        -
                                        -

                                        上传训练文件

                                        -

                                        使用下面命令,可以把本地的数据上传到存储集群中。

                                        -
                                        paddle pfs cp filename /pfs/$DATACENTER/home/$USER/folder/
                                        -
                                        -
                                        -

                                        比如,把之前示例中转换完毕的random_images数据集上传到云端的/home/可以用以下指令:

                                        -
                                        paddle pfs cp random_images-*-of-* /pfs/$DATACENTER/home/$USER/folder/
                                        -
                                        -
                                        -

                                        需要$DATACENTER的配置写到配置文件中,例如

                                        -
                                        # config file
                                        -[datacenter_1]
                                        -username=user
                                        -usercert=user.pem
                                        -userkey=user-key.pem
                                        -endpoint=datacenter1.paddlepaddle.org
                                        -
                                        -[datacenter_2]
                                        -username=user
                                        -usercert=user.pem
                                        -userkey=user-key.pem
                                        -endpoint=datacenter2.paddlepaddle.org
                                        -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        TODO

                                        -
                                        -

                                        文件访问的权限

                                        -

                                        控制用户权限

                                        -
                                          -
                                        • 用户可以把自己的数据分享给别人
                                        • -
                                        -
                                        -
                                        -

                                        文件访问方式

                                        -

                                        不用mount的方式来访问数据,而是直接用API的接口远程访问

                                        -

                                        例如:

                                        -
                                        f = open('/pfs/datacenter_name/home/user_name/test1.dat')
                                        -
                                        -
                                        -
                                        -
                                        -

                                        支持用户自定义的数据预处理job

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/cluster_train/large_model_dist_train.html b/develop/doc_cn/design/cluster_train/large_model_dist_train.html deleted file mode 100644 index fd10e09a642..00000000000 --- a/develop/doc_cn/design/cluster_train/large_model_dist_train.html +++ /dev/null @@ -1,351 +0,0 @@ - - - - - - - - - - - - - Alalysis of large model distributed training in Paddle — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Alalysis of large model distributed training in Paddle

                                        -

                                        NOTE: This is only some note for how we implemeted this scheme in V1, not a new design.

                                        -
                                        -

                                        What is it

                                        -

                                        We often encounter cases that the embedding layer parameters(sparse) are so large that we can not store it in the trainer’s memory when training. So we need to put them to several servers, and fetch them row by row instead of fetch all of the parameters.

                                        -
                                        -
                                        -

                                        How to use

                                        -

                                        Specify command-line argument like --loadsave_parameters_in_pserver=true --ports_num_for_sparse=1 --use_old_updater=1 when starting the paddle trainer. And also add something like --ports_num_for_sparse=1 --pserver_num_threads=5 when starting pserver processes.

                                        -

                                        Accrodingly, configure your embedding layers like:

                                        -
                                        SPARSE_REMOTE=True
                                        -
                                        -w1 = data_layer(name="w1", size=dict_size)
                                        -emb1 = embedding_layer(input=w1, size=32, param_attr=ParameterAttribute(sparse_update=SPARSE_REMOTE))
                                        -w2 = data_layer(name="w2", size=dict_size)
                                        -emb2 = embedding_layer(input=w2, size=32, param_attr=ParameterAttribute(sparse_update=SPARSE_REMOTE))
                                        -...
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Implementation details

                                        -
                                        enum MatType {
                                        -  MAT_NORMAL,
                                        -  MAT_NORMAL_SHARED,
                                        -  MAT_VALUE_SHARED,
                                        -  MAT_SPARSE_ROW_IDS,
                                        -  MAT_SPARSE_ROW_AUTO_GROW,
                                        -  MAT_CACHE_ROW,
                                        -  MAT_SPARSE_ROW,
                                        -  MAT_SPARSE_ROW_PREFETCH,
                                        -  MAT_SPARSE_ROW_PREFETCH_FULL_SIZE,
                                        -};
                                        -
                                        -
                                        -

                                        MAT_SPARSE_ROW_PREFETCH is what we use when configured to fetch only row of matrix when training.

                                        -

                                        In trainer_internal.cpp:L93 trainOneBatch:

                                        -
                                          if (config_->getOptConfig().use_sparse_remote_updater()) {
                                        -    REGISTER_TIMER("prefetch");
                                        -    gradientMachine_->prefetch(inArgs);
                                        -    parameterUpdater_->getParametersRemote();
                                        -  }
                                        -
                                        -
                                        -

                                        When doing actual network forward and backward, at the beginning of each batch, the trainer will try to download one row of data from pserver.

                                        -

                                        In trainer/RemoteParameterUpdater.cpp: parameterUpdater_->getParametersRemote();:

                                        -
                                        if (fullSize) {
                                        -    ...
                                        -} else {
                                        -getParams = [&] {
                                        -    parameterClient_->getParameterSparse(
                                        -        /* recvParameterType= */ PARAMETER_VALUE, sendBackParameterType);
                                        -};
                                        -applyL1 = [](Parameter& para, real decayRate) {
                                        -    para.getMat(PARAMETER_VALUE)->applyL1(/*lr=*/1.0f, decayRate);
                                        -};
                                        -}
                                        -
                                        -
                                        -

                                        Calling parameterClient_->getParameterSparse will do remote call to pserver’s getParameterSparse:

                                        -
                                        void ParameterServer2::getParameterSparse(const SendParameterRequest& request,
                                        -                                          std::vector<Buffer>& inputBuffers,
                                        -                                          SendParameterResponse* response,
                                        -                                          std::vector<Buffer>* outputBuffers) {
                                        -  (void)inputBuffers;
                                        -  auto& buffer = *readWriteBuffer_;
                                        -  size_t numReals = 0;
                                        -  for (const auto& block : request.blocks()) {
                                        -    numReals += getParameterConfig(block).dims(1);
                                        -  }
                                        -  buffer.resize(numReals);
                                        -
                                        -  VLOG(3) << "pserver: getParameterSparse, numReals=" << numReals;
                                        -
                                        -  ReadLockGuard guard(parameterMutex_);
                                        -  size_t offset = 0;
                                        -  for (const auto& block : request.blocks()) {
                                        -    size_t width = getParameterConfig(block).dims(1);
                                        -    Buffer buf = {buffer.data() + offset, width};
                                        -    int type = request.send_back_parameter_type();
                                        -    sendBackParameterSparse(block, type, response, &buf, width, outputBuffers);
                                        -    offset += width;
                                        -  }
                                        -}
                                        -
                                        -
                                        -

                                        getParameterConfig(block).dims(1) returns the width of the current “parameter block”(a shard of parameter object), -then getParameterSparse remote call returns only one row of data to the client.

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/cluster_train/master_server.html b/develop/doc_cn/design/cluster_train/master_server.html deleted file mode 100644 index d731ffebb6a..00000000000 --- a/develop/doc_cn/design/cluster_train/master_server.html +++ /dev/null @@ -1,349 +0,0 @@ - - - - - - - - - - - - - Design Doc: Master Server — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Master Server

                                        -

                                        For an overview of master server’s role, please refer to distributed training design doc. In this design doc we will discuss the master server in more details. The master will be implemented in Go.

                                        -
                                        -

                                        Dataset

                                        -

                                        -

                                        A dataset is a list of files in RecordIO format. A RecordIO file consists of chunks, whereas each chunk consists some records.

                                        -
                                        -
                                        -

                                        Task Queue

                                        -

                                        As mentioned in distributed training design doc, a task is a data shard that the master server assigns to the trainer process to train on. A task consists of one or multiple chunks from one or multiple files. The master server maintains task queues to track the training progress.

                                        -
                                        -

                                        Task Queue Creation

                                        -
                                          -
                                        1. Each trainer will make an RPC call (using Go’s rpc package) to the master server, telling it the RecordIO files representing the dataset specified by the user. Since every trainer will tell the master server the same dataset, only the first RPC call will be honored.

                                          -

                                          The RPC interface is:

                                          -
                                          func (m *RPCServer) ReportDataset(Paths []string, dummy *int) error {
                                          -}
                                          -
                                          -
                                          -
                                        2. -
                                        3. The master server will scan through each RecordIO file to generate the chunk index and know how many chunks does each file have. A chunk can be referenced by the file path and the index of the chunk within the file. The chunk index is in memory data structure that enables fast access to each chunk, and the index of the chunk with the file is an integer start from 0, representing the n-th chunk within the file.

                                          -

                                          The definition of the chunk is:

                                          -
                                          type Chunk struct {
                                          -    Idx   int // index of the chunk within the file
                                          -    Path  string
                                          -    Index recordio.Index // chunk index
                                          -}
                                          -
                                          -
                                          -
                                        4. -
                                        5. Chunks are grouped into tasks, and tasks are filled into the todo queue. The pending queue and the done queue are initialized with no element.

                                          -

                                          The definition of the task is:

                                          -
                                          type Task struct {
                                          -    Index  int
                                          -    Chunks []Chunk
                                          -}
                                          -
                                          -
                                          -

                                          The elements in the tasks queues is of type TaskEntry, containing a timeout counter (described in task retry logic), and a task:

                                          -
                                          type TaskEntry struct {
                                          -    NumTimeout int
                                          -    Task       Task
                                          -}
                                          -
                                          -
                                          -

                                          The definition of task queues is:

                                          -
                                          type TaskQueues struct {
                                          -    Todo    []TaskEntry
                                          -    Pending map[int]TaskEntry // map from task index to task entry
                                          -    Done    []TaskEntry
                                          -}
                                          -
                                          -
                                          -
                                        6. -
                                        -
                                        -
                                        -

                                        Task Queue Persistence

                                        -

                                        The task queues need to be persisted on etcd for fault recovery. Since the task queues only change once a task is completed or timed out, which is not very frequent, we can afford to synchronize with etcd every time the task queues change.

                                        -

                                        We will serialize the task queues data structure with gob encoding, compress with gzip, and save into etcd synchronously under key /task_queues.

                                        -
                                        -
                                        -

                                        Task Dispatch

                                        -

                                        The trainer will make an RPC call to master to get a new task when:

                                        -
                                          -
                                        • the trainer first started, or
                                        • -
                                        • the trainer finishes a task.
                                        • -
                                        -

                                        The RPC interface is:

                                        -
                                        func (m *RPCServer) GetTask(finished *Task, result *Task) error {
                                        -}
                                        -
                                        -
                                        -

                                        Argument finished will be nil when the trainer is just started.

                                        -

                                        During the RPC call the master will do the following:

                                        -
                                          -
                                        • Make a copy of the task queues, and update the copy reflecting the finished tasks and the new pending tasks.
                                        • -
                                        • Synchronize the copy of task queues with etcd using a transaction conditioned on holding the master lock.
                                        • -
                                        • Replace the task queues with the copy and report to the trainer with the new tasks if succeeded, or discard the copy and report the error to the trainer if failed.
                                        • -
                                        -
                                        -
                                        -

                                        Task Retry Logic

                                        -

                                        When a task is dispatched to the trainer, the master will schedule a function for execution after the timeout duration (based on the moving average of task completion time). If the task entry in still in the pending queue, its timeout counter will increase by one, and the task will be moved to todo queue. If the timeout counter is above the threshold, the master will log the error and discard the task.

                                        -

                                        Please note that since a timed out task could be completed after it has been dispatched for retry, so it is possible for a task to be processed multiple times. We do not try to prevent it from happening since it’s fine to train on the same task multiple times due to the stochastic nature of the stochastic gradient decent algorithm.

                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/cluster_train/pserver_client.html b/develop/doc_cn/design/cluster_train/pserver_client.html deleted file mode 100644 index 9a53cc4743b..00000000000 --- a/develop/doc_cn/design/cluster_train/pserver_client.html +++ /dev/null @@ -1,426 +0,0 @@ - - - - - - - - - - - - - Design Doc: The Client Library of Parameter Server — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: The Client Library of Parameter Server

                                        -

                                        For an overview of trainer’s role, please refer to distributed training design doc. In this design doc, we will discuss the parameter server’s client library, which will manage communication with parameter servers. The library will be implemented in Go and made available as a static or dynamic library with a C header file.

                                        -
                                        -

                                        Parameter Partition

                                        -

                                        Each parameter will be partitioned into parameter blocks to make the parameters evenly distributed on parameter servers. The partition is done automatically by the client library. The sparse parameter require a little different treatment:

                                        -
                                        -

                                        Sparse Parameter

                                        -

                                        The sparse parameter is a parameter that is updated sparsely. The name is somewhat misleading, it does not have a sparse representation, it has the same representation as a dense vector.

                                        -

                                        Because a sparse parameter is updated sparsely, the trainer will have to partition the sparse parameter. Because the parameter server will merge all sparse parameter shard into the same file when saving the parameter. It needs special naming convention:

                                        -

                                        If a sparse parameter is partitioned into n shards, they should be named as:

                                        -
                                        name:sparse-0
                                        -name:sparse-1
                                        -...
                                        -name:sparse-n-1
                                        -
                                        -
                                        -

                                        The library is unaware of the partition, and treat each parameter independently. Only when saving parameters, the parameter servers will merge the sparse parameters according to the naming convention.

                                        -
                                        -
                                        -
                                        -

                                        Model Optimization Using Gradients

                                        -

                                        There are two ways to perform model optimization using gradients:

                                        -
                                          -
                                        • On Client

                                          -

                                          The client does multiple steps of forward and backward update. In each step, the gradients are calculated and a new model is generated. After some steps, the client will calculate the difference between the newest model and the old model at step 0. The difference will be updated to parameter servers. Parameter servers will just update parameters using the difference without any optimization using gradients (such as Adam and L1 regularization).

                                          -
                                        • -
                                        • On Parameter Server

                                          -

                                          The client will send accumulated gradients to parameter servers, the parameter server will do the optimization using gradients.

                                          -
                                        • -
                                        -
                                        -
                                        -

                                        L1 and L2 Regularization

                                        -

                                        PaddlePaddle allows L1 or L2 regularizations to be specified per parameter, so when the trainer initializes the parameter it needs include a parameter configuration when L1 or L2 regularization is necessary.

                                        -
                                        -
                                        -

                                        Parameter Initialization

                                        -

                                        The parameters on parameter servers need to be initialized. To provide maximum flexibility, the trainer will initialize the parameters. Only one trainer will do the initialization, the other trainers will wait for the completion of initialization and get the parameters from the parameter servers.

                                        -
                                        -

                                        Trainer Selection

                                        -

                                        To select the trainer for initialization, every trainer will try to get a distributed lock, whoever owns the lock will do the initialization. As illustrated below:

                                        -

                                        -
                                        -
                                        -

                                        Trainer Selection Process

                                        -

                                        The trainer select process is encapsulated in the C API function:

                                        -
                                        int paddle_begin_init_params(paddle_pserver_client* client, const char* config_proto);
                                        -
                                        -
                                        -

                                        The selected trainer’s call to paddle_begin_init_params will return with 1, and the other trainers’ call to paddle_begin_init_params will return 0. paddle_get_params will be blocked until initialization is completed. As illustrated below:

                                        -

                                        -
                                        -
                                        -
                                        -

                                        C Interface

                                        -
                                        typedef enum {
                                        -  PADDLE_ELEMENT_TYPE_INT32   = 0,
                                        -  PADDLE_ELEMENT_TYPE_UINT32  = 1,
                                        -  PADDLE_ELEMENT_TYPE_INT64   = 2,
                                        -  PADDLE_ELEMENT_TYPE_UINT64  = 3,
                                        -  PADDLE_ELEMENT_TYPE_FLOAT32 = 4,
                                        -  PADDLE_ELEMENT_TYPE_FLOAT64 = 5,
                                        -} paddle_element_type;
                                        -
                                        -typedef struct {
                                        -  char*               name;
                                        -  paddle_element_type element_type;
                                        -  unsigned char*      content;
                                        -  int                 content_len;
                                        -} paddle_parameter, paddle_gradient;
                                        -
                                        -typedef int paddle_pserver_client;
                                        -
                                        -/**
                                        - * @brief creates a pserver client that talks to etcd for coordination.
                                        - */
                                        -paddle_pserver_client paddle_new_etcd_pserver_client(char* etcd_addr);
                                        -
                                        -/**
                                        - * @brief creates a pserver client given pserver addresses.
                                        - *
                                        - * @param pserver_addrs comma-separated pserver addresses.
                                        - * @param selected if current pserver client is selected to initialize all parameter servers.
                                        - */
                                        -paddle_pserver_client paddle_new_pserver_client(char* pserver_addrs, int selected);
                                        -void paddle_pserver_client_release(paddle_pserver_client c);
                                        -
                                        -/**
                                        - * @brief paddle_begin_init_params begins to initialize parameters on
                                        - * parameter servers.
                                        - *
                                        - * paddle_begin_init_params will be called from multiple trainers,
                                        - * only one trainer will be selected to initialize the parameters on
                                        - * parameter servers. Other trainers need to get the initialized
                                        - * parameters from parameter servers using @paddle_get_params.
                                        - *
                                        - * @return 1 if the trainer is selected to initialize parameter
                                        - * servers, otherwise 0.
                                        - */
                                        -int paddle_begin_init_params(paddle_pserver_client client);
                                        -
                                        -/**
                                        - * @brief paddle_init_param initializes the parameter on parameter
                                        - * servers.
                                        - *
                                        - * @param param the parameter to initialize.
                                        - * @param param_config_proto the configuration for the parameter.
                                        - * @param config_len the length of param_config_proto
                                        - * @return 0 if successful, otherwise -1. On failure, the trainer
                                        - * needs to restart the entire initialization process (starting from
                                        - * @paddle_begin_init_param). Or simply exit the program and wait for
                                        - * the cluster management system to restart the trainer.
                                        - */
                                        -int paddle_init_param(paddle_pserver_client client, paddle_parameter param, const unsigned char* param_config_proto, int config_len);
                                        -
                                        -/**
                                        - * @brief paddle_finish_init_params tells parameter servers client has
                                        - * sent all parameters to parameter servers as initialization.
                                        - *
                                        - * @return 0 if successful, otherwise -1. On failure, the trainer
                                        - * needs to restart the entire initialization process (starting from
                                        - * @paddle_begin_init_param). Or simply exit the program and wait for
                                        - * the cluster management system to restart the trainer.
                                        - */
                                        -int paddle_finish_init_params(paddle_pserver_client client);
                                        -
                                        -/**
                                        - * @brief paddle_send_grads sends gradients to parameter servers for
                                        - * updating parameters.
                                        - *
                                        - * @param grads the array of gradients to send.
                                        - * @param len the length of the gradient array.
                                        - * @param learning_rate the learning rate for the gradients.
                                        - * @return 0 if successful, otherwise -1.
                                        - */
                                        -int paddle_send_grads(paddle_pserver_client client, const paddle_gradient* grads, int len);
                                        -
                                        -/**
                                        - * @brief paddle_get_params gets parameters from parameter servers.
                                        - *
                                        - * paddle_get_params will block until parameters are initialized on
                                        - * the parameter servers.
                                        - *
                                        - * @param dst the destination array of parameter pointers to save to.
                                        - * The parameter pointer must be pre-popullated with required parameter name,
                                        - * and the content of parameter must be pre-allocated of the size of required
                                        - * parameter on pserver.
                                        - * @param len the length of the names array and the paddle_parameter
                                        - * array.
                                        - * @return 0 if successful, otherwise -1.
                                        - */
                                        -int paddle_get_params(paddle_pserver_client client, paddle_parameter** dst, int len);
                                        -
                                        -/**
                                        - * @brief paddle_save_model indicates parameters to save the parameter
                                        - * to the given path
                                        - *
                                        - * @param path the path to save parameters.
                                        - * @return 0 if successful, otherwise -1.
                                        - */
                                        -int paddle_save_model(paddle_pserver_client client, const char* path);
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/cluster_train/remote_parameter_updater.html b/develop/doc_cn/design/cluster_train/remote_parameter_updater.html deleted file mode 100644 index 3d5853d0cf9..00000000000 --- a/develop/doc_cn/design/cluster_train/remote_parameter_updater.html +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - - - - - - Design Doc: Remote Parameter Updater for Cluster Train — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Remote Parameter Updater for Cluster Train

                                        -

                                        For an overview of distribute training, please refer to distributed training design doc. In this design doc, we will discuss the parameter updater that will use parameter server cclient The Client Library of Parameter Server Design Doc to manage and update parameters.

                                        -
                                        -

                                        Parameter Updater

                                        -

                                        Parameter Updater is used by trainer to manage and update parameter, there are mainly two kind of parameter updater: local and remote, since this design is for cluster train, we will only discuss remote parameter updater here.

                                        -
                                        -

                                        Remote Parameter Updater

                                        -

                                        Remote Parameter Updater manage parameters through remote parameter server with the client that communicate with pserver(The Client Library of Parameter Server Design Doc)

                                        -

                                        In PaddlePaddle Python V2 API, trainer is implemented in python, and the trainer will hold a instance of parameter updater and call it’s functions directly. In this design, we will also expose the api of RemoteParameterUpdater to python with swig.

                                        -
                                        -

                                        Sparse Remote Parameter Updater

                                        -

                                        Since we will only implement dense parameter management new, the mechanism for sparse parameter will be discussed in next stage.

                                        -
                                        -
                                        -
                                        -

                                        Interface Design

                                        -

                                        TBD

                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/cluster_train/save_model.html b/develop/doc_cn/design/cluster_train/save_model.html deleted file mode 100644 index c137aaa38be..00000000000 --- a/develop/doc_cn/design/cluster_train/save_model.html +++ /dev/null @@ -1,368 +0,0 @@ - - - - - - - - - - - - - Design Doc: Save Model — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Save Model

                                        -
                                        -

                                        Overview

                                        -

                                        The model is the output of the training process. There are two -ways from which user can obtain a model:

                                        -
                                          -
                                        • Save model triggered by user code: user code asks PaddlePaddle to -save a model.
                                        • -
                                        • Convert model from the checkpoint: model being converted from -pservers’ periodic checkpoint. In this way, the user can cancel a -job at any time, and still have a relatively fresh model (we -checkpoint around every 5 minutes).
                                        • -
                                        -
                                        -

                                        Trainer Saving Model vs. Pservers Saving Model

                                        -

                                        Both trainers and pservers have access to the model. So the model can -be saved from a trainer or pservers. We need to decide where the model -is saved from.

                                        -
                                        -

                                        Dense Update vs. Sparse Update

                                        -

                                        There are two types of model update methods: dense update and sparse -update (when the model parameter is configured to be sparse).

                                        -
                                          -
                                        • Dense update

                                          -

                                          Every trainer has it’s own full copy of the model. Every model -update will update the entire model.

                                          -
                                        • -
                                        • Sparse update

                                          -

                                          The training input is sparse, and the trainer does not have the -entire model. It will only download the sub-model necessary related -to the input. When updating the model, only the sub-model related to -the training input is updated.

                                          -
                                        • -
                                        -
                                        -
                                        -

                                        Pservers Saving Model

                                        -

                                        The benefit of letting pservers save model is they have the entire -model all the time. However, since pservers are on different nodes, it -requires a merging process to merge model shards into the same -model. Thus requires the pservers to write models to a distributed -filesystem, making the checkpoint shards visible to the merge program.

                                        -
                                        -
                                        -

                                        Trainer Saving Model

                                        -

                                        The benefit of letting one trainer to save the model is it does not -require a distributed filesystem. And it’s reusing the same save model -logic when training locally - except when doing sparse update, the -trainer needs to download the entire model during the saving process.

                                        -
                                        -
                                        -

                                        Conclusion

                                        -

                                        Given trainer saving model does not require a distributed filesystem, -and is an intuitive extension to trainer saving model when training -locally, we decide to let the trainer save the model when doing -distributed training.

                                        -
                                        -
                                        -
                                        -

                                        Convert Model from Checkpoint

                                        -

                                        TODO

                                        -
                                        -
                                        -
                                        -

                                        Timeline

                                        -

                                        We first implement trainer save the model. Converting the latest -snapshot to a model will be a TODO for future.

                                        -
                                        -
                                        -

                                        Trainer Save Model

                                        -
                                        -

                                        Trainer Election

                                        -

                                        One trainer will be elected as the one to save the model. When using -etcd, trainer ID is a randomly generated UUID, the trainer will -contact the master server requesting to save the model, and find out -if itself is elected. When the master server is not used, unique -trainer IDs will be given by the administrator, the trainer whose ID -is “0” is elected to save the model.

                                        -
                                        -
                                        -

                                        Model Save Path

                                        -

                                        Each trainer will be given the directory to save the model. The -elected trainer will save the model to -given-directory/trainerID. Since the trainer ID is unique, this -would prevent concurrent save to the same file when multiple trainers -are elected to save the model when split-brain problem happens.

                                        -
                                        -
                                        -

                                        What Happens When Model Is Saving

                                        -

                                        It takes some time to save model, we need to define what will happen -when save model is taking place.

                                        -

                                        When doing dense update, the trainer uses the local model. Pservers -does not need to pause model update.

                                        -

                                        When doing sparse update. The trainer needs to download the entire -model while saving. To get the most accurate model, the model update -needs to be paused before the download starts and resumed after the -download finishes. Otherwise, the trainer gets a model that is -“polluted”: some part of the model is old, some part of the model is -new.

                                        -

                                        It’s unclear that the “polluted” model will be inferior due to the -stochastic nature of deep learning, and pausing the model update will -add more complexity to the system. Since supporting sparse update is a -TODO item. We defer the evaluation of pause the model update or not -during saving model to the future.

                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/cluster_train/submit-job.html b/develop/doc_cn/design/cluster_train/submit-job.html deleted file mode 100644 index 05aaeea8f68..00000000000 --- a/develop/doc_cn/design/cluster_train/submit-job.html +++ /dev/null @@ -1,397 +0,0 @@ - - - - - - - - - - - - - Submit a Distributed Training Job — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Submit a Distributed Training Job

                                        -

                                        The user can submit a distributed training job with Python code, rather than with a command-line interface.

                                        -
                                        -

                                        Runtime Environment On Kubernetes

                                        -

                                        For a distributed training job, there is two Docker image called runtime Docker image and base Docker image. The runtime Docker image is the Docker image that gets scheduled by Kubernetes to run during training. The base Docker image is for building the runtime Docker image.

                                        -
                                        -

                                        Base Docker Image

                                        -

                                        Usually, the base Docker image is PaddlePaddle product Docker image including paddle binary files and python package. And of course, users can specify any image name hosted on any docker registry which users have the access right.

                                        -
                                        -
                                        -

                                        Runtime Docker Image

                                        -

                                        The trainer package which user upload and some Python dependencies are packaged into a runtime Docker image based on base Docker image.

                                        -
                                          -
                                        • Handle Python Dependencies

                                          -

                                          You need to provide requirements.txt file in your trainer-package folder. Example:

                                          -
                                          pillow
                                          -protobuf==3.1.0
                                          -
                                          -
                                          -

                                          More details about requirements, an example project looks like:

                                          -
                                            paddle_example
                                          -    |-quick_start
                                          -      |-trainer.py
                                          -      |-dataset.py
                                          -      |-requirements.txt
                                          -
                                          -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Submit Distributed Training Job With Python Code

                                        -

                                        -
                                          -
                                        • paddle.job.dist_train() will call the Job Server API /v1/packages to upload the trainer package and save them on CephFS, and then call /v1/trainer/job to submit the PaddlePaddle distributed job.
                                        • -
                                        • /v1/trainer/job will start a building job for preparing the runtime Docker image. When the building job is finished, Job Server will submit the PaddlePaddle distributed job to Kubernetes.
                                        • -
                                        • NOTE: For the first version, we will not prepare the runtime Docker image, instead, the package is uploaded to Paddle Cloud, and Paddle Cloud will mount the package in a temporary folder into the base Docker image. We will not support custom Python dependencies in the first version as well.
                                        • -
                                        -

                                        You can call paddle.job.dist_train and provide distributed training configuration as the parameters:

                                        -
                                        paddle.job.dist_train(
                                        -  trainer=dist_trainer(),
                                        -  paddle_job=PaddleJob(
                                        -    job_name = "paddle-cloud",
                                        -    entry_point = "python %s"%__file__,
                                        -    trainer_package = "/example/word2vec",
                                        -    image = "yancey1989/paddle-job",
                                        -    trainers = 10,
                                        -    pservers = 3,
                                        -    trainer_cpu = 1,
                                        -    trainer_gpu = 1,
                                        -    trainer_mem = "10G",
                                        -    pserver_cpu = 1,
                                        -    pserver_mem = "2G"
                                        -  ))
                                        -
                                        -
                                        -

                                        The parameter trainer of paddle.job.dist_train is a function and you can implement it as follows:

                                        -
                                        def dist_trainer():
                                        -  def trainer_creator():
                                        -    trainer = paddle.v2.trainer.SGD(...)
                                        -    trainer.train(...)
                                        -  return trainer_creator
                                        -
                                        -
                                        -

                                        The pseudo code of paddle.job.dist_train is as follows:

                                        -
                                        def dist_train(trainer, paddle_job):
                                        -  # if the code is running on cloud, set PADDLE_ON_CLOUD=YES
                                        -  if os.getenv("RUNNING_ON_CLOUD", "NO") == "NO":
                                        -    #submit the paddle job
                                        -    paddle_job.submit()
                                        -  else:
                                        -    #start the training
                                        -    trainer()
                                        -
                                        -
                                        -
                                        -

                                        PaddleJob Parameters

                                        -

                                        parameter | type | explanation -— | — | — -job_name | str | the unique name for the training job -entry_point | str | entry point for startup trainer process -trainer_package | str | trainer package file path which user have the access right -image|str|the base image for building the runtime image -pservers|int| Parameter Server process count -trainers|int| Trainer process count -pserver_cpu|int| CPU count for each Parameter Server process -pserver_mem|str| memory allocated for each Parameter Server process, a plain integer using one of these suffixes: E, P, T, G, M, K -trainer_cpu|int| CPU count for each Trainer process -trainer_mem|str| memory allocated for each Trainer process, a plain integer using one of these suffixes: E, P, T, G, M, K -trainer_gpu|int| GPU count for each Trainer process, if you only want CPU, do not set this parameter

                                        -
                                        -
                                        -

                                        Deploy Parameter Server, Trainer and Master Process

                                        -
                                          -
                                        • Deploy PaddlePaddle Parameter Server processes, it’s a Kubernetes ReplicaSet.
                                        • -
                                        • Deploy PaddlePaddle Trainer processes, it’s a Kubernetes Job.
                                        • -
                                        • Deploy PaddlePaddle Master processes, it’s a Kubernetes ReplicaSet.
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Job Server

                                        -
                                          -
                                        • RESTful API

                                          -

                                          Job server provides RESTful HTTP API for receiving the trainer package and displaying -PaddlePaddle job related informations.

                                          -
                                            -
                                          • POST /v1/package receive the trainer package and save them on CephFS
                                          • -
                                          • POST /v1/trainer/job submit a trainer job
                                          • -
                                          • GET /v1/jobs/ list all jobs
                                          • -
                                          • GET /v1/jobs/<job-name> the status of a job
                                          • -
                                          • DELETE /v1/jobs/<job-name> delete a job
                                          • -
                                          • GET /v1/version job server version
                                          • -
                                          -
                                        • -
                                        • Build Runtime Docker Image on Kubernetes

                                          -

                                          paddle.job.dist_train will upload the trainer package to Job Server, save them on the distributed filesystem, and then start up a job for building the runtime Docker image that gets scheduled by Kubernetes to run during training.

                                          -

                                          There are some benefits for building runtime Docker image on JobServer:

                                          -
                                            -
                                          • On Paddle Cloud, users will run the trainer code in a Jupyter Notebook which is a Kubernetes Pod, if we want to execute docker build in the Pod, we should mount the host’s docker.sock to the Pod, user’s code will connect the host’s Docker Engine directly, it’s not safe.
                                          • -
                                          • Users only need to upload the training package files, does not need to install docker engine, docker registry as dependencies.
                                          • -
                                          • If we want to change another image type, such as RKT, users do not need to care about it.
                                          • -
                                          -
                                        • -
                                        • Deploy Parameter Server, Trainer and Master Processes

                                          -

                                          POST /v1/trainer/job receives the distributed training parameters, and deploy the job as follows:

                                          -
                                            -
                                          • Deploy PaddlePaddle Parameter Server processes, it’s a Kubernetes ReplicaSet.
                                          • -
                                          • Deploy PaddlePaddle Trainer processes, it’s a Kubernetes Job.
                                          • -
                                          • Deploy PaddlePaddle Master processes, it’s a Kubernetes ReplicaSet.
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/concurrent_programming.html b/develop/doc_cn/design/concurrent_programming.html deleted file mode 100644 index 9996b90bf67..00000000000 --- a/develop/doc_cn/design/concurrent_programming.html +++ /dev/null @@ -1,421 +0,0 @@ - - - - - - - - - - - - - Design Doc: Concurrent Programming with Fluid — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Concurrent Programming with Fluid

                                        -

                                        With PaddlePaddle Fluid, users describe a program other than a model. The program is a ProgramDesc protobuf message. TensorFlow/MxNet/Caffe2 applications generate protobuf messages too, but their protobuf messages represent the model, a graph of operators, but not the program that trains/uses the model.

                                        -

                                        Many know that when we program TensorFlow, we can specify the device on which each operator runs. This allows us to create a concurrent/parallel AI application. An interesting questions is how does a ProgramDesc represents a concurrent program?

                                        -

                                        The answer relies on the fact that a ProgramDesc is similar to an abstract syntax tree (AST) that describes a program. So users just program a concurrent program that they do with any concurrent programming language, e.g., Go.

                                        -
                                        -

                                        An Analogy

                                        -

                                        The following table compares concepts in Fluid and Go

                                        -

                                        | Go | Fluid | -|—-|——-| -|user-defined functions | layers | -| control-flow and built-in functions | intrinsics/operators | -| goroutines, channels | class ThreadPool | -| runtime | class Executor |

                                        -
                                        -
                                        -

                                        An Example Concurrent Program

                                        -

                                        To review all above concepts in an example, let us take a simple program and writes its distributed version.

                                        -

                                        Suppose that we want to parallelize a naive Fluid program (written in Go and calling Fluid’s Go binding) that multiplies two tensors.

                                        -
                                        import "fluid"
                                        -
                                        -func paddlepaddle() {
                                        -  X = fluid.read(...)
                                        -  W = fluid.Tensor(...)
                                        -  Y = fluid.mult(X, W)
                                        -}
                                        -
                                        -
                                        -

                                        Please be aware that the Fluid’s Go binding provides the default main function, which calls the paddlepaddle function, which, in this case, is defined in above program and creates the following ProgramDesc message.

                                        -
                                        message ProgramDesc {
                                        -  block[0] = Block {
                                        -    vars = [X, W, Y],
                                        -    ops = [
                                        -      read(output = X)
                                        -      assign(input = ..., output = W)
                                        -      mult(input = {X, W}, output = Y)
                                        -    ],
                                        -  }
                                        -}
                                        -
                                        -
                                        -

                                        Then, the default main function calls fluid.run(), which creates an instance of the class Executor and calls Executor.Run(block[0]), where block[0] is the first and only block defined in above ProgramDesc message.

                                        -

                                        The default main function is defined as follows:

                                        -
                                        func main() {
                                        -  paddlepaddle()
                                        -  fluid.run()
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -

                                        The Concurrent Version

                                        -

                                        By parallelizing the above program, we could support very big tensor X by splitting into small pieces {x_1, x_2, ...} and sent each piece to worker process/node for parallel multiplication.

                                        -

                                        In this case, we can write a transpiler that takes a ProgramDesc message that represents the above example program and outputs two ProgramDesc messages, one for running on the master process/node, and the other one for worker processes/nodes.

                                        -
                                        -

                                        The Master Program

                                        -

                                        The master program could look like the following:

                                        -
                                        message ProgramDesc {
                                        -  block[0] = Block {
                                        -    vars = [X, L, Y],
                                        -    ops = [
                                        -      read(output = X)
                                        -      kube_get_workers_addrs(output = L)
                                        -      Y = tensor_array(len(L))
                                        -      parallel_for(input = X, output = Y, 
                                        -                   attrs = {L, block_id(1)}) # referring to block 1
                                        -    ]
                                        -  }
                                        -  
                                        -  block[1] = Block {
                                        -    parent = 0,
                                        -    vars = [x, y, index],
                                        -    ops = [
                                        -      slice(input = [X, index], output = x) # index is initialized by parallel_for
                                        -      send(input = x, attrs = L[index])
                                        -      recv(outputs = y, attrs = L[index])
                                        -      assign(input = y, output = Y[index])
                                        -    ]
                                        -  }
                                        -}
                                        -
                                        -
                                        -

                                        The equivalent Fluid program (calling the Go binding) is:

                                        -
                                        func main() {  //// block 0
                                        -  X = fluid.read(...)
                                        -  L = fluid.k8s.get_worker_addrs()
                                        -  Y = fluid.tensor_array(len(L))
                                        -  fluid.parallel_for(X, L, 
                                        -                     func(index int) {  //// block 1
                                        -                       x = X[index]
                                        -                       fluid.send(L[index], x)
                                        -                       y = fluid.recv(L[index])
                                        -                       Y[index] = y
                                        -                     })
                                        -}
                                        -
                                        -
                                        -

                                        An explanation of the above program:

                                        -
                                          -
                                        • fluid.k8s is a package that provides access to Kubernetes API.
                                        • -
                                        • fluid.k8s.get_worker_addrs returns the list of IP and ports of all pods of the current job except for the current one (the master pod).
                                        • -
                                        • fluid.tensor_array creates a tensor array. fluid.parallel_for creates a ParallelFor intrinsic, which, when executed,
                                            -
                                          1. creates len(L) scopes, each for the concurrent running of the sub-block (block 1 in this case), and initializes a variable named “index” in the scope to an integer value in the range [0, len(L)-1], and
                                          2. -
                                          3. creates len(L) threads by calling into the ThreadPool singleton, each thread
                                              -
                                            1. creates an Executor instance, and
                                            2. -
                                            3. calls Executor.Run(block), where block is block 1 as explained above.
                                            4. -
                                            -
                                          4. -
                                          -
                                        • -
                                        -
                                          -
                                        1. Please be aware that block 1 is a sub-block of block 0, so ops in block 1 could refer to variables defined in block 0.
                                        2. -
                                        -
                                        -
                                        -

                                        The Worker Program

                                        -

                                        The worker program looks like

                                        -
                                        func main() {
                                        -  W = Tensor(...)
                                        -  x = fluid.listen_and_do(
                                        -        fluid.k8s.self_addr(),
                                        -        func(input Tensor) {
                                        -          output = fluid.mult(input, W)
                                        -        })
                                        -}
                                        -
                                        -
                                        -

                                        where

                                        -
                                          -
                                        • fluid.listen_and_do creates a ListenAndDo intrinsic, which, when executed,
                                            -
                                          1. listens on the current pod’s IP address, as returned by fliud.k8s.self_addr(),
                                          2. -
                                          3. once a connection is established,
                                              -
                                            1. creates a scope of two parameters, “input” and “output”,
                                            2. -
                                            3. reads a Fluid variable and saves it into “input”,
                                            4. -
                                            5. creates an Executor instance and calls Executor.Run(block), where the block is generated by running the lambda specified as the second parameter of fluid.listen_and_do.
                                            6. -
                                            -
                                          4. -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Summarization

                                        -

                                        From the above example, we see that:

                                        -
                                          -
                                        1. Fluid enables the imperative programming paradigm by:
                                            -
                                          1. letting users describe a program, but not a model (a sequence of layers, or a graph of operators), and
                                          2. -
                                          3. call the fluid.run function that runs the program implicitly.
                                          4. -
                                          -
                                        2. -
                                        3. The program is described as a ProgramDesc protobuf message.
                                        4. -
                                        5. Function Executor.Run takes a block, instead of a ProgramDesc, as its parameter.
                                        6. -
                                        7. fluid.run calls Executor.Run to run the first block in the ProgramDesc message.
                                        8. -
                                        9. Executor.Run‘s implementation is extremely simple – it doesn’t plan the execution nor create threads; instead, it runs on the current thread and execute intrinsics/operators’ Run method sequentially as they appear in the Block.ops array.
                                        10. -
                                        11. Intrinsics/operators’ Run method might create threads. For example, the ListenAndDo operator creates a thread to handle each incoming request.
                                        12. -
                                        13. Threads are not necessarily OS thread; instead, they could be green threads managed by ThreadPool. Multiple green threads might run on the same OS thread. An example green threads is Go’s goroutines.
                                        14. -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/cpp_data_feeding.html b/develop/doc_cn/design/cpp_data_feeding.html deleted file mode 100644 index d0f5160d917..00000000000 --- a/develop/doc_cn/design/cpp_data_feeding.html +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - C++ Data Feeding — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        C++ Data Feeding

                                        -

                                        In training with Paddle V2 API, data feeding wholly dependents on Python code. To get rid of the Python environment and achieve the goal of “wrapping the whole training by a while loop op” in Paddle Fluid, a C++ data feeding mechanism is required.

                                        -

                                        In this document we show the fundamental design of C++ data feeding process, which includes the data reading, shuffling and batching.

                                        -
                                        -

                                        Reader

                                        -

                                        A new concept named ‘Reader’ is introduced. Reader is a series of inherited classes which can be hold by our Variable and they are used to read or process file data.

                                        -
                                        -

                                        ReaderBase

                                        -

                                        ReaderBase is the abstract base class of all readers. It defines the all readers’ interfaces.

                                        -
                                        class ReaderBase {
                                        - public:
                                        -  explicit ReaderBase(const std::vector<DDim>& shapes) : shapes_(shapes) {
                                        -    PADDLE_ENFORCE(!shapes_.empty());
                                        -  }
                                        -  // Read the next batch of data. (A 'batch' can be only one instance)
                                        -  virtual void ReadNext(std::vector<LoDTensor>* out) = 0;
                                        -  // Show whether the next bacth exists.
                                        -  virtual bool HasNext() const = 0;
                                        -  
                                        -  // Reinitialize the reader and read the file from the begin.
                                        -  virtual void ReInit() = 0;
                                        -  
                                        -  // Get a certain read in data's shape.
                                        -  DDim shape(size_t idx) const;
                                        -  // Get shapes of all read in data.
                                        -  std::vector<DDim> shapes() const { return shapes_; }
                                        -  // Set shapes of read in data.
                                        -  void set_shapes(const std::vector<DDim>& shapes) { shapes_ = shapes; }
                                        -
                                        -  virtual ~ReaderBase() {}
                                        -
                                        - protected:
                                        -  std::vector<DDim> shapes_;
                                        -};
                                        -
                                        -
                                        -
                                        -
                                        -

                                        FileReader and DecoratedReader

                                        -

                                        These two classes are derived from the ReaderBase and will further be derived by respective specific readers. That is to say, in our design, there are two kinds of readers: file readers and decorated readers. A file reader reads from a file of some specific format, and yield only one instance of data at a time. e.g. RecordIO reader, jpg reader, .... A decorated reader takes another reader(both file reader and decorated reader are OK) as its ‘underlying reader’. It gets data from its underlying reader, does some process on them(shuffling, or batching), then yields processed data. The output data of a decorated reader can be a single instance or a batch. ShuffleReader and BatchReader are both decorated readers.

                                        -

                                        All the readers share exactly the same interfaces defined in ReaderBase. So they can be decorated for more than one time: We can shuffle a reader’s outputs and then batch the shuffle outputs. The interface consistency also allows related ops use readers without knowing what they are exactly.

                                        -
                                        -
                                        -

                                        ReaderHolder

                                        -

                                        Different readers belong to different class types. It leads to a problem: How can we drop them into Variables and fetch them out by a unified method? For example, if a Variable holds a BatchReader, we can not get it by the following code:

                                        -
                                        var->Get<ReaderBase>("batch_reader");
                                        -
                                        -
                                        -

                                        we have to write:

                                        -
                                        var->Get<BatchReader>("batch_reader");
                                        -
                                        -
                                        -

                                        This requires each time getting a reader from a variable we must know the reader’s type exactly. It is nearly impossible.

                                        -

                                        To solve this problem, we introduce ReaderHolder as a wrapper. It acts as an empty decorator of ReaderBase, which erases reader’s type. With ReaderHolder we are able to fetch all types of readers by var->Get<ReaderHolder>("...") and regard the obtained object as a reader.

                                        -
                                        -
                                        - -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/csp.html b/develop/doc_cn/design/csp.html deleted file mode 100644 index 3b43da3f4de..00000000000 --- a/develop/doc_cn/design/csp.html +++ /dev/null @@ -1,459 +0,0 @@ - - - - - - - - - - - - - Design Doc: CSP in PaddlePaddle Fluid — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: CSP in PaddlePaddle Fluid

                                        -
                                        -

                                        Motivation

                                        -

                                        Concurrent programming is important for deep learning. Few example applications are:

                                        -
                                          -
                                        1. The main thread keeps reading the next mini-batch while another thread uses the GPU for computing.
                                        2. -
                                        3. The main thread performs the computation while another thread uploads the local gradients from each trainer to the parameter server.
                                        4. -
                                        -

                                        Most DL systems, including TensorFlow, Caffe2, and MxNet, can asynchronously execute operators in a graph. However, Fluid doesn’t have the concept of a graph at all, as the design goal of Fluid is that of a programming language.

                                        -
                                        -
                                        -

                                        Concurrent Programming Models

                                        -

                                        There were many concurrent programming models, implemented in various forms:

                                        -

                                        | concurrent programming model | implementation | -|—–|—–| -| mutex | types and functions in standard libraries | -| semaphore | types and functions in standard libraries | -| communicating sequential processes (CSP) | Go programming language | -| actor model | Erlang programming language | -| message passing | MPI | -| bulk synchronous parallel (BSP) | Pregel distributed programming framework |

                                        -

                                        Since Fluid was designed to be a programming language, we would like to implement CSP in Fluid.

                                        -
                                        -

                                        CSP v.s. Actor Model

                                        -

                                        A well-known implementation of Actor Model is the Erlang programming language. In Actor Model, processes could send messages to another process and receive messages from another process given the process IDs. We can find the three ingredients, process with ID, send, and recv, in MPI too. Indeed, we can rewrite Erlang programs in Python + MPI with possibly fewer lines of code. Our concern with Actor Model is that it doesn’t seem reasonable to implement process management in a programming language’s runtime library; instead, it should be the operating systems’ responsibility to manage processes and libraries like MPI for send/recv.

                                        -
                                        -
                                        -
                                        -

                                        CSP in Fluid

                                        -

                                        Fluid has two fundamental control-flows: if-else and while. If we are to implement CSP, we need the following:

                                        -
                                          -
                                        1. a new data type: channel and operators send and recv,
                                        2. -
                                        3. goroutine or thread, and
                                        4. -
                                        5. a new control-flow: select.
                                        6. -
                                        -

                                        We also need Python wrappers for the above components.

                                        -

                                        The type channel is conceptually the blocking queue. In Go, its implemented is a blocking circular queue, which supports send and recv.

                                        -

                                        The select operation has been in OS kernels long before Go language. All Unix kernels implement system calls poll and select. They monitor multiple file descriptors to see if I/O is possible on any of them. This takes O(N) time. Since Linux 2.6, a new system call, epoll, can do the same in O(1) time. In BSD systems, there is a similar system call kqueue. Go’s Linux implementation uses epoll.

                                        -

                                        It might be a good idea to implement Fluid’s select using epoll too. In this design doc, we start from the O(N) way so that we could focus on Python binding and the syntax.

                                        -
                                        -

                                        Type Channel

                                        -

                                        Fluid supports many data types:

                                        -
                                          -
                                        1. Tensor,
                                        2. -
                                        3. Row-sparse Tensor
                                        4. -
                                        5. LoD Tensor,
                                        6. -
                                        7. Tensor array, etc
                                        8. -
                                        -

                                        Each data type is registered in the framework.proto as an enum value. To add a new type channel, we need to add a new type enum.

                                        -

                                        To expose a C++ type to Python, we need to edit the pybind.cc file. Here is an example how we expose C++ class LoDTensor.

                                        -
                                        -
                                        -
                                        -

                                        Syntax Design

                                        -
                                        -

                                        Create Channel

                                        -

                                        In Go, we create a channel by specifying the element type and buffer size:

                                        -
                                        ch  := make(chan int)       // a channel without buffer
                                        -ch1 := make(chan int, 100)  // a channel that can buffer 100 ints.
                                        -
                                        -
                                        -

                                        In Fluid, we should be able to do the same:

                                        -
                                        ch  = fluid.make_channel(dtype=INT)
                                        -ch1 = fluid.make_channel(dtype=INT, 100)
                                        -
                                        -
                                        -

                                        In addition to that, we want channels that can hold more complex element types, e.g., Tensors of float16:

                                        -
                                        ch = fluid.make_channel(dtype=Tensor, etype=float16)
                                        -
                                        -
                                        -

                                        or Tensors of Tensors of float16 etc.

                                        -

                                        The point here is that we need a consistent way to compose types, like in C++ we can have Tensor<Tensor<...<float16>...> >.

                                        -
                                        -
                                        -

                                        Send and Recv

                                        -

                                        Go’s CSP implementation depends on data type channel. There are two types of channels:

                                        -
                                          -
                                        1. The unblocked channel, or buffered channel, is a blocking queue with a non-zero sized buffer. The sending to buffered channel blocks if the buffer is full, and the receive operation blocks if the buffer is empty.
                                        2. -
                                        3. blocked channel, or unbuffered channel, is a blocking queue with no buffer. Both sending and receiving block with unbuffered channels.
                                        4. -
                                        -

                                        There are four types of actions with a channel:

                                        -
                                          -
                                        1. Create a channel

                                          -
                                          ch := make(chan int) // this is an unbuffered channel
                                          -ch := make(chan int, 100) // this is a buffered channel of 100 ints.
                                          -
                                          -
                                          -
                                        2. -
                                        3. Send

                                          -
                                          ch <- 111
                                          -
                                          -
                                          -
                                        4. -
                                        5. Recv

                                          -
                                          y, ok <- ch
                                          -
                                          -
                                          -
                                        6. -
                                        7. Close

                                          -
                                          close(ch)
                                          -
                                          -
                                          -

                                          Please be aware that a closed channel is not a nil channel, which is var ch chan int.

                                          -
                                        8. -
                                        -

                                        There are some axioms with channels:

                                        -
                                          -
                                        1. A send to a nil channel blocks forever
                                        2. -
                                        3. A receive from a nil channel blocks forever
                                        4. -
                                        5. A send to a closed channel panics
                                        6. -
                                        7. A receive from a closed channel returns the residual values and then zeros.
                                        8. -
                                        -

                                        In Fluid, we have buffered channels and unbuffered channels

                                        -

                                        The following program illustrates the Python syntax for accessing Fluid buffers.

                                        -
                                        import fluid
                                        -
                                        -buffer_size = 10
                                        -ch = fluid.make_channel(dtype=INT, buffer_size)
                                        -
                                        -# Now write three elements to the channel
                                        -with fluid.while(steps=buffer_size):
                                        -  fluid.send(ch, step)
                                        -
                                        -fluid.close_channel(ch)
                                        -
                                        -with fluid.while(steps=buffer_size):
                                        -  fluid.print(fluid.recv(ch))
                                        -
                                        -
                                        -

                                        The following example shows that to avoid the always-blocking behavior of unbuffered channels, we need to use Fluid’s goroutines.

                                        -
                                        import fluid
                                        -
                                        -ch = fluid.make_channel(dtype=INT)
                                        -
                                        -with fluid.go():
                                        -  fluid.send(ch)
                                        -
                                        -y = fluid.recv(ch)
                                        -
                                        -fluid.close_channel(ch)
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Select

                                        -

                                        In Go, the select statement lets a goroutine wait on multiple communication operations. A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.

                                        -
                                        ch1  := make(chan int)       
                                        -ch2  := make(chan int, 100)
                                        -
                                        -x := 0
                                        -
                                        -for {
                                        -    select {
                                        -    case ch1 <- x:
                                        -      x := x + 1
                                        -    case y <- ch2:
                                        -      fmt.Println("Received on channel")
                                        -    default:
                                        -      fmt.Println("Default")
                                        -    }
                                        -  }
                                        -
                                        -
                                        -

                                        In Fluid, we should be able to do the same:

                                        -
                                        ch1  = fluid.make_chan(dtype=INT)
                                        -ch2 = fluid.make_chan(dtype=INT, 100)
                                        -
                                        -sel = fluid.select()
                                        -
                                        -with sel.case(ch1, 'w', X):
                                        -    fluid.layers.increment(X)
                                        -
                                        -with sel.case(ch2, 'r', Y):
                                        -    fluid.print("Received on Channel")
                                        -
                                        -with sel.default():
                                        -    fluid.print("Default")
                                        -
                                        -
                                        -
                                        -

                                        In the above code snippet, X and Y are variables. Now let us look at each of these statements one by one.

                                        -
                                          -
                                        • sel.case(ch1, 'w', X) : This specifies that we are writing to ch1 and we want to write the integer in variable X to the channel. The character w is used here to make the syntax familiar to write syntax in Python I/O.
                                        • -
                                        • sel.case(ch2, 'r', Y) : This specifies that we would like to read the result from ch2 into variable Y. The character r is used here to make the syntax familiar to read syntax in Python I/O.
                                        • -
                                        • sel.default() : This is equivalent to the default in Go select. If none of the channels are ready for read or write, then the fluid code in the default block will be executed.
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Example Programs

                                        -
                                        -

                                        1. RPC between Trainers and Parameter Servers

                                        -
                                        -
                                        -

                                        2. Concurrent Minibatch Loading

                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/dist_refactor/distributed_architecture.html b/develop/doc_cn/design/dist_refactor/distributed_architecture.html deleted file mode 100644 index 99c2c2ab628..00000000000 --- a/develop/doc_cn/design/dist_refactor/distributed_architecture.html +++ /dev/null @@ -1,432 +0,0 @@ - - - - - - - - - - - - - Design Doc: Distributed Training Architecture — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Distributed Training Architecture

                                        -
                                        -

                                        Abstract

                                        -

                                        PaddlePaddle version 0.10.0 uses the “trainer-parameter server” architecture. We run multiple instances of trainers (where each trainer runs the same model) and parameter servers for distributed training. This architecture serves well, but has few limitations:

                                        -
                                          -
                                        1. There is a need to write special code that handles tasks which should only be run on a single trainer. E.g., initializing the model, saving the model etc.
                                        2. -
                                        3. Model parallelism is hard: It would need all the if-else branches conditioned on the trainer ID to partition the model onto the trainers, and eventually manually writing out the inter-model-shard communication code to communicate between different trainers.
                                        4. -
                                        5. The user can not directly specify the parameter update rule: This would need to modify the parameter server code and compile a new binary. This makes things more complicated for researchers: A lot of extra effort is required to make this work. Besides, the training job submission program may not allow running arbitrary binaries.
                                        6. -
                                        -

                                        This design doc discusses PaddlePaddle’s new distributed training architecture that addresses the above mentioned limitations.

                                        -
                                        -
                                        -

                                        Analysis

                                        -

                                        The assumption is that the user writes the trainer program in either Python or C++.

                                        -
                                        -

                                        Limitation 1

                                        -

                                        There are two basic functionalities in the trainer program:

                                        -
                                          -
                                        1. The training logic such as loading / saving the model and printing out the logs.
                                        2. -
                                        3. The neural network definition such as the definition of the data layer, the fully connected layer, the cost function and the -optimizer.
                                        4. -
                                        -

                                        When we train using PaddlePaddle v0.10.0 in a distributed fashion, multiple instances of the same Python code are run on different nodes, hence both: the -training logic as well as the neural network computation logic, is replicated.

                                        -

                                        The tasks that only need to be run once belong to the training logic. Hence if we only replicate the neural network computation part, and do not -replicate the training logic, the limitation mentioned above can be avoided.

                                        -
                                        -
                                        -

                                        Limitation 2

                                        -

                                        Model parallelism means that a single model is partitioned into different components and each node runs one of the component separately. This comes at the extra cost of managing the -inter-model-shard communication between nodes.

                                        -

                                        PaddlePaddle should ideally be able to modify the neural network computation and figure out the support for model parallelism automatically. However, the -computation is only specified in Python code which sits outside of PaddlePaddle, hence PaddlePaddle can not support the feature in this setup.

                                        -

                                        Similar to how a compiler uses an intermediate representation (IR) so that the programmer does not need to manually optimize their code for most of the cases, we can have an intermediate representation in PaddlePaddle as well. The compiler optimizes the IR as follows:

                                        -

                                        -

                                        PaddlePaddle can support model parallelism by converting the IR so that the user no longer needs to manually perform the computation and operations in the Python component:

                                        -

                                        -

                                        The IR for PaddlePaddle after refactoring is called a Block, it specifies the computation dependency graph and the variables used in the computation.

                                        -
                                        -
                                        -

                                        Limitation 3

                                        -

                                        The user can not directly specify the parameter update rule for the parameter server in the Python module, since the parameter server does not use the same computation definition as the trainer. Instead, the update rule is baked inside the parameter server. The user can not specify the update rule explicitly.

                                        -

                                        This could be fixed by making the parameter server also run an IR, which can be different to the trainer side -For a detailed explanation, refer to this document - -Design Doc: Parameter Server

                                        -
                                        -
                                        -
                                        -

                                        Distributed Training Architecture

                                        -

                                        The revamped distributed training architecture can address the above discussed limitations. Below is the illustration of how it does so:

                                        -

                                        -

                                        The major components are: Python API, Distribute Transpiler and Remote Executor.

                                        -
                                        -

                                        Python API

                                        -

                                        Python API is the Python library that user’s Python code invokes, to read the data, build the neural network topology, and start training, etc.

                                        -
                                        images = fluid.layers.data(name='pixel', shape=[1, 28, 28], dtype='float32')
                                        -label = fluid.layers.data(name='label', shape=[1], dtype='int64')
                                        -...
                                        -predict = fluid.layers.fc(input=conv_pool_2, size=10, act="softmax")
                                        -cost = fluid.layers.cross_entropy(input=predict, label=label)
                                        -avg_cost = fluid.layers.mean(x=cost)
                                        -optimizer = fluid.optimizer.Adam(learning_rate=0.01)
                                        -optimizer.minimize(avg_cost)
                                        -
                                        -train_reader = paddle.batch(
                                        -    paddle.reader.shuffle(
                                        -        paddle.dataset.mnist.train(), buf_size=500),
                                        -    batch_size=BATCH_SIZE)
                                        -
                                        -place = fluid.CPUPlace()
                                        -exe = fluid.Executor(place)
                                        -
                                        -for pass_id in range(10):
                                        -    for data in train_reader():
                                        -        loss, acc = exe.run(trainer_prog,
                                        -                            feed=feeder.feed(data),
                                        -                            fetch_list=[avg_cost])
                                        -
                                        -
                                        -

                                        The code above is a typical local training program, the “Training Program” is built using helper functions such as -fluid.layer.fc. The training is done by calling Executor.run -iteratively.

                                        -

                                        For more details, the implementation of IR is Program, and ProgramDesc is the protobuf type.

                                        -

                                        Executor simply runs the ProgramDesc. For local training you generally use -Executor to run the program locally. For any kind of distributed training, you can use -RemoteExecutor to specify desired distributed training method with some optional arguments.

                                        -
                                        -
                                        -

                                        Distributed Transpiler

                                        -

                                        The Distributed Transpiler automatically converts the IR (in protobuf format) to partitioned IRs. Then -the Remote Executor dispatches the new IRs to Remote Executors across the cluster. -Below are the steps that are followed :

                                        -
                                          -
                                        1. User only need to change Executor to RemoteExecutor to change local program to distributed program.
                                        2. -
                                        3. RemoteExecutor calls Distributed Transpiler to “transpile” user’s program to several IRs representing a -distributed training program:
                                            -
                                          1. Parse configurations from RemoteExecutor.
                                          2. -
                                          3. Determine the type of distributed program, can be DataParallelism, ModelParallelism or Streaming.
                                          4. -
                                          5. Partition the ProgramDesc according to type and add send / recv OP pair on the boundaries. Take -DataParallelism type for example, it removes the optimization operators and add a send OP to the -“trainer” role, then add the optimization operators to the parameter server role within the recv OP.
                                          6. -
                                          -
                                        4. -
                                        5. Dispatch the partitioned graph to different RemoteExecutor in the cluster.
                                        6. -
                                        7. RemoteExecutor on each node run the received ProgramDesc utill the end.
                                        8. -
                                        -
                                        -
                                        -

                                        RemoteExecutor

                                        -

                                        As shown in the graph, RemoteExecutor.run sends the IR to the cluster for Execution. -You can also use parameter fetch_list to interactively fetch variable back to local for -log printing.

                                        -

                                        The Python RemoteExecutor is derived from Executor class.

                                        -
                                        exe = RemoteExecutor(
                                        -    feed=feeder.feed(data),
                                        -    fetch_list=[avg_cost],
                                        -    job_desc=JobDesc(
                                        -      jobname,
                                        -      num_trainer,
                                        -      num_pserver,
                                        -      cpu_per_trainer,
                                        -      gpu_per_trainer,
                                        -      mem_per_trainer,
                                        -      cpu_per_pserver,
                                        -      mem_per_pserver
                                        -    ))
                                        -for data in train_reader():
                                        -    loss, acc = exe.run(trainer_prog,
                                        -                        feed=feeder.feed(data),
                                        -                        fetch_list=[avg_cost])
                                        -
                                        -
                                        -

                                        JobDesc object describe the distributed job resource specification to run on -Cluster environment.

                                        -

                                        -

                                        RemoteExecutor.run sends the ProgramDesc and -TrainingJob -to a server in the cluster which executes RemoteExecutor.listen. This server is responsible -to start the final Kubernetes Jobs to run the different role of ProgramDesc from ConfigMap.

                                        -
                                        -
                                        -

                                        Placement Algorithm

                                        -

                                        Our first implementation will only support “trainer-parameter server” placement: the parameters, initializers, and optimizers are all placed on the PaddlePaddle runtimes with the parameter server role. Everything else will be placed on the PaddlePaddle runtimes with the trainer role. This has the same functionality as the “trainer-parameter server” architecture of PaddlePaddle v0.10.0, but is more generic and flexible.

                                        -

                                        In the future, a more general placement algorithm should be implemented, which makes placements according to the input IR, and a model of device computation time and device communication time. Model parallelism requires the generic placement algorithm.

                                        -
                                        -
                                        -

                                        Local Training Architecture

                                        -

                                        The local training architecture will be the same as the distributed training architecture, the difference is that everything runs locally, and there is just one PaddlePaddle runtime:

                                        -

                                        -
                                        -
                                        -

                                        Training Data

                                        -

                                        In PaddlePaddle v0.10.0, training data is typically read -with data reader from Python. This approach is -no longer efficient when training distributedly since the Python -process no longer runs on the same node with the trainer processes, -the Python reader will need to read from the distributed filesystem -(assuming it has the access) and send to the trainers, doubling the -network traffic.

                                        -

                                        When doing distributed training, the user can still use Python data -reader: the training data are sent with Executor.run. However, should -be used for debugging purpose only. The users are encouraged to use -the read data OPs.

                                        -
                                        -
                                        - -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/dist_refactor/multi_cpu.html b/develop/doc_cn/design/dist_refactor/multi_cpu.html deleted file mode 100644 index 3573981c48a..00000000000 --- a/develop/doc_cn/design/dist_refactor/multi_cpu.html +++ /dev/null @@ -1,314 +0,0 @@ - - - - - - - - - - - - - Design Doc: Execute the Program with Multi CPU — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Execute the Program with Multi CPU

                                        -
                                        -

                                        Abstract

                                        -

                                        This Design Doc propose an approach to make the user-defined Op graph -running with multi-CPU, we will use an auto transpiler to convert the user-defined -Op graph to a multi-CPU Op graph, and run ParallelDo Op to run the graph.

                                        -
                                        -
                                        -

                                        Transpiler

                                        -

                                        -

                                        After converted:

                                        -

                                        -
                                        -
                                        -

                                        Implement

                                        -
                                          -
                                        • Multi-CPU Transpiler will convert the graph to a multi-CPU graph -which would be executed with multi-threads.

                                          -
                                        • -
                                        • BlockingCounter will Init/Decrement an atomic counter, and Blocking Wait -for the atomic counter become 0:

                                          -
                                          BlockingCounter bc(thread_count);
                                          -for (int i = 0; i < thread_count; ++i) {
                                          -  thread_pool->Start([&bc] {bc.DecrementCount(); })
                                          -}
                                          -bc.Wait();
                                          -
                                          -
                                          -
                                        • -
                                        • ParallelDo Operator

                                          -
                                            -
                                          • Initialize a thread pool which is a Singleton.
                                          • -
                                          • Use a block id as the input, and create run the specify Block on independent scope -with multi-threads.
                                          • -
                                          • Initialize a BlockingCounter instance and wait until all threads are done.
                                          • -
                                          -
                                        • -
                                        • Split Operator will split the Input Tensor into a TensorArray.

                                          -
                                        • -
                                        • Merge merge all the gradients which calculated in different threads -with mean/sum/max/min... method, and then run the Optimizer Op to optimize W.

                                          -
                                        • -
                                        -
                                        -
                                        -

                                        TODO

                                        -
                                          -
                                        • Improve the optimizer stage with multi-threads, since we could -assign the parameters to the different threads and execute -optimizer with multi-threads.
                                        • -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/dist_refactor/parameter_server.html b/develop/doc_cn/design/dist_refactor/parameter_server.html deleted file mode 100644 index c3583de4ad8..00000000000 --- a/develop/doc_cn/design/dist_refactor/parameter_server.html +++ /dev/null @@ -1,362 +0,0 @@ - - - - - - - - - - - - - Design Doc: Parameter Server — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Parameter Server

                                        -
                                        -

                                        Abstract

                                        -

                                        We propose an approach to implement the parameter server. In this -approach, there is no fundamental difference between the trainer and -the parameter server: they both run subgraphs, but subgraphs of -different purposes.

                                        -
                                        -
                                        -

                                        Background

                                        -

                                        The previous implementations of the parameter server do not run a -fluid sub-program. Parameter initialization, optimizer computation, network -communication and checkpointing are implemented twice on both the -trainer as well as the parameter server.

                                        -

                                        It would be great if we can write code once and use them on both: the -trainer and the parameter server, since this reduces code duplication and -improves extensibility. Given that after the current refactoring, we are -representing everything as a computation graph on the -trainer. Representing everything as a computation graph on the parameter -server becomes a natural extension.

                                        -
                                        -
                                        -

                                        Design

                                        -
                                        -

                                        Distributed Transpiler

                                        -

                                        The Distributed Transpiler converts the user-defined fluid program -into sub-programs to be scheduled on different nodes with the following -steps:

                                        -
                                          -
                                        1. OP placement: the OPs will be placed on different nodes according -to a heuristic that minimizes the estimated total computation -time. Currently we will use a simple heuristic that puts parameter -variable on parameter server workers and everything else on trainer -workers.
                                        2. -
                                        3. Add communication OPs to enable the communication between nodes.
                                        4. -
                                        -

                                        We will need these OPs: Send, Recv, Enqueue, Dequeue.

                                        -

                                        Below is an example of converting the user defined graph to the -subgraphs for the trainer and the parameter server:

                                        -

                                        -

                                        After converting:

                                        -

                                        -
                                          -
                                        1. The parameter variable W and its optimizer program are placed on the parameter server.
                                        2. -
                                        3. Operators are added to the program.
                                            -
                                          • Send sends data to the connected Recv operator. The -scheduler on the receive node will only schedule Recv operator -to run when the Send operator has ran (the Send OP will mark -the Recv OP runnable automatically).
                                          • -
                                          • Enqueue enqueues the input variable, it can block until space -become available in the queue.
                                          • -
                                          • Dequeue outputs configurable numbers of tensors from the -queue. It will block until the queue has the required number of -tensors.
                                          • -
                                          -
                                        4. -
                                        -
                                        -
                                        -

                                        Benefits

                                        -
                                          -
                                        • Model parallelism becomes easier to implement: it is an extension to -the trainer - parameter server approach. We can have several “Transpilers” -to achieve different goals.
                                        • -
                                        • User-defined optimizer is easier to add - user can now express it as -a sub-program.
                                        • -
                                        • No more duplication logic inside the trainer and the parameter -server mentioned in the background section.
                                        • -
                                        -
                                        -
                                        -

                                        Challenges

                                        -
                                          -
                                        • It is important to balance the parameter shards on multiple -parameter servers. If a single parameter is very big (for example: some -word-embedding, fully connected, softmax layer), we need to -automatically partition the single parameter onto different -parameter servers when possible (only element-wise optimizer depends -on the parameter variable).
                                        • -
                                        • In the “Async SGD” figure, the “W” variable on the parameter server -could be read and written concurrently. See -here for more -details about concurrent program in Fluid.
                                        • -
                                        -
                                        -
                                        -

                                        Discussion

                                        -
                                          -
                                        • Can the Enqueue OP be implemented under our current tensor design -(put the input tensor into the queue tensor)?
                                        • -
                                        • Dequeue OP will have variable numbers of output (depending on the -min_count attribute), does our current design support it? (similar -question for the Add OP)
                                        • -
                                        -
                                        - -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/error_clip.html b/develop/doc_cn/design/error_clip.html deleted file mode 100644 index f6054af0bec..00000000000 --- a/develop/doc_cn/design/error_clip.html +++ /dev/null @@ -1,340 +0,0 @@ - - - - - - - - - - - - - Error Clip — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Error Clip

                                        -
                                        -

                                        Overview

                                        -

                                        Error clip is widely used in model training to prevent gradient exploding. It takes some specific rules to adjust variables’ gradients and prevent them from being too large. With it, values of a gradient will be checked before they are taken by the next grad_op and be shrunk if necessary.

                                        -
                                        -
                                        -

                                        Usage

                                        -

                                        Users are allowed to assign different error clip methods or attributes to different Variables. Users can specify it as a parameter of Variable‘s constructor:

                                        -
                                        var = framework.Variable(..., error_clip=myErrorClip, ...)
                                        -
                                        -
                                        -

                                        The default value of error_clip is None, which means no error clip is employed. When it’s not None, it should take an object of BaseErrorClipAttr‘s derived class. So far, BaseErrorClipAttr has only one derived class: ErrorClipByValue, whose constructor is:

                                        -
                                        ErrorClipByValue(max, min=None)
                                        -
                                        -
                                        -

                                        max and min represent the maximal and minimal clip threshold respectively. In backward pass, all values of var‘s gradient greater than max or less than min will be clipped to max and min respectively. When the min is None, the minimal threshold will be assigned with -max automatically.

                                        -

                                        So we can enable the error clip with threshold [-5.0, 5.0] for variable var by:

                                        -
                                        var = framework.Variable(..., error_clip=ErrorClipByValue(max=5.0), ...)
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Implementation

                                        -

                                        The BaseErrorClipAttr and its derived class ErrorClipByValue are defined in clip.py.

                                        -
                                        class BaseErrorClipAttr(object):
                                        -    def append_clip_op(self, block, grad_name):
                                        -        raise NotImplementedError()
                                        -
                                        -
                                        -class ErrorClipByValue(BaseErrorClipAttr):
                                        -    def __init__(self, max, min=None):
                                        -        max = float(max)
                                        -        if min is None:
                                        -            min = -max
                                        -        else:
                                        -            min = float(min)
                                        -        self.max = max
                                        -        self.min = min
                                        -
                                        -    def append_clip_op(self, block, grad_name):
                                        -        clip_op_desc = block.desc.append_op()
                                        -        clip_op_desc.set_type("clip")
                                        -        clip_op_desc.set_input("X", [grad_name])
                                        -        clip_op_desc.set_output("Out", [grad_name])
                                        -        clip_op_desc.set_attr("min", self.min)
                                        -        clip_op_desc.set_attr("max", self.max)
                                        -
                                        -
                                        -

                                        The BaseErrorClipAttr have one main member functions: append_clip_op(self, block, grad_name).

                                        -

                                        This function is used to create a clip_op and append it to the end of given block. For different error clip algorithm require different clip_op, the function is defined as virtual in the base class. All derived classes must implement their own versions of this function.

                                        -

                                        These clip_ops should be inserted after grad_ops whose output gradients need to be clipped. It is equivalent to appending some clip_ops to the end of the target block every time a new grad_op is added.

                                        -
                                        for op_desc in grad_op_descs:
                                        -        new_op_desc = target_block.desc.append_op()
                                        -        new_op_desc.copy_from(op_desc)
                                        -        callback(block=target_block, context=grad_to_var)
                                        -
                                        -
                                        -

                                        Here we employ a callback function to complete this kind of jobs. In _append_backward_ops_ function, each time after a grad_op is added to the target_block, a callback function is invoked. The logic of clip_op appending can be implemented inside the callback function.

                                        -

                                        The callback function for clip_op appending is defined in clip.py:

                                        -
                                        def error_clip_callback(block, context):
                                        -    # the context is a grad_to_var map
                                        -    grad_to_var = context
                                        -    op_desc = block.desc.op(block.desc.op_size() - 1)
                                        -    for grad_n in filter(lambda n: grad_to_var.has_key(n),
                                        -                         op_desc.output_arg_names()):
                                        -        fwd_var = block.var_recursive(grad_to_var[grad_n])
                                        -        error_clip = getattr(fwd_var, "error_clip", None)
                                        -        if not (error_clip is None or isinstance(error_clip,
                                        -                                                 BaseErrorClipAttr)):
                                        -            raise TypeError(
                                        -                "Variable's error_clip should be an instance of BaseErrorClipAttr or None."
                                        -            )
                                        -        if error_clip is not None:
                                        -            error_clip.append_clip_op(block, grad_n)
                                        -
                                        -
                                        -

                                        This function takes a block and a context(which is actually a grad_to_var map) as inputs. It checks each output of the last OpDesc in the block. Notice that the last OpDesc of the block must be a grad_op and its outputs must be some forward variables’ gradients. If an output gradient’s corresponding forward variable has an attribute of error_clip, error_clip_callback will call the error_clip‘s append_clip_op function to append the required clip_op into the block.

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/evaluator.html b/develop/doc_cn/design/evaluator.html deleted file mode 100644 index 938b2de2417..00000000000 --- a/develop/doc_cn/design/evaluator.html +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - Evaluator Design — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Evaluator Design

                                        -
                                        -

                                        Problem Statement

                                        -

                                        During training or inference, we provide an evaluation function to measure the model performance, for example, accuracy, precision, etc. In the operator based framework design, the data passes through the network pipeline batch by batch. As a result, inside the operator, we only calculate the metrics for one minibatch. Thus, we need to provide a mechanism to calculate the metrics for each N pass/batch the user wants.

                                        -
                                        -
                                        -

                                        Evaluator Design

                                        -

                                        Currently, every operation is expressed in the graph. We divide the evaluator process into three steps.

                                        -
                                          -
                                        1. Initialize the metric state and add it into the block.
                                        2. -
                                        3. Calculate the concerned metrics for every mini-batch. The single evaluator operator is only responsible for calculating the necessary statistics for one mini-batch. For example, the accuracy operator only calculates the accuracy for a minibatch data if run once.
                                        4. -
                                        -
                                          -
                                        1. Merge the mini-batch statistics to form the evaluation result for multiple mini-batches. When it comes to distributed training/Multi-GPU training, aggregate the value from different devices.
                                        2. -
                                        -
                                        -
                                        -

                                        Implementation

                                        -

                                        This design is shown in the Python API. -Each metric operator needs to caculate the metric statistic and return the batch-aware states. Python side is responsible for accumulating the states for each pass.

                                        -
                                        class Evaluator(object):
                                        -    """
                                        -    Evaluator Base class.
                                        -    """
                                        -    def __init__(self, name, **kwargs):
                                        -       """
                                        -       Different evaluator may has different metric states. E.g, Accuracy need two variables, total and right sample counts.
                                        -       Auc need four variables, `true_positives`,
                                        -         `true_negatives`, `false_positives` and `false_negatives`. So every evaluator should create its needed variables and append to main_program
                                        -
                                        -       The initialization of Evaluator should be responsible for:
                                        -       create metric states and append to the main_program
                                        -       """ 
                                        -       pass
                                        -
                                        -    def _update_ops(self, input, label, **kwargs)
                                        -       """
                                        -       Add mini-batch evaluator caculate operators to the main_program.
                                        -       Add increment operator to accumulate the metric states.
                                        -       """
                                        -    
                                        -
                                        -    def reset(self, executor, reset_program=None):
                                        -      """
                                        -      Reset metric states at the begin of each pass/user specified batch number.
                                        -      Execute the reset_program to reset the states.
                                        -      """
                                        -      
                                        -
                                        -    def eval(self, executor, eval_program=None):
                                        -      """
                                        -      Merge the mini-batch statistics to form the evaluation result for multiple mini-batches.
                                        -      Execute the eval_program and return the result.
                                        -      """
                                        -      return eval_result
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/executor.html b/develop/doc_cn/design/executor.html deleted file mode 100644 index c452460306c..00000000000 --- a/develop/doc_cn/design/executor.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - - - - - - - - - Executor Design Doc — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Executor Design Doc

                                        -
                                        -

                                        Motivation

                                        -

                                        In fluid, we encourage the user to use deep learning programming paradigms to describe the training process. When the user-written Python program is executed, it will first create a protobuf message -ProgramDesc that describes the process and is conceptually like an abstract syntax tree.

                                        -

                                        The executor runs the ProgramDesc like an interpreter. ProgramDesc contains the intrinsics (operators in this case) and variables which will be used, executor explicitly executes the stored precompiled code.

                                        -
                                        -
                                        -

                                        Overview

                                        -

                                        An executor takes a ProgramDesc, a block_id and a Scope. The ProgramDesc is a list of blocks and each block contains the protobuf definition of all the parameters and operators in the block. The block_id specifies the entrance block. And the Scope is the container of all the variable instances, which is persistent throughout different runs.

                                        -
                                        -
                                        -

                                        Executor

                                        -

                                        The Executor explicitly executes all the intrinsics (operators here) in the block_idth block of a ProgramDesc. Essentially, it instantiates Variables and Operators, then runs all the operators in sequence one-by-one. -It is very similar to how a push stack frame works when entering a block, following which it cleans up all the temporary variables when a mini-batch is finished. It does not however, have the stack frame pop process.

                                        -
                                        -

                                        The interface

                                        -
                                          Executor(places);
                                        -
                                        -
                                        -

                                        A executor does not own any computing resources, a user can only construct an executor using the specified places.

                                        -
                                        -
                                        -

                                        Running an Executor

                                        -
                                          void Run(ProgramDesc, Scope, block_id, create_local_scope);
                                        -
                                        -
                                        -

                                        An Executor only provides a unified way to execute ProgramDesc. ProgramDesc is the target that will be executed, the Scope specifies the variable container, the block_id indicates the entrance block and create_local_scope is a boolean that states whether it will destroy the temporary variables after the execution is finished.

                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/file_manager/README.html b/develop/doc_cn/design/file_manager/README.html deleted file mode 100644 index d0345f86ab0..00000000000 --- a/develop/doc_cn/design/file_manager/README.html +++ /dev/null @@ -1,373 +0,0 @@ - - - - - - - - - - - - - FileManager设计文档 — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        FileManager设计文档

                                        -
                                        -

                                        目标

                                        -

                                        在本文档中,我们设计说明了名为FileManager系统,方便用户上传自己的训练数据以进行分布式训练

                                        -

                                        主要功能包括:

                                        -
                                          -
                                        • 提供常用的命令行管理命令管理文件和目录
                                        • -
                                        • 支持大文件的断点上传、下载
                                        • -
                                        -
                                        -
                                        -

                                        名词解释

                                        -
                                          -
                                        • PFS:是Paddlepaddle cloud File System的缩写,是对用户文件存储空间的抽象,与之相对的是local filesystem。目前我们用CephFS来搭建。
                                        • -
                                        • CephFS:一个POSIX兼容的文件系统。
                                        • -
                                        • Chunk:逻辑划上文件分块的单位。
                                        • -
                                        -
                                        -
                                        -

                                        模块

                                        -
                                        -

                                        架构图

                                        -

                                        -
                                        -
                                        -

                                        PFSClient

                                        -
                                          -
                                        • 功能: 详细设计link
                                            -
                                          • 提供用户管理文件的命令
                                          • -
                                          • 需要可以跨平台执行
                                          • -
                                          -
                                        • -
                                        • 双向验证PFSClient需要和Ingress之间做双向验证tls,所以用户需要首先在cloud.paddlepaddle.org上注册一下,申请用户空间,并且把系统生成的CA(certificate authority)、Key、CRT(CA signed certificate)下载到本地,然后才能使用PFSClient。
                                        • -
                                        -
                                        -
                                        -

                                        Ingress

                                        -
                                          -
                                        • 功能:提供七层协议的反向代理、基于粘性会话的负载均衡功能。
                                        • -
                                        • 透传用户身份的办法Ingress需要把PFSClient的身份信息传给PFSServer,配置的方法参考link
                                        • -
                                        -
                                        -
                                        -

                                        PFSServer

                                        -

                                        PFSServer提供RESTful API接口,接收处理PFSClient端的文件管理请求,并且把结果返回PFSClient端。

                                        -

                                        RESTful API

                                        -
                                          -
                                        • /api/v1/files
                                            -
                                          • GET /api/v1/files: Get metadata of files or directories.
                                          • -
                                          • POST /api/v1/files: Create files or directories.
                                          • -
                                          • PATCH /api/v1/files: Update files or directories.
                                          • -
                                          • DELETE /api/v1/files: Delete files or directories.
                                          • -
                                          -
                                        • -
                                        • /api/v1/file/chunks
                                            -
                                          • GET /api/v1/storage/file/chunks: Get chunks’s metadata of a file.
                                          • -
                                          -
                                        • -
                                        • /api/v1/storage/files
                                            -
                                          • GET /api/v1/storage/files: Download files or directories.
                                          • -
                                          • POST /api/v1/storage/files: Upload files or directories.
                                          • -
                                          -
                                        • -
                                        • /api/v1/storage/file/chunks
                                            -
                                          • GET /api/v1/storage/file/chunks: Download chunks’s data.
                                          • -
                                          • POST /api/v1/storage/file/chunks: Upload chunks’s data.
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        文件传输优化

                                        -
                                        -

                                        分块文件传输

                                        -

                                        用户文件可能是比较大的,上传到Cloud或者下载到本地的时间可能比较长,而且在传输的过程中也可能出现网络不稳定的情况。为了应对以上的问题,我们提出了Chunk的概念,一个Chunk由所在的文件偏移、数据、数据长度及校验值组成。文件的上传和下载都是通过对Chunk的操作来实现的。由于Chunk比较小(默认256K),完成一个传输动作完成的时间也比较短,不容易出错。PFSClient需要在传输完毕最后一个Chunk的时候检查destination文件的MD5值是否和source文件一致。

                                        -

                                        一个典型的Chunk如下所示:

                                        -
                                        type Chunk struct {
                                        -    fileOffset int64
                                        -    checksum uint32
                                        -    len     uint32
                                        -    data    []byte
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -

                                        生成sparse文件

                                        -

                                        当destination文件不存在或者大小和source文件不一致时,可以用Fallocate生成sparse文件,然后就可以并发写入多个Chunk。

                                        -
                                        -
                                        -

                                        覆盖不一致的部分

                                        -

                                        文件传输的的关键在于需要PFSClient端对比source和destination的文件Chunks的checksum是否保持一致,不一致的由PFSClient下载或者传输Chunk完成。这样已经传输成功的部分就不用重新传输了。

                                        -
                                        -
                                        -
                                        -

                                        用户使用流程

                                        -

                                        参考link

                                        -
                                        -
                                        -

                                        框架生成

                                        -

                                        swagger生成PFSClient和PFSServer的框架部分,以便我们可以把更多的精力放到逻辑本身上。

                                        -
                                        - -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/file_manager/pfs/pfsclient.html b/develop/doc_cn/design/file_manager/pfs/pfsclient.html deleted file mode 100644 index 61fd0d04c04..00000000000 --- a/develop/doc_cn/design/file_manager/pfs/pfsclient.html +++ /dev/null @@ -1,399 +0,0 @@ - - - - - - - - - - - - - PFSClient — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        PFSClient

                                        -
                                        -

                                        Description

                                        -

                                        The pfs command is a Command Line Interface to manage your files on PaddlePaddle Cloud

                                        -
                                        -
                                        -

                                        Synopsis

                                        -
                                        paddle [options] pfs <subcommand> [parameters]
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Options

                                        -
                                        --profile (string)
                                        -    Use a specific profile from your credential file.
                                        -
                                        ---help (string)
                                        -    Display more information about command
                                        -
                                        ---version
                                        -    Output version information and exit
                                        -
                                        ---debug
                                        -    Show detailed debugging log 
                                        -    
                                        ---only-show-errors (boolean) 
                                        -    Only errors and warnings are displayed. All other output is suppressed.
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Path Arguments

                                        -

                                        When using a command, we need to specify path arguments. There are two path argument type: localpath and pfspath.

                                        -

                                        A pfspath begin with /pfs, eg: /pfs/$DATACENTER/home/$USER/folder.

                                        -

                                        Here is how to config datacenters.

                                        -
                                        -
                                        -

                                        order of Path Arguments

                                        -

                                        Commonly, if there are two path arguments, the first is the source, and the second is the destination.

                                        -
                                        -
                                        -

                                        Subcommonds

                                        -
                                          -
                                        • rm - remove files or directories
                                        • -
                                        -
                                        Synopsis:
                                        -    rm [-r] [-v] <PFSPath> ...
                                        -
                                        -Options:
                                        -    -r 
                                        -        Remove directories and their contents recursively 
                                        -    -v      
                                        -        Cause rm to be verbose, showing files after they are removed.
                                        -    
                                        -Examples:
                                        -    paddle pfs rm /pfs/$DATACENTER/home/$USER/file
                                        -    paddle pfs rm -r /pfs/$DATACENTER/home/$USER/folder
                                        -
                                        -
                                        -
                                          -
                                        • mv - move (rename) files
                                        • -
                                        -
                                        Synopsis:
                                        -    mv [-f | -n] [-v] <LocalPath> <PFSPath>
                                        -    mv [-f | -n] [-v] <LocalPath> ... <PFSPath>
                                        -    mv [-f | -n] [-v] <PFSPath> <LocalPath> 
                                        -    mv [-f | -n] [-v] <PFSPath> ... <LocalPath> 
                                        -    mv [-f | -n] [-v] <PFSPath> <PFSPath> 
                                        -    mv [-f | -n] [-v] <PFSPath> ... <PFSPath> 
                                        -    
                                        -Options:
                                        -    -f      
                                        -        Do not prompt for confirmation before overwriting the destination path.  (The -f option overrides previous -n options.)
                                        -    -n      
                                        -        Do not overwrite an existing file.  (The -n option overrides previous -f options.)
                                        -    -v      
                                        -        Cause mv to be verbose, showing files after they are moved.
                                        -        
                                        -Examples:
                                        -    paddle pfs mv ./text1.txt /pfs/$DATACENTER/home/$USER/text1.txt
                                        -
                                        -
                                        -
                                          -
                                        • cp - copy files or directories
                                        • -
                                        -
                                        Synopsis:
                                        -    cp [-r] [-f | -n] [-v] [--preserve--links] <LocalPath> <PFSPath>
                                        -    cp [-r] [-f | -n] [-v] [--preserve--links] <LocalPath> ... <PFSPath>
                                        -    cp [-r] [-f | -n] [-v] [--preserve--links] <PFSPath> <LocalPath> 
                                        -    cp [-r] [-f | -n] [-v] [--preserve--links] <PFSPath> ... <LocalPath>
                                        -    cp [-r] [-f | -n] [-v] [--preserve--links] <PFSPath> <PFSPath> 
                                        -    cp [-r] [-f | -n] [-v] [--preserve--links] <PFSPath> ... <PFSPath>
                                        -
                                        -Options:
                                        -    -r
                                        -        Copy directories recursively
                                        -    -f      
                                        -        Do not prompt for confirmation before overwriting the destination path.  (The -f option overrides previous -n options.)
                                        -    -n      
                                        -        Do not overwrite an existing file.  (The -n option overrides previous -f options.)
                                        -    -v      
                                        -        Cause cp to be verbose, showing files after they are copied.
                                        -    --preserve--links
                                        -       Reserve links when copy links
                                        -       
                                        -Examples:
                                        -    paddle pfs cp ./file /pfs/$DATACENTER/home/$USER/file
                                        -    paddle pfs cp /pfs/$DATACENTER/home/$USER/file ./file
                                        -
                                        -
                                        -
                                          -
                                        • ls- list files
                                        • -
                                        -
                                        Synopsis:
                                        -    ls [-r] <PFSPath> ...
                                        -    
                                        -Options:
                                        -    -R
                                        -        List directory(ies) recursively
                                        -
                                        -Examples:
                                        -    paddle pfs ls  /pfs/$DATACENTER/home/$USER/file
                                        -    paddle pfs ls  /pfs/$DATACENTER/home/$USER/folder
                                        -
                                        -
                                        -
                                          -
                                        • mkdir - mkdir directory(ies) -Create intermediate directory(ies) as required.
                                        • -
                                        -
                                        Synopsis:
                                        -    mkdir <PFSPath> ...
                                        -
                                        -Examples:
                                        -    paddle pfs mkdir  /pfs/$DATACENTER/home/$USER/folder
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/float16.html b/develop/doc_cn/design/float16.html deleted file mode 100644 index f65440a8a15..00000000000 --- a/develop/doc_cn/design/float16.html +++ /dev/null @@ -1,378 +0,0 @@ - - - - - - - - - - - - - Design Doc: float16 — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: float16

                                        -
                                        -

                                        Why float16

                                        -

                                        Half precision (float16) is a binary floating-point format that occupies 16 bits in memory. float16 is half the size of traditional 32-bit single precision format (float) and has lower precision and smaller range.

                                        -

                                        When high precision computation is not required, using float16 data type could potentially

                                        -
                                          -
                                        • reduce storage space, memory bandwidth, and power usages;
                                        • -
                                        • increase the chance of data fitting into a smaller cache of lower latency;
                                        • -
                                        • provide arithmetic speed up if supported by hardware.
                                        • -
                                        -
                                        -
                                        -

                                        Survey of current float16 support

                                        -

                                        A brief survey of float16 support on different compilers, hardwares, and libraries can be found below. Interested readers can refer to link1 and link2 for more info.

                                        -

                                        The goal of float16 is to serve as a key for the executor to find and run the correct version of compute method specialized for float16 in operator kernel. It should be compatible with various natively supported float16 implementations including __half for cuda, float16_t for ARM, and Eigen::half for Eigen to make writing customized float16 kernels easier.

                                        -
                                        -

                                        Compiler

                                        -
                                          -
                                        • nvcc supports __half data type after CUDA 7.5.
                                        • -
                                        • __fp16 or float16_t is supported as storage type for gcc >= 6.1 and clang >= 3.4.
                                        • -
                                        • __fp16 or float16_t is supported as arithmetic type for gcc >= 7.1 and clang >= 3.9.
                                        • -
                                        -
                                        -
                                        -

                                        Hardware

                                        -
                                          -
                                        • __half is supported on GPU with compute capability >= 5.3.
                                        • -
                                        • __fp16 is supported as storage type for ARMv7-A, ARMv8-A, and above.
                                        • -
                                        • __fp16 is supported as arithmetic type after ARMv8.2-A (currently, the only microarchitecture implementing ARMv8.2-A is ARM Cortex-A75, which is announced in May 2017. There seems to be no application processors currently available on market that adopts this architecture. It is reported that Qualcomm Snapdragon 845 uses Cortex-A75 design and will be available in mobile devices in early 2018).
                                        • -
                                        -
                                        -
                                        -

                                        Libraries

                                        -
                                          -
                                        • Eigen >= 3.3 supports float16 calculation on both GPU and CPU using the Eigen::half class. It is mostly useful for Nvidia GPUs because of the overloaded arithmetic operators using cuda intrinsics. It falls back to using software emulation on CPU for calculation and there is no special treatment to ARM processors.
                                        • -
                                        • ARM compute library >= 17.02.01 supports NEON FP16 kernels (requires ARMv8.2-A CPU).
                                        • -
                                        -
                                        -
                                        -

                                        CUDA version issue

                                        -

                                        There are currently three versions of CUDA that supports __half data type, namely, CUDA 7.5, 8.0, and 9.0. -CUDA 7.5 and 8.0 define __half as a simple struct that has a uint16_t data (see cuda_fp16.h) as follows:

                                        -
                                        typedef struct __align__(2) {
                                        -   unsigned short x;
                                        -} __half;
                                        -
                                        -typedef __half half;
                                        -
                                        -
                                        -

                                        This struct does not define any overloaded arithmetic operators. So you have to directly use __hadd instead of + to correctly add two half types:

                                        -
                                        __global__ void Add() {
                                        -  half a, b, c;
                                        -  c = __hadd(a, b); // correct
                                        -  c = a + b; // compiler error: no operator "+" matches these operands
                                        -}
                                        -
                                        -
                                        -

                                        CUDA 9.0 provides a major update to the half data type. The related code can be found in the updated cuda_fp16.h and the newly added cuda_fp16.hpp.

                                        -

                                        Essentially, CUDA 9.0 renames the original __half type in 7.5 and 8.0 as __half_raw, and defines a new __half class type that has constructors, conversion operators, and also provides overloaded arithmetic operators such as follows:

                                        -
                                        typedef struct __CUDA_ALIGN__(2) {
                                        -    unsigned short x;
                                        -} __half_raw;
                                        -
                                        -
                                        -struct __CUDA_ALIGN__(2) __half {
                                        -protected:
                                        -    unsigned short __x;
                                        -public:
                                        -    // constructors and conversion operators from/to 
                                        -    // __half_raw and other built-in data types
                                        -}
                                        -
                                        -typedef __half half;
                                        -
                                        -__device__ __forceinline__ 
                                        -__half operator+(const __half &lh, const __half &rh) { 
                                        -    return __hadd(lh, rh); 
                                        -}
                                        -
                                        -// Other overloaded operators
                                        -
                                        -
                                        -

                                        This new design makes c = a + b work correctly for CUDA half data type.

                                        -
                                        -
                                        -
                                        -

                                        Implementation

                                        -

                                        The float16 class holds a 16-bit uint16_t data internally.

                                        -
                                        struct float16 {
                                        -  uint16_t x;
                                        -};
                                        -
                                        -
                                        -

                                        float16 supports the following features:

                                        -
                                          -
                                        • constructors / assignment operators that take input from primitive data types including bool, integers of various length, float, and double.
                                        • -
                                        • constructors / assignment operators that take input from __half on cuda, float16_t on ARM, and Eigen::half on Eigen.
                                        • -
                                        • conversion operators to primitive data types and half precision data types on cuda, ARM and Eigen.
                                        • -
                                        • overloaded arithmetic operators for cuda, arm, and non-arm cpu, respectively. These operators will take advantage of the cuda and ARM intrinsics on the corresponding hardware.
                                        • -
                                        -

                                        To support the above features, two fundamental conversion functions are provided:

                                        -
                                        float16 float_to_half_rn(float f);  // convert to half precision in round-to-nearest-even mode
                                        -float half_to_float(float16 h);
                                        -
                                        -
                                        -

                                        which provides one-to-one conversion between float32 and float16. These twos functions will do different conversion routines based on the current hardware. CUDA/ARM instrinsics will be used when the corresonding hardware is available. If the hardware or compiler level does not support float32 to float16 conversion, software emulation will be performed to do the conversion.

                                        -
                                        -
                                        -

                                        To do

                                        -

                                        After float16 class is available, some of the future items are below:

                                        -
                                          -
                                        • Update pybind/tensor_py.h to bind c++ float16 with numpy float16.
                                        • -
                                        • Modify GetKernelType() method in framework/operator.h to make it compatible with float16.
                                        • -
                                        • Create a type-casting operator that can convert the data type in tensor between float16 and other types.
                                        • -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/fluid.html b/develop/doc_cn/design/fluid.html deleted file mode 100644 index 1b426d65624..00000000000 --- a/develop/doc_cn/design/fluid.html +++ /dev/null @@ -1,358 +0,0 @@ - - - - - - - - - - - - - Design Doc: PaddlePaddle Fluid — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: PaddlePaddle Fluid

                                        -
                                        -

                                        Why Fluid

                                        -

                                        When Baidu developed PaddlePaddle in 2013, the only well-known open source deep learning system at the time was Caffe. However, when PaddlePaddle was open-sourced in 2016, many other choices were available. There was a challenge – what is the need for open sourcing yet another deep learning framework?

                                        -

                                        Fluid is the answer. Fluid is similar to PyTorch and TensorFlow Eager Execution, which describes the “process” of training or inference using the concept of a model. In fact in PyTorch, TensorFlow Eager Execution and Fluid, there is no concept of a model at all. The details are covered in the sections below. Fluid is currently more extreme in the above mentioned idea than PyTorch and Eager Execution, and we are trying to push Fluid towards the directions of a compiler and a new programming language for deep learning.

                                        -
                                        -
                                        -

                                        The Evolution of Deep Learning Systems

                                        -

                                        Deep learning infrastructure is one of the fastest evolving technologies. Within four years, there have already been three generations of technologies invented.

                                        -

                                        | Existed since | model as sequence of layers | model as graph of operators | No model | -|–|–|–|–| -| 2013 | Caffe, Theano, Torch, PaddlePaddle | | | -| 2015 | | TensorFlow, MxNet, Caffe2, ONNX, n-graph | | -| 2016 | | | PyTorch, TensorFlow Eager Execution, PaddlePaddle Fluid |

                                        -

                                        From the above table, we see that the deep learning technology is evolving towards getting rid of the concept of a model. To understand the reasons behind this direction, a comparison of the programming paradigms or the ways to program deep learning applications using these systems, would be helpful. The following section goes over these.

                                        -
                                        -
                                        -

                                        Deep Learning Programming Paradigms

                                        -

                                        With the systems listed as the first or second generation, e.g., Caffe or TensorFlow, an AI application training program looks like the following:

                                        -
                                        x = layer.data("image")
                                        -l = layer.data("label")
                                        -f = layer.fc(x, W)
                                        -s = layer.softmax(f)
                                        -c = layer.mse(l, s)
                                        -
                                        -for i in xrange(1000): # train for 1000 iterations
                                        -    m = read_minibatch()
                                        -    forward({input=x, data=m}, minimize=c)
                                        -    backward(...)
                                        -
                                        -print W # print the trained model parameters.
                                        -
                                        -
                                        -

                                        The above program includes two parts:

                                        -
                                          -
                                        1. The first part describes the model, and
                                        2. -
                                        3. The second part describes the training process (or inference process) for the model.
                                        4. -
                                        -

                                        This paradigm has a well-known problem that limits the productivity of programmers. If the programmer made a mistake in configuring the model, the error messages wouldn’t show up until the second part is executed and forward and backward propagations are performed. This makes it difficult for the programmer to debug and locate a mistake that is located blocks away from the actual error prompt.

                                        -

                                        This problem of being hard to debug and re-iterate fast on a program is the primary reason that programmers, in general, prefer PyTorch over the older systems. Using PyTorch, we would write the above program as following:

                                        -
                                        W = tensor(...)
                                        -
                                        -for i in xrange(1000): # train for 1000 iterations
                                        -    m = read_minibatch()
                                        -    x = m["image"]
                                        -    l = m["label"]
                                        -    f = layer.fc(x, W)
                                        -    s = layer.softmax(f)
                                        -    c = layer.mse(l, s)
                                        -    backward()
                                        -
                                        -print W # print the trained model parameters.
                                        -
                                        -
                                        -

                                        We can see that the main difference is the moving the model configuration part (the first step) into the training loop. This change would allow the mistakes in model configuration to be reported where they actually appear in the programming block. This change also represents the model better, or its forward pass, by keeping the configuration process in the training loop.

                                        -
                                        -
                                        -

                                        Describe Arbitrary Models for the Future

                                        -

                                        Describing the process instead of the model also brings Fluid, the flexibility to define different non-standard models that haven’t been invented yet.

                                        -

                                        As we write out the program for the process, we can write an RNN as a loop, instead of an RNN as a layer or as an operator. A PyTorch example would look like the following:

                                        -
                                        for i in xrange(1000):
                                        -    m = read_minibatch()
                                        -    x = m["sentence"]
                                        -    for t in xrange x.len():
                                        -        h[t] = the_step(x[t])
                                        -
                                        -
                                        -

                                        With Fluid, the training loop and the RNN in the above program are not really Python loops, but just a “loop structure” provided by Fluid and implemented in C++ as the following:

                                        -
                                        train_loop = layers.While(cond)
                                        -with train_loop.block():
                                        -  m = read_minibatch()
                                        -  x = m["sentence"]
                                        -  rnn = layers.While(...)
                                        -  with rnn.block():
                                        -    h[t] = the_step(input[t])
                                        -
                                        -
                                        -

                                        An actual Fluid example is described here.

                                        -

                                        From the example, the Fluid programs look very similar to their PyTorch equivalent programs, except that Fluid’s loop structure, wrapped with Python’s with statement, could run much faster than just a Python loop.

                                        -

                                        We have more examples of the if-then-else structure of Fluid.

                                        -
                                        -
                                        -

                                        Turing Completeness

                                        -

                                        In computability theory, a system of data-manipulation rules, such as a programming language, is said to be Turing complete if it can be used to simulate any Turing machine. For a programming language, if it provides if-then-else and loop, it is Turing complete. From the above examples, Fluid seems to be Turing complete; however, it is noteworthy to notice that there is a slight difference between the if-then-else of Fluid and that of a programming language. The difference being that the former runs both of its branches and splits the input mini-batch into two – one for the True condition and another for the False condition. This hasn’t been researched in depth if this is equivalent to the if-then-else in programming languages that makes them Turing-complete. Based on a conversation with Yuang Yu, it seems to be the case but this needs to be looked into in-depth.

                                        -
                                        -
                                        -

                                        The Execution of a Fluid Program

                                        -

                                        There are two ways to execute a Fluid program. When a program is executed, it creates a protobuf message ProgramDesc that describes the process and is conceptually like an abstract syntax tree.

                                        -

                                        There is a C++ class Executor, which runs a ProgramDesc, similar to how an interpreter runs a Python program.

                                        -

                                        Fluid is moving towards the direction of a compiler, which is explain in fluid.

                                        -
                                        -
                                        -

                                        Backward Compatibility of Fluid

                                        -

                                        Given all the advantages from the removal of the concept of a model, hardware manufacturers might still prefer the existence of the concept of a model, so it would be easier for them to support multiple frameworks all at once and could run a trained model during inference. For example, Nervana, a startup company acquired by Intel, has been working on an XPU that reads the models in the format known as n-graph. Similarly, Movidius is producing a mobile deep learning chip that reads and runs graphs of operators. The well-known ONNX is also a file format of graphs of operators.

                                        -

                                        For Fluid, we can write a converter that extracts the parts in the ProgramDesc protobuf message, converts them into a graph of operators, and exports the graph into the ONNX or n-graph format.

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/fluid_compiler.html b/develop/doc_cn/design/fluid_compiler.html deleted file mode 100644 index 7b1a0f8a85d..00000000000 --- a/develop/doc_cn/design/fluid_compiler.html +++ /dev/null @@ -1,360 +0,0 @@ - - - - - - - - - - - - - PaddlePaddle Fluid: Towards a Compiled Programming Language — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        -
                                          -
                                        • Docs »
                                        • - -
                                        • PaddlePaddle Fluid: Towards a Compiled Programming Language
                                        • -
                                        • - - - View page source - - -
                                        • -
                                        -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        PaddlePaddle Fluid: Towards a Compiled Programming Language

                                        -

                                        As described in fluid.md, when a Fluid application program -runs, it generates a ProgramDesc protobuf message as an intermediate -representation of itself. The C++ class Executor can run this -protobuf message as an interpreter. This article describes the Fluid -compiler.

                                        -

                                        -
                                        -

                                        ProgramDesc

                                        -

                                        Before we go deeper into the idea of compiled language, let us take a -look at a simple example Fluid application.

                                        -
                                        import "fluid"
                                        -
                                        -func paddlepaddle() {
                                        -  X = fluid.read(...)
                                        -  W = fluid.Tensor(...)
                                        -  Y = fluid.mult(X, W)
                                        -}
                                        -
                                        -
                                        -

                                        This program consists of a block of three operators – -read, assign, and mult. Its ProgramDesc message looks like -the following

                                        -
                                        message ProgramDesc {
                                        -  block[0] = Block {
                                        -    vars = [X, W, Y],
                                        -    ops = [
                                        -      read(output = X)
                                        -      assign(input = ..., output = W)
                                        -      mult(input = {X, W}, output = Y)
                                        -    ],
                                        -  }
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Transpilers

                                        -

                                        We can write a transpiler program that takes a ProgramDesc, e.g., -the above one, and outputs another ProgramDesc. Let us take some -examples:

                                        -
                                          -
                                        1. Memory optimization transpiler: We can write a transpiler that -inserts some FreeMemoryOps in the above example ProgramDesc so -to free memory early, before the end of an iteration, so to keep a -small memory footprint.
                                        2. -
                                        3. Distributed training transpiler: We can write a transpiler that -converts aProgramDesc into its distributed version of two -ProgramDescs – one for running by the trainer processes and the -other for the parameter server.
                                        4. -
                                        -

                                        In the rest of this article, we talk about a special kind of -transpiler, Native code generator, which takes a ProgramDesc and -generates a .cu (or .cc) file, which could be built by C++ -compilers (gcc, nvcc, icc) into binaries.

                                        -
                                        -
                                        -

                                        Native Code Generator

                                        -

                                        For the above example, the native code generator transpiler, say, the -CUDA code generator, should generate a main function:

                                        -
                                        void main() {
                                        -  auto X = fluid_cuda_read(...);
                                        -  auto W = fluid_cuda_create_tensor(...);
                                        -  auto Y = fluid_cuda_mult(X, W);
                                        -}
                                        -
                                        -
                                        -

                                        and the definitions of functions fluid_cuda_read, -fluid_cuda_create_tensor, and fluid_cuda_mult. Please be aware -that each function could just define a C++ instance of an operator and -run it. For example

                                        -
                                        paddle::Tensor fluid_cuda_read(...) {
                                        -  paddle::Tensor t;
                                        -  paddle::operator::Read r(&t, ...);
                                        -  r.Run();
                                        -  return t;
                                        -}
                                        -
                                        -
                                        -

                                        For computational operators that have multiple kernels, each for a -specific hardware platform, for example, the mult operator, the -generated code should call its CUDA kernel:

                                        -
                                        paddle::Tensor fluid_cuda_mult(const paddle::Tensor& a, 
                                        -                               const paddle::Tensor& b) {
                                        -  paddle::Tensor t;
                                        -  paddle::operator::Mult m(a, b, ...);
                                        -  Mult.Run(cuda_context);
                                        -}
                                        -
                                        -
                                        -

                                        where cuda_context could be a global variable of type -paddle::CUDADeviceContext.

                                        -
                                        -
                                        -

                                        Multi-Block Code Generation

                                        -

                                        Most Fluid application programs may have more than one blocks. To -execute them, we need to trace scopes.

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/functions_operators_layers.html b/develop/doc_cn/design/functions_operators_layers.html deleted file mode 100644 index 0bf43baabca..00000000000 --- a/develop/doc_cn/design/functions_operators_layers.html +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - - - - - - Design Doc: Functions, Operators, and Layers — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Functions, Operators, and Layers

                                        -

                                        In a DL system, we can compose one or more fine grained operators into a coarse grained one. For example, the FC layer can be composed of a multiplication operator and an add operator.

                                        -

                                        Historically, some fine grained operations are known as operators, and some coarse level ones are known as layers. But we need a well-defined separation.

                                        -

                                        In general, operators are those very fine grained operations, e.g., mul and add. In the implementation, we can write them as C++ functions:

                                        -
                                        template <typename T> T add(T x, T y) { return x + y; }
                                        -template <typename T> T mul(T x, T y) { return x * y; }
                                        -
                                        -
                                        -

                                        Then we can wrap them into operators which are C++ classes and can be created from Python bindings by name. A C macro can do this. For example, the following macro invocation

                                        -
                                        #define MAKE_FUNCTION_OPERATOR(mul);
                                        -
                                        -
                                        -

                                        generates

                                        -
                                        template <typename T> class mulOp : public OperatorBase {...};
                                        -REGISTER_OP(mulOp<float32>, "mul");
                                        -
                                        -
                                        -

                                        so that in Python we can create operator mul by:

                                        -
                                        X1 = Var()
                                        -X2 = Var()
                                        -Y = Var()
                                        -paddle.cpp.create_operator("mul", input=[X1, X2], output=Y)
                                        -
                                        -
                                        -

                                        Also, at the same time, we can compose a coarse level C++ operator class by composing functions mul and add:

                                        -
                                        template <typename T>
                                        -class FCOp : public OperatorBase {
                                        - public:
                                        -  void Run(...) {
                                        -    add(mul(Input<T>("X"), Input<T>("W")), Input<T>("b");
                                        -  }
                                        -};
                                        -REGISTER_OP(FCOp, "fc");
                                        -
                                        -
                                        -

                                        We need to support such composition in Python as well. To do so, we need a higher level Python wrapping of operator creation than paddle.cpp.create_operator. This higher level operator API should be compatible with the layer API.

                                        -

                                        Let’s explain using an example. Suppose that we are going to compose the FC using mul and add in Python, we’d like to have Python functions mul and add defined in module operator:

                                        -
                                        def operator.mul(X1, X2):
                                        -    O = Var()
                                        -    paddle.cpp.create_operator("mul", input={X1, Y1}, output=O)
                                        -    return O
                                        -
                                        -def operator.add(X1, X2):
                                        -    O = Var()
                                        -    paddle.cpp.create_operator("add", input={X1, X2}, output=O)
                                        -    return O
                                        -
                                        -
                                        -

                                        Above code snippets are automatically generated. Given them, users can define

                                        -
                                        def layer.fc(X):
                                        -    W = Var()
                                        -    b = Var()
                                        -    return operator.add(operator.mul(X, W), b)
                                        -
                                        -
                                        -

                                        If we don’t have operator.mul and operator.add, the definiton of layer.fc would be complicated:

                                        -
                                        def layer.fc(X):
                                        -    W = Var()
                                        -    b = Var()
                                        -    O1 = Var()
                                        -    paddle.cpp.create_operator("mul", input=[X, W], output=O1)
                                        -    O2 = Var()
                                        -    paddle.cpp.create_operator("add", input=[O1, b], output=O2)
                                        -    return O2
                                        -
                                        -
                                        -

                                        We’d like to have Python bindings to operators in package paddle.operator, and Python compositions of operators in package paddle.layer. So we have the following concepts in above illustrative example:

                                        -

                                        | C++ functions/functors | mul | add | | | -|————————|————–|————–|————-|———-| -| C++ operator class | mulOp | addOp | FCOp | | -| Python binding | operator.mul | operator.add | operator.fc | | -| Python function | | | | layer.fc |

                                        -

                                        This is how we differentiate layer and operators in PaddlePaddle:

                                        -
                                          -
                                        • those defined in C++ and have a lightweighted Python wrapper in module operators are operators; whereas
                                        • -
                                        • those who don’t have C++ implementations but a Python implementation that compose C++ operators are known as layers.
                                        • -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/gan_api.html b/develop/doc_cn/design/gan_api.html deleted file mode 100644 index 2be8c4c38c2..00000000000 --- a/develop/doc_cn/design/gan_api.html +++ /dev/null @@ -1,526 +0,0 @@ - - - - - - - - - - - - - Design for GAN — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design for GAN

                                        -

                                        GAN (General Adversarial Net [https://arxiv.org/abs/1406.2661]) is an important model for unsupervised learning and widely used in many areas.

                                        -

                                        It applies several important concepts in machine learning system design, including building and running subgraphs, dependency tracing, different optimizers in one executor and so forth.

                                        -

                                        In our GAN design, we wrap it as a user-friendly easily customized python API to design different models. We take the conditional DC-GAN (Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks [https://arxiv.org/abs/1511.06434]) as an example due to its good performance on image generation.

                                        -

                                        -
                                        -Figure 1. The overall running logic of GAN. The black solid arrows indicate the forward pass; the green dashed arrows indicate the backward pass of generator training; the red dashed arrows indicate the backward pass of the discriminator training. The BP pass of the green (red) arrow should only update the parameters in the green (red) boxes. The diamonds indicate the data providers. d\_loss and g\_loss marked in red and green are the two targets we would like to run. -

                                        The operators, layers and functions required/optional to build a GAN demo is summarized in https://github.com/PaddlePaddle/Paddle/issues/4563.

                                        -

                                        -
                                        -Figure 2. Photo borrowed from the original DC-GAN paper. -

                                        -

                                        The Conditional-GAN might be a class.

                                        -

                                        This design we adopt the popular open source design in https://github.com/carpedm20/DCGAN-tensorflow and https://github.com/rajathkmp/DCGAN. It contains following data structure:

                                        -
                                          -
                                        • DCGAN(object): which contains everything required to build a GAN model. It provides following member functions methods as API:
                                        • -
                                        • init(...): Initialize hyper-parameters (like conv dimension and so forth), and declare model parameters of discriminator and generator as well.
                                        • -
                                        • generator(z, y=None): Generate a fake image from input noise z. If the label y is provided, the conditional GAN model will be chosen. -Returns a generated image.
                                        • -
                                        • discriminator(image): -Given an image, decide if it is from a real source or a fake one. -Returns a 0/1 binary label.
                                        • -
                                        • build_model(self): -build the whole GAN model, define training loss for both generator and discrimator.
                                        • -
                                        -
                                        -
                                        -

                                        Discussion on Engine Functions required to build GAN

                                        -
                                          -
                                        • Trace the tensor and variable dependency in the engine executor. (Very critical, otherwise GAN can’be be trained correctly)
                                        • -
                                        • Different optimizers responsible for optimizing different loss.
                                        • -
                                        -

                                        To be more detailed, we introduce our design of DCGAN as following:

                                        -
                                        -

                                        Class member Function: Initializer

                                        -
                                          -
                                        • Set up hyper-parameters, including condtional dimension, noise dimension, batch size and so forth.
                                        • -
                                        • Declare and define all the model variables. All the discriminator parameters are included in the list self.theta_D and all the generator parameters are included in the list self.theta_G.
                                        • -
                                        -
                                        class DCGAN(object):
                                        -  def __init__(self, y_dim=None):
                                        -  
                                        -    # hyper parameters  
                                        -    self.y_dim = y_dim # conditional gan or not
                                        -    self.batch_size = 100
                                        -    self.z_dim = z_dim # input noise dimension
                                        -
                                        -    # define parameters of discriminators
                                        -    self.D_W0 = pd.Variable(shape=[3,3, 1, 128], data=pd.gaussian_normal_randomizer())
                                        -    self.D_b0 = pd.Variable(np.zeros(128)) # variable also support initialization using a  numpy data
                                        -    self.D_W1 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer())
                                        -    self.D_b1 = pd.Variable(np.zeros(128)) # variable also support initialization using a  numpy data
                                        -    self.D_W2 = pd.Varialble(np.random.rand(128, 1))
                                        -    self.D_b2 = pd.Variable(np.zeros(128))
                                        -    self.theta_D = [self.D_W0, self.D_b0, self.D_W1, self.D_b1, self.D_W2, self.D_b2]
                                        -
                                        -    # define parameters of generators
                                        -    self.G_W0 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer())
                                        -    self.G_b0 = pd.Variable(np.zeros(128)) # variable also support initialization using a  numpy data
                                        -    self.G_W1 = pd.Variable(shape=[784, 128], data=pd.gaussian_normal_randomizer())
                                        -    self.G_b1 = pd.Variable(np.zeros(128)) # variable also support initialization using a  numpy data
                                        -    self.G_W2 = pd.Varialble(np.random.rand(128, 1))
                                        -    self.G_b2 = pd.Variable(np.zeros(128))
                                        -    self.theta_G = [self.G_W0, self.G_b0, self.G_W1, self.G_b1, self.G_W2, self.G_b2]
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Class member Function: Generator

                                        -
                                          -
                                        • Given a noisy input z, returns a fake image.
                                        • -
                                        • Concatenation, batch-norm, FC operations required;
                                        • -
                                        • Deconv layer required, which is missing now...
                                        • -
                                        -
                                        class DCGAN(object):
                                        -  def generator(self, z, y = None):
                                        -    # input z: the random noise
                                        -    # input y: input data label (optional)
                                        -    # output G_im: generated fake images
                                        -    
                                        -    if not self.y_dim:
                                        -      z = pd.layer.concat(1, [z, y])
                                        -      
                                        -    G_h0 = pd.layer.fc(z, self.G_w0, self.G_b0)
                                        -    G_h0_bn = pd.layer.batch_norm(G_h0)
                                        -    G_h0_relu = pd.layer.relu(G_h0_bn)
                                        -    
                                        -    G_h1 = pd.layer.deconv(G_h0_relu, self.G_w1, self.G_b1)
                                        -    G_h1_bn = pd.layer.batch_norm(G_h1)
                                        -    G_h1_relu = pd.layer.relu(G_h1_bn)
                                        -    
                                        -    G_h2 = pd.layer.deconv(G_h1_relu, self.G_W2, self.G_b2))
                                        -    G_im = pd.layer.tanh(G_im)
                                        -    return G_im
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Class member function: Discriminator

                                        -
                                          -
                                        • Given a noisy input z, returns a fake image.
                                        • -
                                        • Concatenation, Convolution, batch-norm, FC, Leaky-ReLU operations required;
                                        • -
                                        -
                                        class DCGAN(object):
                                        -  def discriminator(self, image):
                                        -    # input image: either generated images or real ones
                                        -    # output D_h2: binary logit of the label
                                        -
                                        -    D_h0 = pd.layer.conv2d(image, w=self.D_w0, b=self.D_b0)
                                        -    D_h0_bn = pd.layer.batchnorm(h0)
                                        -    D_h0_relu = pd.layer.lrelu(h0_bn)
                                        -    
                                        -    D_h1 = pd.layer.conv2d(D_h0_relu, w=self.D_w1, b=self.D_b1)
                                        -    D_h1_bn = pd.layer.batchnorm(D_h1)
                                        -    D_h1_relu = pd.layer.lrelu(D_h1_bn)
                                        -    
                                        -    D_h2 = pd.layer.fc(D_h1_relu, w=self.D_w2, b=self.D_b2)
                                        -    return D_h2
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Class member function: Build the model

                                        -
                                          -
                                        • Define data readers as placeholders to hold the data;
                                        • -
                                        • Build generator and discriminators;
                                        • -
                                        • Define two training losses for discriminator and generator, respectively. -If we have execution dependency engine to back-trace all tensors, the module building our GAN model will be like this:
                                        • -
                                        -
                                        class DCGAN(object):
                                        -  def build_model(self):
                                        -    if self.y_dim:
                                        -        self.y = pd.data(pd.float32, [self.batch_size, self.y_dim])
                                        -    self.images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size])
                                        -    self.faked_images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size])
                                        -    self.z = pd.data(tf.float32, [None, self.z_size])
                                        -    
                                        -    # step 1: generate images by generator, classify real/fake images with discriminator
                                        -    if self.y_dim: # if conditional GAN, includes label
                                        -        self.G = self.generator(self.z, self.y)
                                        -        self.D_t = self.discriminator(self.images)
                                        -        # generated fake images
                                        -        self.sampled = self.sampler(self.z, self.y)
                                        -        self.D_f = self.discriminator(self.G)
                                        -    else: # original version of GAN
                                        -        self.G = self.generator(self.z)
                                        -        self.D_t = self.discriminator(self.images)
                                        -        # generate fake images
                                        -        self.sampled = self.sampler(self.z)
                                        -        self.D_f = self.discriminator(self.images)
                                        -    
                                        -    # step 2: define the two losses
                                        -    self.d_loss_real = pd.reduce_mean(pd.cross_entropy(self.D_t, np.ones(self.batch_size))
                                        -    self.d_loss_fake = pd.reduce_mean(pd.cross_entropy(self.D_f, np.zeros(self.batch_size))
                                        -    self.d_loss = self.d_loss_real + self.d_loss_fake
                                        -    
                                        -    self.g_loss = pd.reduce_mean(pd.cross_entropy(self.D_f, np.ones(self.batch_szie))
                                        -
                                        -
                                        -

                                        If we do not have dependency engine but blocks, the module building our GAN model will be like this:

                                        -
                                        class DCGAN(object):
                                        -  def build_model(self, default_block):
                                        -    # input data in the default block
                                        -    if self.y_dim:
                                        -        self.y = pd.data(pd.float32, [self.batch_size, self.y_dim])
                                        -    self.images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size])
                                        -    # self.faked_images = pd.data(pd.float32, [self.batch_size, self.im_size, self.im_size])
                                        -    self.z = pd.data(tf.float32, [None, self.z_size])
                                        -
                                        -    # step 1: generate images by generator, classify real/fake images with discriminator
                                        -    with pd.default_block().g_block():
                                        -      if self.y_dim: # if conditional GAN, includes label
                                        -        self.G = self.generator(self.z, self.y)
                                        -        self.D_g = self.discriminator(self.G, self.y)
                                        -      else: # original version of GAN
                                        -        self.G = self.generator(self.z)
                                        -        self.D_g = self.discriminator(self.G, self.y)
                                        -      self.g_loss = pd.reduce_mean(pd.cross_entropy(self.D_g, np.ones(self.batch_szie))
                                        -    
                                        -    with pd.default_block().d_block():
                                        -      if self.y_dim: # if conditional GAN, includes label
                                        -        self.D_t = self.discriminator(self.images, self.y)
                                        -        self.D_f = self.discriminator(self.G, self.y)
                                        -      else: # original version of GAN
                                        -        self.D_t = self.discriminator(self.images)
                                        -        self.D_f = self.discriminator(self.G)
                                        -
                                        -      # step 2: define the two losses
                                        -      self.d_loss_real = pd.reduce_mean(pd.cross_entropy(self.D_t, np.ones(self.batch_size))
                                        -      self.d_loss_fake = pd.reduce_mean(pd.cross_entropy(self.D_f, np.zeros(self.batch_size))
                                        -      self.d_loss = self.d_loss_real + self.d_loss_fake
                                        -
                                        -
                                        -

                                        Some small confusion and problems with this design:

                                        -
                                          -
                                        • D_g and D_f are actually the same thing, but has to be written twice; i.e., if we want to run two sub-graphs conceptually, the same codes have to be written twice if they are shared by the graph.
                                        • -
                                        • Requires ability to create a block anytime, rather than in if-else or rnn only;
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Main function for the demo:

                                        -

                                        Generally, the user of GAN just need to the following things:

                                        -
                                          -
                                        • Define an object as DCGAN class;
                                        • -
                                        • Build the DCGAN model;
                                        • -
                                        • Specify two optimizers for two different losses with respect to different parameters.
                                        • -
                                        -
                                        # pd for short, should be more concise.
                                        -from paddle.v2 as pd
                                        -import numpy as np
                                        -import logging
                                        -
                                        -if __name__ == "__main__":
                                        -    # dcgan class in the default graph/block
                                        -    # if we use dependency engine as tensorflow
                                        -    # the codes, will be slightly different like:
                                        -    # dcgan = DCGAN()
                                        -    # dcgan.build_model()
                                        -    with pd.block() as def_block:
                                        -      dcgan = DCGAN()
                                        -      dcgan.build_model(def_block)
                                        -
                                        -    # load mnist data
                                        -    data_X, data_y = self.load_mnist()
                                        -    
                                        -    # Two subgraphs required!!!
                                        -    with pd.block().d_block():
                                        -      d_optim = pd.train.Adam(lr = .001, beta= .1)
                                        -      d_step = d_optim.minimize(dcgan.d_loss, dcgan.theta_D)
                                        -    with pd.block.g_block():
                                        -      g_optim = pd.train.Adam(lr = .001, beta= .1)
                                        -      g_step = pd.minimize(dcgan.g_loss, dcgan.theta_G)
                                        -
                                        -    # executor
                                        -    sess = pd.executor()
                                        -    
                                        -    # training
                                        -    for epoch in xrange(10000):
                                        -      for batch_id in range(N / batch_size):
                                        -        idx = ...
                                        -        # sample a batch
                                        -        batch_im, batch_label = data_X[idx:idx+batch_size], data_y[idx:idx+batch_size]
                                        -        # sample z
                                        -        batch_z = np.random.uniform(-1., 1., [batch_size, z_dim])
                                        -
                                        -        if batch_id % 2 == 0:
                                        -          sess.run(d_step, 
                                        -                   feed_dict = {dcgan.images: batch_im,
                                        -                                dcgan.y: batch_label,
                                        -                                dcgan.z: batch_z})
                                        -        else:
                                        -          sess.run(g_step,
                                        -                   feed_dict = {dcgan.z: batch_z})
                                        -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        More thinking about dependency engine v.s. block design:

                                        -
                                          -
                                        • What if we just want to run an intermediate result? Do we need to run the whole block/graph?
                                        • -
                                        • Should we call eval() to get the fake images in the first stage? And then train the discriminator in the second stage?
                                        • -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/graph.html b/develop/doc_cn/design/graph.html deleted file mode 100644 index 73ea1280ca2..00000000000 --- a/develop/doc_cn/design/graph.html +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - Design Doc: Computations as a Graph — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Computations as a Graph

                                        -

                                        A primary goal of the refactorization of PaddlePaddle is a more flexible representation of deep learning computation, in particular, a graph of operators and variables, instead of sequences of layers as before.

                                        -

                                        This document explains that the construction of a graph as three steps:

                                        -
                                          -
                                        • construct the forward part
                                        • -
                                        • construct the backward part
                                        • -
                                        • construct the optimization part
                                        • -
                                        -
                                        -

                                        The Construction of a Graph

                                        -

                                        Let us take the problem of image classification as a simple example. The application program that trains the model looks like:

                                        -
                                        x = layer.data("images")
                                        -l = layer.data("label")
                                        -y = layer.fc(x)
                                        -cost = layer.mse(y, l)
                                        -optimize(cost)
                                        -train(cost, reader=mnist.train())
                                        -
                                        -
                                        -
                                        -

                                        Forward Part

                                        -

                                        The first four lines of above program build the forward part of the graph.

                                        -

                                        -

                                        In particular, the first line x = layer.data("images") creates variable x and a Feed operator that copies a column from the minibatch to x. y = layer.fc(x) creates not only the FC operator and output variable y, but also two parameters, W and b, and the initialization operators.

                                        -

                                        Initialization operators are kind of “run-once” operators – the Run method increments a class data member counter so to run at most once. By doing so, a parameter wouldn’t be initialized repeatedly, say, in every minibatch.

                                        -

                                        In this example, all operators are created as OpDesc protobuf messages, and all variables are VarDesc. These protobuf messages are saved in a BlockDesc protobuf message.

                                        -
                                        -
                                        -

                                        Backward Part

                                        -

                                        The fifth line optimize(cost) calls two functions, ConstructBackwardGraph and ConstructOptimizationGraph.

                                        -

                                        ConstructBackwardGraph traverses the forward graph in the BlockDesc protobuf message and builds the backward part.

                                        -

                                        -

                                        According to the chain rule of gradient computation, ConstructBackwardGraph would

                                        -
                                          -
                                        1. create a gradient operator G for each operator F,
                                        2. -
                                        3. make all inputs, outputs, and outputs’ gradient of F as inputs of G,
                                        4. -
                                        5. create gradients for all inputs of F, except for those who don’t have gradients, like x and l, and
                                        6. -
                                        7. make all these gradients as outputs of G.
                                        8. -
                                        -
                                        -
                                        -

                                        Optimization Part

                                        -

                                        For each parameter, like W and b created by layer.fc, marked as double circles in above graphs, ConstructOptimizationGraph creates an optimization operator to apply its gradient. Here results in the complete graph:

                                        -

                                        -
                                        -
                                        -
                                        -

                                        Block and Graph

                                        -

                                        The word block and graph are interchangable in the desgin of PaddlePaddle. A Block is a metaphore of the code and local variables in a pair of curly braces in programming languages, where operators are like statements or instructions. A graph of operators and variables is a representation of the block.

                                        -

                                        A Block keeps operators in an array BlockDesc::ops

                                        -
                                        message BlockDesc {
                                        -  repeated OpDesc ops = 1;
                                        -  repeated VarDesc vars = 2;
                                        -}
                                        -
                                        -
                                        -

                                        in the order that they appear in user programs, like the Python program at the beginning of this article. We can imagine that in ops, we have some forward operators, followed by some gradient operators, and then some optimization operators.

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/graph_survey.html b/develop/doc_cn/design/graph_survey.html deleted file mode 100644 index 560d8df6a4c..00000000000 --- a/develop/doc_cn/design/graph_survey.html +++ /dev/null @@ -1,453 +0,0 @@ - - - - - - - - - - - - - Survey on Graph — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Survey on Graph

                                        -

                                        Neural network framework often provides symbolic API for users to write network topology conveniently. This doc manily focus on symbolic API in most popular neural network frameworks, and try to find out how to parse symbolic configuration to a portable file, such as protobuf or json.

                                        -
                                        -

                                        Mxnet

                                        -

                                        The core concept of symbolic API is Symbol. Mxnet implements Symbol class in C++, and export to Python using C-API. Please refer to the comments in Mxnet:

                                        -

                                        Symbol is help class used to represent the operator node in Graph. -Symbol acts as an interface for building graphs from different components like Variable, Functor and Group. Symbol is also exported to python front-end (while Graph is not) to enable quick test and deployment. Conceptually, symbol is the final operation of a graph and thus including all the information required (the graph) to evaluate its output value.

                                        -

                                        A simple network topology wrote by Symbol is as follows:

                                        -
                                        def get_symbol(num_classes=10, **kwargs):
                                        -    data = mx.symbol.Variable('data')
                                        -    data = mx.symbol.Flatten(data=data)
                                        -    fc1  = mx.symbol.FullyConnected(data = data, name='fc1', num_hidden=128)
                                        -    act1 = mx.symbol.Activation(data = fc1, name='relu1', act_type="relu")
                                        -    fc2  = mx.symbol.FullyConnected(data = act1, name = 'fc2', num_hidden = 64)
                                        -    act2 = mx.symbol.Activation(data = fc2, name='relu2', act_type="relu")
                                        -    fc3  = mx.symbol.FullyConnected(data = act2, name='fc3', num_hidden=num_classes)
                                        -    mlp  = mx.symbol.SoftmaxOutput(data = fc3, name = 'softmax')
                                        -    return mlp
                                        -
                                        -
                                        -

                                        Varible here is actually a Symbol. Every basic Symbol will correspond to one Node, and every Node has its own NodeAttr. There is a op field in NodeAttr class, when a Symbol represents Variable(often input data), the op field is null.

                                        -

                                        Symbol contains a data member, std::vector outputs, and NodeEntry cantains a poniter to Node. We can follow the Node pointer to get all the Graph.

                                        -

                                        And Symbol can be saved to a Json file.

                                        -

                                        Here is a detailed example:

                                        -
                                        >>> import mxnet as mx
                                        ->>> data = mx.symbol.Variable('data')
                                        ->>> print data.debug_str()
                                        -Variable:data
                                        -
                                        ->>> data = mx.symbol.Flatten(data=data)
                                        ->>> print data.debug_str()
                                        -Symbol Outputs:
                                        -    output[0]=flatten0(0)
                                        -Variable:data
                                        ---------------------
                                        -Op:Flatten, Name=flatten0
                                        -Inputs:
                                        -    arg[0]=data(0) version=0
                                        -
                                        ->>> fc1  = mx.symbol.FullyConnected(data = data, name='fc1', num_hidden=128)
                                        ->>> print fc1.debug_str()
                                        -Symbol Outputs:
                                        -    output[0]=fc1(0)
                                        -Variable:data
                                        ---------------------
                                        -Op:Flatten, Name=flatten0
                                        -Inputs:
                                        -    arg[0]=data(0) version=0
                                        -Variable:fc1_weight
                                        -Variable:fc1_bias
                                        ---------------------
                                        -Op:FullyConnected, Name=fc1
                                        -Inputs:
                                        -    arg[0]=flatten0(0)
                                        -    arg[1]=fc1_weight(0) version=0
                                        -    arg[2]=fc1_bias(0) version=0
                                        -Attrs:
                                        -    num_hidden=128
                                        -
                                        -
                                        -
                                        -
                                        -

                                        TensorFlow

                                        -

                                        The core concept of symbolic API is Tensor. Tensorflow defines Tensor in Python. Please refer to the comments in TensorFlow:

                                        -

                                        A Tensor is a symbolic handle to one of the outputs of an Operation. It does not hold the values of that operation’s output, but instead provides a means of computing those values in a TensorFlow Session.

                                        -

                                        A simple example is as follows:

                                        -
                                          # Build a dataflow graph.
                                        -  c = tf.constant([[1.0, 2.0], [3.0, 4.0]])
                                        -  d = tf.constant([[1.0, 1.0], [0.0, 1.0]])
                                        -  e = tf.matmul(c, d)
                                        -
                                        -  # Construct a `Session` to execute the graph.
                                        -  sess = tf.Session()
                                        -
                                        -  # Execute the graph and store the value that `e` represents in `result`.
                                        -  result = sess.run(e)
                                        -
                                        -
                                        -

                                        The main method of Tensor is as follows:

                                        -
                                        @property
                                        -def op(self):
                                        -  """The `Operation` that produces this tensor as an output."""
                                        -  return self._op
                                        -
                                        -@property
                                        -def dtype(self):
                                        -   """The `DType` of elements in this tensor."""
                                        -  return self._dtype
                                        -
                                        -@property
                                        -def graph(self):
                                        -  """The `Graph` that contains this tensor."""
                                        -  return self._op.graph
                                        -
                                        -@property
                                        -def name(self):
                                        -  """The string name of this tensor."""
                                        -  if not self._op.name:
                                        -    raise ValueError("Operation was not named: %s" % self._op)
                                        -  return "%s:%d" % (self._op.name, self._value_index)
                                        -
                                        -@property
                                        -def device(self):
                                        -  """The name of the device on which this tensor will be produced, or None."""
                                        -  return self._op.device
                                        -
                                        -
                                        -

                                        Tensor can be taken as target to run by session. Tensor contains all the information of Graph, and tracks data dependency.

                                        -

                                        Here is a detailed example:

                                        -
                                        >>> import tensorflow as tf
                                        ->>> c = tf.constant([[1.0, 2.0], [3.0, 4.0]])
                                        ->>> print c.graph
                                        -<tensorflow.python.framework.ops.Graph object at 0x10f256d50>
                                        ->>> d = tf.constant([[1.0, 1.0], [0.0, 1.0]])
                                        ->>> print d.graph
                                        -<tensorflow.python.framework.ops.Graph object at 0x10f256d50>
                                        ->>> e = tf.matmul(c, d)
                                        ->>> print e.graph
                                        -<tensorflow.python.framework.ops.Graph object at 0x10f256d50>
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Dynet

                                        -

                                        The core concept of symbolic API is Expression, and Dynet defines Expression class in C++.

                                        -

                                        A simple example is as follows:

                                        -
                                        ComputationGraph cg;
                                        -Expression W = parameter(cg, pW);
                                        -
                                        -Expression in = input(cg, xs[i]);
                                        -Expression label = input(cg, ys[i]);
                                        -Expression pred = W * in;
                                        -Expression loss = square(pred - label);
                                        -
                                        -
                                        -

                                        The input data and parameter are also represented by Expression. Every basci Expression corresponds to a Node. And input data is also a Node.

                                        -

                                        Expression has a data member ComputationGraph, and ComputationGraph will be modified in users’ configuring process. Expression can be a running target, beacuse Expression contains all dependency.

                                        -

                                        Here is a detailed example:

                                        -

                                        write topology in C++

                                        -
                                        ComputationGraph cg;
                                        -Expression W = parameter(cg, pW);
                                        -cg.print_graphviz();
                                        -
                                        -Expression pred = W * xs[i];
                                        -cg.print_graphviz();
                                        -
                                        -Expression loss = square(pred - ys[i]);
                                        -cg.print_graphviz();
                                        -
                                        -
                                        -

                                        compile and print

                                        -
                                        # first print
                                        -digraph G {
                                        -  rankdir=LR;
                                        -  nodesep=.05;
                                        -  N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"];
                                        -}
                                        -# second print
                                        -digraph G {
                                        -  rankdir=LR;
                                        -  nodesep=.05;
                                        -  N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"];
                                        -  N1 [label="v1 = v0 * -0.98"];
                                        -  N0 -> N1;
                                        -}
                                        -# third print
                                        -digraph G {
                                        -  rankdir=LR;
                                        -  nodesep=.05;
                                        -  N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"];
                                        -  N1 [label="v1 = v0 * -0.98"];
                                        -  N0 -> N1;
                                        -  N2 [label="v2 = -1.88387 - v1"];
                                        -  N1 -> N2;
                                        -  N3 [label="v3 = -v2"];
                                        -  N2 -> N3;
                                        -  N4 [label="v4 = square(v3)"];
                                        -  N3 -> N4;
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Conclusion

                                        -

                                        Actually, Symbol/Tensor/Expression in Mxnet/TensorFlow/Dynet are the same level concepts. We use a unified name Expression here, this level concept has following features:

                                        -
                                          -
                                        • Users wirte topoloy with symbolic API, and all return value is Expression, including input data and parameter.
                                        • -
                                        • Expression corresponds with a global Graph, and Expression can also be composed.
                                        • -
                                        • Expression tracks all dependency and can be taken as a run target
                                        • -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/if_else_op.html b/develop/doc_cn/design/if_else_op.html deleted file mode 100644 index c7c101cd58b..00000000000 --- a/develop/doc_cn/design/if_else_op.html +++ /dev/null @@ -1,309 +0,0 @@ - - - - - - - - - - - - - The IfElse Operator — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        The IfElse Operator

                                        -

                                        PaddlePaddle’s IfElse operator differs from TensorFlow’s:

                                        -
                                          -
                                        • the TensorFlow version takes a scalar boolean value as the condition so that the whole mini-batch goes to either the true or the false branch, whereas
                                        • -
                                        • the PaddlePaddle version takes a vector of boolean value as the condition, and instances corresponding to true values go to the true branch, those corresponding to false values go to the false branch.
                                        • -
                                        -
                                        -

                                        Example

                                        -

                                        The following PaddlePaddle program shows the usage of the IfElse operator:

                                        -
                                        import paddle as pd
                                        -
                                        -x = minibatch([10, 20, 30]) # shape=[None, 1]
                                        -y = var(1) # shape=[1], value=1
                                        -z = minibatch([10, 20, 30]) # shape=[None, 1]
                                        -cond = larger_than(x, 15) # [false, true, true]
                                        -
                                        -ie = pd.ifelse()
                                        -with ie.true_block():
                                        -    d = pd.layer.add(x, y)
                                        -    ie.output(d, pd.layer.softmax(d))
                                        -with ie.false_block():
                                        -    d = pd.layer.fc(z)
                                        -    ie.output(d, d+1)
                                        -o1, o2 = ie(cond)
                                        -
                                        -
                                        -

                                        A challenge to implement the IfElse operator is to infer those variables to be split, or, say, to identify the variable of the mini-batch or those derived from the mini-batch.

                                        -

                                        An equivalent C++ program is as follows:

                                        -
                                        namespace pd = paddle;
                                        -
                                        -int x = 10;
                                        -int y = 1;
                                        -int z = 10;
                                        -bool cond = false;
                                        -int o1, o2;
                                        -if (cond) {
                                        -  int d = x + y;
                                        -  o1 = z;
                                        -  o2 = pd::layer::softmax(z);
                                        -} else {
                                        -  int d = pd::layer::fc(z);
                                        -  o1 = d;
                                        -  o2 = d+1;
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/infer_var_type.html b/develop/doc_cn/design/infer_var_type.html deleted file mode 100644 index 4b303634d3f..00000000000 --- a/develop/doc_cn/design/infer_var_type.html +++ /dev/null @@ -1,326 +0,0 @@ - - - - - - - - - - - - - Design Doc: InferVarType — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: InferVarType

                                        -
                                        -

                                        The Problem Posed

                                        -

                                        The variable in our design can hold variant types. Such as LoDTensor and SelectedRows. An operator should be able to inference the variable types of its output.

                                        -

                                        For example, a lookup table operator takes two LoDTensor; one is a float tensor as the embedding table, the other is an int tensor as word ID. The gradient operator of lookup table will generate a SelectedRows as its output. A sum operator can take both LoDTensor and SelectedRows as its inputs and will generate a LoDTensor if any of its inputs is LoDTensor, otherwise, the sum operator will generate SelectedRows as its output.

                                        -

                                        The variable type will be constant at runtime. Every variable’s type can either be set by the user (input data and parameter) or be inferred by the operator in compile time.

                                        -
                                        -
                                        -

                                        Proposed Solution

                                        -

                                        The InferVarType is a compile-time function which is registered to each operator. The inferface of that function is:

                                        -
                                        using InferVarTypeFN = std::function<
                                        -    void (const OpDescBind& /*op_desc*/, BlockDescBind* /*block*/)>;
                                        -
                                        -
                                        -

                                        It takes an operator description as its input and will write the output variable type and store them in block description.

                                        -

                                        The InferVarTypeFN will be registered in OpInfo, to replace infer_var_type_ field. The OpInfo should be

                                        -
                                        struct OpInfo {
                                        -  InferVarTypeFN infer_var_type_;
                                        -  ...
                                        -};
                                        -
                                        -
                                        -

                                        The default InferVarType will set output type as LoDTensor. It can be done by GetInferVarType().

                                        -
                                        void DefaultInferVarType(const OpDescBind& op_desc, BlockDescBind* block) {
                                        -  // set the output type of variable as `LoDTensor`.
                                        -  // ...
                                        -}
                                        -
                                        -struct OpInfo {
                                        -  InferVarTypeFN infer_var_type_;
                                        -  InferVarTypeFN GetInferVarType() const {
                                        -    if (infer_var_type_) {
                                        -      return infer_var_type_;
                                        -    } else {
                                        -      return DefaultInferVarType;
                                        -    }
                                        -  }
                                        -};
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Register InferVarType

                                        -

                                        We provide a thin base class for registering an InferVarTypeFN. To use a base class will ease the implementation of registry since we can detect the registry entry is an InferVarTypeFN or not.

                                        -
                                        class VarTypeInferer {
                                        -public:
                                        -  virtual void operator()(const OpDescBind& op_desc, BlockDescBind* block) const = 0;
                                        -}
                                        -
                                        -
                                        -

                                        Operator developers can write the specialize VarTypeInferer as follow.

                                        -
                                        class SpecialVarTypeInferer : public VarTypeInferer {
                                        -public:
                                        -  virtual void operator()(const OpDescBind& op_desc, BlockDescBind* block) const {
                                        -    // .. own logic
                                        -  }
                                        -}
                                        -
                                        -
                                        -

                                        Then user can register the InferVarType just like GradOpDescMaker and OpInfoMaker.

                                        -
                                        REGISTER_OPERATOR(some_op, OpType, SpecialVarTypeInferer, ...);
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/kernel_hint_design.html b/develop/doc_cn/design/kernel_hint_design.html deleted file mode 100644 index e19fd72eff0..00000000000 --- a/develop/doc_cn/design/kernel_hint_design.html +++ /dev/null @@ -1,314 +0,0 @@ - - - - - - - - - - - - - Problem — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Problem

                                        -

                                        In PaddlePaddle’s Design, one Operator may have multiple kernels. Users may have some personal preference to choose a certain type of kernel for an operator, such as force_cpu to choose a CPU kernel, use_cudnn to choose a CUDNN kernel, we need to provide a way for users to do this.

                                        -

                                        In the current design, we use KernelType to describe one kernel.

                                        -
                                        struct KernelType {
                                        -  Place place_;
                                        -  DataType data_type_;
                                        -  LayoutType layout_;
                                        -};
                                        -
                                        -
                                        -

                                        place_ data_type_ and layout_ can be got from the input tensors of the operator, GetActualKernelType(inputs) use inputs to infer the proper kernel key that fit the incoming data, but users can not directly configure it.

                                        -

                                        The design also provides a virtual method GetExpectedKernelType that user can overload and use to choose the KernelType they want to use.

                                        -

                                        So we should send the information user defined in proto to GetExpectedKernelType for choosing a kernel.

                                        -

                                        The problem is, how should we define and send the information for GetExpectedKernelType to use?

                                        -
                                        -
                                        -

                                        Solution

                                        -
                                        -

                                        Potential choice

                                        -
                                          -
                                        1. Do nothing, let the user add the information they want to operator‘s attribute and get them inside GetExpectedKernelType, this can work properly. But there is a little problem that users may define many kinds of hints for the same purpose, such as force_cpu, use_cpu, cpu_kernel to choose CPU kernel, and use_cudnn, force_cudnn, cudnn_kernel to choose CUDNN kernel.
                                        2. -
                                        3. Pre-define all the needed option and use a single attr key such as kernel_hint for the user, this is not so flexible if the user wants to define some more kind of hint.
                                        4. -
                                        -
                                        -
                                        -

                                        Final choice

                                        -

                                        To provide enough flexibility while avoiding confusion definition, we can define some global constants for these attribute names, such as force_cpu, use_cudnn, use_mkldnn for a user to choose.

                                        -

                                        In C++

                                        -
                                        const std::string kForceCPU = "force_cpu";
                                        -const std::string kUseCUDNN = "use_cudnn";
                                        -const std::string kUseMKLDNN = "use_mkldnn";
                                        -
                                        -KernelType GetExpectedKernelType() {
                                        -  if (Attr<bool>(kForceCPU)) {
                                        -    return KernelType(CPUPlace, ...)
                                        -  } else {
                                        -    ...
                                        -  }
                                        -}
                                        -
                                        -
                                        -

                                        In Python code

                                        -
                                        FORCE_CPU = core.kForceCPU()
                                        -
                                        -def xx_layer(..., force_cpu=false):
                                        -  layer_helper = LayerHelper(...)
                                        -  layer_helper.append_op(
                                        -    type="xx",
                                        -    attr={FORCE_CPU: force_cpu})
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/kernel_selection.html b/develop/doc_cn/design/kernel_selection.html deleted file mode 100644 index 8915a43af01..00000000000 --- a/develop/doc_cn/design/kernel_selection.html +++ /dev/null @@ -1,345 +0,0 @@ - - - - - - - - - - - - - Background — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Background

                                        -

                                        Every operator has many kernels because there are multiple data types, places, data layout, library type that Fluid supports. We use the OpKernelType to describe kernel types that operators can hold.

                                        -

                                        The OpKernelType is as follows:

                                        -
                                        struct OpKernelType {
                                        -  Place place_;
                                        -  DataType data_type_;
                                        -  DataLayout data_layout_;
                                        -  LibraryType library_type_;
                                        -};
                                        -
                                        -
                                        -
                                          -
                                        • The place_ is a descriptor of the device, e.g., CPUPlace, CUDAPlace.
                                        • -
                                        • The data_type_ is the data type that this kernel performs on, e.g., FP32, INT64. Note that one kernel may have inputs with different data types. However, it will be a major data_type. For example, the cross_entropy takes int64 as it label, and double/float as its input logit and output cost. The major data_type of cross_entropy is float or double.
                                        • -
                                        • The data_layout_ is useful for some computational library. One example is that MKLDNN uses many kinds of layout, such as nChw8c. Each kind of layout will invoke the different kernel.
                                        • -
                                        • The library_type_ describes the computational library, e.g., MKLDNN, CUDNN.
                                        • -
                                        -
                                        -
                                        -

                                        Problem

                                        -

                                        We register a kernel for every operator and every kernel type ideally. However, it is impracticable for the following situations.

                                        -
                                          -
                                        1. Some operators, like CRF, are complicated and inefficient to be implemented on GPU. The CRF operator will only have a CPU kernel.
                                        2. -
                                        3. Some operators will take too many memory. It is better to force them into CPU. However, the rest of operators in this neural network will be performed on GPU, i.e., model parallel problem.
                                        4. -
                                        5. Some layout and place are particular. One example is that MKLDNN uses nChw8 and there is no other library uses nChw8c.
                                        6. -
                                        -

                                        Take one situation to give a detailed explanation, if we have two Operators: OP1 and OP2, OP1 has one output op1_to_op2, and op1_to_op2 is the input of OP2.

                                        -

                                        If OP1 and OP2 run on the same place(for example CPUPlace), then op1_2_op2 can be used directly by OP2.

                                        -
                                        OP1(CPUPlace)
                                        -     |
                                        - op1_2_op2
                                        -     |
                                        -OP2(CPUPlace)
                                        -
                                        -
                                        -

                                        If OP1 and OP2 run one different place, then OP2 cannot use op1_2_op2 directly.

                                        -

                                        Problems under these situations are similar. We can formalize this problem as follow.

                                        -

                                        We register kernels with types $KT = {kt_1, kt_2, kt_3, ...}$ for one operator. The inputs of this operator should be run on kernel type $kt_{?}$, which the $kt_{?} \notin KT$. How to cast the input of this operator from $kt_{?}$ to any of kernel type in $KT$.

                                        -
                                        -
                                        -

                                        Solution: data transform

                                        -

                                        It is clear that transforming inputs of an operator to adapt another kernel type is not related to the particular operator. So we should register these transformation methods as global methods.

                                        -

                                        We can infer kernel type for each input of an operator. We let this kernel type as actual kernel type for var, which means this kernel type is the kernel type that can process this input variable.

                                        -

                                        We can get a kernel type by 1) The configuration of operator description. (Users may want to force use MKL for conv operator). 2) The place of the current executor. (Executor is running on GPU). This kernel type is what we expect the operator will be performed on. We let this kernel type as expect kernel type.

                                        -

                                        We transform the input data from actual to expect if the actual kernel type is not as same as expect kernel type.

                                        -

                                        The algorithm is described as following

                                        -
                                        void OperatorWithKernel::Run(
                                        -        const Scope& scope,
                                        -        const platform::Place& place) const {
                                        -  ExecutionContext ctx(...);
                                        -  auto expected_kernel_key = this->GetExpectedKernelType(ctx);
                                        -
                                        -  Scope& new_scope = scope.NewScope();
                                        -
                                        -  for (auto& var_name : this->Inputs()) {
                                        -    auto* tensor_in = GetTensor(var_name);
                                        -    auto kernel_type_for_var = this->GetKernelTypeForVar(...);
                                        -    if (kernel_type_for_var.place_ != expected_kernel_key.place_) {
                                        -      auto* trans_var = new_scope.Var(var_name);
                                        -      auto* out = DataTransform(expected_kernel_key,
                                        -                                kernel_type_for_var,
                                        -                                *tensor_in);
                                        -      CopyVariableWithTensor(...);
                                        -    }
                                        -  }
                                        -
                                        -  auto kernel = kernels.find(expected_kernel_key);
                                        -  kernel->Compute(ExecutionContext(...));
                                        -}
                                        -
                                        -
                                        -

                                        then the actual process for the multi-device above will be:

                                        -
                                        OP1(CPUPlace)
                                        -     |
                                        -op1_2_op2(on CPU)
                                        -     |
                                        -[transform](from CPU to GPU)
                                        -     |
                                        -op1_2_op2(on GPU)
                                        -     |
                                        -OP2(CUDAPlace)
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/memory_optimization.html b/develop/doc_cn/design/memory_optimization.html deleted file mode 100644 index c7d87940ee1..00000000000 --- a/develop/doc_cn/design/memory_optimization.html +++ /dev/null @@ -1,454 +0,0 @@ - - - - - - - - - - - - - Memory Optimization — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Memory Optimization

                                        -
                                        -

                                        Problem

                                        -

                                        In a lecture from Andrew Ng, he attributes the recent sucess of AI due to a combination of these:

                                        -
                                          -
                                        • Availability of Big Data
                                        • -
                                        • Supercomputing power to process this Big Data over very large neural networks
                                        • -
                                        • Modern algorithms
                                        • -
                                        -

                                        Following graph shows the details:

                                        -

                                        -

                                        Larger model usually bring better performance. However, GPU memory is limited. For example, the memory size of a GTX TITAN X is only 12GB. To train complex and large models, we have to take care of memory usage. Besides, memory optimization is also necessary in both online/mobile inference.

                                        -
                                        -
                                        -

                                        Solution

                                        -
                                        -

                                        Basic Strategy

                                        -

                                        There are some basic strategies to improve memory usage, including in-place operations and memory sharing.

                                        -
                                        -

                                        In-place Operation

                                        -

                                        In a relu activation operator:

                                        -

                                        $y = \max(x, 0)$

                                        -

                                        If the variable x is not used in any other operator, we can make an in-place operation. In other words, the memory block of variable y and variable x will be the same. In-place operations will save 50% memory occupancy immediately.

                                        -
                                        -
                                        -

                                        Memory Sharing

                                        -

                                        Not all operators support in-place operations. Memory sharing is a more general strategy.

                                        -

                                        Following is an example:

                                        -
                                        a = op1(b, c);
                                        -d = op2(a)
                                        -e = op3(d, f)
                                        -
                                        -
                                        -

                                        In this case, variable a is no longer used, and op2 does not support in-place operation. After op2 finishes, we can put the memory of variable a to a memory pool. Then, variable e can share the memory of variable a from the pool.

                                        -
                                        -
                                        -
                                        -

                                        Live Variable Analysis

                                        -

                                        It’s not enough to only have some basic strategies. The pre-requisite of memory optimization is to know if a variable is still “live” after an operation.

                                        -

                                        In our design, the neural network topology is defined as a program. Luckily, live variable analysis is a classic problem in compilers which can be used in many stages, such as register allocation.

                                        -

                                        In compilers, the front end of the compiler translates programs into an intermediate language with an unbounded number of temporary variables. This program must run on a machine with a bounded number of registers. Two temporary variables a and b can fit into the same register, if a and b are never “in use” at the same time. Thus, many temporary variables can fit in few registers; if they don’t all fit, the excess tempory variables can be kept in memory.

                                        -

                                        Therefore, the compiler needs to analyze the intermediate-representation program to determine which temporary variables are in use at the same time. We say a variable is “live” if it holds a value that may be needed in the future, so this analysis is called liveness analysis.

                                        -

                                        We can leran these techniques from compilers. There are mainly two stages to make live variable analysis:

                                        -
                                          -
                                        • construct a control flow graph
                                        • -
                                        • solve the dataflow equations
                                        • -
                                        -
                                        -

                                        Control Flow Graph

                                        -

                                        To perform analysis on a program, it is often useful to make a control flow graph. A control flow graph (CFG) in computer science is a representation, using graph notation, of all paths that might be traversed through a program during its execution. Each statement in the program is a node in the flow graph; if statemment x can be followed by statement y, there is an egde from x to y.

                                        -

                                        Following is the flow graph for a simple loop.

                                        -

                                        -
                                        -
                                        -

                                        Dataflow Analysis

                                        -

                                        Liveness of variable “flows” around the edges of the control flow graph; determining the live range of each variable is an example of a dataflow problem. Dataflow analysis is a technique for gathering information about the possible set of values calculated at various points in a computer program.

                                        -

                                        A simple way to perform data-flow analysis of programs is to set up dataflow equations for each node of the control flow graph and solve them by repeatedly calculating the output from the input locally at each node until the whole system stabilizes.

                                        -
                                          -
                                        • Flow Graph Terminology
                                        • -
                                        -

                                        A flow graph node has out-edges that lead to sucessor nodes, and in-edges that come from predecessor nodes. The set pred[n] is all the predecessors of node n, and succ[n] is the set of sucessors. -In former control flow graph, the out-edges of node 5 are 5 –> 6 and 5 –> 2, and succ[5] = {2, 6}. The in-edges of 2 are 5 –> 2 and 1 –> 2, and pred[2] = {1, 5}.

                                        -
                                          -
                                        • Uses and Defs
                                        • -
                                        -

                                        An assignmemt to a variable or temporary defines that variable. An occurence of a variable on the right-hand side of an assginment(or in other expressions) uses the variable. We can define the def of a variable as the set of graph nodes that define it; or the def of a graph node as the set of variables that it defines; and the similarly for the use of a variable or graph node. In former control flow graph, def(3) = {c}, use(3) = {b, c}.

                                        -
                                          -
                                        • Liveness
                                        • -
                                        -

                                        A variable is live on an edge if there is a directed path from that edge to a use of the variable that does not go through any def. A variable is live-in at a node if it is live on any of the in-edges of that node; it is live-out at a node if it is live on any of the out-edges of the node.

                                        -

                                        The calcution of liveness can be solved by iteration until a fixed pointer is reached. Following is the recursive formula:

                                        -

                                        -
                                        -
                                        -
                                        -

                                        Memory optimization transpiler

                                        -

                                        At last, we take basic strategy and liveness analysis techniques learning from compilers to implement our memory optimization transpiler.

                                        -
                                        -

                                        add in-place attribute

                                        -

                                        In-place is a built-in attribute of an operator. Since we treat in-place and other operators differently, we have to add an in-place attribute for every operator.

                                        -
                                        -
                                        -

                                        contruct control flow graph

                                        -

                                        Following is the ProgramDesc protobuf of machine translation example.

                                        -
                                          -
                                        • Block0:
                                        • -
                                        -
                                        lookup_table
                                        -mul
                                        -...
                                        -while(sub-block idx 1)
                                        -...
                                        -array_to_lod_tensor
                                        -cross_entropy
                                        -...
                                        -while_grad(sub-block idx 2)
                                        -read_from_array
                                        -array_to_lod_tensor
                                        -...
                                        -
                                        -
                                        -
                                          -
                                        • Block1
                                        • -
                                        -
                                        read_from_array
                                        -read_from_array
                                        -...
                                        -write_to_array
                                        -increment
                                        -write_to_array
                                        -less_than
                                        -
                                        -
                                        -
                                          -
                                        • Block2
                                        • -
                                        -
                                        read_from_array
                                        -increment
                                        -...
                                        -write_to_array
                                        -write_to_array
                                        -
                                        -
                                        -

                                        We can transfer all the operators and variables in ProgramDesc to build a control flow graph.

                                        -
                                        class ControlFlowGraph(object):
                                        -    def __init__(self, Program):
                                        -        self._sucessors = defaultdict(set)
                                        -        self._presucessors = defaultdict(set)
                                        -        self._uses = defaultdict(set)
                                        -        self._defs = defaultdict(set)
                                        -        self._live_in = defaultdict(set)
                                        -        self._live_out = defaultdict(set)
                                        -        self._program = Program
                                        -    
                                        -    def build(self):
                                        -        pass
                                        -    
                                        -    def dataflow_analysis(self):
                                        -        pass
                                        -        
                                        -    def memory_optimization(self):
                                        -        pass
                                        -        
                                        -    def get_program(self):
                                        -        return self._program
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Make dataflow analysis

                                        -

                                        We follow the guide from compilers and try to solve the dataflow equation to get liveness of every variable. If the live-in of an operator node is different from the live-out, then we can make memory sharing.

                                        -

                                        For example:

                                        -
                                        a = op1(b, c);
                                        -d = op2(a)
                                        -e = op3(d, f)
                                        -
                                        -
                                        -

                                        The dataflow analysis result is:

                                        -
                                        live_in(op1) = {b, c, f}
                                        -live_out(op1) = {a, f}
                                        -
                                        -live_in(op2) = {a, f}
                                        -live_out(op2) = {d, f}
                                        -
                                        -live_in(op3) = {d, f}
                                        -live_out(op3) = {}
                                        -
                                        -
                                        -

                                        After op1, we can process variable b and variable c; After op2, we can process variable a. After op3, we can process variable d and variable f.

                                        -
                                        -
                                        -

                                        memory sharing policy

                                        -

                                        A memory pool will be mantained in the stage of memory optimization. Each operator node will be scanned to determine memory optimization is done or not. If an operator satifies the requirement, following policy will be taken to handle input/output variables.

                                        -
                                        if op.support_inplace():
                                        -    i --> pool
                                        -    pool --> o
                                        -else:
                                        -    pool --> o
                                        -    i --> pool
                                        -
                                        -
                                        -
                                        -
                                        -
                                        - -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/mkl/mkl_packed.html b/develop/doc_cn/design/mkl/mkl_packed.html deleted file mode 100644 index db2edaa0555..00000000000 --- a/develop/doc_cn/design/mkl/mkl_packed.html +++ /dev/null @@ -1,388 +0,0 @@ - - - - - - - - - - - - - Intel® MKL Packed on PaddlePaddle: Design Doc — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Intel® MKL Packed on PaddlePaddle: Design Doc

                                        - -
                                        -

                                        Overview

                                        -

                                        我们计划将 Intel® MKL 中引入的 GEMM Packed APIs[1] 集成到 PaddlePaddle 中,充分发挥英特尔平台的优势,有效提升PaddlePaddle在英特尔架构上的性能。 -现阶段的优化主要针对 Recurrent Neural Network(以下简称RNN)相关层(包括RecurrentLayer, GatedRecurrentLayerLstmLayer), 以及 PaddlePaddle V1 API。

                                        -
                                        -
                                        -

                                        Key Points

                                        -
                                        -

                                        Background

                                        -

                                        目前PaddlePaddle采用了 Intel® MKL库的cblas_?gemm函数,这个函数本身会在计算前将原数据转换为更适合英特尔平台的内部格式。

                                        -
                                          -
                                        1. 转换耗时 这一数据格式的转换操作(Packing),在问题本身的计算量比较小的时候,显得相对来说较为耗时。例如在DeepSpeech2 [2] 的Vanilla RNN部分中,矩阵大小是batch_size * 2048
                                        2. -
                                        3. 转换冗余 由于在现有的某些情况下(例如RNN),多次调用 cblas_?gemm 会使用相同的原数据,因此,每次调用时对原数据的重复Packing便成为了冗余。
                                        4. -
                                        -

                                        为了最大程度减少多次调用 cblas_?gemm 在Packing上的耗时,Intel® MKL 引入了以下四个API:

                                        -
                                        - -
                                        -

                                        通过使用这些API,我们可以先完成对原数据的Packing操作,再把已转换为Packed格式的数据传递给那些复用同一数据的gemm_compute函数,从而避免了Packing冗余。

                                        -
                                        -
                                        -

                                        Solution

                                        -

                                        在RNN的情况下,同一次前向、后向(forward/backward)过程中所有时间步(time step)共享同一个权重(weight)。当只做推断(inference)时,各次前向之间也都使用了相同的权重,没有必要在每次前向中每个时间步的计算时对权重进行重复的Packing操作。

                                        -

                                        我们通过使用新引入的GEMM Packed APIs,在层初始化的时候,先完成对权重的Packing操作,然后在前向,后向时复用已经转换过的权重,并在每次权重更新后,对新的权重进行转换用于下次迭代。

                                        -
                                          -
                                        • 优化前,对于序列长度(sequence length)为T的网络模型(model), N次迭代执行的转换次数为:
                                            -
                                          • inferenceN * T
                                          • -
                                          • training2 * N * T
                                          • -
                                          -
                                        • -
                                        • 优化后,对于同样设置的网络模型,其转换次数减少至:
                                            -
                                          • inference1
                                          • -
                                          • training2 * N
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Actions

                                        -

                                        添加的相关文件和目录结构如下:

                                        -
                                        PaddlePaddle/Paddle
                                        -├── ...
                                        -└── paddle/
                                        -    ├── ...
                                        -    └── gserver/
                                        -        ├── ...
                                        -        ├── layers/
                                        -        │   ├── ...
                                        -        │   ├── MKLPackedRecurrentLayer.*
                                        -        |   ├── MKLPackedGatedRecurrentLayer.*
                                        -        |   ├── MKLPackedLstmLayer.*
                                        -        |   └── MKLPackedGemm.h
                                        -        └── tests/
                                        -            ├── ...
                                        -            └── test_MKLPacked.cpp
                                        -
                                        -
                                        -
                                        -

                                        CMake

                                        -

                                        在对应的CMakeLists.txt中根据WITH_MKL是否打开,来决定是否开启MKL Packed相关功能。

                                        -
                                        -
                                        -

                                        Layers

                                        -

                                        所有的MKLPacked*Layer都继承于PaddlePaddle的基类Layer, 并添加头文件 MKLPackedGemm.h,该文件对相关GEMM Packed APIs做了封装。

                                        -
                                        -
                                        -

                                        Unit Tests

                                        -

                                        我们会添加test_MKLPacked.cpp用于MKL Packed优化后layer的测试。 -对于每一个新加的RNN layer,我们会对比如下2个方面:

                                        -
                                          -
                                        1. 对比优化后layer自身,sequence mode(rnn_use_batch=false)与batch mode(rnn_use_batch=true)的结果。
                                        2. -
                                        3. 对比优化后layer与相对应的PaddlePaddle原有layer, 在batch mode下的结果。
                                        4. -
                                        -
                                        -
                                        -

                                        Python API

                                        -

                                        计划在paddle/utils.Flags中添加use_mkl_packed的flag,用于选择是否使用相关功能,并且当编译时WITH_MKL=ON的情况下,默认设置为true

                                        -

                                        同时,在python/paddle/trainer/config_parser.py中对应的layer处,添加use_mkl_packed这个选择,方便用户在Python端选择是否启用这个功能。

                                        -

                                        具体实现方式比如:

                                        -
                                        use_mkl_packed = bool(int(g_command_config_args.get("use_mkl_packed", 0)))
                                        -if use_mkl_packed:
                                        -    self.layer_type = mkl_packed_*
                                        -
                                        -
                                        -

                                        所有相关的layer_type会以*mkl_packed_*开头,这些会在MKLPacked*Layer注册layer的时候保证,以示区分。

                                        -
                                        -
                                        -

                                        Benchmarking

                                        -

                                        会添加相应的脚本用于测试和对比在使用MKL Packed recurrent layers 前后的网络性能。

                                        -
                                        -
                                        - -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/mkl/mkldnn.html b/develop/doc_cn/design/mkl/mkldnn.html deleted file mode 100644 index 2c986c167aa..00000000000 --- a/develop/doc_cn/design/mkl/mkldnn.html +++ /dev/null @@ -1,469 +0,0 @@ - - - - - - - - - - - - - Intel® MKL-DNN on PaddlePaddle: Design Doc — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Intel® MKL-DNN on PaddlePaddle: Design Doc

                                        -

                                        我们计划将英特尔深度神经网络数学库Intel MKL-DNN -(Intel Math Kernel Library for Deep Neural Networks)集成到PaddlePaddle, -充分展现英特尔平台的优势,有效提升PaddlePaddle在英特尔架构上的性能。

                                        -
                                        -
                                        -Figure 1. PaddlePaddle on IA -

                                        近期目标

                                        -
                                          -
                                        • 完成常用Layer的MKL-DNN实现。
                                        • -
                                        • 完成常见深度神经网络VGG,GoogLeNet 和 ResNet的MKL-DNN实现。
                                        • -
                                        -

                                        目前的优化,主要针对PaddlePaddle在重构之前的代码框架以及V1的API。 -具体的完成状态可以参见这里

                                        - -
                                        -

                                        Overview

                                        -

                                        我们会把MKL-DNN会作为第三方库集成进PaddlePaddle,与其他第三方库一样,会在编译PaddlePaddle的时候下载并编译MKL-DNN。

                                        -

                                        同时,为了进一步提升PaddlePaddle在基本数学运算的计算速度,我们也将MKLML即(MKL small library[1]) -作为另一个第三方库集成进PaddlePaddle,它只会包括生成好的动态库和头文件。

                                        -

                                        MKL,MKLML以及MKL-DNN三者关系如下表:

                                        -

                                        | Name | Open Source | License | Descriptions | -| :———- | :————— | :———- | :———— | -| MKL | No | Proprietary | Accelerate math processing routines | -| MKLML | No | Proprietary | Small package of MKL, especially for Machine Learning | -| MKL-DNN | Yes | Apache 2.0 | Accelerate primitives processing routines especially for Deep Neural Networks |

                                        -

                                        MKLML可以与MKL-DNN共同使用,以此达到最好的性能。

                                        -
                                        -
                                        -Figure 2. PaddlePaddle with MKL Engines -
                                        -
                                        -

                                        Actions

                                        -

                                        添加的相关文件和目录结构如下:

                                        -
                                        PaddlePaddle/Paddle
                                        -├── ...
                                        -├── cmake/
                                        -│   ├── external/
                                        -│   │   ├── ...
                                        -│   │   ├── mkldnn.cmake
                                        -│   │   └── mklml.cmake
                                        -└── paddle/
                                        -    ├── ...
                                        -    ├── math/
                                        -    │   ├── ...
                                        -    │   └── MKLDNNMatrix.*
                                        -    └── gserver/
                                        -        ├── ...
                                        -        ├── layers/
                                        -        │   ├── ...
                                        -        │   └── MKLDNN*Layer.*
                                        -        ├── activations/
                                        -        │   ├── ...
                                        -        │   └── MKLDNNActivations.*
                                        -        └── tests/
                                        -            ├── ...
                                        -            ├── MKLDNNTester.*
                                        -            └── test_MKLDNN.cpp
                                        -
                                        -
                                        -
                                        -

                                        CMake

                                        -

                                        CMakeLists.txt中提供一个与MKL有关的总开关:WITH_MKL,它负责决定编译时是否使用MKLML和MKL-DNN

                                        -
                                          -
                                        • WITH_MKLML 控制是否使用MKLML库。 -当打开WITH_MKL时,会自动使用MKLML库作为PaddlePaddle的CBLAS和LAPACK库,同时会开启Intel OpenMP用于提高MKLML的性能。 -编译时会把对应的头文件和库放在build/third_party/install/mklml/*目录下对应的地方。 -MKLML的库目前都是动态库,主要包括libiomp5.solibmklml_intel.so
                                        • -
                                        • WITH_MKLDNN 控制是否使用MKL-DNN。 -当开启WITH_MKL时,会自动根据硬件配置[2]选择是否编译MKL-DNN。 -编译时会把对应的头文件和库放在build/third_party/install/mkldnn/*目录下对应的地方。 -MKL-DNN的库目前只有动态库libmkldnn.so
                                        • -
                                        -
                                        -
                                        -

                                        Matrix

                                        -

                                        目前在PaddlePaddle中数据都是以NCHW的格式存储,但是在MKL-DNN中的排列方式不止这一种。 -所以我们定义了一个MKLDNNMatrix用于管理MKL-DNN数据的不同格式以及相互之间的转换。

                                        -
                                        -
                                        -Figure 3. MKLDNNMatrix -
                                        -
                                        -

                                        Layers

                                        -

                                        所有MKL-DNN的Layers都会继承于MKLDNNLayer,该类继承于PaddlePaddle的基类Layer。 -在MKLDNNLayer中会提供一些必要的接口和函数,并且会写好forwardbackward的基本逻辑, -子类只需要使用定义好的接口,实现具体的函数功能即可。

                                        -
                                        -
                                        -Figure 4. MKLDNNLayer -

                                        每个MKLDNNLayer都包含用于内部存储和外部存储的一系列MKLDNNMatrix:

                                        -
                                          -
                                        • 内部存储(internel memory):inVal_,inGrad_,outVal_outGrad_,分别代表输入数据,输入梯度,输出数据和输出梯度。
                                        • -
                                        • 外部存储(external memory):都是以ext开头,比如extInVal_extInGrad_,它们主要是用于, -当数据格式与PaddlePaddle默认的NCHW格式不匹配时,转换内存的工作。 -需要注意的是,PaddlePaddle的activation会直接使用output_.valueoutput_.grad, -所以extOutVal_extOutGrad_必须分别与output_.valueoutput_.grad共享内存, -如果不需要外部存储用于转换,那么对应的内部存储也会与它们共享内存。
                                        • -
                                        • 转换函数(resetXXX): 包括resetInValueresetInGradresetOutValueresetOutGrad, -表示对输入数据,输入梯度,输出数据和输出梯度的转换。 -这些函数会根据输入参数重新设置内部和外部存储,当然这两者也可以相等,即表示不需要转换。
                                        • -
                                        -

                                        注意:每个MKLDNNlayer的子类只需要使用内部存储就可以了,所有外部的转换工作都会在reset系列函数中都准备好。

                                        -
                                        -
                                        -

                                        Activations

                                        -

                                        在重构前的PaddlePaddle中,激活函数是独立于Layer的概念,并且输入输出都是共用一块内存, -所以添加了对应的MKLDNNActivation来实现,方式类似于MKLDNNLayer

                                        -
                                        -
                                        -

                                        Parameters

                                        -

                                        对于有参数的层,我们会保证MKLDNNLayer使用的参数与PaddlePaddle申请的buffer共用一块内存。 -如果存在数据排列格式不一样的情况时,我们会在网络训练之前把格式转换为MKL-DNN希望的格式, -在训练结束的时候再保存为PaddlePaddle的格式,但是整个训练过程中不需要任何转换。 -这样既使得最终保存的参数格式与PaddlePaddle一致,又可以避免不必要的转换。

                                        -
                                        -
                                        -

                                        Gradients

                                        -

                                        由于MKL-DNN的操作都是直接覆盖的形式,也就是说输出的结果不会在原来的数据上累加, -这样带来的好处就是不需要一直清空memory,节省了不必要的操作。 -但是注意的是,当网络出现分支且在backward的时候,需要累加不同Layer传过来的梯度。 -所以在MKLDNNlayer中实现了一个merge的方法,此时每个小分支的Input Gradient -会先临时保存在MKLDNNMatrix中,由分支处的Layer负责求和,并把结果放到当前层的output_.grad中。 -所以整体上,在实现每个子类的时候就不需要关心分支的事情了。

                                        -
                                        -
                                        -Figure 5. Merge Gradients -
                                        -
                                        -

                                        Unit Tests

                                        -

                                        我们会添加test_MKLDNN.cppMKLDNNTester.*用于MKL-DNN的测试。 -测试分为每个Layer(或Activation)的单元测试和简单网络的整体测试。 -每个测试会对比PaddlePaddle中CPU算出的结果与MKL-DNN的结果,小于某个比较小的阈值认为通过。

                                        -
                                        -
                                        -

                                        Python API

                                        -

                                        目前只考虑v1 API

                                        -

                                        计划在python/paddle/trainer/config_parser.py里面添加use_mkldnn这个选择,方便用户选择使用MKL-DNN的layers。

                                        -

                                        具体实现方式比如:

                                        -
                                        use_mkldnn = bool(int(g_command_config_args.get("use_mkldnn", 0)))
                                        -if use_mkldnn
                                        -    self.layer_type = mkldnn_*
                                        -
                                        -
                                        -

                                        所有MKL-DNN的layer_type会以*mkldnn_*开头,这些会在MKLDNN*Layer注册layer的时候保证,以示区分。

                                        -

                                        同时,会在paddle/utils.Flags中添加一个use_mkldnn的flag,用于选择是否使用MKL-DNN的相关功能。

                                        -
                                        -
                                        -

                                        Benchmarking

                                        -

                                        会添加相应的脚本在这里,用于测试和对比在使用MKL-DNN前后的CNN网络性能。 -测试的性能对比结果会在IntelOptimizedPaddle.md

                                        -
                                        -
                                        -

                                        Others

                                        -
                                          -
                                        1. 如果在使用MKL-DNN的情况下,会把CPU的Buffer对齐为4096,具体可以参考MKL-DNN中的memory
                                        2. -
                                        3. 深入PaddlePaddle,寻找有没有其他可以优化的可能,进一步优化。比如可能会用OpenMP改进SGD的更新性能。
                                        4. -
                                        -
                                        -
                                        -
                                        -

                                        Design Concerns

                                        -

                                        为了更好的符合PaddlePaddle的代码风格[3],同时又尽可能少的牺牲MKL-DNN的性能[4]。

                                        -

                                        我们总结出一些特别需要注意的点:

                                        -
                                          -
                                        1. 使用**deviceId_**。为了尽可能少的在父类Layer中添加变量或者函数, -我们决定使用已有的deviceId_变量来区分layer的属性,定义-2MKLDNNLayer特有的设备ID。
                                        2. -
                                        3. 重写父类Layer的init函数,修改deviceId_-2,代表这个layer是用于跑在MKL-DNN的环境下。
                                        4. -
                                        5. 创建MKLDNNBase,定义一些除了layer和memory相关的类和函数。 -包括MKL-DNN会用到MKLDNNStreamCPUEngine,和未来可能还会用到FPGAEngine等。
                                        6. -
                                        7. 如果MKL-DNN layer的后面接有cpu device,那么就会使output_.valueextOutVal_共享内存, -同时数据格式就是NCHW,这样下一个cpu device就能拿到正确的数据。 -在有普通的CPU layer时, extOutVal_extOutGrad_的格式始终是NCHW或者NC
                                        8. -
                                        -
                                        -
                                        -

                                        References

                                        -
                                          -
                                        1. MKL small libraryIntel MKL的一个子集。 -主要包括了深度学习相关的数学原语与操作,一般由MKL-DNN在发布新版本时一起更新。
                                        2. -
                                        3. MKL-DNN System Requirements。 -目前在PaddlePaddle中,仅会在支持AVX2指令集及以上的机器才使用MKL-DNN。
                                        4. -
                                        5. 原来的方案会引入nextLayer的信息。 -但是在PaddlePaddle中,无论是重构前的layer还是重构后的op,都不会想要知道next layer/op的信息。
                                        6. -
                                        7. MKL-DNN的高性能格式与PaddlePaddle原有的NCHW不同(PaddlePaddle中的cuDNN部分使用的也是NCHW,所以不存在这个问题)。 -所以需要引入一个转换方法,并且只需要在必要的时候转换这种格式,才能更好的发挥MKL-DNN的性能。
                                        8. -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/mkl/mkldnn_fluid.html b/develop/doc_cn/design/mkl/mkldnn_fluid.html deleted file mode 100644 index a0bca9184f6..00000000000 --- a/develop/doc_cn/design/mkl/mkldnn_fluid.html +++ /dev/null @@ -1,413 +0,0 @@ - - - - - - - - - - - - - Design Doc: Add MKLDNN Kernel in Fluid Operator — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Add MKLDNN Kernel in Fluid Operator

                                        -
                                        -

                                        Principles

                                        -

                                        First of all, we should follow some basical principles like:

                                        -
                                          -
                                        1. How to write a new operator. We are trying to add a new kind of kernel into operators, so basically we should follow this doc.
                                        2. -
                                        3. Supporting new Device/Library. Since MKLDNN is a new library to fluid, we should add MKLDNNDeviceContext and maybe mkldnn_helper.h, just like cudnn_helper.h.
                                        4. -
                                        5. Switch Kernel. Another important point is that we should ensure the data synchronization between different kernel types, which is this topic. So basically we should override GetExpectedKernelType and trans functions to support switching kernels.
                                        6. -
                                        7. The Keys of Operator Kernel Type. Kernel Type is a pivotal conception which can record the Place, Library, DataType and Layout.
                                        8. -
                                        -
                                        -
                                        -

                                        Sulution

                                        -

                                        In general, there are four parts we should follow to run a MKL-DNN primitive.

                                        -
                                          -
                                        • Create a primitive descriptor that describe this operator
                                        • -
                                        • Create a primitive itself by primitive descriptor and the engine
                                        • -
                                        • Create all memory buffers that primitive needed
                                        • -
                                        • Launch a stream to execute the primitive created -More details can refer to here.
                                        • -
                                        -

                                        It’s better to avoid reinitialization of primitives and memory handles in the first three stages in every iteration. So we plan to create a map to record all the primitive and memory, which should not take too much memories as discussed here.

                                        -

                                        It’s assumed that following three conditions should be satisfied.

                                        -
                                          -
                                        1. there is a unique key for each operator instance. May be the actual name of Output Tensor.
                                        2. -
                                        3. the Input Tensor inside Compute function is the one after converted.
                                        4. -
                                        5. we can get the phase(eg. is_test) inside Compute function, otherwise we need to expose this attribue to user.
                                        6. -
                                        -
                                        -

                                        Compute

                                        -

                                        The algorithm of Compute would be described as follow, let’s take conv like an example.

                                        -
                                          PADDLE_ENFORCE(platform::is_cpu_place(ctx.GetPlace()), "It must use CPUPlace.");
                                        -  PADDLE_ENFORCE(platform::is_mkldnn_library(ctx.GetLibrary()), "It must use MKLDNN Library.");
                                        -
                                        -  auto& dev_ctx = ctx.template device_context<platform::MKLDNNDeviceContext>();
                                        -
                                        -  // find primitive by unique key from mkldnn context
                                        -  // the op_key should be a unique name of this op instance
                                        -  auto& p = dev_ctx.findPrimitive(op_key + "_fwd");
                                        -
                                        -  // assuming the input tensor inside this compute function is the one after converted
                                        -  // this point should be guarantee by another mechanism
                                        -  auto& i = dev_ctx.findMemory(op_key + "_input");
                                        -  
                                        -  if (p == nullptr || i == nullptr || inputSizeChanged(p, i))  {
                                        -    auto fwd_primitive_desc = createPrimitiveDesc(ctx);
                                        -    auto* input = ctx.Input<Tensor>("Input");
                                        -    auto* filter = ctx.Input<Tensor>("Filter");
                                        -    auto* output = ctx.Output<Tensor>("Output");
                                        -    shared_ptr<mkldnn::memory> in(new mkldnn::memory(fwd_primitive_desc->src_primitive_desc(), input->data<T>()));
                                        -    shared_ptr<mkldnn::memory> wgt(new mkldnn::memory(fwd_primitive_desc->weights_primitive_desc(), filter->data<T>()));
                                        -    shared_ptr<mkldnn::memory> out(new mkldnn::memory(fwd_primitive_desc->dst_primitive_desc(), output->mutable_data<T>(ctx.GetPlace())));
                                        -    shared_ptr<mkldnn::conv_fwd> fwd_primitive(new mkldnn::conv_fwd(*fwd_primitive_desc, *in, *wgt, *out));
                                        -
                                        -    dev_ctx.addMemory(op_key+"_input", in);
                                        -    dev_ctx.addMemory(op_key+"_output", out);
                                        -    dev_ctx.addMemory(op_key+"_filer", wgt);
                                        -    dev_ctx.addPrimitive(op_key+"_fwd", fwd_primitive);
                                        -    dev_ctx.addPrimitiveDesc(op_key+"_fwd_PD", fwd_primitive_desc);
                                        -  }
                                        -
                                        -  p = dev_ctx.findPrimitive(op_key + "_fwd");
                                        -
                                        -  PADDLE_ENFORCE(p, "Should have forward Primitive");
                                        -  PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_input"), "Should have input memory");
                                        -  PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_output"), "Should have output memory");
                                        -  PADDLE_ENFORCE(dev_ctx.findMemory(op_unique_key+"_filter"), "Should have filter memory");
                                        -  PADDLE_ENFORCE(dev_ctx.findPrimitiveDesc(op_unique_key+"_fwd_PD"), "Should have forward PrimitiveDesc");
                                        -  dev_ctx.submit(p);
                                        -  dev_ctx.execute();  // the convert primitive should have already contained.
                                        -
                                        -
                                        -

                                        The createPrimitiveDesc returns the primitive descripotor of this operator, would be like this:

                                        -
                                          auto* input = ctx.Input<Tensor>("Input");
                                        -  auto* filter = ctx.Input<Tensor>("Filter");
                                        -  auto* output = ctx.Output<Tensor>("Output");
                                        -  std::vector<int> strides = ctx.Attr<std::vector<int>>("strides");
                                        -  std::vector<int> paddings = ctx.Attr<std::vector<int>>("paddings");
                                        -  std::vector<int> dilations = ctx.Attr<std::vector<int>>("dilations");
                                        -  int groups = ctx.Attr<int>("groups");
                                        -  algorithm algo = static_cast<algorithm>(ctx.Attr<int>("convolution_algorithm_option"));
                                        -  prop_kind pk = ctx.Attr<bool>("is_test") ? prop_kind::forward_inference : prop_kind::forward_training;
                                        -    
                                        -  auto fwd_desc = mkldnn::conv_fwd::desc(/* all the setting above*/);
                                        -  shared_ptr<mkldnn::conv_fwd::primitive_desc> fwd_primitive_desc(new mkldnn::conv_fwd::primitive_desc(fwd_desc, ctx.getEngine()));
                                        -
                                        -  return fwd_primitive_desc;
                                        -  }
                                        -
                                        -
                                        -
                                        -
                                        -

                                        MKLDNNDeviceContext

                                        -

                                        MKLDNNDeviceContext, which is very straightforward, should contain some base information like: stream, engine and the map needed.

                                        -
                                        -
                                        -

                                        mkldnn_helper

                                        -

                                        Some functions would be put in paddle/platform/mkldnn_helper.h.

                                        -
                                          -
                                        • create MKLDNN memories
                                        • -
                                        • create MKLDNN primitives
                                        • -
                                        • error check function
                                        • -
                                        • etc
                                        • -
                                        -
                                        -
                                        -

                                        Kernel Switch

                                        -

                                        We should reorder the different Layout from other device or to other device. GetExpectedKernelType and trans functions can help us to implement it.

                                        -

                                        GetExpectedKernelType should get the context, and this operator can return the best KernelType. -trans would be like this:

                                        -
                                        void trans(inputs, ctx) override {
                                        -  if (NoNeedTrans()) {
                                        -    return;
                                        -  }
                                        -  // find reorder primitive by op_key from context
                                        -  auto& dev_ctx = ctx.template device_context<platform::MKLDNNDeviceContext>();
                                        -  auto& p = dev_ctx.findPrimitive(op_key + "_reorder_input");
                                        -  auto& i = dev_ctx.findMemory(op_key + "_src_input");
                                        -
                                        -  if (p == nullptr || i == nullptr || changeSized(i, input)) {
                                        -    auto prim = createPrimitiveDesc(ctx);
                                        -    auto src = createMemory(memoryDesc(input->dims(), actual_layout), input->data);
                                        -    auto newbuffer = paddle::memory::Alloc(ctx.GetPlace(), input->size_in_bytes());
                                        -    auto dst = createMemory(p->expected_desc(), newbuffer->data);
                                        -    auto reorder_primitive(new mkldnn::reorder(src, dst));
                                        -
                                        -    dev_ctx.addMemory(op_key+"_src_input", src);
                                        -    dev_ctx.addMemory(op_key+"_input", dst);
                                        -    dev_ctx.addPrimitive(op_key+"_reorder_input", reorder_primitive);
                                        -  }
                                        -
                                        -  p = dev_ctx.findPrimitive(op_key + "_reorder_input");
                                        -  PADDLE_ENFORCE(p, "Should have Reorder Primitive");
                                        -  dev_ctx.submit(p);
                                        -  if (! this->isMKLDNNKernel()) {
                                        -    // execute immediately only if this is not mkldnn kernel function.
                                        -    // otherwise, it can be executed with the operator primitive in Compute
                                        -    dev_ctx.stream();
                                        -  }
                                        -  // after submit, the input tensor in ExecutionContext should be changed as the converted one
                                        -  // there should be another mechanism to ensure this
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Unit Test

                                        -

                                        All the functions should be tested corresponding. -TBD

                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/model_format.html b/develop/doc_cn/design/model_format.html deleted file mode 100644 index a4d812c0691..00000000000 --- a/develop/doc_cn/design/model_format.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - - - - - - - - Design Doc: Model Format — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Model Format

                                        -
                                        -

                                        Motivation

                                        -

                                        A model is an output of the training process. One complete model consists of two parts, the topology and the parameters. In order to support industrial deployment, the model format must be self-complete and must not expose any training source code.

                                        -

                                        As a result, In PaddlePaddle, the topology is represented as a ProgramDesc, which describes the model structure. The parameters contain all the trainable weights in the model. We must support large size parameters and efficient serialization/deserialization of parameters.

                                        -
                                        -
                                        -

                                        Implementation

                                        -

                                        The topology is saved as a plain text in a detailed self-contain protobuf file.

                                        -

                                        The parameters are saved as a binary file. As we all know, the protobuf message has a limit of 64M size. We have done a benchmark experiment, which shows that protobuf is not fit for the task.

                                        -

                                        As a result, we design a particular format for tensor serialization. By default, an arbitrary tensor in Paddle is a LoDTensor, and has a description information proto of LoDTensorDesc. We save the DescProto as the byte string header. It contains all the necessary information, such as the dims, and the LoD information in LoDTensor. A tensor stores values in a continuous memory buffer. For speed we dump the raw memory to disk and save it as the byte string content. So, the binary format of one tensor is,

                                        -

                                        The table below shows a tensor’s byte view in detail. Note that all the signed values are written in the little-endian format.

                                        -

                                        |field name | type | description | -| — | — | — | -| version | uint32_t | Version of saved file. Always 0 now. | -| tensor desc length | uint32_t | TensorDesc(Protobuf message) length in bytes. | -| tensor desc | void* | TensorDesc protobuf binary message | -| tensor data | void* | Tensor’s data in binary format. The length of tensor_data is decided by TensorDesc.dims() and TensorDesc.data_type() | -| lod_level | uint64_t | Level of LoD | -| length of lod[0] | uint64_t | [Optional] length of lod[0] in bytes. | -| data of lod[0] | uint64_t* | [Optional] lod[0].data() | -| ... | ... | ... |

                                        -
                                        -
                                        -

                                        Summary

                                        -
                                          -
                                        • We introduce a model format.
                                        • -
                                        • The model represented by its forward-pass computation procedure is saved in a ProgramDesc protobuf message.
                                        • -
                                        • A bunch of specified format binary tensors describe the parameters.
                                        • -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/multi_language_interface/00.why_plain_c.html b/develop/doc_cn/design/multi_language_interface/00.why_plain_c.html deleted file mode 100644 index b9145baccfc..00000000000 --- a/develop/doc_cn/design/multi_language_interface/00.why_plain_c.html +++ /dev/null @@ -1,399 +0,0 @@ - - - - - - - - - - - - - Paddle多语言接口实现 — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Paddle多语言接口实现

                                        -
                                        -

                                        背景

                                        -

                                        Paddle需要一个多语言接口,这个接口需要做到:

                                        -
                                          -
                                        • 有标准的,良好的文档
                                            -
                                          • 例如Python可以使用Sphinx生成API文档,golang可以使用GoDoc生成文档。这都需要这个接口按照约定俗成的规则来注释完备。
                                          • -
                                          -
                                        • -
                                        • 不同语言的接口适应不同语言的特性
                                            -
                                          • 例如Java与Python的错误处理是直接扔出来Exception,而对于golang错误处理应该使用返回值。
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -

                                        基本要求

                                        -

                                        Paddle的多语言接口实现包括一下几个方面:

                                        -
                                          -
                                        • 我们使用动态库来分发Paddle。在这个动态库中不嵌入任何其他语言的解释器,也不使用其他动态库。
                                        • -
                                        • 这个动态库使用C99标准的头文件导出一些函数,不使用/导出C++符号。
                                        • -
                                        • 不导出Paddle内部的结构体、类,仅仅使用void*指针作为类型的句柄(handler)。
                                        • -
                                        • 不使用SWIG这种代码生成器,而是手写多语言绑定。
                                        • -
                                        -
                                        -
                                        -

                                        原因

                                        -
                                        -

                                        使用动态库来分发Paddle

                                        -
                                          -
                                        • Paddle的链接方式比较复杂
                                            -
                                          • 如果用户要把Paddle的静态库(libpaddle.a)链接到自己的程序里,得使用 --whole-archive (for GCC) 或者 --force_load (for Clang) 参数,来确保把 libpaddle.a 里所有的符号都写入自己的程序的二进制文件里。这是因为 Paddle 的源码里使用了object factory design pattern
                                          • -
                                          -
                                        • -
                                        • 编译型语言,例如C/C++使用静态库和动态库难度差不多。但是解释性语言,例如Python或者Java,只能调用Paddle的动态库,否则得把Paddle静态库链接到解释器里。
                                            -
                                          • 解释性语言实际运行的二进制是解释器本身,如果调用静态库只能将静态库与解释器链接。例如对于Java来说,便是将静态库加入JVM中。这对于通常的Java的开发者来说,是不常见的做法。
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -

                                        动态库中不嵌入任何其他语言的解释器

                                        -
                                          -
                                        • 目前Paddle的进程模型是C++内部驱动Python解释器进行模型配置解析和数据读取
                                        • -
                                        • 我们最终的动态库中不嵌入Python或者其他任何语言的解释器。模型配置解析,数据读取均交由其他语言完成
                                        • -
                                        -

                                        现阶段Paddle有一个问题是,Paddle内嵌的Python解释器和外部使用的Python如果版本不同,会直接报错退出。

                                        -
                                        -
                                        -

                                        Paddle动态库中,不引用其他动态库

                                        -
                                          -
                                        • 即这个动态库是不依赖于其他任何文件的,可以在任何机器上执行的。
                                        • -
                                        -
                                        -
                                        -

                                        这个动态库使用C99标准的头文件导出一些函数,不使用/导出C++符号

                                        -
                                          -
                                        • 由于C++编译器没有名字修饰的规范,不同版本的编译器之间,对于同一段C++代码生成的符号可能不一致。而多语言接口需要直接读取生成的二进制(动态库),需要有稳定的导出符号。
                                        • -
                                        • C语言是有导出符号的标准的,并且在常见的平台上,都是ABI调用标准的。
                                        • -
                                        • 大多数语言都支持使用C语言API
                                        • -
                                        • 使用C99而不使用C89,是因为C99支持Fixed-width integer typesBoolean type
                                        • -
                                        • 使用C99而不使用C11的原因是,C11并没有Paddle特别需要的特性,且C99相对于C11使用更加广泛。
                                        • -
                                        -
                                        -
                                        -

                                        不导出Paddle内部的结构体、类,仅仅使用void*指针作为类型的句柄(handler)

                                        -
                                          -
                                        • Paddle内部的类为C++书写,直接导出到C的接口比较困难。
                                        • -
                                        • 在C-API中使用void*来表示Paddle内部类。再在每一个API中自己检查类型。
                                        • -
                                        -

                                        在C的头文件 paddle_matrix.h 中:

                                        -
                                        typedef void* paddle_matrix;
                                        -typedef int paddle_error;
                                        -
                                        -extern "C"
                                        -paddle_error paddle_matrix_get_shape(paddle_matrix matrix,
                                        -                                     uint64_t* width,
                                        -                                     uint64_t* height);
                                        -
                                        -
                                        -

                                        而在CPP里面实现这个C的接口,文件 paddle_matrix.cpp

                                        -
                                        #include "paddle/math/matrix.h"
                                        -extern "C"
                                        -paddle_error paddle_matrix_shape(paddle_matrix matrix,
                                        -                                 uint64_t *width,
                                        -                                 uint64_t *height) {
                                        -  auto m = (paddle::capi::CMatrix*)(matrix);
                                        -  *width = m->width();
                                        -  *height = m->height();
                                        -}
                                        -
                                        -
                                        -

                                        其中paddle/capi/CMatrix.hpp文件内容为:

                                        -
                                        namespace paddle {
                                        -namespace math {  
                                        -
                                        -class CMatrix {
                                        -  std::shared_ptr<paddle::Matrix> mat;
                                        -};
                                        -
                                        -}  // namespace math
                                        -}  // namespace paddle
                                        -
                                        -
                                        -
                                        -
                                        -

                                        不使用SWIG这种代码生成器,而是手写多语言绑定

                                        -
                                          -
                                        • SWIG是一个多语言接口的代码生成器。他的目标是使用C/C++写代码,SWIG直接读取C/C++的头文件,生成各种语言的绑定代码。
                                            -
                                          • 对于多语言接口,SWIG需要写一个interface文件。这个文件具有独特的语法,学习成本高。且增加一个第三方语言,就需要对这个第三方语言增加一些定义。有的时候,interface文件的写法非常tricky。社区贡献代码学习成本高。
                                          • -
                                          • SWIG暴露的接口保留了C++的接口样式,很难保证多语言代码风格的一致性。(函数命名,错误处理)
                                              -
                                            • 因为SWIG在第三方语言中暴露的函数名,类名和C++中完全一致。C++的命名风格并不能适应其他第三方语言。如果使用SWIG我们需要将在interface文件里,将大量的SomeCppClass重命名成some_python_class,或者SomeGoTypes
                                            • -
                                            • 对于不同语言,错误处理的方式也不尽相同。例如对于Java或者Python,最常见的错误处理方式是Exception,而对于Golang,错误处理方式是返回值。而SWIG只能简单的暴露C++接口,无法做到对于各种语言错误处理方式的适配。
                                            • -
                                            -
                                          • -
                                          • 对于大多数语言,直接使用C语言的.h并不困难。例如Python的cffi或者Cython, golang的cgo
                                          • -
                                          • SWIG支持的语言或者解释器有局限。例如对于Python,使用SWIG只支持CPython解释器,而不支持PyPy解释器。
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        原因列表

                                        -

                                        | 结论 | 对比 | 原因 | -|—| — | — | -| 使用动态库 | 不使用静态库 | 解释型语言只能调用动态库,Paddle静态库链接复杂 | -| 不嵌入其他语言解释器 | 不嵌入Python解释器 | Paddle C++目前嵌入Python解释器,会导致不同版本Python在一个进程里的bug | -| 不引用其他动态库 | | Paddle一个动态库可以在任何Linux系统上运行 | -| 使用C99做接口 | 不使用C++做接口 | C有标准的ABI,C99是目前C最广泛的使用标准,且C99支持bool类型和定长整数(uint64_t等)类型 | -| 使用void*作为类句柄 | 不显示的写每个类具体包含什么| 实现简单,并且让接口脱离实现细节 | -| 手写多语言绑定 | 不使用SWIG | 使用SWIG需要多语言绑定的开发人员熟练掌握SWIG配置,社区参与困难。SWIG生成的代码不能保证多语言代码风格的一致性 |

                                        -
                                        -
                                        -

                                        实现

                                        -

                                        参考Inference implementation

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/multi_language_interface/01.inference_implementation.html b/develop/doc_cn/design/multi_language_interface/01.inference_implementation.html deleted file mode 100644 index 27f4d7343eb..00000000000 --- a/develop/doc_cn/design/multi_language_interface/01.inference_implementation.html +++ /dev/null @@ -1,398 +0,0 @@ - - - - - - - - - - - - - C-API 模型推断实现文档 — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        C-API 模型推断实现文档

                                        -

                                        本文档描述Paddle C-API的实现细节。Paddle C-API是多语言API的基础部分。Paddle需要暴露的API很多。先实现模型推断的API,通过模型推断API的实现作为一个样例,来进行讨论。至于为什么需要C-API,请参考Why Plain C

                                        - -
                                        -

                                        暴露接口原则

                                        -
                                          -
                                        1. 所有的接口均为C接口。即使用extern "C"
                                        2. -
                                        3. 除构造某种类型的函数(paddle_matrix_create等),其他函数均返回paddle_error。且调用时不能抛出异常或出现运行时错误。
                                        4. -
                                        5. 所有类型名为paddle_类型名,所有与类型相关的函数,函数名为paddle_类型名_函数名
                                        6. -
                                        7. 如果某一个Paddle Core概念(GradientMachine/Matrix)需要被暴露到其他语言,那么
                                            -
                                          • 为了暴露的接口尽量简单。只暴露概念的接口,而不暴露概念的实现。即暴露GradientMachine或者Matrix但不暴露RecurrentGradientMachineCpuSparseMatrix
                                          • -
                                          • 暴露这个概念必要函数。必要是指,即完成某一个任务的最少函数。
                                          • -
                                          -
                                        8. -
                                        9. 不在capi接口层做过多封装。
                                            -
                                          • 如果某一个Paddle概念必须要暴露,但是又过于琐碎。不在capi这一层进行封装,而是直接修改Paddle Core。让Paddle核心中,这一概念不再琐碎。
                                          • -
                                          -
                                        10. -
                                        -
                                        -
                                        -

                                        目录结构

                                        -
                                        Paddle
                                        -  `-- paddle
                                        -        `-- capi
                                        -              `-- examples  # The example project for C-API.
                                        -              `-- tests  # unittests for C-API
                                        -              `-- capi.h  # C-API header file.
                                        -              `-- capi_private.h  # The shared header file between implementation sources.
                                        -              `-- matrix.{h, cpp}
                                        -              `-- gradient_machine.{h, cpp}
                                        -              `-- ...
                                        -
                                        -
                                        -

                                        Paddle的C-API目录结构如上图表所示。这个目录中除了capi_private.h之外的所有头文件,均会被安装到include/paddle路径下。C-API生成的二进制文件会被安装到lib目录下。即,安装后的目录结构为

                                        -
                                        `-- include
                                        -      `-- paddle
                                        -             `-- capi.h
                                        -             `-- matrix.h
                                        -             `-- gradient_machine.h
                                        -             `-- ...
                                        -`-- lib
                                        -     `-- libpaddle_capi_shared.{so, dylib}  # In mac, dynamic libary's file name extention is `dylib`
                                        -     `-- libpaddle_capi_whole.a  # static library for all symbols of Paddle.
                                        -
                                        -
                                        -
                                        -
                                        -

                                        实现方式

                                        -

                                        下面分别介绍某一类文件的实现方式。

                                        -
                                        -

                                        capi.h

                                        -

                                        capi.h是用户使用C-API时所唯一需要引入的头文件。在capi.h中,引入了类型的头文件,matrix.h, gradient_machine.h。在引入其他类型的头文件时,使用相对路径的引用方式。即#include "matrix.h"

                                        -
                                        -
                                        -

                                        具体某种类型的头文件

                                        -

                                        具体某种类型的头文件,即例如matrix.hgradient_machine.h等。在这些头文件中,包含了某种类型的类型定义和暴露的全部函数。

                                        -

                                        这个头文件不假设其他文件的引用顺序,即使用户直接引用某种类型的头文件,也不应该报错(虽然不鼓励这样)。如果某一个类型需要引用另一个类型,例如gradient_machine需要引用matrix,则直接引入另一种类型的头文件,即#include "matrix.h"

                                        -
                                        -
                                        -

                                        capi_private.h

                                        -

                                        capi_prviate.h是各个实现中共享的头文件,他主要包含了实际暴露的类型结构。在用户使用C-API时,Paddle的类型全部退化成void *,即typedef paddle_matrix void*。但,对于每种C-API暴露的类型,均是在capi_private.h中实现的结构体。

                                        -
                                        struct CMatrix {
                                        -   int type = MatrixType;
                                        -   std::shared_ptr<paddle::Matrix> mat;
                                        -};
                                        -
                                        -
                                        -

                                        通常,这个结构体包含两个项目。

                                        -
                                          -
                                        • type是一个类型的标志。对于每种类型,type字段均不尽相同。这样,即使C-API接受的类型全是void *,我们也可以确定每一个参数的类型。

                                          -
                                          void some_c_api_function(void* some_instance) {
                                          -   int* type = (int *) some_instance;
                                          -   switch (*type) {
                                          -     case MatrixType:
                                          -       CMatrix* mat = (CMatrix *) some_instance;
                                          -       ...
                                          -     ...
                                          -   }
                                          -}
                                          -
                                          -
                                          -
                                        • -
                                        • 这个结构体中的另一个项目是,Paddle Core中这一类型接口的智能指针(shared_ptr)。

                                          -
                                            -
                                          • 使用智能指针的原因是: 用户可以安全的释放某个C-API的实例,而不必在意Paddle Core是否还在使用这个实例。
                                          • -
                                          • 例如,用户通过C-API获得了神经网络的参数实例。当用户使用完这个参数后,直接删除这个参数即可。即便Paddle Core中的模型还在使用这个参数,这个参数也不会一并删除。
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -

                                        具体某种类型的实现文件

                                        -

                                        具体某种类型的实现文件,即matrix.cpp, gradient_machine.cpp等文件。在这些文件中,使用C++ 11实现了C-API的接口,并且使用extern "C"导出这些接口。在实现过程中,对输入参数的安全性进行了必要的判断,并将C-API接口的参数转发给Paddle Core

                                        -
                                        -
                                        -

                                        libpaddle_capi_shared.{so, dylib}

                                        -

                                        libpaddle_capi_shared是C-API导出的动态库。这个动态库的连接参数与Paddle的其他二进制(例如paddle_trainer)类似。用户可以直接使用这个动态库来引入Paddle C-API。具体使用方法为-lpaddle_capi_shared

                                        -
                                        -
                                        -

                                        libpaddle_capi_whole.a

                                        -

                                        libpaddle_capi_whole是C-API导出的静态库。这个静态库包含了Paddle的全部符号。他是将libpaddle_gserver.a, libpaddle_math.a, libpaddle_capi.a等全部静态库中的目标文件全部打包后产生的文件。具体使用方法为--whole-archive -lpaddle_capi_whole --no-whole-archive

                                        -
                                        -
                                        -

                                        examples

                                        -

                                        在样例中,使用C99开发了模型预测的样例代码。具体请参考example/README.md

                                        -
                                        -
                                        -
                                        -

                                        编译选项

                                        -

                                        C-API的编译选项默认关闭,打开这个编译选项,需要在cmake的时候,设置

                                        -
                                        cmake ${YOUR_SOURCE_ROOT} -DWITH_C_API=ON -DWITH_PYTHON=OFF -DWITH_SWIG_PY=OFF
                                        -
                                        -
                                        -

                                        编译C-API的时候推荐Paddle不嵌入Python解释器,也不生成SWIG接口,具体原因参考Why Plain C

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/operator_kernel_type.html b/develop/doc_cn/design/operator_kernel_type.html deleted file mode 100644 index b17355df42d..00000000000 --- a/develop/doc_cn/design/operator_kernel_type.html +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - - - - Design Doc: The Keys of Operator Kernel Type — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: The Keys of Operator Kernel Type

                                        -
                                        -

                                        Problem

                                        -

                                        An operator can have different kernel implementations, and each operator will have a map to store the related kernels. Fluid uses OpKernelType as a key to identify a unique kernel. Before an operator runs, a certain type of kernel must be chosen via a key of OpKernelType. Currently, OpKernelType is defined as follows:

                                        -
                                        struct OpKernelType {
                                        -  platform::Place place_;
                                        -  proto::DataType data_type_;
                                        -};
                                        -
                                        -
                                        -

                                        For more details, please refer to codes in github.

                                        -

                                        It contains two keys, Place and DataType. And these two keys will be hashed to a unique key to represent a certain type of kernel. However, these two keys do not provide enough information. We need a more complete representation of OpKernelType.

                                        -

                                        We often implement a kernel of an operator with some computing library on certain device(place). Please note that computing library and device do not have a one-to-one correspondence. A device can have a lot of computing libraries and a computing library can also support different devices.

                                        -

                                        For example, Eigen library supports Nvidia GPU/AMD GPU/CPU and MKLDNN library supports Intel CPU/Intel FPGA. Both Place and Library should be a key of OpKernelType.

                                        -

                                        Different DataTypes, such as fp64/fp32/int8, will obviously have different kernels. But different data layout of a Tensor will also lead to different implementations. Please refer to the batch norm operator kernels as an example. Data layout should also be taken into consideration.

                                        -
                                        -
                                        -

                                        Solution

                                        -

                                        There are four keys to determine a kernel type of an operator: Place/Library/DataType/Layout.

                                        -
                                        struct OpKernelType {
                                        -  platform::Place place_;
                                        -  platform::Library library_;
                                        -  proto::DataType data_type_;
                                        -  framework::Layout layout_;
                                        -};
                                        -
                                        -
                                        -

                                        The details are as follows:

                                        -
                                        -

                                        Place

                                        -

                                        Place is defined as:

                                        -
                                        typedef boost::variant<CUDAPlace, ROCmPlace, FPGAPlace, CPUPlace> Place;
                                        -
                                        -
                                        -

                                        Place represents the device memory where data is located.

                                        -
                                        -
                                        -

                                        Library

                                        -

                                        One operator kernel is usually implemented based on one library. Library is defined as a enum variable:

                                        -
                                        enum Library { Plain, MKLDNN, CUDNN };
                                        -
                                        -
                                        -

                                        We use Plain enumerator to represent default library. Since most operators in Fluid are implemented based on the Eigen library, we take Eigen library as the Plain enumerator. -A library usually has a corresponding DeviceContext which contains some handles needed for computation. Fluid now has two default DeviceContexts for CPU and CUDA, namely, CPUDeviceContext and CUDADeviceContext. CPUDeviceContext contains an Eigen library handle and CDUADeviceContext contains an Eigen library handle and a cuBLAS handle.

                                        -

                                        If we want to support new library, a new enumerator need to be added to Library and a corresponding new LibraryDeviceContext need to be created.

                                        -
                                        -
                                        -

                                        DataType

                                        -

                                        DataType is defined in framework.proto. Currently, int32/int64/fp32/fp64 are supported.

                                        -
                                        -
                                        -

                                        Layout

                                        -

                                        Actually, a Tensor is a view of a block of memory. Besides a pointer to the memory, we also have to get some other descriptions of this block of memory, such as shape(ddim), stride, and layout.

                                        -

                                        Different layout leads to different implementation of the operator kernel. There are mainly 4 principles we have to follow to support layout in our Fluid framework.

                                        -
                                          -
                                        • We take layout as a data member of Tensor. Layout is actually a enum variable. If Fluid is built with MKLDNN, then the memory format in MKLDNN will also be added into this enum variable.
                                        • -
                                        • Users have to set layout for input data. And some operators like fill_constant/random, also have to set layout for generating data. Of course, we can have some default layout, like NCHW.
                                        • -
                                        • The inference of Layout is at run-time, not at compile-time.
                                        • -
                                        • Every operator has to implement different kernels for different layouts. Let’s take MKLDNN as an example. If we want to implement an MKLDNN convolution operator, we have to implement all the kernels for different layouts, which are listed here. And we will have a special macro to register kernels for MKLDNN operators.
                                        • -
                                        -

                                        Layout is also defined as a enum variable:

                                        -
                                        enum Layout {
                                        -  kNCHW,
                                        -  kNHWC,
                                        -#ifdef PADDLE_WITH_MKLDNN
                                        -  knChw8c
                                        -  ...
                                        -#endif
                                        -};
                                        -
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/ops/rnn.html b/develop/doc_cn/design/ops/rnn.html deleted file mode 100644 index b5772973253..00000000000 --- a/develop/doc_cn/design/ops/rnn.html +++ /dev/null @@ -1,394 +0,0 @@ - - - - - - - - - - - - - RNNOp design — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        RNNOp design

                                        -

                                        This document describes the RNN (Recurrent Neural Network) operator and how it is implemented in PaddlePaddle. The RNN op requires that all instances in a mini-batch have the same length. We will have a more flexible dynamic RNN operator in the future.

                                        -
                                        -

                                        RNN Algorithm Implementation

                                        -

                                        - -

                                        The above diagram shows an RNN unrolled into a full network.

                                        -

                                        There are several important concepts here:

                                        -
                                          -
                                        • step-net: the sub-graph that runs at each step.
                                        • -
                                        • memory, $h_t$, the state of the current step.
                                        • -
                                        • ex-memory, $h_{t-1}$, the state of the previous step.
                                        • -
                                        • initial memory value, the memory of the first (initial) step.
                                        • -
                                        -
                                        -

                                        Step-scope

                                        -

                                        There could be local variables defined in each step-net. PaddlePaddle runtime realizes these variables in step-scopes which are created for each step.

                                        -

                                        -
                                        -Figure 2 illustrates the RNN's data flow -

                                        Please be aware that every step runs the same step-net. Each step does the following:

                                        -
                                          -
                                        1. Creates the step-scope.
                                        2. -
                                        3. Initializes the local variables including step-outputs, in the step-scope.
                                        4. -
                                        5. Runs the step-net, which uses the above mentioned variables.
                                        6. -
                                        -

                                        The RNN operator will compose its output from step outputs in each of the step scopes.

                                        -
                                        -
                                        -

                                        Memory and Ex-memory

                                        -

                                        Let’s give more details about memory and ex-memory using a simple example:

                                        -

                                        $$ -h_t = U h_{t-1} + W x_t -$$,

                                        -

                                        where $h_t$ and $h_{t-1}$ are the memory and ex-memory (previous memory) of step $t$ respectively.

                                        -

                                        In the implementation, we can make an ex-memory variable either “refer to” the memory variable of the previous step, -or copy the memory value of the previous step to the current ex-memory variable.

                                        -
                                        -
                                        -

                                        Usage in Python

                                        -

                                        For more information on Block, please refer to the design doc.

                                        -

                                        We can define an RNN’s step-net using a Block:

                                        -
                                        import paddle as pd
                                        -
                                        -X = some_op() # x is some operator's output and is a LoDTensor
                                        -a = some_op()
                                        -
                                        -# declare parameters
                                        -W = pd.Variable(shape=[20, 30])
                                        -U = pd.Variable(shape=[20, 30])
                                        -
                                        -rnn = pd.create_rnn_op(output_num=1)
                                        -with rnn.stepnet():
                                        -    x = rnn.add_input(X)
                                        -    # declare a memory (rnn's step)
                                        -    h = rnn.add_memory(init=a)
                                        -    # h.pre_state(), the previous memory of rnn
                                        -    new_state = pd.add_two( pd.matmul(W, x) + pd.matmul(U, h.pre_state()))
                                        -    # update current memory
                                        -    h.update(new_state)
                                        -    # indicate that h variables in all step scopes should be merged
                                        -    rnn.add_outputs(h)
                                        -
                                        -out = rnn()
                                        -
                                        -
                                        -

                                        Python API functions in above example:

                                        -
                                          -
                                        • rnn.add_input: indicates that the parameter is a variable that will be segmented into step-inputs.
                                        • -
                                        • rnn.add_memory: creates a variable used as the memory.
                                        • -
                                        • rnn.add_outputs: marks the variables that will be concatenated across steps into the RNN output.
                                        • -
                                        -
                                        -
                                        -

                                        Nested RNN and LoDTensor

                                        -

                                        An RNN whose step-net includes other RNN operators is known as an nested RNN.

                                        -

                                        For example, we could have a 2-level RNN, where the top level corresponds to paragraphs, and the lower level corresponds to sentences. Each step of the higher level RNN also receives an input from the corresponding step of the lower level, and additionally the output from the previous time step at the same level.

                                        -

                                        The following figure illustrates feeding in text into the lower level, one sentence at a step, and the feeding in step outputs to the top level. The final top level output is about the whole text.

                                        -

                                        - -

                                        import paddle as pd
                                        -
                                        -W = pd.Variable(shape=[20, 30])
                                        -U = pd.Variable(shape=[20, 30])
                                        -
                                        -W0 = pd.Variable(shape=[20, 30])
                                        -U0 = pd.Variable(shape=[20, 30])
                                        -
                                        -# a is output of some op
                                        -a = some_op()
                                        -
                                        -# chapter_data is a set of 128-dim word vectors
                                        -# the first level of LoD is sentence
                                        -# the second level of LoD is a chapter
                                        -chapter_data = pd.Variable(shape=[None, 128], type=pd.lod_tensor, level=2)
                                        -
                                        -def lower_level_rnn(paragraph):
                                        -    '''
                                        -    x: the input
                                        -    '''
                                        -    rnn = pd.create_rnn_op(output_num=1)
                                        -    with rnn.stepnet():
                                        -        sentence = rnn.add_input(paragraph, level=0)
                                        -        h = rnn.add_memory(shape=[20, 30])
                                        -        h.update(
                                        -            pd.matmul(W, sentence) + pd.matmul(U, h.pre_state()))
                                        -        # get the last state as sentence's info
                                        -        rnn.add_outputs(h)
                                        -    return rnn
                                        -
                                        -top_level_rnn = pd.create_rnn_op(output_num=1)
                                        -with top_level_rnn.stepnet():
                                        -    paragraph_data = rnn.add_input(chapter_data, level=1)
                                        -    low_rnn = lower_level_rnn(paragraph_data)
                                        -    paragraph_out = low_rnn()
                                        -
                                        -    h = rnn.add_memory(init=a)
                                        -    h.update(
                                        -        pd.matmul(W0, paragraph_data) + pd.matmul(U0, h.pre_state()))
                                        -    top_level_rnn.add_outputs(h)
                                        -
                                        -# output the last step
                                        -chapter_out = top_level_rnn(output_all_steps=False)
                                        -
                                        -
                                        -

                                        In the above example, the construction of the top_level_rnn calls lower_level_rnn. The input is an LoD Tensor. The top level RNN segments input text data into paragraphs, and the lower level RNN segments each paragraph into sentences.

                                        -

                                        By default, the RNNOp will concatenate the outputs from all the time steps. -If the output_all_steps is set to False, it will only output the final time step.

                                        -

                                        - -

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/ops/sequence_decoder.html b/develop/doc_cn/design/ops/sequence_decoder.html deleted file mode 100644 index 639f9071873..00000000000 --- a/develop/doc_cn/design/ops/sequence_decoder.html +++ /dev/null @@ -1,469 +0,0 @@ - - - - - - - - - - - - - Design: Sequence Decoder Generating LoDTensors — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design: Sequence Decoder Generating LoDTensors

                                        -

                                        In tasks such as machine translation and visual captioning, -a sequence decoder is necessary to generate sequences, one word at a time.

                                        -

                                        This documentation describes how to implement the sequence decoder as an operator.

                                        -
                                        -

                                        Beam Search based Decoder

                                        -

                                        The beam search algorithm is necessary when generating sequences. It is a heuristic search algorithm that explores the paths by expanding the most promising node in a limited set.

                                        -

                                        In the old version of PaddlePaddle, the C++ class RecurrentGradientMachine implements the general sequence decoder based on beam search, due to the complexity involved, the implementation relies on a lot of special data structures that are quite trivial and hard to be customized by users.

                                        -

                                        There are a lot of heuristic tricks in the sequence generation tasks, so the flexibility of sequence decoder is very important to users.

                                        -

                                        During the refactoring of PaddlePaddle, some new concepts are proposed such as: LoDTensor and TensorArray that can better support the sequence usage, and they can also help make the implementation of beam search based sequence decoder more transparent and modular .

                                        -

                                        For example, the RNN states, candidates IDs and probabilities of beam search can be represented all as LoDTensors; -the selected candidate’s IDs in each time step can be stored in a TensorArray, and Packed to the sentences translated.

                                        -
                                        -
                                        -

                                        Changing LoD’s absolute offset to relative offsets

                                        -

                                        The current LoDTensor is designed to store levels of variable-length sequences. It stores several arrays of integers where each represents a level.

                                        -

                                        The integers in each level represent the begin and end (not inclusive) offset of a sequence in the underlying tensor, -let’s call this format the absolute-offset LoD for clarity.

                                        -

                                        The absolute-offset LoD can retrieve any sequence very quickly but fails to represent empty sequences, for example, a two-level LoD is as follows

                                        -
                                        [[0, 3, 9]
                                        - [0, 2, 3, 3, 3, 9]]
                                        -
                                        -
                                        -

                                        The first level tells that there are two sequences:

                                        -
                                          -
                                        • the first’s offset is [0, 3)
                                        • -
                                        • the second’s offset is [3, 9)
                                        • -
                                        -

                                        while on the second level, there are several empty sequences that both begin and end at 3. -It is impossible to tell how many empty second-level sequences exist in the first-level sequences.

                                        -

                                        There are many scenarios that rely on empty sequence representation, for example in machine translation or visual captioning, one instance has no translation or the empty candidate set for a prefix.

                                        -

                                        So let’s introduce another format of LoD, -it stores the offsets of the lower level sequences and is called relative-offset LoD.

                                        -

                                        For example, to represent the same sequences of the above data

                                        -
                                        [[0, 3, 6]
                                        - [0, 2, 3, 3, 3, 9]]
                                        -
                                        -
                                        -

                                        the first level represents that there are two sequences, -their offsets in the second-level LoD is [0, 3) and [3, 5).

                                        -

                                        The second level is the same with the relative offset example because the lower level is a tensor. -It is easy to find out the second sequence in the first-level LoD has two empty sequences.

                                        -

                                        The following examples are based on relative-offset LoD.

                                        -
                                        -
                                        -

                                        Usage in a simple machine translation model

                                        -

                                        Let’s start from a simple machine translation model that is simplified from the machine translation chapter to draw a blueprint of what a sequence decoder can do and how to use it.

                                        -

                                        The model has an encoder that learns the semantic vector from a sequence, and a decoder which uses the sequence encoder to generate new sentences.

                                        -

                                        Encoder

                                        -
                                        import paddle as pd
                                        -
                                        -dict_size = 8000
                                        -source_dict_size = dict_size
                                        -target_dict_size = dict_size
                                        -word_vector_dim = 128
                                        -encoder_dim = 128
                                        -decoder_dim = 128
                                        -beam_size = 5
                                        -max_length = 120
                                        -
                                        -# encoder
                                        -src_word_id = pd.data(
                                        -    name='source_language_word',
                                        -    type=pd.data.integer_value_sequence(source_dict_dim))
                                        -src_embedding = pd.embedding(size=source_dict_size, size=word_vector_dim)
                                        -
                                        -src_word_vec = pd.lookup(src_embedding, src_word_id)
                                        -
                                        -encoder_out_seq = pd.gru(input=src_word_vec, size=encoder_dim)
                                        -
                                        -encoder_ctx = pd.last_seq(encoder_out_seq)
                                        -# encoder_ctx_proj is the learned semantic vector
                                        -encoder_ctx_proj = pd.fc(
                                        -    encoder_ctx, size=decoder_dim, act=pd.activation.Tanh(), bias=None)
                                        -
                                        -
                                        -

                                        Decoder

                                        -
                                        def generate():
                                        -    decoder = pd.while_loop()
                                        -    with decoder.step():
                                        -        decoder_mem = decoder.memory(init=encoder_ctx)  # mark the memory
                                        -        generated_ids = decoder.memory() # TODO init to batch_size <s>s
                                        -        generated_scores = decoder.memory() # TODO init to batch_size 1s or 0s
                                        -
                                        -        target_word = pd.lookup(trg_embedding, gendrated_ids)
                                        -        # expand encoder_ctx's batch to fit target_word's lod
                                        -        # for example
                                        -        # decoder_mem.lod is
                                        -        # [[0 1 3],
                                        -        #  [0 1 3 6]]
                                        -        # its tensor content is [a1 a2 a3 a4 a5]
                                        -        # which means there are 2 sentences to translate
                                        -        #   - the first sentence has 1 translation prefixes, the offsets are [0, 1)
                                        -        #   - the second sentence has 2 translation prefixes, the offsets are [1, 3) and [3, 6)
                                        -        # the target_word.lod is
                                        -        # [[0, 1, 6]
                                        -        #  [0, 2, 4, 7, 9 12]]
                                        -        # which means 2 sentences to translate, each has 1 and 5 prefixes
                                        -        # the first prefix has 2 candidates
                                        -        # the following has 2, 3, 2, 3 candidates
                                        -        # the encoder_ctx_expanded's content will be
                                        -        # [a1 a1 a2 a2 a3 a3 a3 a4 a4 a5 a5 a5]
                                        -        encoder_ctx_expanded = pd.lod_expand(encoder_ctx, target_word)
                                        -        decoder_input = pd.fc(
                                        -            act=pd.activation.Linear(),
                                        -            input=[target_word, encoder_ctx_expanded],
                                        -            size=3 * decoder_dim)
                                        -        gru_out, cur_mem = pd.gru_step(
                                        -            decoder_input, mem=decoder_mem, size=decoder_dim)
                                        -        scores = pd.fc(
                                        -            gru_out,
                                        -            size=trg_dic_size,
                                        -            bias=None,
                                        -            act=pd.activation.Softmax())
                                        -        # K is an config
                                        -        topk_scores, topk_ids = pd.top_k(scores, K)
                                        -        topk_generated_scores = pd.add_scalar(topk_scores, generated_scores)
                                        -
                                        -        selected_ids, selected_generation_scores = decoder.beam_search(
                                        -            topk_ids, topk_generated_scores)
                                        -
                                        -        # update the states
                                        -        decoder_mem.update(cur_mem)  # tells how to update state
                                        -        generated_ids.update(selected_ids)
                                        -        generated_scores.update(selected_generation_scores)
                                        -
                                        -        decoder.output(selected_ids)
                                        -        decoder.output(selected_generation_scores)
                                        -
                                        -translation_ids, translation_scores = decoder()
                                        -
                                        -
                                        -

                                        The decoder.beam_search is an operator that, given the candidates and the scores of translations including the candidates, -returns the result of the beam search algorithm.

                                        -

                                        In this way, users can customize anything on the input or output of beam search, for example:

                                        -
                                          -
                                        1. Make the corresponding elements in topk_generated_scores zero or some small values, beam_search will discard this candidate.
                                        2. -
                                        3. Remove some specific candidate in selected_ids.
                                        4. -
                                        5. Get the final translation_ids, remove the translation sequence in it.
                                        6. -
                                        -

                                        The implementation of sequence decoder can reuse the C++ class: RNNAlgorithm, -so the python syntax is quite similar to that of an RNN.

                                        -

                                        Both of them are two-level LoDTensors:

                                        -
                                          -
                                        • The first level represents batch_size of (source) sentences.
                                        • -
                                        • The second level represents the candidate ID sets for translation prefix.
                                        • -
                                        -

                                        For example, 3 source sentences to translate, and has 2, 3, 1 candidates.

                                        -

                                        Unlike an RNN, in sequence decoder, the previous state and the current state have different LoD and shape, and an lod_expand operator is used to expand the LoD of the previous state to fit the current state.

                                        -

                                        For example, the previous state:

                                        -
                                          -
                                        • LoD is [0, 1, 3][0, 2, 5, 6]
                                        • -
                                        • content of tensor is a1 a2 b1 b2 b3 c1
                                        • -
                                        -

                                        the current state is stored in encoder_ctx_expanded:

                                        -
                                          -
                                        • LoD is [0, 2, 7][0 3 5 8 9 11 11]
                                        • -
                                        • the content is
                                            -
                                          • a1 a1 a1 (a1 has 3 candidates, so the state should be copied 3 times for each candidates)
                                          • -
                                          • a2 a2
                                          • -
                                          • b1 b1 b1
                                          • -
                                          • b2
                                          • -
                                          • b3 b3
                                          • -
                                          • None (c1 has 0 candidates, so c1 is dropped)
                                          • -
                                          -
                                        • -
                                        -

                                        The benefit from the relative offset LoD is that the empty candidate set can be represented naturally.

                                        -

                                        The status in each time step can be stored in TensorArray, and Packed to a final LoDTensor. The corresponding syntax is:

                                        -
                                        decoder.output(selected_ids)
                                        -decoder.output(selected_generation_scores)
                                        -
                                        -
                                        -

                                        The selected_ids are the candidate ids for the prefixes, and will be Packed by TensorArray to a two-level LoDTensor, where the first level represents the source sequences and the second level represents generated sequences.

                                        -

                                        Packing the selected_scores will get a LoDTensor that stores scores of each translation candidate.

                                        -

                                        Packing the selected_generation_scores will get a LoDTensor, and each tail is the probability of the translation.

                                        -
                                        -
                                        -

                                        LoD and shape changes during decoding

                                        -

                                        - -

                                        According to the image above, the only phase that changes the LoD is beam search.

                                        -
                                        -
                                        -

                                        Beam search design

                                        -

                                        The beam search algorithm will be implemented as one method of the sequence decoder and has 3 inputs:

                                        -
                                          -
                                        1. topk_ids, the top K candidate ids for each prefix.
                                        2. -
                                        3. topk_scores, the corresponding scores for topk_ids
                                        4. -
                                        5. generated_scores, the score of the prefixes.
                                        6. -
                                        -

                                        All of these are LoDTensors, so that the sequence affiliation is clear. Beam search will keep a beam for each prefix and select a smaller candidate set for each prefix.

                                        -

                                        It will return three variables:

                                        -
                                          -
                                        1. selected_ids, the final candidate beam search function selected for the next step.
                                        2. -
                                        3. selected_scores, the scores for the candidates.
                                        4. -
                                        5. generated_scores, the updated scores for each prefix (with the new candidates appended).
                                        6. -
                                        -
                                        -
                                        -

                                        Introducing the LoD-based Pack and Unpack methods in TensorArray

                                        -

                                        The selected_ids, selected_scores and generated_scores are LoDTensors that exist at each time step, -so it is natural to store them in arrays.

                                        -

                                        Currently, PaddlePaddle has a module called TensorArray which can store an array of tensors. It is better to store the results of beam search in a TensorArray.

                                        -

                                        The Pack and UnPack in TensorArray are used to pack tensors in the array to an LoDTensor or split the LoDTensor to an array of tensors. -It needs some extensions to support the packing or unpacking an array of LoDTensors.

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/optimizer.html b/develop/doc_cn/design/optimizer.html deleted file mode 100644 index 17dd53a9cbc..00000000000 --- a/develop/doc_cn/design/optimizer.html +++ /dev/null @@ -1,349 +0,0 @@ - - - - - - - - - - - - - Optimizer Design — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Optimizer Design

                                        -
                                        -

                                        The Problem

                                        -

                                        A PaddlePaddle program, or a block, is a sequence of operators operating variables. A training program needs to do three kinds of works:

                                        -
                                          -
                                        1. the forward pass, which computes intermediate results and the cost(s),
                                        2. -
                                        3. the backward pass, which derives gradients from intermediate results and costs, and
                                        4. -
                                        5. the optimization pass, which update model parameters to optimize the cost(s).
                                        6. -
                                        -

                                        These works rely on three kinds of operators:

                                        -
                                          -
                                        1. forward operators,
                                        2. -
                                        3. gradient operators, and
                                        4. -
                                        5. optimization operators.
                                        6. -
                                        -

                                        It’s true that users should be able to create all these operators manually by calling some low-level API, but it would be much more convenient if they could only describe the forward pass and let PaddlePaddle create the backward and optimization operators automatically.

                                        -

                                        In this design, we propose a high-level API that automatically derives the optimisation pass and operators from the forward pass.

                                        -
                                        -
                                        -

                                        High-level Python API to describe the training process

                                        -
                                          -
                                        1. User write code to describe the network:

                                          -
                                          images = layer.data("images")
                                          -labels = layer.data("labels")
                                          -w1 = pd.var("w1")
                                          -b1 = pd.var("b1")
                                          -hidden = layer.fc(images, w=w1, b=b1)
                                          -cost = layer.mse(hidden, labels)
                                          -
                                          -
                                          -

                                          The above code snippet will create forward operators in Block.

                                          -
                                        2. -
                                        -
                                          -
                                        1. Users create a certain kind of Optimizer with some argument.

                                          -
                                          optimizer = AdagradOptimizer(learing_rate=0.001)
                                          -
                                          -
                                          -
                                        2. -
                                        3. Users use the optimizer to minimize a certain cost through updating parameters in parameter_list.

                                          -
                                          opt_op_list = optimizer.minimize(cost, parameter_list=[w1, b1])
                                          -
                                          -
                                          -

                                          The above code snippet will create gradient and optimization operators in Block. The return value of minimize() is list of optimization operators that will be run by session.

                                          -
                                        4. -
                                        5. Users use Session/Executor to run this opt_op_list as target to do training.

                                          -
                                          sess.run(target= opt_op_list, ...)
                                          -
                                          -
                                          -
                                        6. -
                                        -
                                        -

                                        Optimizer Python interface:

                                        -
                                        class Optimizer(object):
                                        -    """Optimizer Base class.
                                        -
                                        -    """
                                        -
                                        -    def __init__(self):
                                        -        pass
                                        -
                                        -    def create_optimization_pass(self, parameters_and_grads):
                                        -        """Add optimization operators to update gradients to variables.
                                        -
                                        -        Args:
                                        -          parameters_and_grads: a list of (variable, gradient) pair to update.
                                        -
                                        -        Returns:
                                        -          optmization_op_list: a list of optimization operator that will update parameter using gradient.
                                        -        """
                                        -        return None
                                        -
                                        -    def minimize(self, loss, parameter_list):
                                        -        """Add operations to minimize `loss` by updating `parameter_list`.
                                        -
                                        -        This method combines interface `append_backward()` and
                                        -        `create_optimization_pass()` into one.
                                        -        """
                                        -        params_grads = self.create_backward_pass(loss, parameter_list)
                                        -        update_ops = self.create_optimization_pass(params_grads)
                                        -        return update_ops
                                        -
                                        -
                                        -
                                        -

                                        Users can inherit the Optimizer above to create their own Optimizer with some special logic, such as AdagradOptimizer.

                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/paddle_nccl.html b/develop/doc_cn/design/paddle_nccl.html deleted file mode 100644 index 0aecbabc185..00000000000 --- a/develop/doc_cn/design/paddle_nccl.html +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - Design Doc: NCCL support in Paddle Fluid — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: NCCL support in Paddle Fluid

                                        -
                                        -

                                        Abstract

                                        -

                                        This Design Doc refers to the NCCL feature in paddle. We propose an approach to support NCCL library both on a single machine and multiple machines. We wrapper the NCCL primitives Broadcast, Allreduce, Reduce as operators to utilize Multi-GPU powers in one script.

                                        -
                                        -
                                        -

                                        Motivation

                                        -

                                        NCCL is a NVIDIA library support Multi-GPU communicating and optimized for NVIDIA GPUs, it provides routines such as all-gather, all-reduce, broadcast, reduce, reduce-scatter, that can achieve high bandwidth over PCIe and NVLink high-speed interconnect. With NCCL library, we can easily accelerate the training in parallel.

                                        -
                                          -
                                        • Pros
                                        • -
                                        -
                                          -
                                        1. easily plug-in with NCCL2 library.
                                        2. -
                                        3. high performance in NVIDIA GPUs.
                                        4. -
                                        5. MPI like primitives, which have low learning cost for users.
                                        6. -
                                        -
                                          -
                                        • Cons
                                        • -
                                        -
                                          -
                                        1. Only design for NVIDIA GPUs, not a general multi-device solution.
                                        2. -
                                        3. Although NCCL1 is opensourced under BSD license, but NCCL2 is not opensourced anymore.
                                        4. -
                                        -

                                        At the beginning of training, the framework needs to distribute the same parameters to every GPU, and merge the gradients at any time user interests.

                                        -

                                        As a result, during training, we need the operations of peer to peer copy between different GPUs, aggregating gradients/parameters from GPUs, and broadcasting parameters to GPUs. Every GPU only need to run the operator with correct place information.

                                        -

                                        Besides, it needs interfaces to synchronize model update with each different GPU Cards.

                                        -
                                        -
                                        -

                                        Implementation

                                        -

                                        As mentioned above, we wrap the NCCL routines as several kinds of operators. Need to note that NCCL need to create Communicator between gpu at the beginning, so there is a NCCLInit operator created.

                                        -
                                        -

                                        Transpiler

                                        -

                                        To be compatible with parameter server design doc, the transpiler compiles the user defined operation graph into sub-graphs to be executed on different devices.

                                        -
                                          -
                                        1. The user-defined model will be a single device program

                                          -
                                        2. -
                                        3. Broadcast/Reduce operators between GPUs will be inserted into the program, even for the multi-node, may insert the Send, Recv operator.

                                          -

                                          Broadcast, AllReduce in a single machine. And Broadcast, AllReduce, Send, Recv in multiple machines

                                          -

                                          -
                                        4. -
                                        -

                                        After compiling, the graph as shows

                                        -

                                        -

                                        Operators are added to the sub-graphs. Every GPU assigned a role of rank0, rank1 etc.

                                        -
                                          -
                                        • Broadcast. Broadcast operator distribute initialized parameter to all the GPUs from the GPU who owns it. e.g. fromrank0 GPU.
                                        • -
                                        • AllReduce. AllReduce operator synchronizes parameters/gradients between GPUs. AllReduce implemented in the Ring-Based communicating method, avoid of the bottle neck in a single GPU.
                                        • -
                                        -

                                        Need to notice that AllReduce operator force GPUs synchronized at that point. The whole training process in asynchronous or synchronous mode depends on the AllReduce point in the graph.

                                        -

                                        As it shown in the picture, when each GPU compute the gradient of W, followed with a AllReduce operator, accumulate the dW to full batch of data, then run the optimize process individually and apply the gradient to its W.

                                        -
                                          -
                                        • AllReduce -Need to note that our AllReduce operator is a ring-base AllReduce implementation. If we use the NCCL2 AllReduce primitive, every GPU optimized full batch of data, wasted (n-1) GPU compute resources. In addition, NCCL2 built-in AllReduce will only utilize the communicating resource during synchronization, then update the gradient will be a subsequent phase. In fact, we can amortize the update gradient time cost into the communicating phase. The process is
                                        • -
                                        -
                                          -
                                        1. Every parameter has its root card. That card will responsible for aggregating the gradients from GPUs.
                                        2. -
                                        3. The whole model’s parameter will be hashed to different root card, ensure the load balance between GPUs.
                                        4. -
                                        5. Logically neighberhood card will start send parameter to the next one. After one round, the parameter main card will aggregate the full gradients.
                                        6. -
                                        7. Then the root card will optimize the parameter.
                                        8. -
                                        9. This parameter card will send its optimized result to its neighberhood, then the neighberhood will send parameter to its next one.
                                        10. -
                                        11. Finish the sychronization round.
                                        12. -
                                        -

                                        The total time cost will be 2 * (n-1) * per-parameter-send-time, we reach the goal of amortize the upgrade time into communicating phase.

                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/parallel_do.html b/develop/doc_cn/design/parallel_do.html deleted file mode 100644 index 5f2a1ab1e4d..00000000000 --- a/develop/doc_cn/design/parallel_do.html +++ /dev/null @@ -1,418 +0,0 @@ - - - - - - - - - - - - - Design Doc: Parallel_Do in PaddlePaddle — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Parallel_Do in PaddlePaddle

                                        -

                                        In PaddlePaddle, we use parallel_do primitive to represent multithread data parallel processing.

                                        -
                                        -

                                        Design overview

                                        -

                                        The definition of a parallel_do op looks like the following

                                        -
                                        AddInput(kInputs, "Inputs needed to be split onto different devices").AsDuplicable();
                                        -AddInput(kParameters, "Parameters are duplicated over different devices")
                                        -    .AsDuplicable();
                                        -AddInput(kPlaces, "Devices used for parallel processing");
                                        -AddOutput(kOutputs, "Outputs needed to be merged from different devices").AsDuplicable();
                                        -AddOutput(kParallelScopes,
                                        -          "Scopes for all local variables in forward pass. One scope for each device");
                                        -AddAttr<framework::BlockDesc *>(kParallelBlock,
                                        -                                "List of operaters to be executed in parallel");
                                        -
                                        -
                                        -

                                        A vanilla implementation of parallel_do can be shown as the following (| means single thread and -|||| means multiple threads)

                                        -
                                        In the forward pass
                                        -  |      Split input onto different devices
                                        -  |      Copy parameter onto different devices
                                        -  ||||   Compute forward pass in parallel
                                        -  |      Merge output from different devices
                                        -
                                        -In the backward pass
                                        -  |      Split output@grad onto different devices
                                        -  ||||   Compute backward pass in parallel
                                        -  |      accumulate param@grad from different devices to the first device
                                        -  |      Merge input@grad from different devices
                                        -  |      Copy param@grad to the place of parallel_do_op
                                        -
                                        -
                                        -

                                        This implementation allows to write mixed device program like this

                                        -
                                        W1 = fluid.tensor(size=[100,20], parameter=true)
                                        -W2 = fluid.tensor(size=[20,15], parameter=true)
                                        -
                                        -data = layers.data()
                                        -
                                        -gpu_places = layers.get_place(use_gpu=True)
                                        -# parallel processing on multiple GPUs
                                        -pd = ParallelDo(gpu_places)
                                        -with pd.do(input=data):
                                        -    prediction = softmax(fc(fc(data, W1), W2))
                                        -    write_output(prediction)
                                        -prediction = pd()
                                        -loss = cross_entropy(prediction, label)
                                        -
                                        -
                                        -

                                        And the programDesc are like the following

                                        -
                                        # start_program will be run by executor(CPUPlace), all w1, w2 will be allocated on CPU
                                        -start_program
                                        -{
                                        -  vars: w1, w2
                                        -  ops: init(w1), init(w2)
                                        -}
                                        -
                                        -main_program
                                        -{
                                        -block0 {
                                        -  vars: data, places, w1, w2, w1_grad, w2_grad,
                                        -  ops: data, get_place, parallel_do(block1),
                                        -       parallel_do_grad(block2),
                                        -       sgd(w2, w2_grad),
                                        -       sgd(w1, w1_grad)
                                        -}
                                        -block1 { # the forward pass
                                        -  parent_block: 0
                                        -  vars: data, h1, h2, loss
                                        -  ops: fc, fc, softmax
                                        -}
                                        -block2 { # the backward pass
                                        -  parent_block: 1
                                        -  vars: data_grad, h1_grad, h2_grad, loss_gard, local_w1_grad, local_w2_grad
                                        -  ops: softmax_grad,
                                        -       fc_grad
                                        -       fc_grad
                                        -}
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Performance Imporvement

                                        -

                                        There are serial places we can make this parallel_do faster.

                                        -
                                        -

                                        forward: split input onto different devices

                                        -

                                        If the input of the parallel_do is independent from any prior opeartors, we can avoid this step by -prefetching the input onto different devices in a seperate background thread. And the python code -looks like this.

                                        -
                                        pd = ParallelDo(gpu_places)
                                        -with pd.do():
                                        -    feature = get_data_from_prefetch_queue(gpu_places)
                                        -    prediction = my_net(feature)
                                        -    write_output(activation)
                                        -
                                        -
                                        -
                                        -
                                        -

                                        forward: Copy parameter to onto different devices

                                        -

                                        We can avoid this step by making each device have a copy of the parameter. This requires:

                                        -
                                          -
                                        1. fluid.default_start_up_program() to be run on all devices
                                        2. -
                                        3. In the backward, allreduce param@grad at different devices, this requires
                                            -
                                          1. backward.py add allreduce operators at parallel_do_grad
                                          2. -
                                          3. allreduce operators need to be called in async mode to achieve maximum throughput
                                          4. -
                                          -
                                        4. -
                                        5. apply gradients related op(i.e. cliping, normalization, decay, sgd) on different devices in parallel
                                        6. -
                                        -

                                        By doing so, we also avoided “backward: accumulate param@grad from different devices to the first device”. -And the ProgramDesc looks like the following

                                        -
                                        # w1, w2 will be allocated on all GPUs
                                        -start_program
                                        -{
                                        -block0 {
                                        -  parallel_do(block1)
                                        -}
                                        -block1 {
                                        -  parent_block: 0
                                        -  vars: w1, w2
                                        -  ops: init(w1), init(w2)
                                        -}
                                        -}
                                        -
                                        -main_program
                                        -{
                                        -block0 {
                                        -  vars: data, places, w1, w2
                                        -  ops: data, get_place, parallel_do(block1),
                                        -       parallel_do_grad(block2),      # append_backward
                                        -       parallel_do(block3)            # append_optimization
                                        -       
                                        -}
                                        -block1 {
                                        -  parent_block: 0
                                        -  vars: data, h1, h2, loss
                                        -  ops: fc, fc, softmax
                                        -}
                                        -block2 {
                                        -  parent_block: 1
                                        -  vars: data_grad, h1_grad, h2_grad, loss_gard, w1_grad, w2_grad
                                        -  ops: softmax_grad,
                                        -       fc_grad, allreduce(places, scopes, w1_grad),
                                        -       fc_grad, allreduce(places, scopes, w2_grad)
                                        -}
                                        -block3 {
                                        -  parent_block: 0
                                        -  vars: lr
                                        -  ops: sgd(w2, w2_grad),
                                        -       sgd(w1, w1_grad)
                                        -}
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/parameter_average.html b/develop/doc_cn/design/parameter_average.html deleted file mode 100644 index 04fcebf40ff..00000000000 --- a/develop/doc_cn/design/parameter_average.html +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - - - - - - Averaging Parameter in PaddlePaddle — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Averaging Parameter in PaddlePaddle

                                        -
                                        -

                                        Why Averaging

                                        -

                                        In a large scale machine learning setup where the size of the training data is huge, it could take us a large number of iterations over the training data before we can achieve the optimal values of parameters of our model. Looking at the problem setup, it is desirable if we can obtain the optimal values of parameters by going through the data in as few passes as we can.

                                        -

                                        Polyak and Juditsky (1992) showed that the test performance of simple average of parameters obtained by Stochastic Gradient Descent (SGD) is as good as that of parameter values that are obtained by training the model over and over again, over the training dataset.

                                        -

                                        Hence, to accelerate the speed of Stochastic Gradient Descent, Averaged Stochastic Gradient Descent (ASGD) was proposed in Polyak and Juditsky (1992). For ASGD, the running average of parameters obtained by SGD, is used as the estimator for
                                        . The averaging is done as follows:

                                        -


                                        -

                                        We propose averaging for any optimizer similar to how ASGD performs it, as mentioned above.

                                        -
                                        -

                                        How to perform Parameter Averaging in PaddlePaddle

                                        -

                                        Parameter Averaging in PaddlePaddle works in the following way during training :

                                        -
                                          -
                                        1. It will take in an instance of a normal optimizer as an input, e.g. RMSPropOptimizer
                                        2. -
                                        3. The optimizer itself is responsible for updating the parameters.
                                        4. -
                                        5. The ParameterAverageOptimizer maintains a separate copy of the parameters for itself:
                                            -
                                          1. In concept, the values of this copy are the average of the values of the parameters in the most recent N batches.
                                          2. -
                                          3. However, saving all the N instances of the parameters in memory is not feasible.
                                          4. -
                                          5. Therefore, an approximation algorithm is used.
                                          6. -
                                          -
                                        6. -
                                        -

                                        Hence, overall we have have two copies of the parameters: one for the optimizer itself, and one for the ParameterAverageOptimizer. The former should be used in back propagation, while the latter should be used during testing and should be saved.

                                        -

                                        During the testing/ saving the model phase, we perform the following steps:

                                        -
                                          -
                                        1. Perform the delayed operations.
                                        2. -
                                        3. Save current values of the parameters to a temporary variable.
                                        4. -
                                        5. Replace the values of the parameters with the averaged values.
                                        6. -
                                        7. Perform testing and/or save the parameters.
                                        8. -
                                        9. Restore the values of the parameters once done.
                                        10. -
                                        -
                                        -
                                        -

                                        How to implement Averaging of Parameter in PaddlePaddle

                                        -

                                        We can add the ParameterAverageOptimizer op to the graph through Python API. Using this approach, we manually add this op to the graph and direct the output of the optimizer op to this op during training.

                                        -
                                        **Advantages**:
                                        -- Allows for greater flexibility to the users of PaddlePaddle. Using this approach, the users can plug different optimizers into ParameterAverageOptimizer by passing in the optimizer to the op.
                                        -- Makes it easy for the users to customize and extend the framework.
                                        -
                                        -**Disadvantages**:
                                        -- Implementation requires re-writing the averaging methodology in Python.  
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Low-Level implementation

                                        -

                                        In the new design, we propose to create a new operation for averaging parameter updates (ParameterAverageOptimizer). For now, we can add an op that takes in the following as input:

                                        -
                                          -
                                        • the optimizer
                                        • -
                                        • the window_size to keep the updates
                                        • -
                                        -

                                        The ParameterAverageOptimizer op can be like any other operator with its own CPU/GPU implementation either using Eigen or separate CPU and GPU kernels. As the initial implementation, we can implement the kernel using Eigen following the abstraction pattern implemented for Operators. We also want to support the case when the Trainer/Optimizer runs on the GPU while ParameterAverageOptimizer runs on a CPU.

                                        -

                                        The idea of building an op for averaging is in sync with the refactored PaddlePaddle philosophy of using operators to represent any computation unit. The way the op will be added to the computation graph will be decided by the layer functions in Python API.

                                        -
                                        -
                                        -

                                        Python API implementation for ParameterAverageOptimizer

                                        -

                                        Based on Polyak and Juditsky (1992), we can generalize the averaging of updates to any optimizer. The input to the op would be the following:

                                        -
                                          -
                                        • Any optimizer (RMSProp , AdaGrad etc.)
                                        • -
                                        • A window size. The op keeps accumulating updated parameter values over a window of N batches and takes an average. Move the averaged value to a buffer when window is full to avoid loss of precision.
                                        • -
                                        -

                                        Using the ParameterAverageOptimizer op, any user can add the operation to their computation graphs. However, this will require a lot of lines of code and we should design Python APIs that support averaging. As per the PaddlePaddle Python API design, the layer functions are responsible for creating operators, operator parameters and variables. Since ParameterAverageOptimizer will be an operator, it makes sense to create it in the layer functions. -We will have a wrapper written in Python that will support the functionality and implement the actual core computation in C++ core as we have done for other Optimizers

                                        -
                                        -

                                        Creation of the ParameterAverageOptimizer operator

                                        -

                                        There are two ways for creating the ParameterAverageOptimizer op:

                                        -
                                          -
                                        1. We create the op immediately while building the computation graph.
                                        2. -
                                        3. We add the op in a lazy manner, just before the backward pass, similar to the way the optimization ops are added.
                                        4. -
                                        -

                                        The proposal is to add the op immediately while building the computation graph.

                                        -
                                        -
                                        -

                                        High-level API

                                        -

                                        In PaddlePaddle Python API, users will primarily rely on layer functions to create neural network layers. Hence, we also need to provide parameter average functionality in layer functions.

                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/parameters_in_cpp.html b/develop/doc_cn/design/parameters_in_cpp.html deleted file mode 100644 index 511079254de..00000000000 --- a/develop/doc_cn/design/parameters_in_cpp.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - - - - - - - - Design Doc: The C++ Class Parameters — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: The C++ Class Parameters

                                        -

                                        Parameters is a concept we designed in PaddlePaddle V2 API. Parameters is a container of parameters, which makes PaddlePaddle capable of sharing parameter between topologies. We described usages of Parameter in api.md.

                                        -

                                        We used Python to implement Parameters when designing V2 API before. There are several defects for the current implementation:

                                        -
                                          -
                                        • We just use memcpy to share Parameters between topologies, but this is very inefficient.
                                        • -
                                        • We did not support sharing Parameters while training. We just trigger memcpy when start training.
                                        • -
                                        -

                                        It is necessary that we implement Parameters in CPP side. However, it could result a code refactoring for PaddlePaddle, because PaddlePaddle was designed for training only one topology before, i.e., each GradientMachine contains its Parameter as a data member. In current PaddlePaddle implementation, there are three concepts associated with Parameters:

                                        -
                                          -
                                        1. paddle::Parameter. A Parameters is a container for paddle::Parameter. -It is evident that we should use paddle::Parameter when developing Parameters. -However, the Parameter class contains many functions and does not have a clear interface. -It contains create/store Parameter, serialize/deserialize, optimize(i.e SGD), randomize/zero. -When we developing Parameters, we only use create/store Parameter functionality. -We should extract functionalities of Parameter into many classes to clean PaddlePaddle CPP implementation.
                                        2. -
                                        3. paddle::GradientMachine and its sub-classes, e.g., paddle::MultiGradientMachine, paddle::NeuralNetwork. -We should pass Parameters to paddle::GradientMachine when forward/backward to avoid memcpy between topologies. -Also, we should handle multi-GPU/CPU training, because forward and backward would perform on multi-GPUs and multi-CPUs. -Parameters should dispatch the parameter value to each device, and gather the parameter gradient from each device.
                                        4. -
                                        5. paddle::ParameterUpdater. The ParameterUpdater is used to update parameters in Paddle. -So Parameters should be used by paddle::ParameterUpdater, and paddle::ParameterUpdater should optimize Parameters (by SGD).
                                        6. -
                                        -

                                        The step by step approach for implementation Parameters in PaddlePaddle C++ core is listed below. Each step should be a PR and could be merged into PaddlePaddle one by one.

                                        -
                                          -
                                        1. Clean paddle::Parameter interface. Extract the functionalities of paddle::Parameter to prepare for the implementation of Parameters.
                                        2. -
                                        3. Implementation a Parameters class. It just stores the paddle::Parameter inside. Make GradientMachine uses Parameters as a class member.
                                        4. -
                                        5. Make Parameters support Multi-CPU and Multi-GPU training to prepare for sharing Parameter between topologies. -Because we need share Parameters between topologies, it is Parameters‘s response to exchange Parameters between GPUs. -GradientMachine should not handle how to exchange Parameters because GradientMachine only used to train one topology and we need to support train many topologies in Paddle, i.e., there could be many GradientMachines use one Parameters.
                                            -
                                          • We should use a global function to exchange Parameters between GPUs, not a member function in Parameters. The MultiGradientMachine invoke this function, which uses Parameters as this function inputs.
                                          • -
                                          • The MultiGradientMachine contains many functionalities. Extracting the Parameters exchanging logic could make MultiGradientMachine clearer and simpler.
                                          • -
                                          -
                                        6. -
                                        7. Make Parameters as an argument for forward/backward function, not a data member for GradientMachine. For example, forward could be forward(const Parameters& params, ...) and backward could be backward(Parameters* params, ...). After this step, Paddle could share Parameters between topologies.
                                        8. -
                                        9. ParameterUpdater is invoked by GradientMachine and Trainer, but it updates Parameters. In the end of this code refactoring, we could change ParameterUpdater directly uses Parameters to make ParameterUpdater‘s implementation clear.
                                        10. -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/profiler.html b/develop/doc_cn/design/profiler.html deleted file mode 100644 index ac5d8803e35..00000000000 --- a/develop/doc_cn/design/profiler.html +++ /dev/null @@ -1,351 +0,0 @@ - - - - - - - - - - - - - Introduction — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Introduction

                                        -

                                        There are many performance analysis tools for different programming languages and different software frameworks. For most popular deep learning frameworks, they use several programming languages and adapt to heterogeneous platforms. Similar to most of the deep learning frameworks, PaddlePaddle also uses C++, CUDA and Python as the basic programming languages to adapt to run on CPU and GPU devices. The nvprof tools is usually used to analyse the CUDA program. We have a document to profile CPU and Python program by yep and Google’s perftools to profile only the CPU and Python program. But for PaddlePaddle fluid, the operator is the basic computing unit. The developers usually want to collect the time of each operator and locate bottlenecks. The nvprof usually collect the timeline of CUDA-related activities on both CPU and GPU, including kernel execution, memory transfers, memory set and CUDA API calls and events or metrics for CUDA kernels. And the yep and Google's perftools can’t collect the timeline for CUDA program. All these tools can’t collect time in the operator level. So we design this profiling tool.

                                        -
                                        -
                                        -

                                        Architecture

                                        -

                                        The work flow for most task is as follows. Each operator will run many times in the all iterations. So the profiler must collect the total time of each operator during the iteration. For more, sometimes, the developers may want to collect more detailed time span inside the operator or record time span for elsewhere, this requires that the profiler must support to record the nested time span. And in order to speedup training, all the deep learning frameworks support parallel computing, including multiple threads on CPU and multiple GPUs. So the profiler must be able to collect the timeline for each thread. In addition, the profiler also occupies certain resources. It must can be easily to be enabled or disabled by the developers. At last, the profiler should present a human-readable report.

                                        -
                                        for i in xrange(M):  # M is  the iteration number
                                        -  for op in operator_lists: # The `operator_lists` contains all the operators in the network.
                                        -    op.run();
                                        -
                                        -
                                        -

                                        In summary, the proflier should have following features:

                                        -
                                          -
                                        • records time span in loop.
                                        • -
                                        • supports nested time span.
                                        • -
                                        • supports multiple threads/multiple GPUs.
                                        • -
                                        • supports to be enabled and disabled by users.
                                        • -
                                        -

                                        But how to record the time for the mixed C++ and CUDA program? There many C++ APIs to get the current calendar time in host program. But for GPU, the CUDA kernels may be executed concurrently if they are in different streams and the CUDA kernels is asynchronous with the host program if there is no the synchronous aftern the CUDA kernels. CUDA provides event to monitor the device and perform accurate timing. Inspired by PyTorch and CUDA event, we also design and apply the events to record the timeline. Then summarize and present statistics based on these events.

                                        -

                                        The overall flow is shown as the following figure.

                                        -


                                        -
                                        -

                                        Event

                                        -

                                        In above work flow, a pair of events are needed before and after the piece of code to collect time. So the event has a flag to mark whether it is a starting event or an ending event. Except this two kinds of event, sometime, a only marker with a text message is needed, for example, a marker to specify the profiling start or end. There are three kinds of event:

                                        -
                                        enum EventKind {
                                        -  kMark,
                                        -  kPushRange,
                                        -  kPopRange};
                                        -
                                        -
                                        -
                                          -
                                        • kMark: only a marker without time range.
                                        • -
                                        • kPushRange: mark the starting event for time range.
                                        • -
                                        • kPopRange: mark the ending event for time range.
                                        • -
                                        -

                                        For the CPU code, the events only need to record the current time. For the CUDA code, the event management functions of CUDA are used. For many pieces of code, an event lists are used to record each piece.

                                        -
                                        class Event {
                                        - public:
                                        -  // The DeviceContext is used to get current  CUDA stream.
                                        -  Event(EventKind kind, std::string name, uint32_t thread_id,
                                        -        const platform::DeviceContext* dev_ctx = nullptr);
                                        -  double CpuElapsedUs(const Event& e) const;
                                        -  double CudaElapsedUs(const Event& e) const;
                                        -
                                        - private:
                                        -  EventKind kind_;
                                        -  std::string name_;
                                        -  uint32_t thread_id_;
                                        -  int64_t cpu_ns_;
                                        -#ifdef PADDLE_WITH_CUDA
                                        -  cudaEvent_t event_ = nullptr;
                                        -  int device_ = -1;
                                        -#endif
                                        -};
                                        -
                                        -struct EventList {
                                        -  std::forward_list<std::vector<Event>> event_blocks;
                                        -};
                                        -
                                        -
                                        -

                                        As mentioned above, there is no need to record the timeline when disabling the profiler. So there is a global state to enable or disable the profiler.

                                        -
                                        enum ProfilerState {
                                        -  kDisabled, 
                                        -  kCPU,
                                        -  kCUDA
                                        -};
                                        -ProfilerState g_state;
                                        -
                                        -
                                        -
                                          -
                                        • kDisabled: the disabled state.
                                        • -
                                        • kCPU: CPU profiling state.
                                        • -
                                        • kCUDA: GPU profiling state.
                                        • -
                                        -

                                        A pair of starting and ending events are pushed to event lists in constructor and destructor of RecordEvent. So the timeline is recorded for the code in the lifecycle of an object of RecordEvent.

                                        -
                                        struct RecordEvent {
                                        -  explicit RecordEvent(const std::string name,
                                        -                       platform::DeviceContext* dev_ctx = nullptr) {
                                        -    if (kState == ProfilerState::kDisabled) return;
                                        -    // push the starting event to the event lists.
                                        -  }
                                        -  ~RecordEvent() {
                                        -    if (kState == ProfilerState::kDisabled) return;
                                        -    // push the ending event to the event lists.
                                        -  }
                                        -};
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/program.html b/develop/doc_cn/design/program.html deleted file mode 100644 index c77c4405eb8..00000000000 --- a/develop/doc_cn/design/program.html +++ /dev/null @@ -1,386 +0,0 @@ - - - - - - - - - - - - - Design Doc: PaddlePaddle Programs — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: PaddlePaddle Programs

                                        -
                                        -

                                        Compile and Execution

                                        -

                                        A PaddlePaddle program consists of two parts – the first generates a ProgramDesc protobuf message that describes the program, and the second runs this message using a C++ class Executor.

                                        -

                                        A simple example PaddlePaddle program can be found in graph.md:

                                        -
                                        x = layer.data("images")
                                        -l = layer.data("label")
                                        -y = layer.fc(x)
                                        -cost = layer.mse(y, l)
                                        -optimize(cost)
                                        -train(cost, reader=mnist.train())
                                        -
                                        -
                                        -

                                        The first five lines of the following PaddlePaddle program generates, or, compiles, the ProgramDesc message. The last line runs it.

                                        -
                                        -
                                        -

                                        Programs and Blocks

                                        -

                                        The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.

                                        -
                                          -
                                        • program: some nested blocks
                                        • -
                                        • block:
                                            -
                                          • some local variable definitions, and
                                          • -
                                          • a sequence of operators
                                          • -
                                          -
                                        • -
                                        -

                                        The concept of block comes from usual programs. For example, the following C++ program has three blocks:

                                        -
                                        int main() { // block 0
                                        -  int i = 0;
                                        -  if (i < 10) { // block 1
                                        -    for (int j = 0; j < 10; j++) { // block 2
                                        -    }
                                        -  }
                                        -  return 0;
                                        -}
                                        -
                                        -
                                        -

                                        The following PaddlePaddle program has three blocks:

                                        -
                                        import paddle as pd  // block 0
                                        -
                                        -x = minibatch([10, 20, 30]) # shape=[None, 1]
                                        -y = var(1) # shape=[1], value=1
                                        -z = minibatch([10, 20, 30]) # shape=[None, 1]
                                        -cond = larger_than(x, 15) # [false, true, true]
                                        -
                                        -ie = pd.ifelse()
                                        -with ie.true_block():  // block 1
                                        -    d = pd.layer.add_scalar(x, y)
                                        -    ie.output(d, pd.layer.softmax(d))
                                        -with ie.false_block():  // block 2
                                        -    d = pd.layer.fc(z)
                                        -    ie.output(d, d+1)
                                        -o1, o2 = ie(cond)
                                        -
                                        -
                                        -
                                        -
                                        -

                                        BlockDesc and ProgramDesc

                                        -

                                        All protobuf messages are defined in framework.proto.

                                        -

                                        BlockDesc is straight-forward – it includes local variable definitions, vars, and a sequence of operators, ops.

                                        -
                                        message BlockDesc {
                                        -  required int32 parent = 1;
                                        -  repeated VarDesc vars = 2;
                                        -  repeated OpDesc ops = 3;
                                        -}
                                        -
                                        -
                                        -

                                        The parent ID indicates the parent block so that operators in a block can refer to variables defined locally and also those defined in their ancestor blocks.

                                        -

                                        All hierarchical blocks in a program are flattened and stored in an array. The block ID is the index of the block in this array.

                                        -
                                        message ProgramDesc {
                                        -  repeated BlockDesc blocks = 1;
                                        -}
                                        -
                                        -
                                        -
                                        -

                                        Global Block

                                        -

                                        The global block is the first one in the above array.

                                        -
                                        -
                                        -
                                        -

                                        Operators that Use Blocks

                                        -

                                        In the above example, the operator IfElseOp has two blocks – the true branch and the false branch.

                                        -

                                        The definition of OpDesc shows that an operator could have some attributes:

                                        -
                                        message OpDesc {
                                        -  AttrDesc attrs = 1;
                                        -  ...
                                        -}
                                        -
                                        -
                                        -

                                        and an attribute could be of type block, which is, in fact, a block ID as described above:

                                        -
                                        message AttrDesc {
                                        -  required string name = 1;
                                        -
                                        -  enum AttrType {
                                        -    INT = 1,
                                        -    STRING = 2,
                                        -    ...
                                        -    BLOCK = ...
                                        -  }
                                        -  required AttrType type = 2;
                                        -
                                        -  optional int32 block = 10; // when type == BLOCK
                                        -  ...
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -

                                        InferShape

                                        -

                                        With this design, the InferShape function should take the following parameters:

                                        -
                                        void InferShape(int current_block,
                                        -                int current_operator,
                                        -                ProgramDesc* program // might change VarDesc values.
                                        -                ) {
                                        -  ...
                                        -}
                                        -
                                        -
                                        -

                                        where

                                        -
                                          -
                                        • current_block indices into ProgramDesc::blocks,
                                        • -
                                        • current_operator indices into BlockDesc::ops.
                                        • -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/prune.html b/develop/doc_cn/design/prune.html deleted file mode 100644 index 3cdfec2a6b2..00000000000 --- a/develop/doc_cn/design/prune.html +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - Prune — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Prune

                                        -
                                        -

                                        Motivation

                                        -

                                        We want to support running inference, training and checkpointing in one ProgramDesc. We implement -void Prune(const ProgramDesc* input, ProgramDesc* output) function, which takes a ProgramDesc -and generate a pruned ProgramDesc.

                                        -
                                        -
                                        -

                                        Challenge

                                        -

                                        Pruning need to support both variables and operators being evaluation targets. Consider the following -different situations.

                                        -
                                        # Case 1: run foward pass.
                                        -cost_np = session.run(target=cost)
                                        -# Case 2: run backward passing.
                                        -opts_np, _ = session.run(target=[cost, opt])
                                        -# Case 3: run checkpointing
                                        -_ = session.run(target=checkpoint)
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Solution

                                        -

                                        To support evaluation of operators, we add is_target field in the OpDesc.

                                        -
                                        message OpDesc {
                                        -  required string type = 3;
                                        -  repeated Var inputs = 1;
                                        -  repeated Var outputs = 2;
                                        -  repeated Attr attrs = 4;
                                        -  optional bool is_target = 5 [ default = false ];
                                        -};
                                        -
                                        -
                                        -

                                        To support evaluation of variables, we add fetch_op. -For each variable in the target, we insert a fetch_op into the ProgramDesc with variable being -fetch_op‘s input. Then we also set fetch_op is a target.

                                        -
                                        -

                                        Algorithm

                                        -

                                        If an operator needs to be run, it must fall into one of the following cases:

                                        -
                                          -
                                        1. It is the target.
                                        2. -
                                        3. It is depended by some other ops, meaning its output is some other op’s input.
                                        4. -
                                        -

                                        The first case can be checked by op_desc.is_traget() . The second case can be implement as

                                        -
                                        bool HasDependentVar(const OpDesc& op_desc, const std::set<string>& dependent_vars) {
                                        -  for (auto& var : op_desc.outputs()) {
                                        -    for (auto& argu : var.arguments()) {
                                        -      if (dependent_vars.count(argu) != 0) {
                                        -        return true;
                                        -      }
                                        -    }
                                        -  }
                                        -  return false;
                                        -}
                                        -
                                        -
                                        -

                                        Then the whole algorithm can be implemented as the following code.

                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/python_api.html b/develop/doc_cn/design/python_api.html deleted file mode 100644 index f73acddccb2..00000000000 --- a/develop/doc_cn/design/python_api.html +++ /dev/null @@ -1,534 +0,0 @@ - - - - - - - - - - - - - Design Doc: Python API — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Python API

                                        -

                                        Due to the refactorization of the PaddlePaddle core, we need Python classes to construct corresponding protobuf messages that describe a DL program.

                                        -

                                        | Python classes | Protobuf messages | -| — | — | -| Program | ProgramDesc | -| Block | BlockDesc | -| Operator | OpDesc | -| Variable | VarDesc |

                                        -

                                        Please be aware that these Python classes need to maintain some construction-time information, which are not part of the protobuf messages.

                                        -
                                        -

                                        Core Concepts

                                        -
                                        -

                                        Program

                                        -

                                        A ProgramDesc describes a DL program, which is composed of an array of BlockDescs. The BlockDescs in a ProgramDesc can have a tree-like hierarchical structure. However, the ProgramDesc onlys stores a flattened array of BlockDescs. A BlockDesc refers to its parent block by its index in the array. For example, operators in the step block of an RNN operator need to be able to access variables in its ancestor blocks.

                                        -

                                        Whenever we create a block, we need to set its parent block to the current block, hence the Python class Program needs to maintain a data member current_block.

                                        -
                                        class Program(objects):
                                        -    def __init__(self):
                                        -        self.desc = core.NewProgram() # a C++ ProgramDesc pointer.
                                        -        self.blocks = vector<Block>()
                                        -        self.blocks.append(Block(self, -1)) # the global block
                                        -        self.current_block = 0          # initialized to the global block
                                        -
                                        -    def global_block():
                                        -        return self.blocks[0]
                                        -
                                        -    def current_block():
                                        -        return self.get_block(self.current_block)
                                        -
                                        -    def rollback():
                                        -        self.current_block = self.current_block().parent_idx
                                        -
                                        -    def create_block():
                                        -        new_block_idx = len(self.block)
                                        -        self.blocks.append(Block(self, self.current_block))
                                        -        self.current_block = new_block_idx
                                        -        return current_block()
                                        -
                                        -
                                        -

                                        Program is an accessor to the protobuf message ProgramDesc, which is created in C++ space, because the InferShape function is in C++, which manipulates VarDesc messages, which are in turn members of BlockDesc, which is a member of ProgramDesc.

                                        -

                                        Program creates the first block as the global block in its constructor. All parameters and their initializer operators are in the global block.

                                        -
                                        -
                                        -

                                        Block

                                        -

                                        A Block includes

                                        -
                                          -
                                        1. a map from variable names to an instance of the Python Variable class, and
                                        2. -
                                        3. a list of Operator instances.
                                        4. -
                                        -
                                        class Block(objects):
                                        -    def __init__(self, program, parent_idx):
                                        -        self.desc = core.NewBlock(program.desc)
                                        -        self.program = program
                                        -        self.vars = map<string, Variable>()
                                        -        self.ops = vector<Operator>()
                                        -        self.parent_idx = parent_idx
                                        -
                                        -    def create_var(self, ...):
                                        -        return Variable(self, ...)
                                        -
                                        -    def _create_global_var(self, ...):
                                        -        program.global_block().create_var(...)
                                        -
                                        -    def create_parameter(self, name, ...):
                                        -        # Parameter is a subclass of variable. See Parameter section for details.
                                        -        self.vars[name] = Parameter(self._create_global_var(...), ...)
                                        -        return self.vars[name]
                                        -
                                        -    def append_operator(self, ...):
                                        -        self.ops.append(Operator(self, ...))
                                        -
                                        -    def prepend_operator(self, ...): # Parameter's ctor prepands initialize operators.
                                        -       self.ops.prepend(Operator(self, ...))
                                        -
                                        -
                                        -

                                        create_parameter is necessary because parameters are global variables, defined in the global block, but can be created in some sub-blocks. For example, an FC layer in the step block of an RNN operator.

                                        -

                                        prepend_operator is necessary because the constructor of Parameter needs to create the initialize (or load) operator of the parameter, and would like to put it in the preamble of the global block.

                                        -
                                        -
                                        -

                                        Operator

                                        -

                                        The Operator class fills in the OpDesc message and calls the C++ function InferShape to infer the output shapes from the input shapes.

                                        -
                                        class Operator(object):
                                        -    def __init__(self,
                                        -                 block,  # Block
                                        -                 type,   # string
                                        -                 inputs, # dict<string, Variable>
                                        -                 outputs,# dict<stirng, Variable>
                                        -                 attrs   # dict<string, Any>
                                        -                 ):
                                        -        self.desc = core.NewOpDesc(block.desc, type, inputs, outputs, attrs)
                                        -        core.infer_shape(self.desc, inputs, outputs)
                                        -
                                        -    def type(self):
                                        -        return self.desc.type()
                                        -
                                        -
                                        -

                                        Operator creates the OpDesc message in C++ space, so that it can call the InferShape function, which is in C++.

                                        -
                                        -
                                        -

                                        Variable

                                        -

                                        Operators take Variables as its inputs and outputs.

                                        -
                                        class Variable(object):
                                        -    def __init__(self,
                                        -                 block=None,      # Block
                                        -                 name=None,       # string
                                        -                 shape,           # tuple
                                        -                 dtype="float32", # string
                                        -                 lod_level=None   # int
                                        -                 ):
                                        -        if name is None:
                                        -            name = unique_name_generator()
                                        -        self.name = name
                                        -        self.block = block
                                        -        self.desc = core.NewVarDesc(block.desc, name, shape, lod_level)
                                        -        self.writer = None
                                        -
                                        -
                                        -

                                        Please be aware of self.writer, that tracks operator who creates the variable. It possible that there are more than one operators who write a variable, but in Python space, each write to a variable is represented by a Variable class. This is guaranteed by the fact that core.NewVarDesc must NOT create a new VarDesc message if its name already exists in the specified block.

                                        -
                                        -
                                        -

                                        Parameter

                                        -

                                        A parameter is a global variable with an initializer (or load) operator.

                                        -
                                        class Parameter(Variable):
                                        -    def __init__(self,
                                        -                 block=None,      # Block
                                        -                 name=None,       # string
                                        -                 shape,           # tuple
                                        -                 dtype="float32", # string
                                        -                 lod_level=None   # int
                                        -                 trainable,       # bool
                                        -                 initialize_op_attrs,
                                        -                 optimize_op_attrs):
                                        -        super(Parameter, self).__init__(block, name, shape, dtype, lod_level)
                                        -        self.trainable = trainable
                                        -        self.optimize_op_attrs = optimize_op_attrs
                                        -        block.prepend(Operator(block,  # Block
                                        -                               initialize_op_attrs['type'],   # string
                                        -                               None,   # no inputs
                                        -                               self,   # output is the parameter
                                        -                               initialize_op_attrs)
                                        -
                                        -
                                        -

                                        When users create a parameter, they can call

                                        -
                                        program.create_parameter(
                                        -  ...,
                                        -  init_attr={
                                        -    type: "uniform_random",
                                        -    min: -1.0,
                                        -    max: 1.0,
                                        -  })
                                        -)
                                        -
                                        -
                                        -

                                        In above example, init_attr.type names an initialize operator. It can also name the load operator

                                        -
                                        init_attr={
                                        - type: "load",
                                        - filename: "something.numpy",
                                        -}
                                        -
                                        -
                                        -

                                        optimize_op_attrs is not in the VarDesc message, but kept in the Python instance, as it will be used in the Python space when creating the optimize operator’s OpDesc, and will be in the OpDesc message.

                                        -
                                        -
                                        -
                                        -

                                        Layer Function

                                        -

                                        A layer is a Python function that creates some operators and variables. Layers simplify the work of application programmers.

                                        -

                                        Layer functions take Variable and configuration parameters as its input and return the output variable(s).

                                        -

                                        For example, FullyConnected take one or more variable as its input. The input could be input data or another layer’s output. There are many configuration options for a FullyConnected layer, such as layer size, activation, parameter names, initialization strategies of parameters, and so on. The FullyConnected layer will return an output variable.

                                        -
                                        -

                                        Necessity for reusing code between layer functions

                                        -

                                        There are a lot of code that can be reused. Such as

                                        -
                                          -
                                        • Give the default value of configuration. e.g., default initialize strategy for parameters is uniform random with min = -1.0, max = 1.0. and default initialize strategy for bias is to fill zero.
                                        • -
                                        • Append the activation operator.
                                        • -
                                        • Create a temporary variable.
                                        • -
                                        • Create parameter.
                                        • -
                                        • Generate a unique name.
                                        • -
                                        • Add a bias.
                                        • -
                                        • ...
                                        • -
                                        -

                                        A mechanism to reuse code between layer functions is necessary. It will be around 150 lines of code if we write a FullyConnected layer without any helper functions.

                                        -
                                        -
                                        -

                                        Comparision between global functions and helper class

                                        -

                                        The FullyConnected layer will be as follow when we provide global functions:

                                        -
                                        def fc_layer(input, size, param_attr=None, bias_attr=None, act=None, name=None):
                                        -  if name is None:
                                        -    name = unique_name("fc")
                                        -  input = multiple_input(input)
                                        -  param_attr = default_param_attr(param_attr)
                                        -  param_attr = multiple_param_attr(param_attr, len(input))
                                        -
                                        -  # mul
                                        -  mul_results = []
                                        -  for ipt, attr in zip(input, param_attr):
                                        -    shape = ipt.shape[1:] + [size]
                                        -    w = g_program.global_block().create_parameter(shape, ipt.dtype, name, attr)
                                        -    tmp = create_tmp_var(name)
                                        -    g_program.current_block().append_op("mul", {ipt, w}, {tmp})
                                        -  mul_results.append(tmp)
                                        -
                                        -  # add sum
                                        -  ...
                                        -  # add bias
                                        -  ...
                                        -  # add activation
                                        -  ...
                                        -  return out
                                        -
                                        -
                                        -

                                        We can provide many helpers functions for layer developers. However, there are several disadvantages for global helper functions:

                                        -
                                          -
                                        1. We need a namespace for these methods, then layer developers can quickly figure out what method they can use.
                                        2. -
                                        3. Global functions will force layer developers to pass its parameter time by time.
                                        4. -
                                        -

                                        So we provide a helper class, LayerHelper, to share code between layer functions. The FullyConnected Layer will be as follow.

                                        -
                                        def fc_layer(input, size, param_attr=None, bias_attr=None, act=None, name=None):
                                        -  helper = LayerHelper(locals())  # pass all parameter to LayerHelper
                                        -
                                        -  mul_results = []
                                        -  for ipt, param in helper.iter_multiple_input_and_param():
                                        -    w = helper.create_parameter(shape=ipt.shape[1:] + [size], dtype = ipt.dtype)
                                        -    tmp = helper.create_tmp_variable()
                                        -    helper.append_op('mul', {ipt, w}, {tmp})
                                        -    mul_results.append(tmp)
                                        -
                                        -  pre_bias = helper.add_sum(mul_results)
                                        -  pre_activation = helper.add_bias(pre_bias)
                                        -  return helper.add_activation(pre_activation)
                                        -
                                        -
                                        -

                                        We not only use the fewer lines of code to write fc_layer but also make the code clearer to understand. At the same time, layer developers can figure out what function they can invoke by typing helper. in a python editor.

                                        -
                                        -
                                        -

                                        Implementation of layer helper

                                        -

                                        We just keep all parameters of a layer function as a dictionary in layer helper as a private data member. Every method of layer helper will look up the dictionary after it is invoked. In that way, we can implement a layer helper for all layer functions even some layer does not contain some operator. For example, The activation is used by the FullyConnected layer or convolution layers, but a cross-entropy layer does not use it. The example code of add_activation are:

                                        -
                                        class LayerHelper(object):
                                        -  def __init__(self, **kwargs):  # kwargs is short for `keyword arguments`
                                        -    self.kwargs = kwargs
                                        -
                                        -  def add_activation(self, input_var):
                                        -    act = self.kwargs.get("act", None)  # default value is None
                                        -    if act is None:  # do nothing if no act
                                        -      return input_var
                                        -
                                        -    tmp = self.create_tmp_var(self)
                                        -    self.append_op(type=act, input=input_var, output=tmp)
                                        -    return tmp
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Return value of layer functions

                                        -

                                        The layer will return a Variable, which is also the output of an operator. However, outputs of a layer function have more attributes than an operator. There are parameter variables, and their gradient variables need to return. To return them is useful. For example,

                                        -
                                          -
                                        1. Users can debug the network by printing parameter gradients.
                                        2. -
                                        3. Users can append attributes to a parameter, such as, param.stop_gradient=True will make a parameter stop generate the gradient. We can fix the parameter value during training by using this attribute.
                                        4. -
                                        -

                                        However, it is good to return a Variable for layers, since all layers and operators use Variables as their parameters. We can just append a param field and a grad field for layer function since the Python is dynamic typing.

                                        -

                                        The sample usage is

                                        -
                                        data = fluid.layers.data(...)
                                        -hidden = fluid.layers.fc(data, ...)
                                        -...
                                        -
                                        -executor.run(fetch_list=[hidden.param, hidden.param.grad], ...)
                                        -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Optimizer

                                        -

                                        Optimizer Design Doc

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/reader/README.html b/develop/doc_cn/design/reader/README.html deleted file mode 100644 index f7edc8e5c96..00000000000 --- a/develop/doc_cn/design/reader/README.html +++ /dev/null @@ -1,446 +0,0 @@ - - - - - - - - - - - - - Python Data Reader Design Doc — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Python Data Reader Design Doc

                                        -

                                        During the training and testing phases, PaddlePaddle programs need to read data. To help the users write code that performs reading input data, we define the following:

                                        -
                                          -
                                        • A reader: A function that reads data (from file, network, random number generator, etc) and yields the data items.
                                        • -
                                        • A reader creator: A function that returns a reader function.
                                        • -
                                        • A reader decorator: A function, which takes in one or more readers, and returns a reader.
                                        • -
                                        • A batch reader: A function that reads data (from reader, file, network, random number generator, etc) and yields a batch of data items.
                                        • -
                                        -

                                        and also provide a function which can convert a reader to a batch reader, frequently used reader creators and reader decorators.

                                        -
                                        -

                                        Data Reader Interface

                                        -

                                        Data reader doesn’t have to be a function that reads and yields data items. It can just be any function without any parameters that creates an iterable (anything can be used in for x in iterable) as follows:

                                        -
                                        iterable = data_reader()
                                        -
                                        -
                                        -

                                        The item produced from the iterable should be a single entry of data and not a mini batch. The entry of data could be a single item or a tuple of items. Item should be of one of the supported types (e.g., numpy 1d array of float32, int, list of int etc.)

                                        -

                                        An example implementation for single item data reader creator is as follows:

                                        -
                                        def reader_creator_random_image(width, height):
                                        -    def reader():
                                        -        while True:
                                        -            yield numpy.random.uniform(-1, 1, size=width*height)
                                        -    return reader
                                        -
                                        -
                                        -

                                        An example implementation for multiple item data reader creator is as follows:

                                        -
                                        def reader_creator_random_image_and_label(width, height, label):
                                        -    def reader():
                                        -        while True:
                                        -            yield numpy.random.uniform(-1, 1, size=width*height), label
                                        -    return reader
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Batch Reader Interface

                                        -

                                        Batch reader can be any function without any parameters that creates an iterable (anything can be used in for x in iterable). The output of the iterable should be a batch (list) of data items. Each item inside the list should be a tuple.

                                        -

                                        Here are some valid outputs:

                                        -
                                        # a mini batch of three data items. Each data item consist three columns of data, each of which is 1.
                                        -[(1, 1, 1),
                                        -(2, 2, 2),
                                        -(3, 3, 3)]
                                        -
                                        -# a mini batch of three data items, each data item is a list (single column).
                                        -[([1,1,1],),
                                        -([2,2,2],),
                                        -([3,3,3],)]
                                        -
                                        -
                                        -

                                        Please note that each item inside the list must be a tuple, below is an invalid output:

                                        -
                                         # wrong, [1,1,1] needs to be inside a tuple: ([1,1,1],).
                                        - # Otherwise it is ambiguous whether [1,1,1] means a single column of data [1, 1, 1],
                                        - # or three columns of data, each of which is 1.
                                        -[[1,1,1],
                                        -[2,2,2],
                                        -[3,3,3]]
                                        -
                                        -
                                        -

                                        It is easy to convert from a reader to a batch reader:

                                        -
                                        mnist_train = paddle.dataset.mnist.train()
                                        -mnist_train_batch_reader = paddle.batch(mnist_train, 128)
                                        -
                                        -
                                        -

                                        It is also straight forward to create a custom batch reader:

                                        -
                                        def custom_batch_reader():
                                        -    while True:
                                        -        batch = []
                                        -        for i in xrange(128):
                                        -            batch.append((numpy.random.uniform(-1, 1, 28*28),)) # note that it's a tuple being appended.
                                        -        yield batch
                                        -
                                        -mnist_random_image_batch_reader = custom_batch_reader
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Usage

                                        -

                                        Following is how we can use the reader with PaddlePaddle: -The batch reader, a mapping from item(s) to data layer, the batch size and the number of total passes will be passed into paddle.train as follows:

                                        -
                                        # two data layer is created:
                                        -image_layer = paddle.layer.data("image", ...)
                                        -label_layer = paddle.layer.data("label", ...)
                                        -
                                        -# ...
                                        -batch_reader = paddle.batch(paddle.dataset.mnist.train(), 128)
                                        -paddle.train(batch_reader, {"image":0, "label":1}, 128, 10, ...)
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Data Reader Decorator

                                        -

                                        The Data reader decorator takes in a single reader or multiple data readers and returns a new data reader. It is similar to a python decorator, but it does not use @ in the syntax.

                                        -

                                        Since we have a strict interface for data readers (no parameters and return a single data item), a data reader can be used in a flexible way using data reader decorators. Following are a few examples:

                                        -
                                        -

                                        Prefetch Data

                                        -

                                        Since reading data may take some time and training can not proceed without data, it is generally a good idea to prefetch the data.

                                        -

                                        Use paddle.reader.buffered to prefetch data:

                                        -
                                        buffered_reader = paddle.reader.buffered(paddle.dataset.mnist.train(), 100)
                                        -
                                        -
                                        -

                                        buffered_reader will try to buffer (prefetch) 100 data entries.

                                        -
                                        -
                                        -

                                        Compose Multiple Data Readers

                                        -

                                        For example, if we want to use a source of real images (say reusing mnist dataset), and a source of random images as input for Generative Adversarial Networks.

                                        -

                                        We can do the following :

                                        -
                                        def reader_creator_random_image(width, height):
                                        -    def reader():
                                        -        while True:
                                        -            yield numpy.random.uniform(-1, 1, size=width*height)
                                        -    return reader
                                        -
                                        -def reader_creator_bool(t):
                                        -    def reader:
                                        -        while True:
                                        -            yield t
                                        -    return reader
                                        -
                                        -true_reader = reader_creator_bool(True)
                                        -false_reader = reader_creator_bool(False)
                                        -
                                        -reader = paddle.reader.compose(paddle.dataset.mnist.train(), data_reader_creator_random_image(20, 20), true_reader, false_reader)
                                        -# Skipped 1 because paddle.dataset.mnist.train() produces two items per data entry.
                                        -# And we don't care about the second item at this time.
                                        -paddle.train(paddle.batch(reader, 128), {"true_image":0, "fake_image": 2, "true_label": 3, "false_label": 4}, ...)
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Shuffle

                                        -

                                        Given the shuffle buffer size n, paddle.reader.shuffle returns a data reader that buffers n data entries and shuffles them before a data entry is read.

                                        -

                                        Example:

                                        -
                                        reader = paddle.reader.shuffle(paddle.dataset.mnist.train(), 512)
                                        -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Q & A

                                        -
                                        -

                                        Why does a reader return only a single entry, and not a mini batch?

                                        -

                                        Returning a single entry makes reusing existing data readers much easier (for example, if an existing reader returns 3 entries instead if a single entry, the training code will be more complicated because it need to handle cases like a batch size 2).

                                        -

                                        We provide a function: paddle.batch to turn (a single entry) reader into a batch reader.

                                        -
                                        -
                                        -

                                        Why do we need a batch reader, isn’t is sufficient to give the reader and batch_size as arguments during training ?

                                        -

                                        In most of the cases, it would be sufficient to give the reader and batch_size as arguments to the train method. However sometimes the user wants to customize the order of data entries inside a mini batch, or even change the batch size dynamically. For these cases using a batch reader is very efficient and helpful.

                                        -
                                        -
                                        -

                                        Why use a dictionary instead of a list to provide mapping?

                                        -

                                        Using a dictionary ({"image":0, "label":1}) instead of a list (["image", "label"]) gives the advantage that the user can easily reuse the items (e.g., using {"image_a":0, "image_b":0, "label":1}) or even skip an item (e.g., using {"image_a":0, "label":2}).

                                        -
                                        -
                                        -

                                        How to create a custom data reader creator ?

                                        -
                                        def image_reader_creator(image_path, label_path, n):
                                        -    def reader():
                                        -        f = open(image_path)
                                        -        l = open(label_path)
                                        -        images = numpy.fromfile(
                                        -            f, 'ubyte', count=n * 28 * 28).reshape((n, 28 * 28)).astype('float32')
                                        -        images = images / 255.0 * 2.0 - 1.0
                                        -        labels = numpy.fromfile(l, 'ubyte', count=n).astype("int")
                                        -        for i in xrange(n):
                                        -            yield images[i, :], labels[i] # a single entry of data is created each time
                                        -        f.close()
                                        -        l.close()
                                        -    return reader
                                        -
                                        -# images_reader_creator creates a reader
                                        -reader = image_reader_creator("/path/to/image_file", "/path/to/label_file", 1024)
                                        -paddle.train(paddle.batch(reader, 128), {"image":0, "label":1}, ...)
                                        -
                                        -
                                        -
                                        -
                                        -

                                        How is paddle.train implemented

                                        -

                                        An example implementation of paddle.train is:

                                        -
                                        def train(batch_reader, mapping, batch_size, total_pass):
                                        -    for pass_idx in range(total_pass):
                                        -        for mini_batch in batch_reader(): # this loop will never end in online learning.
                                        -            do_forward_backward(mini_batch, mapping)
                                        -
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/refactorization.html b/develop/doc_cn/design/refactorization.html deleted file mode 100644 index fe1515b9d31..00000000000 --- a/develop/doc_cn/design/refactorization.html +++ /dev/null @@ -1,591 +0,0 @@ - - - - - - - - - - - - - Design Doc: Refactorization Overview — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Refactorization Overview

                                        -

                                        The goals of refactoring include:

                                        -
                                          -
                                        1. Making it easy for external contributors to write new elementary computation operations.
                                        2. -
                                        3. Making the codebase clean and readable.
                                        4. -
                                        5. Designing a new computation representation – a computation graph of operators and variables.
                                        6. -
                                        7. Implementing auto-scalability and auto fault recoverable distributed computing with the help of computation graphs.
                                        8. -
                                        -
                                        -

                                        Computation Graphs

                                        -
                                          -
                                        1. PaddlePaddle represents the computation, training and inference of Deep Learning models, by computation graphs.
                                        2. -
                                        3. Please refer to computation graphs for a concrete example.
                                        4. -
                                        5. Users write Python programs to describe the graphs and run them (locally or remotely).
                                        6. -
                                        7. A graph is composed of variables and operators.
                                        8. -
                                        9. The description of graphs must be serializable/deserializable, so that:
                                            -
                                          1. It can be sent to the cloud for distributed execution, and
                                          2. -
                                          3. It can be sent to clients for mobile or enterprise deployment.
                                          4. -
                                          -
                                        10. -
                                        11. The Python program does two things
                                            -
                                          1. Compilation runs a Python program to generate a protobuf message representation of the graph and send it to
                                              -
                                            1. the C++ library libpaddle.so for local execution,
                                            2. -
                                            3. the master process of a distributed training job for training, or
                                            4. -
                                            5. the server process of a Kubernetes serving job for distributed serving.
                                            6. -
                                            -
                                          2. -
                                          3. Execution executes the graph by constructing instances of class Variable and OperatorBase, according to the protobuf message.
                                          4. -
                                          -
                                        12. -
                                        -
                                        -
                                        -

                                        Description and Realization of Computation Graph

                                        -

                                        At compile time, the Python program generates a protobuf message representation of the graph, or a description of the graph.

                                        -

                                        At runtime, the C++ program realizes the graph and runs it.

                                        -

                                        | | Representation (protobuf messages) | Realization (C++ class objects) | -|—|—|—| -|Data|VarDesc|Variable| -|Operation|OpDesc|Operator| -|Block|BlockDesc|Block|

                                        -

                                        The word graph is interchangeable with block in this document. A graph consists of computation steps and local variables similar to a C++/Java program block, or a pair of parentheses({ and }).

                                        -
                                        -
                                        -

                                        Compilation and Execution

                                        -
                                          -
                                        1. Run a Python program to describe the graph. In particular, the Python application program does the following:
                                            -
                                          1. Create VarDesc to represent local/intermediate variables,
                                          2. -
                                          3. Create operators and set attributes,
                                          4. -
                                          5. Validate attribute values,
                                          6. -
                                          7. Infer the type and the shape of variables,
                                          8. -
                                          9. Plan memory-reuse for variables,
                                          10. -
                                          11. Generate the backward graph
                                          12. -
                                          13. Add optimization operators to the computation graph.
                                          14. -
                                          15. Optionally, split the graph for distributed training.
                                          16. -
                                          -
                                        2. -
                                        3. The invocation of train or infer methods in the Python program does the following:
                                            -
                                          1. Create a new Scope instance in the scope hierarchy for each run of a block,
                                              -
                                            1. realize local variables defined in the BlockDesc message in the new scope,
                                            2. -
                                            3. a scope is similar to the stack frame in programming languages,
                                            4. -
                                            -
                                          2. -
                                          3. Create an instance of class Block, in which,
                                              -
                                            1. realize operators in the BlockDesc message,
                                            2. -
                                            -
                                          4. -
                                          5. Run the Block by calling
                                              -
                                            1. Block::Eval(vector<Variable>* targets) for forward and backward computations, or
                                            2. -
                                            3. Block::Eval(vector<Operator>* targets) for optimization.
                                            4. -
                                            -
                                          6. -
                                          -
                                        4. -
                                        -
                                        -
                                        -

                                        Intermediate Representation (IR)

                                        -
                                        Compile Time -> IR -> Runtime
                                        -
                                        -
                                        -
                                        -

                                        Benefits of IR

                                        -
                                          -
                                        • Optimization

                                          -
                                          Compile Time -> IR -> Optimized IR -> Runtime
                                          -
                                          -
                                          -
                                        • -
                                        • Automatically send partitioned IR to different nodes.

                                          -
                                            -
                                          • Automatic Data Parallelism

                                            -
                                            Compile Time
                                            -|-> Single GPU IR
                                            -    |-> [trainer-IR-0, trainer-IR-1, pserver-IR]
                                            -        |-> Node-0 (runs trainer-IR-0)
                                            -        |-> Node-1 (runs trainer-IR-1)
                                            -        |-> Node-2 (runs pserver-IR)
                                            -
                                            -
                                            -
                                          • -
                                          • Automatic Model Parallelism (planned for future)

                                            -
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Operator/OpWithKernel/OpKernel

                                        -

                                        class_diagram

                                        -
                                        -
                                        -
                                        -

                                        Operator

                                        -

                                        class_diagram

                                        -
                                          -
                                        • Operator is the fundamental building block of the user interface.
                                            -
                                          • Operator stores input/output variable names and attributes.
                                          • -
                                          • The InferShape interface is used to infer the shape of the output variables based on the shapes of the input variables.
                                          • -
                                          • Use Run to compute the output variables from the input variables.
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        OpWithKernel/Kernel

                                        -

                                        class_diagram

                                        -
                                          -
                                        • OpWithKernel inherits Operator.
                                        • -
                                        • OpWithKernel contains a Kernel map.
                                            -
                                          • OpWithKernel::Run get device’s kernel, and invoke OpKernel::Compute.
                                          • -
                                          • OpKernelKey is the map key. Only device place now, but may be data type later.
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Why separate Kernel and Operator

                                        -
                                          -
                                        • Separate GPU and CPU code.
                                            -
                                          • Make Paddle capable of running without GPU.
                                          • -
                                          -
                                        • -
                                        • Make one operator (which is a user interface) and create many implementations.
                                            -
                                          • For example, same multiplication op can have different implementations kernels such as FP16 kernel, FP32 kernel, MKL, eigen kernel.
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Libraries for Kernel development

                                        -
                                          -
                                        • Eigen::Tensor contains basic math and element-wise functions.
                                            -
                                          • Note that Eigen::Tensor has broadcast implementation.
                                          • -
                                          • Limit the number of tensor.device(dev) = in your code.
                                          • -
                                          -
                                        • -
                                        • thrust::transform and std::transform.
                                            -
                                          • thrust has the same API as C++ standard library. Using transform, one can quickly implement customized element-wise kernels.
                                          • -
                                          • thrust, in addition, supports more complex APIs, like scan, reduce, reduce_by_key.
                                          • -
                                          -
                                        • -
                                        • Hand-writing GPUKernel and CPU code
                                            -
                                          • Do not write in header (.h) files. CPU Kernel should be in cpp source (.cc) and GPU kernels should be in cuda (.cu) files. (GCC cannot compile GPU code.)
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Operator Registration

                                        -
                                        -

                                        Why is registration necessary?

                                        -

                                        We need a method to build mappings between Op type names and Op classes.

                                        -
                                        -
                                        -

                                        How is registration implemented?

                                        -

                                        Maintaining a map, whose key is the type name and the value is the corresponding Op constructor.

                                        -
                                        -
                                        -
                                        -
                                        -

                                        The Registry Map

                                        -
                                        -

                                        OpInfoMap

                                        -

                                        op_type(string) -> OpInfo

                                        -

                                        OpInfo:

                                        -
                                          -
                                        • creator: The Op constructor.
                                        • -
                                        • grad_op_type: The type of the gradient Op.
                                        • -
                                        • proto: The Op’s Protobuf, including inputs, outputs and required attributes.
                                        • -
                                        • checker: Used to check attributes.
                                        • -
                                        -
                                        -
                                        -
                                        - -
                                        -
                                        -

                                        Registration Process

                                        -
                                          -
                                        1. Write an Op class and its gradient Op class, if required.
                                        2. -
                                        3. Write an Op maker class. In the constructor of this class, describe the inputs, outputs and attributes of the operator.
                                        4. -
                                        5. Invoke the macro REGISTER_OP. This macro will
                                            -
                                          1. Call maker class to complete proto and checker
                                          2. -
                                          3. Using the completed proto and checker, it will add a new key-value pair to the OpInfoMap
                                          4. -
                                          -
                                        6. -
                                        -
                                        -
                                        -
                                        -

                                        Backward Module (1/2)

                                        -
                                        -

                                        Create Backward Operator

                                        -
                                          -
                                        • Mapping from forward Op to backward Op -backward
                                        • -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Backward Module (2/2)

                                        -
                                        -

                                        Build Backward Network

                                        -
                                          -
                                        • Input: a graph of forward operators
                                        • -
                                        • Output: a graph of backward operators
                                        • -
                                        • Corner cases in construction
                                            -
                                          • Shared Variables => insert an Add operator to combine gradients
                                          • -
                                          • No Gradient => insert a fill_zero_grad operator
                                          • -
                                          • Recursive NetOp => call Backward recursively
                                          • -
                                          • RNN Op => recursively call Backward on stepnet
                                          • -
                                          • RNN Op => recursively call Backward on stepnet
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Scope, Variable, Tensor

                                        -
                                          -
                                        • Tensor is an n-dimension array with type.
                                            -
                                          • Only dims and data pointers are stored in Tensor.
                                          • -
                                          • All operations on Tensor are written in Operator or global functions.
                                          • -
                                          • Variable length Tensor design LoDTensor
                                          • -
                                          -
                                        • -
                                        • Variable instances are the inputs and the outputs of an operator, not just Tensor.
                                            -
                                          • step_scopes in RNN is a variable and not a tensor.
                                          • -
                                          -
                                        • -
                                        • Scope is where variables are stored.
                                            -
                                          • map<string var name, Variable>
                                          • -
                                          • Scope has a hierarchical structure. The local scope can get variables from its parent scope.
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Block (in design)

                                        -
                                        -

                                        the difference between original RNNOp and Block

                                        -
                                          -
                                        • As an operator is more intuitive than RNNOp,
                                        • -
                                        • Offers a new interface Eval(targets) to deduce the minimal block to Run,
                                        • -
                                        • Fits the compile-time/ runtime separation design paradigm.
                                            -
                                          • During the compilation, SymbolTable stores VarDescs and OpDescs and serialize to a BlockDesc
                                          • -
                                          • When graph executes, a Block with BlockDesc is passed. It then creates Op and Var instances and then invokes Run.
                                          • -
                                          -
                                        • -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Milestone

                                        -
                                          -
                                        • Take Paddle/books as the main line, the requirement of the models motivates framework refactoring,
                                        • -
                                        • Model migration
                                            -
                                          • Framework development gives priority support to model migration, for example,
                                              -
                                            • the MNIST demo needs a Python interface,
                                            • -
                                            • the RNN models require the framework to support LoDTensor.
                                            • -
                                            -
                                          • -
                                          • Determine some timelines,
                                          • -
                                          • Frequently used Ops need to be migrated first,
                                          • -
                                          • Different models can be migrated in parallel.
                                          • -
                                          -
                                        • -
                                        • Improve the framework at the same time
                                        • -
                                        • Accept imperfection, concentrate on solving the specific problem at the right price.
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Control the migration quality

                                        -
                                          -
                                        • Compare the performance of migrated models with old ones.
                                        • -
                                        • Follow the google C++ style guide.
                                        • -
                                        • Build the automatic workflow of generating Python/C++ documentations.
                                            -
                                          • The documentation of layers and ops should be written inside the code.
                                          • -
                                          • Take the documentation quality into account when submitting pull requests.
                                          • -
                                          • Preview the documentations, read and improve them from a user’s perspective.
                                          • -
                                          -
                                        • -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/register_grad_op.html b/develop/doc_cn/design/register_grad_op.html deleted file mode 100644 index c0027e02054..00000000000 --- a/develop/doc_cn/design/register_grad_op.html +++ /dev/null @@ -1,336 +0,0 @@ - - - - - - - - - - - - - Design Doc: Gradient Operators Registration — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Gradient Operators Registration

                                        -
                                        -

                                        The Problem Posed

                                        -

                                        Currently, for each C++ operator class definition, a gradient operator creator function is registered, which takes as input a C++ operator instance and returns the corresponding gradient operator instance.

                                        -

                                        However, we noticed two problems with the current design:

                                        -
                                          -
                                        1. As we decided to separate the compilation and the execution phases, we need to change the creator to take an OpDesc protobuf message in a ProgramDesc and inserts corresponding OpDesc messages into the ProgramDesc message.
                                        2. -
                                        3. For some operators, the gradient computation can be written in terms of existing operators. For example, the gradient of minus operator consists of two operators – an identity operator followed by a scale operator. Hence the registration mechanism needs to support mapping from an operator to a set of operators for the gradient computation.
                                        4. -
                                        -
                                        -
                                        -

                                        The Current Implementation

                                        -

                                        Instances of the C++ class OpInfo are stored an associative map whose key is the operator type. The grad_op_type indicates the associated gradient operator type. An operator can create the gradient operator by invoking OpInfo::creator_ of the gradient operator. The pseudo code is as follows

                                        -
                                        struct OpInfo {
                                        -  std::function<OperatorBase*(...)> creator_;
                                        -  std::string grad_op_type_;
                                        -  ...
                                        -};
                                        -
                                        -map<string, OpInfo> OpInfoMap;
                                        -
                                        -OperatorBase* CreateGradientOperator(const OperatorBase& op) {
                                        -  return OpInfoMap.at(op.Type()).creator_(...);
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Proposed Solution

                                        -

                                        The mapping relationship between an operator and its gradient operators is a function. The interface of this function is:

                                        -
                                        // (OpDesc) --> vector<OpDesc>
                                        -std::function<std::vector<OpDescBind>(const OpDescBind&)>;
                                        -
                                        -
                                        -

                                        The function takes an OpDescBind of the forward operator and returns one or many gradient operator descriptions. OpDescBind is a C++ wrapper for the protobuf message OpDesc for rapid manipulation of OpDesc.

                                        -

                                        The GradOpDescMaker will be registered in OpInfo and will replace the grad_op_type_ field. The OpInfo should look like

                                        -
                                        struct OpInfo {
                                        -  std::function<std::vector<std::unique_ptr<OpDescBind>>(const OpDescBind&)>  grad_op_maker_;
                                        -  ...
                                        -};
                                        -
                                        -
                                        -

                                        The grad_op_maker_ is a nullptr if the operator does not have any associated gradient operators.

                                        -

                                        We propose a base class called GradOpDescMakerBase to let operator developers generate Gradient Operators easily. The public interface of that class is

                                        -
                                        class GradOpDescMakerBase {
                                        -public:
                                        -  GradOpDescMakerBase(const OpDescBind& );
                                        -  virtual std::vector<std::unique_ptr<OpDescBind>> operator()()const = 0;
                                        -};
                                        -
                                        -
                                        -

                                        We can convert GradOpDescMakerBase to std::function<std::vector<std::unique_ptr<OpDescBind>>(const OpDescBind&)> by

                                        -
                                        using GradOpMaker = ...;
                                        -std::function<std::vector<OpDescBind>(const OpDescBind&)> func;
                                        -func = [] (const OpDescBind& fwd_op) {
                                        -  GradOpMaker maker(fwd_op);
                                        -  return maker();
                                        -};
                                        -
                                        -
                                        -

                                        We can write many helper functions since the GradOpDescMakerBase is a class now. The basic helper functions get the variables of Input, Output, InputGradient and OutputGradient in the forwarding operator.

                                        -

                                        We should change register macros at the same time. In the current solution, there is no difference between forwarding operators and backward operators. So REGISTER_OP just register one operator. If the REGISTER_OPERATOR contains OpProtoAndCheckerMaker and GradOpDescMaker, we just list them in the same macro. It can be done by a macro contains __VA_ARGS__.

                                        -

                                        The user interface should be

                                        -
                                        vector<OpDesc> MinusOpGradMaker(OpDesc) {...}
                                        -REGISTER_OPERATOR(minus, MinusOp, MinusOpProtoAndCheckerMaker, SumOpGradMaker);
                                        -// Developers can still manually implement gradient operator.
                                        -REGISTER_OPERATOR(minus_grad, MinusGradOp);
                                        -
                                        -
                                        -

                                        The interface of current REGISTER_OP macro could not be changed. In REGISTER_OP, it will invoke REGISTER_OPERATOR two times and generate GradOpDescMaker inside.

                                        -
                                        REGISTER_OP(minus, MinusOp, MinusOpProtoAndCheckerMaker, minus_grad, MinusGradOp);
                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/regularization.html b/develop/doc_cn/design/regularization.html deleted file mode 100644 index 0d13d93e317..00000000000 --- a/develop/doc_cn/design/regularization.html +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - - - - - - - - Regularization in PaddlePaddle — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Regularization in PaddlePaddle

                                        -
                                        -

                                        Introduction to Regularization

                                        -

                                        A central problem in machine learning is how to design an algorithm that will perform well not just on the training data, but also on new data. A frequently faced problem is the problem of overfitting, where the model does not make reliable predictions on new unseen data. Regularization is the process of introducing additional information in order to prevent overfitting. This is usually done by adding extra penalties to the loss function that restricts the parameter spaces that an optimization algorithm can explore.

                                        -
                                        -

                                        Parameter Norm Penalties

                                        -

                                        Most common regularization approaches in deep learning are based on limiting the capacity of the models by adding a parameter norm penalty to the objective function J. This is given as follows:

                                        -


                                        -

                                        The parameter alpha is a hyperparameter that weights the relative contribution of the norm penalty term, omega, relative to the standard objective function J.

                                        -

                                        The most commonly used norm penalties are the L2 norm penalty and the L1 norm penalty. These are given as follows:

                                        -
                                        -

                                        L2 Regularization:

                                        -


                                        -
                                        -
                                        -

                                        L1 Regularization

                                        -


                                        -

                                        A much more detailed mathematical background of regularization can be found here.

                                        -
                                        -
                                        -
                                        -
                                        -

                                        Regularization Survey

                                        -

                                        A detailed survey of regularization in various deep learning frameworks can be found here.

                                        -
                                        -
                                        -

                                        Proposal for Regularization in PaddlePaddle

                                        -
                                        -

                                        Low-Level implementation

                                        -

                                        In the new design, we propose to create new operations for regularization. For now, we can add 2 ops that correspond to the most frequently used regularizations:

                                        -
                                          -
                                        • L2_regularization_op
                                        • -
                                        • L1_regularization_op
                                        • -
                                        -

                                        These ops can be like any other ops with their own CPU/GPU implementations either using Eigen or separate CPU and GPU kernels. As the initial implementation, we can implement their kernels using Eigen following the abstraction pattern implemented for Activation Ops. This abstraction pattern can make it very easy to implement new regularization schemes other than L1 and L2 norm penalties.

                                        -

                                        The idea of building ops for regularization is in sync with the refactored Paddle philosophy of using operators to represent any computation unit. The way these ops will be added to the computation graph, will be decided by the layer functions in Python API.

                                        -
                                        -
                                        -

                                        Computation Graph

                                        -

                                        Below is an example of a really simple feed forward neural network.

                                        -


                                        -

                                        The Python API will modify this computation graph to add regularization operators. The modified computation graph will look as follows:

                                        -


                                        -
                                        -
                                        -

                                        Python API implementation for Regularization

                                        -

                                        Using the low level ops, L2_regularization_op and L1_regularization_op, any user can add regularization to their computation graphs. However, this will require a lot of lines of code and we should design Python APIs that support regularization. An example of such an API can be seen in Keras. As per the PaddlePaddle Python API design, the layer functions are responsible for creating operators, operator parameters and variables. Since regularization is a property of parameters, it makes sense to create these in the layer functions.

                                        -
                                        -

                                        Creation of Regularization ops

                                        -

                                        There are two possibilities for creating the regularization ops:

                                        -
                                          -
                                        1. We create these ops immediately while building the computation graph.
                                        2. -
                                        3. We add these ops in a lazy manner, just before the backward, similar to the way the optimization ops are added.
                                        4. -
                                        -

                                        The proposal is to add these ops in a lazy manner just before the backward pass.

                                        -
                                        -
                                        -

                                        Storage of Regularization attributes

                                        -

                                        Since we want to create the regularization ops in a lazy manner, the regularization attributes (type of regularization and weight of regularization penalty) can be stored as attributes of the Parameter class. This is because regularization is a property of the parameters and storing regularization properties with Parameters also allows for shared parameters.

                                        -
                                        -
                                        -

                                        High-level API

                                        -

                                        In PaddlePaddle Python API, users will primarily rely on layer functions to create neural network layers. Hence, we also need to provide regularization functionality in layer functions. The design of these APIs can be postponed for later right now. A good reference for these APIs can be found in Keras and also by looking at Tensorflow in tf.contrib.layers.

                                        -
                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/releasing_process.html b/develop/doc_cn/design/releasing_process.html deleted file mode 100644 index 35ec97deac8..00000000000 --- a/develop/doc_cn/design/releasing_process.html +++ /dev/null @@ -1,371 +0,0 @@ - - - - - - - - - - - - - PaddlePaddle发行规范 — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        PaddlePaddle发行规范

                                        -

                                        PaddlePaddle使用git-flow branching model做分支管理,使用Semantic Versioning标准表示PaddlePaddle版本号。

                                        -

                                        PaddlePaddle每次发新的版本,遵循以下流程:

                                        -
                                          -
                                        1. develop分支派生出新的分支,分支名为release/版本号。例如,release/0.10.0
                                        2. -
                                        3. 将新分支的版本打上tag,tag为版本号rc.Patch号。第一个tag为0.10.0rc1,第二个为0.10.0rc2,依次类推。
                                        4. -
                                        5. 对这个版本的提交,做如下几个操作:
                                        6. -
                                        -
                                          -
                                        • 使用Regression Test List作为检查列表,测试本次release的正确性。

                                          -
                                            -
                                          • 如果失败,记录下所有失败的例子,在这个release/版本号分支中,修复所有bug后,Patch号加一,到第二步

                                            -
                                          • -
                                          • 修改python/setup.py.in中的版本信息,并将istaged字段设为True

                                            -
                                          • -
                                          • 编译这个版本的python wheel包,并发布到pypi。

                                            -
                                              -
                                            • 由于pypi.python.org目前遵循严格的命名规范PEP 513,在使用twine上传之前,需要重命名wheel包中platform相关的后缀,比如将linux_x86_64修改成manylinux1_x86_64

                                              -
                                            • -
                                            • pypi上的package名称为paddlepaddle和paddlepaddle_gpu,如果要上传GPU版本的包,需要修改build/python/setup.py中,name: “paddlepaddle_gpu”并重新打包wheel包:python setup.py bdist_wheel

                                              -
                                            • -
                                            • 上传方法:

                                              -
                                              cd build/python
                                              -pip install twine
                                              -twine upload dist/[package to upload]
                                              -
                                              -
                                              -
                                            • -
                                            • 编译这个版本的Docker发行镜像,发布到dockerhub。如果失败,修复Docker编译镜像问题,Patch号加一,返回第二步

                                              -
                                            • -
                                            -
                                          • -
                                          -
                                        • -
                                        -
                                          -
                                        1. 第三步完成后,将release/版本号分支合入master分支,并删除release/版本号分支。将master分支的合入commit打上tag,tag为版本号。同时再将master分支合入develop分支。最后删除release/版本号分支。
                                        2. -
                                        3. 协同完成Release Note的书写
                                        4. -
                                        -

                                        需要注意的是:

                                        -
                                          -
                                        • release/版本号分支一旦建立,一般不允许再从develop分支合入release/版本号。这样保证release/版本号分支功能的封闭,方便测试人员测试PaddlePaddle的行为。
                                        • -
                                        • release/版本号分支存在的时候,如果有bugfix的行为,需要将bugfix的分支同时merge到master, developrelease/版本号这三个分支。
                                        • -
                                        -
                                        -

                                        发布wheel包到pypi

                                        -

                                        使用PaddlePaddle CI -完成自动化二进制编译,参考下图,选择需要发布的版本(通常包含一个CPU版本和一个GPU版本),点击”run”右侧的”...”按钮,可以 -弹出下面的选择框,在第二个tab (Changes)里选择需要发布的分支,这里选择0.11.0,然后点击”Run Build”按钮。等待编译完成后 -可以在此页面的”Artifacts”下拉框中找到生成的3个二进制文件,分别对应CAPI,cp27mcp27mu的版本。然后按照上述的方法 -使用twine工具上传即可。

                                        -

                                        -
                                          -
                                        • 注:CI环境使用 https://github.com/PaddlePaddle/buildtools 这里的DockerImage作为编译环境以支持更多的Linux -发型版,如果需要手动编译,也可以使用这些镜像。这些镜像也可以从 https://hub.docker.com/r/paddlepaddle/paddle_manylinux_devel/tags/ 下载得到。
                                        • -
                                        • pypi不支持覆盖上传,所以一个版本号的wheel包发布之后,不可以更改。下一个wheel包需要更新版本号才可以上传。
                                        • -
                                        -
                                        -
                                        -

                                        发布Docker镜像

                                        -

                                        上述PaddlePaddle CI编译wheel完成后会自动将Docker镜像push到DockerHub,所以,发布Docker镜像只需要对自动push的镜像打上 -版本号对应的tag即可:

                                        -
                                          -
                                        1. 进入 https://hub.docker.com/r/paddlepaddle/paddle/tags/ 查看latest tag的更新时间是否在上述编译wheel包完成后是否最新。
                                        2. -
                                        3. 执行 docker pull paddlepaddle/paddle:[latest tag],latest tag可以是latest或latest-gpu等。
                                        4. -
                                        5. 执行 docker tag paddlepaddle/paddle:[latest tag] paddlepaddle/paddle:[version]
                                        6. -
                                        7. 执行 docker push paddlepaddle/paddle:[version]
                                        8. -
                                        -
                                        -
                                        -

                                        PaddlePaddle 分支规范

                                        -

                                        PaddlePaddle开发过程使用git-flow分支规范,并适应github的特性做了一些区别。

                                        -
                                          -
                                        • PaddlePaddle的主版本库遵循git-flow分支规范。其中:
                                            -
                                          • master分支为稳定(stable branch)版本分支。每一个master分支的版本都是经过单元测试和回归测试的版本。
                                          • -
                                          • develop分支为开发(develop branch)版本分支。每一个develop分支的版本都经过单元测试,但并没有经过回归测试。
                                          • -
                                          • release/版本号分支为每一次Release时建立的临时分支。在这个阶段的代码正在经历回归测试。
                                          • -
                                          -
                                        • -
                                        • 其他用户的fork版本库并不需要严格遵守git-flow分支规范,但所有fork的版本库的所有分支都相当于特性分支。
                                            -
                                          • 建议,开发者fork的版本库使用develop分支同步主版本库的develop分支
                                          • -
                                          • 建议,开发者fork的版本库中,再基于develop版本fork出自己的功能分支。
                                          • -
                                          • 当功能分支开发完毕后,向PaddlePaddle的主版本库提交Pull Reuqest,进而进行代码评审。
                                              -
                                            • 在评审过程中,开发者修改自己的代码,可以继续在自己的功能分支提交代码。
                                            • -
                                            -
                                          • -
                                          -
                                        • -
                                        • BugFix分支也是在开发者自己的fork版本库维护,与功能分支不同的是,BugFix分支需要分别给主版本库的masterdevelop与可能有的release/版本号分支,同时提起Pull Request
                                        • -
                                        -
                                        -
                                        -

                                        PaddlePaddle回归测试列表

                                        -

                                        本列表说明PaddlePaddle发版之前需要测试的功能点。

                                        -
                                        -

                                        PaddlePaddle Book中所有章节

                                        -

                                        PaddlePaddle每次发版本首先要保证PaddlePaddle Book中所有章节功能的正确性。功能的正确性包括验证PaddlePaddle目前的paddle_trainer训练和纯使用Python训练模型正确性。

                                        -

                                        | | 新手入门章节 | 识别数字 | 图像分类 | 词向量 | 情感分析 | 语意角色标注 | 机器翻译 | 个性化推荐 | -| — | — | — | — | — | — | — | — | — | -| API.V2 + Docker + GPU | | | | | | | | | -| API.V2 + Docker + CPU | | | | | | | | | -| paddle_trainer + Docker + GPU | | | | | | | | | -| paddle_trainer + Docker + CPU | | | | | | | | | -| API.V2 + Ubuntu + GPU | | | | | | | | | -| API.V2 + Ubuntu + CPU | | | | | | | | | -| paddle_trainer + Ubuntu + GPU | | | | | | | | | -| paddle_trainer + Ubuntu + CPU | | | | | | | | |

                                        -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/scope.html b/develop/doc_cn/design/scope.html deleted file mode 100644 index feab2dd6c33..00000000000 --- a/develop/doc_cn/design/scope.html +++ /dev/null @@ -1,381 +0,0 @@ - - - - - - - - - - - - - Design of Scope in Paddle — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design of Scope in Paddle

                                        -
                                        -

                                        Overview

                                        -

                                        Scope is an important concept in programming languages, which defines a program region that a set of bindings between names and entities applies. In a specific scope, a valid name is uniquely associated with an entity, such as a variable. And in another scope, this name may refer to other entity or nothing at all. It clearly restricts the visibility and validity of names in a program. Hence Scope is introduced to PaddlePaddle to manage variables in context. But different from the original abstract concept, Scope now becomes an object with two important attributes:

                                        -
                                          -
                                        • Scope is an association of a name to variable.
                                        • -
                                        • Variables in a parent scope can be retrieved from local scope.
                                        • -
                                        -

                                        A detailed explanation of these two attributes goes as following.

                                        -
                                        -
                                        -

                                        Scope is an association of a name to variable.

                                        -

                                        Scope is an association of a name to variable. All variables belong to Scope. You need to specify a scope to run a Net, i.e., net.Run(&scope). One net can run in different scopes and update different variable in the scope.

                                        -
                                          -
                                        1. Scope only contains a map of a name to variable.

                                          -

                                          All parameters, data, states in a Net should be variables and stored inside a scope. Each op should get inputs and outputs to do computation from a scope, such as data buffer, state (momentum) etc.

                                          -
                                        2. -
                                        3. Variable can only be created by Scope and a variable can only be got from Scope. User cannot create or get a variable outside a scope. This is a constraints of our framework, and will keep our framework simple and clear.

                                          -
                                        4. -
                                        5. Scope only contains methods that are used to Create and Get Variables. Scope do not contain Operators and have no information to run them. -Net is designed to drive the computation and Scope only contains a map of variables. There is no computation logic inside a Scope. Scope just handles the lifetime management of variables.

                                          -
                                            -
                                          • Create is used to create a Variable by its name and add the mapping relation.
                                          • -
                                          • Get is used to find a Variable by name.
                                          • -
                                          -
                                        6. -
                                        7. Every variable only belongs to one certain Scope.

                                          -

                                          Variable can not belong to many scopes. If you want to use variables from parent scope, you can use parent scope.

                                          -
                                        8. -
                                        9. Scope should destruct all Variables inside it when itself is destructed. User can never store Variable pointer somewhere else.

                                          -

                                          Because Variable can only be got from Scope. When destroying Scope, we also need to destroy all the Variables in it. If user store Variable pointer to private data member or some global variable, the pointer will be an invalid pointer when associated Scope is destroyed.

                                          -
                                        10. -
                                        -
                                        class Scope {
                                        - public:
                                        -  Variable* Var(const std::string& name);
                                        -  const Variable* FindVar(const std::string& name) const;
                                        -
                                        - private:
                                        -    std::unordered_map<std::string, std::unique_ptr<Variable>> vars_;
                                        -};
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Parent scope and local scope

                                        -

                                        Just like scope in programming languages, Scope in the neural network can also be a local scope. There are two attributes about local scope.

                                        -
                                          -
                                        1. We can create local variables in a local scope. When that local scope is destroyed, all local variables should also be destroyed.
                                        2. -
                                        3. Variables in a parent scope can be retrieved from local scopes of that parent scope, i.e., when user get a variable from a scope, it will try to search this variable in current scope. If there is no such variable in the local scope, scope will keep searching from its parent, until the variable is found or there is no parent.
                                        4. -
                                        -
                                        class Scope {
                                        - public:
                                        -  Scope(const std::shared_ptr<Scope>& scope): parent_(scope) {}
                                        -
                                        -  Variable* FindVar(const std::string& name) const {
                                        -    auto it = vars_.find(name);
                                        -    if (it != vars_.end()) {
                                        -      return it->second.get();
                                        -    } else if (parent_ != nullptr) {
                                        -      return parent_->FindVar(name);
                                        -    } else {
                                        -      return nullptr;
                                        -    }
                                        -  }
                                        -
                                        - private:
                                        -  std::shared_ptr<Scope> parent_ {nullptr};
                                        -};
                                        -
                                        -
                                        -

                                        In Scope class, there is a private data member called parent_. parent_ is a smart pointer to its parent scope. When user Get a variable by its name, the name will be searched inside the current scope. If the variable cannot be found locally and parent scope is not a nullptr, the variable will be searched inside that parent scope. parent_ pointer’s default value is nullptr. It means that the scope is a global scope when parent_ is nullptr.

                                        -

                                        A local scope is very useful when we implement Recurrent Neural Network. Each timestep of an RNN should be a Net. Each Net of timestep (StepNet for short) should use an independent local scope. Just like variables in a while loop is inside a local scope in programming languages. By using a single StepNet and changing local scope, we can implement an RNN easily.

                                        -
                                        -
                                        -
                                        -

                                        Interface Design

                                        -
                                        class Variable {
                                        - private:
                                        -  Variable() = default;
                                        -  friend class Scope;
                                        -};
                                        -
                                        -class Scope {
                                        - private:
                                        -  Scope(const std::shared_ptr<Scope>& parent = nullptr);
                                        -
                                        - public:
                                        -  static std::shared_ptr<Scope> Create(const std::shared_ptr<Scope>& parent = nullptr);
                                        -
                                        -  // return nullptr if not found.
                                        -  Variable* FindVar(const std::string& name) const;
                                        -
                                        -  // return if already contains same name variable.
                                        -  Variable* Var(const std::string& name);
                                        -
                                        - private:
                                        -  std::shared_ptr<Scope> parent_;
                                        -  std::unordered_map<std::string, std::unique_ptr<Variable>> vars_;
                                        -};
                                        -
                                        -
                                        -
                                        -

                                        Only scope can create a variable

                                        -

                                        To ensure only scope can create a variable, we should mark Variable‘s constructor as a private member function, and Scope is a friend class of Variable. And then only Var can construct Variable.

                                        -
                                        -
                                        -

                                        When scope destroyed, all variables inside this scope should be destroyed together

                                        -

                                        The scope hold unique pointers for all variables. User can FindVar from scope, but he should not hold this pointer as a member variable. Because when scope is destroyed, all variables inside this scope will be destroyed together.

                                        -
                                        -
                                        -

                                        Sharing a parent scope

                                        -

                                        Local scope contains a parent_ pointer. It is a linked-list for scopes. Using a shared_ptr because when a local scope is using, its parents cannot be destroyed.

                                        -

                                        Also, as the parent scope is a shared_ptr, we can only Create() a scope shared pointer. We cannot construct a scope variable, because it cannot be passed to other scope as parent pointer.

                                        -
                                        -
                                        -

                                        Orthogonal interface

                                        -

                                        FindVar will return nullptr when name is not found. It can be used as Contains method. Var will return an Error when there is a name conflict locally. Combine FindVar and Var, we can implement Var easily.

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/selected_rows.html b/develop/doc_cn/design/selected_rows.html deleted file mode 100644 index 2504b99cd79..00000000000 --- a/develop/doc_cn/design/selected_rows.html +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - Design Doc: Selected Rows — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Selected Rows

                                        -

                                        SelectedRows is a type of sparse tensor data type, which is designed to support embedding operators. The gradient of embedding table is a sparse tensor. Only a few rows are non-zero values in this tensor. It is straight-forward to represent a sparse tensor by the following sparse tensor data structure:

                                        -
                                        class SelectedRows {
                                        - private:
                                        -  vector<int> rows_;
                                        -  Tensor value_;
                                        -  int height_;
                                        -};
                                        -
                                        -
                                        -

                                        The field height_ is the first dimension of SelectedRows. The rows are the indices of the non-zero rows of SelectedRows. The value_ field is an N-dim tensor of shape [rows.size() /* NUM_ROWS */, ...], which supplies values for each row. The dimension of SelectedRows satisfies [height_] + value_.shape[1:].

                                        -

                                        Suppose that a SelectedRows-typed variable x has many rows, but only two of them have values – row 73 is [1, 2] and row 84 is [3, 4], the SelectedRows representation would be:

                                        -
                                        x = SelectedRow {
                                        -  rows = [73, 84],
                                        -  value = [[1, 2], [3,4]]
                                        -}
                                        -
                                        -
                                        -
                                        -

                                        SelectedRows in Protobuf

                                        -

                                        SelectedRows is a type of Variable. VarDesc in protobuf should describe the SelectedRows information. Only the tensor dimension of a SelectedRows will be described in compile-time because the rows_ and value_ are dependent on the training data. -So we use TensorDesc to unify data_type and dims. A LodTensorDesc contains a TensorDesc and lod_level. The description of SelectedRows is a Tensor description.

                                        -
                                        message TensorDesc {
                                        -  required DataType data_type = 1;
                                        -  repeated int64 dims = 2; // [UNK, 640, 480] is saved as [-1, 640, 480]
                                        -}
                                        -
                                        -message LodTensorDesc {
                                        -  required TensorDesc tensor = 1;
                                        -  optional int lod_level = 2;
                                        -}
                                        -
                                        -message VarDesc {
                                        -  required string name = 1;
                                        -  enum VarType { 
                                        -    LOD_TENSOR = 0;
                                        -    SELECTED_ROWS = 1;
                                        -  }
                                        -  required VarType type = 2;
                                        -  optional LodTensorDesc lod_desc = 3;
                                        -  optional TensorDesc selected_rows_desc = 4;
                                        -  optional bool persistable = 5 [ default = false ];
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -

                                        InferShape for Selected Rows

                                        -

                                        Just like LoD information, InferShape method will infer the output tensor type as well. The operator should decide whether its output is a SelectedRows or Dense tensor.

                                        -

                                        For example, the gradient operator of TableLookup will always generate SelectedRows. Its InferShape method should be like following

                                        -
                                        void TableLookupGrad::InferShape(context) {
                                        -  ...
                                        -  context.SetDataType("Embedding.Grad", kSelectedRows);
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Sparse Operators

                                        -

                                        There are several operators that need to be written to support SelectedRows. These are:

                                        -
                                          -
                                        1. Operators which generate SelectedRows gradient. e.g. Gradient of TableLookupOp.
                                        2. -
                                        3. Optimize operators which support SelectedRows gradient. e.g. SGD or AdaGrad for SelectedRows. However, there should be only one SGD operator. OpWithKernel::Run should select a suitable kernel for both dense tensor or SelectedRows.
                                        4. -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/simple_op_design.html b/develop/doc_cn/design/simple_op_design.html deleted file mode 100644 index a52b8731862..00000000000 --- a/develop/doc_cn/design/simple_op_design.html +++ /dev/null @@ -1,449 +0,0 @@ - - - - - - - - - - - - - Interaction between C++ and Python — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Interaction between C++ and Python

                                        -

                                        Users employ API in Python to describe their own network, however, the network construction actually happens in C++. so Protobuf is introduced to send the message between Python and C++.

                                        -

                                        The Interaction between Python and C++ can be simplified as two steps:

                                        -
                                          -
                                        1. C++ tells Python how many Ops there are, and what parameter do users need to offer to initialize a new Op. Python then builds API for each Op at compile time.
                                        2. -
                                        3. Users invoke APIs built by Python and provide necessary parameters. These parameters will be sent to C++ for finishing the Op construction task.
                                        4. -
                                        -
                                        -

                                        Message from C++ to Python

                                        -

                                        We define a Protobuf message class OpProto to hold message needed in the first step. What should an OpProto contain? This question is equivalent to “What message do we need to offer, to build a Python API which is legal and user oriented and can use to describe a whole Op.”

                                        -

                                        Following message are necessary:

                                        -
                                          -
                                        1. Op’s name, and its simple comment.
                                        2. -
                                        3. Input and output variable number; each variable’s name, type, and comment.
                                        4. -
                                        5. Op’s attributes; each attribute includes name, type, comment, default value and value range.
                                        6. -
                                        -

                                        So OpProto can be defined as follows:

                                        -
                                        enum AttrType {
                                        -    INT = 1;
                                        -    FLOAT = 2;
                                        -    STRING = 3;
                                        -    INTS = 4;
                                        -    FLOATS = 5;
                                        -    STRINGS = 6;
                                        -};
                                        -
                                        -message AttrValue {
                                        -    AttrType type = 1;
                                        -    optional int iv = 2;
                                        -    optional float fv = 3;
                                        -    optional string sv = 4;
                                        -    repeated int ivs = 5;
                                        -    repeated float fvs = 6;
                                        -    repeated string svs = 7;
                                        -};
                                        -
                                        -message AttrProto {
                                        -    required string name = 1;
                                        -    required string comment = 2;
                                        -    required AttrType type = 3;
                                        -};
                                        -
                                        -message VarProto {
                                        -    required string name = 1;
                                        -    required string comment = 2;
                                        -    required bool is_tensor = 3;
                                        -};
                                        -
                                        -message OpProto {
                                        -    repeated VarProto inputs = 1;
                                        -    repeated VarProto outputs = 2;
                                        -    repeated AttrProto attrs = 3;
                                        -    required string type = 4;
                                        -    required string comment = 5;
                                        -};
                                        -
                                        -
                                        -

                                        To generate Python code automatically:

                                        -
                                        def create_python_ops_creatation_functions():
                                        -    op_protos = paddle.framework.OpRegistry.get_all_op_proto()
                                        -    for type_name in op_protos:
                                        -        op_proto = op_protos[type_name]
                                        -        def __impl__(**kwargs):  # User must use key word args in Paddle API
                                        -            inputs = [kwargs.get(ipt.name, "") for ipt in op_proto.inputs]
                                        -            outputs = [kwargs.get(opt.name, "") for opt in op_proto.outputs]
                                        -            attrs = [cast_to_op_attr(attr, kwargs.get(attr.name, None)) for attr in op_proto.attrs]
                                        -            opdesc = (input, outputs, type_name, attrs)
                                        -            return paddle.framework.OpRegistry.CreateOp(opdesc)
                                        -        __impl__.__doc__ = create_doc_string(op_proto)
                                        -        globals()[type_name] = __impl__
                                        -
                                        -create_python_ops_creatation_functions()
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Message from Python to C++

                                        -

                                        To hold message needed in the above second step, we define Protobuf message class OpDesc. It is used to hold user-specified parameters in Op describing.

                                        -
                                        message OpDesc {
                                        -    required string type = 1;   
                                        -    repeated string inputs = 2;
                                        -    repeated string outputs = 3;
                                        -    map<string, AttrValue> attrs = 4;
                                        -};
                                        -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        OpProto Register

                                        -

                                        Every Op has its own OpProto. For using convenience, we need to register them and record all their messages. For each Op class, we define a corresponding OpMaker class, in whose constructor we implement the OpProto‘s building process. OpMaker‘s constructor will be invoked by another function OpRegistry::RegisterOp().

                                        -
                                        class OpProtoMaker {
                                        -public:
                                        -    OpProtoMaker(OpProto* proto): proto_(proto) {}
                                        -protected:
                                        -    OpProto* proto_;
                                        -    void AddInput(const std::string& name, const std::string& desc) {...}
                                        -    void AddAttr(const std::string& name, const std::string& desc, TypeId type) {...}
                                        -    void AddComment(const std::string& comment) { ... }
                                        -};
                                        -
                                        -class OpRegistry {
                                        -public:
                                        -    using OpCreator = std::function<OperatorBase* (OpDesc& desc)>;
                                        -    
                                        -    template <typename OpType, typename OpMaker>
                                        -    static void RegisterOp(const std::string& name) {
                                        -        gCreators_[name] = [](const OpDesc& desc) {
                                        -            return new OpType(desc);
                                        -        };
                                        -        OpProto& opProto = gProtos_[name];
                                        -        OpMaker()(&opProto);
                                        -    }
                                        -
                                        -    static map<string, OpCreator> gCreators_;
                                        -    static map<string, OpProto> gProtos_;
                                        -};
                                        -
                                        -template <typename OpType, typename OpMaker>
                                        -class OpRegister {
                                        -  public:
                                        -    OpRegister(std::string type) {
                                        -        OpRegistry::RegisterOp<OpType, OpMaker>(type);
                                        -    }
                                        -};
                                        -
                                        -#define REGISTER_OP(op_class, op_maker_class, type_name)         \
                                        -    class op_class##Register {                                   \
                                        -      private:                                                   \
                                        -        const static OpRegister<#op_class, #op_maker_class> reg; \
                                        -    };                                                           \
                                        -    const Register op_class##Register::reg(#type_name);
                                        -    
                                        -class CosineOp {
                                        -// ...
                                        -}
                                        -
                                        -struct CosineOpProtoMaker : public OpProtoMaker {
                                        -    CosineOpProtoMaker(OpProto* proto) : OpProtoMaker(proto) {
                                        -        AddInput("input", "input of cosine op");
                                        -        AddAttr("scale", "scale of cosine op", float).Default(1.0).GreaterThan(0.0);
                                        -        AddType("cos");
                                        -        AddComment("This is cos op");
                                        -    }
                                        -}
                                        -
                                        -REGISTER_OP(CosineOp, CosineOpProtoMaker, cos);
                                        -
                                        -
                                        -

                                        In REGISTER_OP(CosineOp, CosineOpProtoMaker, cos), we register not only CosineOp but also CosineOpProto. As fields of CosineOpProto, the default value and value range of scale are also registered here.

                                        -
                                        -
                                        -

                                        Python API

                                        -

                                        Python APIs are divided into two types, high-level API and low-level API.

                                        -
                                        -

                                        High-Level API

                                        -

                                        High-level API is called by users directly, so it should keep its style consistent with existing V2 APIs.

                                        -

                                        Here is a sample about how a define a fc layer:

                                        -
                                        hd = fc_layer(input=data, size=56, with_bias=True, activation="sigmoid");
                                        -
                                        -
                                        -

                                        hd is the output of fc_layer and it’s a variable. It can be further sent into other layers as input.

                                        -

                                        The definition of fc_layer():

                                        -
                                        def fc_layer(input, size, with_bias, activation):
                                        -    attr_map = {"size":size}
                                        -    check_attrs(attr_map)
                                        -    w = make_variable('w')
                                        -    if with_bias:
                                        -        b = make_variable('b')
                                        -    else:
                                        -        b = None
                                        -    fc_output = make_variable('fc_output');
                                        -    fc_op(input, w, b, fc_output, attr_map)
                                        -    act_output = make_variable('sigmod_output');
                                        -    if activation == "sigmod":
                                        -        sigmod_op(fc_output, act_output);
                                        -    elif:
                                        -        # ...
                                        -    return act_output;
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Low Leval API

                                        -

                                        In above sample, fc_op and sigmod_op are low-level API. They build OpDesc and invoke corresponding C++ code.

                                        -

                                        TODO

                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/speech/deep_speech_2.html b/develop/doc_cn/design/speech/deep_speech_2.html deleted file mode 100644 index 9062b47c87c..00000000000 --- a/develop/doc_cn/design/speech/deep_speech_2.html +++ /dev/null @@ -1,468 +0,0 @@ - - - - - - - - - - - - - DeepSpeech2 on PaddlePaddle: Design Doc — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        DeepSpeech2 on PaddlePaddle: Design Doc

                                        -

                                        We are planning to build Deep Speech 2 (DS2) [1], a powerful Automatic Speech Recognition (ASR) engine, on PaddlePaddle. For the first-stage plan, we have the following short-term goals:

                                        -
                                          -
                                        • Release a basic distributed implementation of DS2 on PaddlePaddle.
                                        • -
                                        • Contribute a chapter of Deep Speech to PaddlePaddle Book.
                                        • -
                                        -

                                        Intensive system optimization and low-latency inference library (details in [1]) are not yet covered in this first-stage plan.

                                        - -
                                        -

                                        Tasks

                                        -

                                        We roughly break down the project into 14 tasks:

                                        -
                                          -
                                        1. Develop an audio data provider:
                                            -
                                          • Json filelist generator.
                                          • -
                                          • Audio file format transformer.
                                          • -
                                          • Spectrogram feature extraction, power normalization etc.
                                          • -
                                          • Batch data reader with SortaGrad.
                                          • -
                                          • Data augmentation (optional).
                                          • -
                                          • Prepare (one or more) public English data sets & baseline.
                                          • -
                                          -
                                        2. -
                                        3. Create a simplified DS2 model configuration:
                                            -
                                          • With only fixed-length (by padding) audio sequences (otherwise need Task 3).
                                          • -
                                          • With only bidirectional-GRU (otherwise need Task 4).
                                          • -
                                          • With only greedy decoder (otherwise need Task 5, 6).
                                          • -
                                          -
                                        4. -
                                        5. Develop to support variable-shaped dense-vector (image) batches of input data.
                                            -
                                          • Update DenseScanner in dataprovider_converter.py, etc.
                                          • -
                                          -
                                        6. -
                                        7. Develop a new lookahead-row-convolution layer (See [1] for details):
                                            -
                                          • Lookahead convolution windows.
                                          • -
                                          • Within-row convolution, without kernels shared across rows.
                                          • -
                                          -
                                        8. -
                                        9. Build KenLM language model (5-gram) for beam search decoder:
                                            -
                                          • Use KenLM toolkit.
                                          • -
                                          • Prepare the corpus & train the model.
                                          • -
                                          • Create infererence interfaces (for Task 6).
                                          • -
                                          -
                                        10. -
                                        11. Develop a beam search decoder with CTC + LM + WORDCOUNT:
                                            -
                                          • Beam search with CTC.
                                          • -
                                          • Beam search with external custom scorer (e.g. LM).
                                          • -
                                          • Try to design a more general beam search interface.
                                          • -
                                          -
                                        12. -
                                        13. Develop a Word Error Rate evaluator:
                                            -
                                          • update ctc_error_evaluator(CER) to support WER.
                                          • -
                                          -
                                        14. -
                                        15. Prepare internal dataset for Mandarin (optional):
                                            -
                                          • Dataset, baseline, evaluation details.
                                          • -
                                          • Particular data preprocessing for Mandarin.
                                          • -
                                          • Might need cooperating with the Speech Department.
                                          • -
                                          -
                                        16. -
                                        17. Create standard DS2 model configuration:
                                            -
                                          • With variable-length audio sequences (need Task 3).
                                          • -
                                          • With unidirectional-GRU + row-convolution (need Task 4).
                                          • -
                                          • With CTC-LM beam search decoder (need Task 5, 6).
                                          • -
                                          -
                                        18. -
                                        19. Make it run perfectly on clusters.
                                        20. -
                                        21. Experiments and benchmarking (for accuracy, not efficiency):
                                            -
                                          • With public English dataset.
                                          • -
                                          • With internal (Baidu) Mandarin dataset (optional).
                                          • -
                                          -
                                        22. -
                                        23. Time profiling and optimization.
                                        24. -
                                        25. Prepare docs.
                                        26. -
                                        27. Prepare PaddlePaddle Book chapter with a simplified version.
                                        28. -
                                        -
                                        -
                                        -

                                        Task Dependency

                                        -

                                        Tasks parallelizable within phases:

                                        -

                                        Roadmap | Description | Parallelizable Tasks -———– | :———————————— | :——————– -Phase I | Simplified model & components | Task 1 ~ Task 8 -Phase II | Standard model & benchmarking & profiling | Task 9 ~ Task 12 -Phase III | Documentations | Task13 ~ Task14

                                        -

                                        Issue for each task will be created later. Contributions, discussions and comments are all highly appreciated and welcomed!

                                        -
                                        -
                                        -

                                        Design Details

                                        -
                                        -

                                        Overview

                                        -

                                        Traditional ASR (Automatic Speech Recognition) pipelines require great human efforts devoted to elaborately tuning multiple hand-engineered components (e.g. audio feature design, accoustic model, pronuncation model and language model etc.). Deep Speech 2 (DS2) [1], however, trains such ASR models in an end-to-end manner, replacing most intermediate modules with only a single deep network architecture. With scaling up both the data and model sizes, DS2 achieves a very significant performance boost.

                                        -

                                        Please read Deep Speech 2 [1,2] paper for more background knowledge.

                                        -

                                        The classical DS2 network contains 15 layers (from bottom to top):

                                        -
                                          -
                                        • Two data layers (audio spectrogram, transcription text)
                                        • -
                                        • Three 2D convolution layers
                                        • -
                                        • Seven uni-directional simple-RNN layers
                                        • -
                                        • One lookahead row convolution layers
                                        • -
                                        • One fully-connected layers
                                        • -
                                        • One CTC-loss layer
                                        • -
                                        -
                                        -
                                        -Figure 1. Archetecture of Deep Speech 2 Network. -

                                        We don’t have to persist on this 2-3-7-1-1-1 depth [2]. Similar networks with different depths might also work well. As in [1], authors use a different depth (e.g. 2-2-3-1-1-1) for final experiments.

                                        -

                                        Key ingredients about the layers:

                                        -
                                          -
                                        • Data Layers:
                                            -
                                          • Frame sequences data of audio spectrogram (with FFT).
                                          • -
                                          • Token sequences data of transcription text (labels).
                                          • -
                                          • These two type of sequences do not have the same lengthes, thus a CTC-loss layer is required.
                                          • -
                                          -
                                        • -
                                        • 2D Convolution Layers:
                                            -
                                          • Not only temporal convolution, but also frequency convolution. Like a 2D image convolution, but with a variable dimension (i.e. temporal dimension).
                                          • -
                                          • With striding for only the first convlution layer.
                                          • -
                                          • No pooling for all convolution layers.
                                          • -
                                          -
                                        • -
                                        • Uni-directional RNNs
                                            -
                                          • Uni-directional + row convolution: for low-latency inference.
                                          • -
                                          • Bi-direcitional + without row convolution: if we don’t care about the inference latency.
                                          • -
                                          -
                                        • -
                                        • Row convolution:
                                            -
                                          • For looking only a few steps ahead into the feature, instead of looking into a whole sequence in bi-directional RNNs.
                                          • -
                                          • Not nessesary if with bi-direcitional RNNs.
                                          • -
                                          • Row” means convolutions are done within each frequency dimension (row), and no convolution kernels shared across.
                                          • -
                                          -
                                        • -
                                        • Batch Normalization Layers:
                                            -
                                          • Added to all above layers (except for data and loss layer).
                                          • -
                                          • Sequence-wise normalization for RNNs: BatchNorm only performed on input-state projection and not state-state projection, for efficiency consideration.
                                          • -
                                          -
                                        • -
                                        -

                                        Required Components | PaddlePaddle Support | Need to Develop -:————————————- | :————————————– | :———————– -Data Layer I (Spectrogram) | Not supported yet. | TBD (Task 3) -Data Layer II (Transcription) | paddle.data_type.integer_value_sequence | - -2D Convolution Layer | paddle.layer.image_conv_layer | - -DataType Converter (vec2seq) | paddle.layer.block_expand | - -Bi-/Uni-directional RNNs | paddle.layer.recurrent_group | - -Row Convolution Layer | Not supported yet. | TBD (Task 4) -CTC-loss Layer | paddle.layer.warp_ctc | - -Batch Normalization Layer | paddle.layer.batch_norm | - -CTC-Beam search | Not supported yet. | TBD (Task 6)

                                        -
                                        -
                                        -

                                        Row Convolution

                                        -

                                        TODO by Assignees

                                        -
                                        -
                                        -

                                        Beam Search with CTC and LM

                                        -
                                        -
                                        -Figure 2. Algorithm for CTC Beam Search Decoder. -
                                          -
                                        • The Beam Search Decoder for DS2 CTC-trained network follows the similar approach in [3] as shown in Figure 2, with two important modifications for the ambiguous parts:
                                            -
                                            1. -
                                            2. in the iterative computation of probabilities, the assignment operation is changed to accumulation for one prefix may comes from different paths;
                                            3. -
                                            -
                                          • -
                                            1. -
                                            2. the if condition if l^+ not in A_prev then after probabilities’ computation is deprecated for it is hard to understand and seems unnecessary.
                                            3. -
                                            -
                                          • -
                                          -
                                        • -
                                        • An external scorer would be passed into the decoder to evaluate a candidate prefix during decoding whenever a white space appended in English decoding and any character appended in Mandarin decoding.
                                        • -
                                        • Such external scorer consists of language model, word count or any other custom scorers.
                                        • -
                                        • The language model is built from Task 5, with parameters should be carefully tuned to achieve minimum WER/CER (c.f. Task 7)
                                        • -
                                        • This decoder needs to perform with high efficiency for the convenience of parameters tuning and speech recognition in reality.
                                        • -
                                        -
                                        -
                                        -
                                        -

                                        Future Work

                                        -
                                          -
                                        • Efficiency Improvement
                                        • -
                                        • Accuracy Improvement
                                        • -
                                        • Low-latency Inference Library
                                        • -
                                        • Large-scale benchmarking
                                        • -
                                        -
                                        - -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/support_new_device.html b/develop/doc_cn/design/support_new_device.html deleted file mode 100644 index 2d73d81dfb9..00000000000 --- a/develop/doc_cn/design/support_new_device.html +++ /dev/null @@ -1,461 +0,0 @@ - - - - - - - - - - - - - Design Doc: Supporting new Device/Library — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Supporting new Device/Library

                                        -
                                        -

                                        Background

                                        -

                                        Deep learning has a high demand for computing resources. New high-performance devices and computing libraries are appearing very frequently. Deep learning frameworks have to integrate these high-performance devices and computing libraries in a flexible and efficient manner.

                                        -

                                        On one hand, hardware and computing libraries usually do not have a one-to-one correspondence. For example, Intel CPUs support Eigen and MKL computing libraries while Nvidia GPUs support Eigen and cuDNN computing libraries. We have to implement operator specific kernels for each computing library.

                                        -

                                        On the other hand, users usually do not want to care about the low-level hardware and computing libraries when writing a neural network configuration. In Fluid, Layer is exposed in Python, and Operator is exposed in C++. Both Layer and Operator are hardware independent.

                                        -

                                        So, how to support a new Device/Library in Fluid becomes a challenge.

                                        -
                                        -
                                        -

                                        Basic: Integrate A New Device/Library

                                        -

                                        For a general overview of fluid, please refer to the overview doc.

                                        -

                                        There are mainly three parts that we have to consider while integrating a new device/library:

                                        -
                                          -
                                        • Place and DeviceContext: indicate the device id and manage hardware resources
                                        • -
                                        • Memory and Tensor: malloc/free data on certain device
                                        • -
                                        • Math Functor and OpKernel: implement computing unit on certain devices/libraries
                                        • -
                                        -
                                        -

                                        Place and DeviceContext

                                        -

                                        Please note that device and computing library are not one-to-one corresponding. A device can have a lot of computing libraries and a computing library can also support several devices.

                                        -
                                        -

                                        Place

                                        -

                                        Fluid uses class Place to represent the device memory where data is located. If we add another device, we have to add the corresponding DevicePlace.

                                        -
                                                |   CPUPlace
                                        -Place --|   CUDAPlace
                                        -        |   FPGAPlace
                                        -
                                        -
                                        -

                                        And Place is defined as follows:

                                        -
                                        typedef boost::variant<CUDAPlace, CPUPlace, FPGAPlace> Place;
                                        -
                                        -
                                        -
                                        -
                                        -

                                        DeviceContext

                                        -

                                        Fluid uses class DeviceContext to manage the resources in different libraries, such as CUDA stream in CDUADeviceContext. There are also inheritance relationships between different kinds of DeviceContext.

                                        -
                                                        /->  CPUDeviceContext   
                                        -DeviceContext ---->  CUDADeviceContext  
                                        -                \->  FPGADeviceContext
                                        -
                                        -
                                        -

                                        An example of Nvidia GPU is as follows:

                                        -
                                          -
                                        • DeviceContext
                                        • -
                                        -
                                        class DeviceContext {
                                        -  virtual Place GetPlace() const = 0;
                                        -};  
                                        -
                                        -
                                        -
                                          -
                                        • CUDADeviceContext
                                        • -
                                        -
                                        class CUDADeviceContext : public DeviceContext {
                                        -  Place GetPlace() const override { return place_; }
                                        -private:
                                        -  CUDAPlace place_;
                                        -  cudaStream_t stream_; 
                                        -  cublasHandle_t cublas_handle_;
                                        -  std::unique_ptr<Eigen::GpuDevice> eigen_device_;  // binds with stream_
                                        -};
                                        -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Memory and Tensor

                                        -
                                        -

                                        memory module

                                        -

                                        Fluid provides the following memory interfaces:

                                        -
                                        template <typename Place>
                                        -void* Alloc(Place place, size_t size);
                                        -
                                        -template <typename Place>
                                        -void Free(Place place, void* ptr);
                                        -
                                        -template <typename Place>
                                        -size_t Used(Place place);
                                        -
                                        -
                                        -

                                        To implement these interfaces, we have to implement MemoryAllocator for different Devices.

                                        -
                                        -
                                        -

                                        Tensor

                                        -

                                        Tensor holds data with some shape in a specific Place.

                                        -
                                        class Tensor {
                                        - public:
                                        -  /*! Return a pointer to mutable memory block. */
                                        -  template <typename T>
                                        -  inline T* data();
                                        -
                                        -  /**
                                        -   * @brief   Return a pointer to mutable memory block.
                                        -   * @note    If not exist, then allocation.
                                        -   */
                                        -  template <typename T>
                                        -  inline T* mutable_data(platform::Place place);
                                        -
                                        -  /**
                                        -   * @brief     Return a pointer to mutable memory block.
                                        -   *
                                        -   * @param[in] dims    The dimensions of the memory block.
                                        -   * @param[in] place   The place of the memory block.
                                        -   *
                                        -   * @note      If not exist, then allocation.
                                        -   */
                                        -  template <typename T>
                                        -  inline T* mutable_data(DDim dims, platform::Place place);
                                        -
                                        -  /*! Resize the dimensions of the memory block. */
                                        -  inline Tensor& Resize(const DDim& dims);
                                        -
                                        -  /*! Return the dimensions of the memory block. */
                                        -  inline const DDim& dims() const;
                                        -
                                        - private:
                                        -  /*! holds the memory block if allocated. */
                                        -  std::shared_ptr<Placeholder> holder_;
                                        -
                                        -  /*! points to dimensions of memory block. */
                                        -  DDim dim_;
                                        -};
                                        -
                                        -
                                        -

                                        Placeholder is used to delay memory allocation; that is, we can first define a tensor, using Resize to configurate its shape, and then call mutuable_data to allocate the actual memory.

                                        -
                                        paddle::framework::Tensor t;
                                        -paddle::platform::CPUPlace place;
                                        -// set size first
                                        -t.Resize({2, 3});
                                        -// allocate memory on CPU later
                                        -t.mutable_data(place);
                                        -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Math Functor and OpKernel

                                        -

                                        Fluid implements computing units based on different DeviceContexts. Some computing units are shared between operators. This common part will be put in operators/math directory as basic Functors.

                                        -

                                        Let’s take MaxOutFunctor as an example:

                                        -

                                        The interface is defined in the header file.

                                        -
                                        template <typename DeviceContext, typename T>
                                        -class MaxOutFunctor {
                                        - public:
                                        -  void operator()(const DeviceContext& context, const framework::Tensor& input,
                                        -                  framework::Tensor* output, int groups);
                                        -};
                                        -
                                        -
                                        -

                                        CPU implementation is in .cc file

                                        -
                                        template <typename T>
                                        -class MaxOutFunctor<platform::CPUDeviceContext, T> {
                                        -  public:
                                        -  void operator()(const platform::CPUDeviceContext& context,
                                        -                  const framework::Tensor& input, framework::Tensor* output,
                                        -                  int groups) {
                                        -                  ...
                                        -                  }
                                        -};
                                        -
                                        -
                                        -

                                        CUDA implementation is in .cu file

                                        -
                                        template <typename T>
                                        -class MaxOutFunctor<platform::CUDADeviceContext, T> {
                                        - public:
                                        -  void operator()(const platform::CUDADeviceContext& context,
                                        -                  const framework::Tensor& input, framework::Tensor* output,
                                        -                  int groups) {
                                        -                  ...
                                        -                  }
                                        -};                  
                                        -
                                        -
                                        -

                                        We first obtain the computing handle from a concrete DeviceContext and then compute on tensors.

                                        -

                                        The implementation of OpKernel is similar to math functors, the extra thing we need to do is to register the OpKernel in a global map.

                                        -

                                        Fluid provides different register interfaces in op_registry.h

                                        -

                                        Let’s take Crop operator as an example:

                                        -

                                        In .cc file:

                                        -
                                        REGISTER_OP_CPU_KERNEL(crop, ops::CropKernel<float>);
                                        -REGISTER_OP_CPU_KERNEL(
                                        -    crop_grad, ops::CropGradKernel<paddle::platform::CPUDeviceContext, float>);
                                        -
                                        -
                                        -

                                        In .cu file:

                                        -
                                        REGISTER_OP_CUDA_KERNEL(crop, ops::CropKernel<float>);
                                        -REGISTER_OP_CUDA_KERNEL(
                                        -    crop_grad, ops::CropGradKernel<paddle::platform::CUDADeviceContext, float>);
                                        -
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Advanced topics: How to switch between different Device/Library

                                        -

                                        Generally, we will implement OpKernel for all Device/Library of an Operator. We can easily train a Convolutional Neural Network in GPU. However, some OpKernel is not suitable on a specific Device. For example, crf operator can only run on CPU, whereas most other operators can run on GPU. To achieve high performance in such circumstance, we have to switch between different Device/Library.

                                        -

                                        For more details, please refer to following docs:

                                        -
                                          -
                                        • operator kernel type doc
                                        • -
                                        • switch kernel doc
                                        • -
                                        -
                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/switch.html b/develop/doc_cn/design/switch.html deleted file mode 100644 index 18ebc94adb1..00000000000 --- a/develop/doc_cn/design/switch.html +++ /dev/null @@ -1,291 +0,0 @@ - - - - - - - - - - - - - Design Doc: Switch — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design Doc: Switch

                                        -
                                        -
                                        -

                                        Background

                                        -

                                        Many programming languages provide switch as a generalization of if-elif-else. We want to add it to Fluid.

                                        -

                                        The following example shows the usage of fluid.switch.

                                        -
                                        a = fluid.Var(10)
                                        -b = fluid.Var(0)
                                        -
                                        -with switch() as switch:
                                        -    with switch.case(fluid.less_equal(a, 10)):
                                        -        fluid.print("Case 1")
                                        -    with switch.case(fluid.larger(a, 0)):
                                        -        fluid.print("Case 2")
                                        -    with switch.default():
                                        -        fluid.print("Case 3")
                                        -
                                        -
                                        -
                                        -
                                        -

                                        The Semantics

                                        -
                                          -
                                        1. A switch control-flow checks cases one-by-one.
                                        2. -
                                        3. The condition of each case is a boolean value, which is a scalar, and differs from the fluid.if_else control-flow, which condition could be a vector of boolean values.
                                        4. -
                                        5. It runs the first matched case, or the default case if there is one.
                                        6. -
                                        7. Once it matches a case, it runs the corresponding branch and only that branch. It’s like there is a C’s break keyword at the end of each case.
                                        8. -
                                        -

                                        The above program should print and print only “Case 1”.

                                        -

                                        The implementation of the backward pass of the switch control-flow is easier than the backward of the if_else, because switch runs at most one branch, whereas if-else could run more than one branches.

                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/tensor_array.html b/develop/doc_cn/design/tensor_array.html deleted file mode 100644 index 072d9212368..00000000000 --- a/develop/doc_cn/design/tensor_array.html +++ /dev/null @@ -1,511 +0,0 @@ - - - - - - - - - - - - - Design for TensorArray — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Design for TensorArray

                                        -

                                        This design doc presents the necessity of a new C++ class TensorArray. -In addition to the very simple C++ implementation

                                        -
                                        class TensorArray {
                                        - public:
                                        -  explicit TensorArray(const LoDTensor&);
                                        -  explicit TensorArray(size_t size);
                                        -
                                        - private:
                                        -  vector<LoDTensor> values_;
                                        -};
                                        -
                                        -
                                        -

                                        We also need to expose it to PaddlePaddle’s Python API, -because users would want to use it with our very flexible operators WhileLoop. -An example for a RNN based on dynamic operators is

                                        -
                                        input = pd.data(...)
                                        -num_steps = Var(12)
                                        -
                                        -TensorArray states(size=num_steps)
                                        -TensorArray step_inputs(unstack_from=input)
                                        -TensorArray step_outputs(size=num_steps)
                                        -
                                        -W = Tensor(...)
                                        -U = Tensor(...)
                                        -default_state = some_op()
                                        -
                                        -step = Var(1)
                                        -
                                        -wloop = paddle.create_whileloop(loop_vars=[step])
                                        -with wloop.frame():
                                        -    wloop.break_if(pd.equal(step, num_steps)
                                        -    pre_state = states.read(step-1, default_state)
                                        -    step_input = step_inputs.read(step)
                                        -    state = pd.sigmoid(pd.matmul(U, pre_state) + pd.matmul(W, step_input))
                                        -    states.write(step, state)
                                        -    step_outputs.write(step, state) # output state
                                        -    step.update(state+1)
                                        -
                                        -output = step_outputs.stack()
                                        -
                                        -
                                        -
                                        -

                                        Background

                                        -

                                        Steps are one of the core concepts of RNN. In each time step of RNN, there should be several input segments, states, and output segments; all these components act like arrays, for example, call states[step_id] will get the state in step_idth time step.

                                        -

                                        An RNN can be implemented with the following pseudocode

                                        -
                                        Array states;
                                        -Array input_segments;
                                        -Array output_segments;
                                        -Parameter W, U;
                                        -
                                        -step = 1
                                        -seq_len = 12
                                        -while_loop {
                                        -   if (step == seq_len) break;
                                        -    states[step] = sigmoid(W * states[step-1] + U * input_segments[step]);
                                        -    output_segments[step] = states[step] // take state as output
                                        -   step++;
                                        -}
                                        -
                                        -
                                        -

                                        According to the RNN roadmap, there are several different RNNs that PaddlePaddle will eventually support.

                                        -

                                        Currently, the basic RNN implementation supported by PaddlePaddle is the recurrent_op which takes tensors as input and splits them into input_segments.

                                        -

                                        Since a tensor cannot store variable-length sequences directly, PaddlePaddle implements the tensor with level of details (LoDTensor for short). -Segmenting the LoDTensor is much more complicated than splitting a tensor, that makes it necessary to refactor the recurrent_op with LoDTensor segmenting support.

                                        -

                                        As the next step in RNN support, dynamic_recurrent_op should be introduced to handle inputs with variable-length sequences.

                                        -

                                        The implementation is similar to recurrent_op. -The key difference is the way the original input LoDTensors and outupts are split to get the input_segments and the output_segments.

                                        -

                                        Though it can’t be built over recurrent_op or dynamic_recurrent_op directly, -the logic behind splitting a tensor or a LoD tensor into input_segments remains the same.

                                        -
                                        -
                                        -

                                        Why TensorArray

                                        -

                                        The logic behind splitting the inputs to segments, states and outputs is similar and can be shared in a seperate module.

                                        -

                                        The array of states, input_segments and output_segments would be exposed to users when writing a dynamic RNN model similar to the above pseudo codes.

                                        -

                                        So there should be an array-like container, which can store the segments of a tensor or LoD tensor.

                                        -

                                        This container can store an array of tensors and provides several methods to split a tensor or a LoD tensor . -This is where the notion of TensorArray comes from.

                                        -
                                        -
                                        -

                                        Introduce TensorArray to uniform all the three RNNs

                                        -

                                        TensorArray as a new concept is borrowed from TensorFlow, -it is meant to be used with dynamic iteration primitives such as while_loop and map_fn.

                                        -

                                        This concept can be used to support our new design of dynamic operations, and help to refactor some existing variant-sentence-related layers, -such as recurrent_op, RecurrentGradientMachine.

                                        -

                                        In our design for dynamic RNN, -TensorArray is used to segment inputs and store states in all time steps. -By providing some methods similar to a C++ array, -the definition of some state-based dynamic models such as RNN can be more natural and highly flexible.

                                        -
                                        -
                                        -

                                        Dynamic-operations on TensorArray

                                        -

                                        TensorArray will be used directly when defining dynamic models, so some operators listed below should be implemented

                                        -
                                        # several helper operators for TensorArray
                                        -def tensor_array_stack(ta, tensor):
                                        -    '''
                                        -    get a tensor array `ta`, return a packed `tensor`.
                                        -    '''
                                        -    pass
                                        -
                                        -def tensor_array_unstack(tensor, ta):
                                        -    '''
                                        -    get a `tensor`, unstack it and get a tensor array `ta`.
                                        -    '''
                                        -    pass
                                        -
                                        -def tensor_array_write(ta, index, tensor, data_shared):
                                        -    '''
                                        -    get a `tensor` and a scalar tensor `index`, write `tensor` into index-th
                                        -    value of the tensor array `ta`.
                                        -    `data_shared` is an attribute that specifies whether to copy or reference the tensors.
                                        -    '''
                                        -    pass
                                        -
                                        -def tensor_array_read(ta, index, tensor):
                                        -    '''
                                        -    get a tensor array `ta`, a scalar tensor `index`, read the index-th value of
                                        -    `ta` and return as the `tensor`.
                                        -    '''
                                        -    pass
                                        -
                                        -def tensor_array_size(ta, tensor):
                                        -    '''
                                        -    get a tensor array `ta`, return the size of `ta` and return as the scalar `tensor`.
                                        -    '''
                                        -    pass
                                        -
                                        -
                                        -

                                        It is trivial for users to use so many low-level operators, so some helper methods should be proposed in python wrapper to make TensorArray easier to use, -for example

                                        -
                                        class TensorArray:
                                        -    def __init__(self, name):
                                        -        self.name = name
                                        -        self.desc = TensorArrayDesc()
                                        -
                                        -    def stack(self, name=None):
                                        -        '''
                                        -        Pack the values in a `TensorArray` into a tensor with rank one higher
                                        -        than each tensor in `values`.
                                        -        `stack` can be used to split tensor into time steps for RNN or whileloop.
                                        -
                                        -        @name: str
                                        -            the name of the variable to output.
                                        -        '''
                                        -        tensor = Var(name)
                                        -        tensor_array_stack(self.name, tensor)
                                        -        return tensor
                                        -
                                        -    def unstack(self, input):
                                        -        '''
                                        -        Unpacks the given dimension of a rank-`R` tensor into rank-`(R-1)` tensors.
                                        -        `unstack` can be used to concatenate all the time steps for RNN or whileloop.
                                        -
                                        -        @input: str
                                        -            the name of input tensor
                                        -        '''
                                        -        tensor_array_unstack(tensor, self.name)
                                        -
                                        -    def write(self, index, value, data_shared=True):
                                        -        '''
                                        -        Write value into index of the TensorArray.
                                        -        If `data_shared` is set to True, than the index-th value in TensorArray will
                                        -        be shared with the tensor passed in.
                                        -
                                        -        @index: str
                                        -            name of a scalar tensor
                                        -        @value: str
                                        -            name of a tensor
                                        -        @data_shared: bool
                                        -        '''
                                        -        tensor_array_write(self.name, index, value, data_shared)
                                        -
                                        -    def read(self, index, output):
                                        -        '''
                                        -        Read the value at location `index` in the `TensorArray`.
                                        -
                                        -        @index: str
                                        -            name of a scalar tensor
                                        -        @output:
                                        -            name of a output variable
                                        -        '''
                                        -        tensor_array_read(self.name, index, output)
                                        -
                                        -
                                        -    def size(self, output):
                                        -        '''
                                        -        Return the number of values.
                                        -
                                        -        @output: str
                                        -            name of a scalar tensor
                                        -        '''
                                        -        tensor_array_size(self.name, output)
                                        -
                                        -
                                        -
                                        - -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/design/var_desc.html b/develop/doc_cn/design/var_desc.html deleted file mode 100644 index 239004a6a15..00000000000 --- a/develop/doc_cn/design/var_desc.html +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - - - - Background — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        - - - - -
                                        - - - - - - -
                                        -
                                        - - - - - - -
                                        - -
                                        -
                                        -
                                        -
                                        - -
                                        -

                                        Background

                                        -

                                        PaddlePaddle divides the description of neural network computation into two stages: compile time and runtime. At compile time, the neural network computation is described as a ProgramDesc whereas at runtime an Executor interprets the ProgramDesc to compute the operations.

                                        -

                                        PaddlePaddle uses proto message to describe compile time program because :

                                        -
                                          -
                                        1. The computation program description must be serializable and saved in a file.
                                        2. -
                                        3. During distributed training, the serialized program will be sent to multiple workers. It should also be possible to break the program into different components, each of which can be executed on a different worker.
                                        4. -
                                        -

                                        The computation Program consists of nested Blocks. Each Block will consist of data(i.e. Variable) and Operations. The concept to represent them is in the table below.

                                        -

                                        | |compile time|runtime| -|—|—|—| -|Data|VarDesc(proto)|Variable(cpp)| -|Operation|OpDesc(proto)|Operator(cpp)|

                                        -
                                        -
                                        -

                                        Definition of VarType

                                        -

                                        A VarDesc should have a name, type and whether or not it is persistable. The are different kinds of variable types supported in PaddlePaddle, apart from the POD_Types like: LOD_TENSOR, SELECTED_ROWS, FEED_MINIBATCH, FETCH_LIST, STEP_SCOPES, LOD_RANK_TABLE, LOD_TENSOR_ARRAY, PLACE_LIST, READER and CHANNEL. These are declared inside VarType. A VarDesc then looks as the following:

                                        -
                                        message VarDesc {
                                        -  required string name = 1;
                                        -  required VarType type = 2;
                                        -  optional bool persistable = 3 [ default = false ];
                                        -}
                                        -
                                        -
                                        -
                                        -
                                        -

                                        Definition of TensorDesc

                                        -
                                        message TensorDesc {
                                        -  // Should only be PODType. Is enforced in C++
                                        -  required Type data_type = 1;
                                        -  repeated int64 dims = 2; // [UNK, 640, 480] is saved as [-1, 640, 480]
                                        -}
                                        -
                                        -
                                        -

                                        The Type here comes from the enum defined inside of VarType :

                                        -
                                        enum Type {
                                        -  // Pod Types
                                        -  BOOL = 0;
                                        -  INT16 = 1;
                                        -  INT32 = 2;
                                        -  INT64 = 3;
                                        -  FP16 = 4;
                                        -  FP32 = 5;
                                        -  FP64 = 6;
                                        -
                                        -  // Other types that may need additional descriptions
                                        -  LOD_TENSOR = 7;
                                        -  SELECTED_ROWS = 8;
                                        -  FEED_MINIBATCH = 9;
                                        -  FETCH_LIST = 10;
                                        -  STEP_SCOPES = 11;
                                        -  LOD_RANK_TABLE = 12;
                                        -  LOD_TENSOR_ARRAY = 13;
                                        -  PLACE_LIST = 14;
                                        -  READER = 15;
                                        -  CHANNEL = 16;
                                        -}
                                        -
                                        -
                                        -

                                        A TensorDesc describes SelectedRows and LoDTensor. For details of SelectedRows, please reference SelectedRows.

                                        -
                                        -
                                        -

                                        Definition of LodTensorDesc

                                        -
                                        message LoDTensorDesc {
                                        -  required TensorDesc tensor = 1;
                                        -  optional int32 lod_level = 2 [ default = 0 ];
                                        -}
                                        -
                                        -
                                        -

                                        A LoDTensorDesc contains a tensor and a lod_level.

                                        -
                                        -
                                        -

                                        Definition of Variable in Python

                                        -

                                        For Variable in Python, please reference Python API.

                                        -
                                        - - -
                                        -
                                        -
                                        - - -
                                        - -
                                        -

                                        - © Copyright 2016, PaddlePaddle developers. - -

                                        -
                                        - Built with Sphinx using a theme provided by Read the Docs. - -
                                        - -
                                        -
                                        - -
                                        - -
                                        - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/dev/contribute_to_paddle_cn.html b/develop/doc_cn/dev/contribute_to_paddle_cn.html index ce34ba56210..fa6fa9db07b 100644 --- a/develop/doc_cn/dev/contribute_to_paddle_cn.html +++ b/develop/doc_cn/dev/contribute_to_paddle_cn.html @@ -144,6 +144,7 @@ var _hmt = _hmt || [];
                                      • 开发标准
                                      • FAQ
                                          diff --git a/develop/doc_cn/dev/index_cn.html b/develop/doc_cn/dev/index_cn.html index 510faf9c4c6..ef865931a04 100644 --- a/develop/doc_cn/dev/index_cn.html +++ b/develop/doc_cn/dev/index_cn.html @@ -143,6 +143,7 @@ var _hmt = _hmt || [];
                                        • 开发标准
                                        • FAQ
                                            @@ -203,6 +204,7 @@ var _hmt = _hmt || []; diff --git a/develop/doc_cn/dev/new_layer_cn.html b/develop/doc_cn/dev/new_layer_cn.html index 67bdecb088d..142d7172344 100644 --- a/develop/doc_cn/dev/new_layer_cn.html +++ b/develop/doc_cn/dev/new_layer_cn.html @@ -10,7 +10,7 @@ - 实现新的网络层 — PaddlePaddle 文档 + 如何实现新的网络层 — PaddlePaddle 文档 @@ -35,7 +35,10 @@ - + + + + - - - - - - - - - -
                                            - - - - -
                                            - - - - - - -
                                            -
                                            - - - - - - -
                                            - -
                                            -
                                            -
                                            -
                                            - -
                                            -

                                            如何写新的Operator

                                            - -
                                            -

                                            概念简介

                                            -

                                            简单介绍需要用到基类,详细介绍请参考设计文档。

                                            -
                                              -
                                            • framework::OperatorBase: Operator(简写,Op)基类。
                                            • -
                                            • framework::OpKernel: Op计算函数的基类,称作Kernel。
                                            • -
                                            • framework::OperatorWithKernel:继承自OperatorBase,Op有计算函数,称作有Kernel。
                                            • -
                                            • class OpProtoAndCheckerMaker:描述该Op的输入、输出、属性、注释,主要用于Python API接口生成
                                            • -
                                            -

                                            依据是否包含kernel,可以将Op分为两种:包含Kernel的Op和不包含kernel的Op,前者Op的定义继承自OperatorWithKernel,后者继承自OperatorBase。本教程主要介绍带Kernel的Op如何写,简单总结Op需要包含的内容如下:

                                            -

                                            内容 | 定义位置 -————– | :———————- -OpProtoMake定义 | .cc文件,Backward Op不需要定义OpProtoMake -Op定义 | .cc文件 -Kernel实现 | CPU、CUDA共享Kernel实现在.h文件中,否则,CPU 实现在.cc文件中,CUDA 实现在.cu文件中。 -注册Op | Op注册实现在.cc文件;Kernel注册CPU实现在.cc文件中,CUDA实现在.cu文件中

                                            -

                                            实现新的op都添加至目录paddle/operators下,文件命名以*_op.h(如有) 、 *_op.cc*_op.cu(如有)结尾。系统会根据文件名自动构建op和其对应的Python扩展。

                                            -

                                            下面以矩阵乘操作,即MulOp为例来介绍如何写带Kernel的Operator。

                                            -
                                            -
                                            -

                                            实现C++类

                                            -
                                            -

                                            定义ProtoMaker类

                                            -

                                            矩阵乘法的公式:$Out = X * Y$, 可见该计算由两个输入,一个输出组成。

                                            -

                                            首先定义ProtoMaker来描述该Op的输入、输出,并添加注释:

                                            -
                                            class MulOpMaker : public framework::OpProtoAndCheckerMaker {
                                            - public:
                                            -  MulOpMaker(OpProto *proto, OpAttrChecker *op_checker)
                                            -      : OpProtoAndCheckerMaker(proto, op_checker) {
                                            -    AddInput("X", "(Tensor), 2D tensor of size (M x K)");
                                            -    AddInput("Y", "(Tensor), 2D tensor of size (K x N)");
                                            -    AddOutput("Out", "(Tensor), 2D tensor of size (M x N)");
                                            -    AddComment(R"DOC(
                                            -Two Element Mul Operator.
                                            -The equation is: Out = X * Y
                                            -)DOC");
                                            -  }
                                            -};
                                            -
                                            -
                                            -

                                            MulOpMaker继承自framework::OpProtoAndCheckerMaker,构造函数含有2个参数:

                                            -
                                              -
                                            • framework::OpProto : 前者存储Op的输入输出和参数属性,将用于Python API接口的生成。
                                            • -
                                            • framework::OpAttrChecker :后者用于检查参数属性的合法性。
                                            • -
                                            -

                                            构造函数里通过AddInput添加输入参数,通过AddOutput添加输出参数,通过AddComment添加Op的注释。这些函数会将对应内容添加到OpProto中。

                                            -

                                            上面的代码在MulOp中添加两个输入XY,添加了一个输出Out,并解释了各自含义,命名请遵守命名规范

                                            -

                                            再以ScaleOp为例:

                                            -
                                            template <typename AttrType>
                                            -class ScaleOpMaker : public framework::OpProtoAndCheckerMaker {
                                            - public:
                                            -  ScaleOpMaker(OpProto *proto, OpAttrChecker *op_checker)
                                            -      : OpProtoAndCheckerMaker(proto, op_checker) {
                                            -    AddInput("X", "The input tensor of scale operator.").NotInGradient();
                                            -    AddOutput("Out", "The output tensor of scale operator.").NotInGradient();
                                            -    AddComment(R"DOC(Scale operator
                                            -The equation is: Out = scale*X
                                            -)DOC");
                                            -    AddAttr<AttrType>("scale", "scale of scale operator.").SetDefault(1.0);
                                            -  }
                                            -};
                                            -
                                            -
                                            -

                                            这个例子有两处不同:

                                            -
                                              -
                                            • AddInput("X","...").NotInGradient() : 表示X这个输入不参与ScaleOp对应的梯度Op计算之中,如果Op的某个输入不参与反向梯度的计算,请显示地调用.NotInGradient()进行设置。
                                            • -
                                            • AddAttr<AttrType>("scale", "...").SetDefault(1.0); : 增加scale系数,作为参数属性,并且设置默认值为1.0。
                                            • -
                                            -
                                            -
                                            -

                                            定义Operator类

                                            -

                                            下面的点实现了MulOp的定义:

                                            -
                                            class MulOp : public framework::OperatorWithKernel {
                                            - public:
                                            -  using framework::OperatorWithKernel::OperatorWithKernel;
                                            -
                                            - protected:
                                            -  void InferShape(const framework::InferShapeContext &ctx) const override {
                                            -    auto dim0 = ctx.Input<Tensor>("X")->dims();
                                            -    auto dim1 = ctx.Input<Tensor>("Y")->dims();
                                            -    PADDLE_ENFORCE_EQ(dim0.size(), 2,
                                            -                      "input X(%s) should be a tensor with 2 dims, a matrix",
                                            -                      ctx.op_.Input("X"));
                                            -    PADDLE_ENFORCE_EQ(dim1.size(), 2,
                                            -                      "input Y(%s) should be a tensor with 2 dims, a matrix",
                                            -                      ctx.op_.Input("Y"));
                                            -    PADDLE_ENFORCE_EQ(
                                            -        dim0[1], dim1[0],
                                            -        "First matrix's width must be equal with second matrix's height.");
                                            -    ctx.Output<Tensor>("Out")->Resize({dim0[0], dim1[1]});
                                            -  }
                                            -};
                                            -
                                            -
                                            -

                                            MulOp继承自OperatorWithKernelpublic成员:

                                            -
                                            using framework::OperatorWithKernel::OperatorWithKernel;
                                            -
                                            -
                                            -

                                            这句表示使用基类OperatorWithKernel的构造函数,也可写成:

                                            -
                                            MulOp(const std::string &type, const framework::VariableNameMap &inputs,
                                            -      const framework::VariableNameMap &outputs,
                                            -      const framework::AttributeMap &attrs)
                                            -  : OperatorWithKernel(type, inputs, outputs, attrs) {}
                                            -
                                            -
                                            -

                                            还需要重写InferShape接口。InferShape为const函数,不能修改Op的成员变量,参数为const framework::InferShapeContext &ctx,通过该参数可获取到输入输出以及属性。它的功能是:

                                            -
                                              -
                                            • 1). 做检查, 尽早报错:检查输入数据维度、类型等是否合法。
                                            • -
                                            • 2). 设置输出Tensor的形状。
                                            • -
                                            -

                                            通常OpProtoMakerOp类的定义写在.cc文件中,和下面将要介绍的注册函数一起放在.cc

                                            -
                                            -
                                            -

                                            定义OpKernel类

                                            -

                                            MulKernel继承自framework::OpKernel,带有下面两个模板参数:

                                            -
                                              -
                                            • typename DeviceContext: 表示设备类型,不同设备(CPU、CUDA)共享同一个Kernel时,需加该模板参数,不共享则不加,一个不共享的例子是OnehotCrossEntropyOpKernel
                                            • -
                                            • typename T : 表示数据类型,如float, double等。
                                            • -
                                            -

                                            需要为MulKernel类重写Compute接口。

                                            -
                                              -
                                            • Compute接受一个输入参数:const framework::ExecutionContext& context
                                            • -
                                            • InferShapeContext相比,ExecutionContext增加了设备类型,同样可获取到输入输出和属性参数。
                                            • -
                                            • Compute函数里实现OpKernel的具体计算逻辑。
                                            • -
                                            -

                                            下面是 MulKernel Compute的实现:

                                            -
                                            template <typename DeviceContext, typename T>
                                            -class MulKernel : public framework::OpKernel {
                                            -public:
                                            -void Compute(const framework::ExecutionContext& context) const override {
                                            -  auto* X = context.Input<Tensor>("X");
                                            -  auto* Y = context.Input<Tensor>("Y");
                                            -  auto* Z = context.Output<Tensor>("Out");
                                            -  Z->mutable_data<T>(context.GetPlace());
                                            -  auto& device_context = context.template device_context<DeviceContext>();
                                            -  math::matmul<DeviceContext, T>(*X, false, *Y, false, 1, Z, 0, device_context);
                                            -}
                                            -};
                                            -
                                            -
                                            -

                                            需要注意:不同设备(CPU、CUDA)共享一个Op定义,是否则共享同一个OpKernel,取决于Compute调用的函数是否支持不同设备。

                                            -

                                            MulOp的CPU、CUDA实现共享同一个KernelOpKernel不共享的例子可以参考:OnehotCrossEntropyOpKernel

                                            -

                                            为了使OpKernel的计算过程书写更加简单,并且CPU、CUDA的代码可以复用,我们通常借助 Eigen unsupported Tensor模块来实现Compute接口。关于在PaddlePaddle中如何使用Eigen库,请参考使用文档

                                            -

                                            到此,前向Op实现完成。接下来,需要在.cc文件中注册该op和kernel。 -反向Op类的定义,反向OpKernel的定义与前向Op类似,这里不再赘述。但需注意反向Op没有ProtoMaker

                                            -
                                            -
                                            -

                                            注册Operator

                                            -
                                              -
                                            • .cc文件中注册前向、反向Op类,注册CPU Kernel。

                                              -
                                              namespace ops = paddle::operators;
                                              -REGISTER_OP(mul, ops::MulOp, ops::MulOpMaker, mul_grad, ops::MulOpGrad);
                                              -REGISTER_OP_CPU_KERNEL(mul, ops::MulKernel<paddle::platform::CPUDeviceContext, float>);
                                              -REGISTER_OP_CPU_KERNEL(mul_grad,
                                              -              ops::MulGradKernel<paddle::platform::CPUDeviceContext, float>);
                                              -
                                              -
                                              -

                                              在上面的代码中:

                                              -
                                                -
                                              • REGISTER_OP : 注册ops::MulOp类,类型名为mul,该类的ProtoMakerops::MulOpMaker,注册ops::MulOpGrad,类型名为mul_grad
                                              • -
                                              • REGISTER_OP_WITHOUT_GRADIENT : 用于注册没有反向的Op。
                                              • -
                                              • REGISTER_OP_CPU_KERNEL :注册ops::MulKernel类,并特化模板参数为paddle::platform::CPUPlacefloat类型,同理,注册ops::MulGradKernel类。
                                              • -
                                              -
                                            • -
                                            -
                                              -
                                            • .cu文件中注册CUDA Kernel。

                                              -
                                                -
                                              • 请注意,如果CUDA Kernel的实现基于Eigen unsupported模块,那么在 .cu的开始请加上宏定义 #define EIGEN_USE_GPU,代码示例如下:
                                              • -
                                              -
                                              // if use Eigen unsupported module before include head files
                                              -#define EIGEN_USE_GPU
                                              -
                                              -namespace ops = paddle::operators;
                                              -REGISTER_OP_CUDA_KERNEL(mul, ops::MulKernel<paddle::platform::CUDADeviceContext, float>);
                                              -REGISTER_OP_CUDA_KERNEL(mul_grad,
                                              -                       ops::MulGradKernel<paddle::platform::CUDADeviceContext, float>);
                                              -
                                              -
                                              -
                                            • -
                                            -
                                            -
                                            -

                                            编译

                                            -

                                            运行下面命令可以进行编译:

                                            -
                                            make mul_op
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            绑定Python

                                            -

                                            系统会对新增的op自动绑定Python,并链接到生成的lib库中。

                                            -
                                            -
                                            -

                                            实现单元测试

                                            -

                                            单测包括对比前向Op不同设备(CPU、CUDA)的实现、对比反向OP不同设备(CPU、CUDA)的实现、反向Op的梯度测试。下面介绍介绍MulOp的单元测试

                                            -
                                            -

                                            前向Operator单测

                                            -

                                            Op单元测试继承自OpTest。各项更加具体的单元测试在TestMulOp里完成。测试Operator,需要:

                                            -
                                              -
                                            1. setUp函数定义输入、输出,以及相关的属性参数。
                                            2. -
                                            3. 生成随机的输入数据。
                                            4. -
                                            5. 在Python脚本中实现与前向operator相同的计算逻辑,得到输出值,与operator前向计算的输出进行对比。
                                            6. -
                                            7. 反向计算已经自动集成进测试框架,直接调用相应接口即可。
                                            8. -
                                            -
                                            import unittest
                                            -import numpy as np
                                            -from op_test import OpTest
                                            -
                                            -
                                            -class TestMulOp(OpTest):
                                            -    def setUp(self):
                                            -        self.op_type = "mul"
                                            -        self.inputs = {
                                            -            'X': np.random.random((32, 84)).astype("float32"),
                                            -            'Y': np.random.random((84, 100)).astype("float32")
                                            -        }
                                            -        self.outputs = {'Out': np.dot(self.inputs['X'], self.inputs['Y'])}
                                            -
                                            -    def test_check_output(self):
                                            -        self.check_output()
                                            -
                                            -    def test_check_grad_normal(self):
                                            -        self.check_grad(['X', 'Y'], 'Out', max_relative_error=0.5)
                                            -
                                            -    def test_check_grad_ingore_x(self):
                                            -        self.check_grad(
                                            -            ['Y'], 'Out', max_relative_error=0.5, no_grad_set=set("X"))
                                            -
                                            -    def test_check_grad_ingore_y(self):
                                            -        self.check_grad(
                                            -            ['X'], 'Out', max_relative_error=0.5, no_grad_set=set('Y'))
                                            -
                                            -
                                            -

                                            上面的代码首先导入依赖的包,下面是对setUp函数中操作的重要变量的详细解释:

                                            -
                                              -
                                            • self.op_type = "mul" : 定义类型,与operator注册时注册的类型一致。
                                            • -
                                            • self.inputs : 定义输入,类型为numpy.array,并初始化。
                                            • -
                                            • self.outputs : 定义输出,并在Python脚本中完成与operator同样的计算逻辑,返回Python端的计算结果。
                                            • -
                                            -
                                            -
                                            -

                                            反向operator单测

                                            -

                                            而反向测试中:

                                            -
                                              -
                                            • test_check_grad_normal中调用check_grad使用数值法检测梯度正确性和稳定性。
                                                -
                                              • 第一个参数["X", "Y"] : 指定对输入变量XY做梯度检测。
                                              • -
                                              • 第二个参数"Out" : 指定前向网络最终的输出目标变量Out
                                              • -
                                              • 第三个参数max_relative_error:指定检测梯度时能容忍的最大错误值。
                                              • -
                                              -
                                            • -
                                            • test_check_grad_ingore_xtest_check_grad_ingore_y分支用来测试只需要计算一个输入梯度的情况。
                                            • -
                                            -
                                            -
                                            -

                                            编译和执行

                                            -

                                            python/paddle/v2/framework/tests 目录下新增的 test_*.py 单元测试会被自动加入工程进行编译。

                                            -

                                            请注意,不同于Op的编译测试,运行单元测试测时需要编译整个工程,并且编译时需要打开WITH_TESTING, 即cmake paddle_dir -DWITH_TESTING=ON。编译成功后,执行下面的命令来运行单元测试:

                                            -
                                            make test ARGS="-R test_mul_op -V"
                                            -
                                            -
                                            -

                                            或者:

                                            -
                                            ctest -R test_mul_op
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            注意事项

                                            -
                                              -
                                            • 为每个Op创建单独的*_op.h(如有)、*_op.cc*_op.cu(如有)。不允许一个文件中包含多个Op,这将会导致编译出错。
                                            • -
                                            • 注册Op时的类型名,需要和该Op的名字一样。即不允许在A_op.cc里面,注册REGISTER_OP(B, ...)等,这将会导致单元测试出错。
                                            • -
                                            • 如果Op没有实现CUDA Kernel,请不要创建空的*_op.cu,这将会导致单元测试出错。
                                            • -
                                            • 如果多个Op依赖一些共用的函数,可以创建非*_op.*格式的文件来存放,如gather.h文件。
                                            • -
                                            -
                                            -
                                            - - -
                                            -
                                            -
                                            - - -
                                            - -
                                            -

                                            - © Copyright 2016, PaddlePaddle developers. - -

                                            -
                                            - Built with Sphinx using a theme provided by Read the Docs. - -
                                            - -
                                            -
                                            - -
                                            - -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/dev/use_eigen_cn.html b/develop/doc_cn/dev/use_eigen_cn.html deleted file mode 100644 index 4397f646227..00000000000 --- a/develop/doc_cn/dev/use_eigen_cn.html +++ /dev/null @@ -1,388 +0,0 @@ - - - - - - - - - - - - - 在Paddle中如何使用Eigen — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                            - - - - -
                                            - - - - - - -
                                            -
                                            - - - - - - -
                                            - -
                                            -
                                            -
                                            -
                                            - -
                                            -

                                            在Paddle中如何使用Eigen

                                            -

                                            神经网络本质上是一个计算图,计算需要的数据存放在Tensor中,而计算过程是由Operartor来描述的。在执行时,Operator调用对应OpKernel中的Compute接口,实现对Tensor的操作。

                                            -
                                            -

                                            Eigen Tensor模块

                                            -

                                            Eigen Tensor模块对element-wise计算提供了强大的支持,并且书写一份代码,可以同时在CPU、GPU执行。但Eigen Tensor是一个正在开发中的模块,因此可能测试不够完备,文档较少。

                                            -

                                            关于Eigen Tensor模块的详细介绍请参考文档1文档2

                                            -
                                            -
                                            -

                                            paddle::framework::Tensor

                                            -

                                            Paddle Tensor定义在framework目录下,其主要接口如下:

                                            -
                                            class Tensor {
                                            - public:
                                            -  /*! Return a pointer to mutable memory block. */
                                            -  template <typename T>
                                            -  inline T* data();
                                            -  
                                            -  /**
                                            -   * @brief   Return a pointer to mutable memory block.
                                            -   * @note    If not exist, then allocation.
                                            -   */
                                            -  template <typename T>
                                            -  inline T* mutable_data(platform::Place place);
                                            -  
                                            -  /**
                                            -   * @brief     Return a pointer to mutable memory block.
                                            -   *
                                            -   * @param[in] dims    The dimensions of the memory block.
                                            -   * @param[in] place   The place of the memory block.
                                            -   *
                                            -   * @note      If not exist, then allocation.
                                            -   */
                                            -  template <typename T>
                                            -  inline T* mutable_data(DDim dims, platform::Place place);
                                            -  
                                            -  /*! Resize the dimensions of the memory block. */
                                            -  inline Tensor& Resize(const DDim& dims);
                                            -  
                                            -  /*! Return the dimensions of the memory block. */
                                            -  inline const DDim& dims() const;
                                            -
                                            - private:  
                                            -  /*! holds the memory block if allocated. */
                                            -  std::shared_ptr<Placeholder> holder_;
                                            -  
                                            -  /*! points to dimensions of memory block. */
                                            -  DDim dim_;
                                            -};
                                            -
                                            -
                                            -

                                            Placeholder的作用是延迟分配内存,即我们可以先定义一个Tensor,然后使用Resize接口设置Tensor的大小,最后再调用mutable_data接口分配实际的内存。

                                            -
                                            paddle::framework::Tensor t;
                                            -paddle::platform::CPUPlace place;
                                            -// set size first
                                            -t.Resize({2, 3});
                                            -// allocate memory on CPU later
                                            -t.mutable_data(place);
                                            -
                                            -
                                            -
                                            -
                                            -

                                            paddle::framework::Tensor使用样例

                                            -

                                            下面以AddOp为例说明Tensor的使用过程:

                                            -
                                              -
                                            • InferShape
                                            • -
                                            -

                                            在运行神经网络计算图时,我们先调用每个OperatorInferShape接口,根据输入Tensor的大小来设置输出Tensor的大小,Resize接口会被调用。

                                            -
                                            void InferShape(const framework::InferShapeContext &ctx) const override {
                                            -  PADDLE_ENFORCE_EQ(ctx.Input<Tensor>("X")->dims(),
                                            -                    ctx.Input<Tensor>("Y")->dims(),
                                            -                    "Two input of Add Op's dimension must be same.");
                                            -  ctx.Output<Tensor>("Out")->Resize(ctx.Input<Tensor>("X")->dims());
                                            -}
                                            -
                                            -
                                            -
                                              -
                                            • Run
                                            • -
                                            -

                                            OperatorRun接口最终会调用对应OpKernelCompute接口,在这时真正的分配内存,mutable_data接口会被调用。

                                            -
                                            void Compute(const framework::ExecutionContext& context) const override {
                                            -  auto* input0 = context.Input<Tensor>("X");
                                            -  auto* input1 = context.Input<Tensor>("Y");
                                            -  auto* output = context.Output<Tensor>("Out");
                                            -
                                            -  output->mutable_data<T>(context.GetPlace());
                                            -
                                            -  auto x = EigenVector<T>::Flatten(*input0);
                                            -  auto y = EigenVector<T>::Flatten(*input1);
                                            -  auto z = EigenVector<T>::Flatten(*output);
                                            -
                                            -  auto place = context.GetEigenDevice<Place>();
                                            -
                                            -  z.device(place) = x + y;
                                            -}
                                            -
                                            -
                                            -
                                            -
                                            -

                                            paddle::framework::Tensor到EigenTensor的转换

                                            -

                                            如上一小节所示,在具体的计算中,我们需要先把输入Tensor和输出Tensor转换为Eigen支持的格式。我们在eigen.h中提供了一些全局函数用来实现paddle::framework::Tensor到EigenTensor/EigenMatrix/EigenVector/EigenScalar的转换。

                                            -

                                            以EigenTensor为例,做一个介绍

                                            -
                                            Tensor t;
                                            -float* p = t.mutable_data<float>(make_ddim({1, 2, 3}), platform::CPUPlace());
                                            -for (int i = 0; i < 1 * 2 * 3; i++) {
                                            -  p[i] = static_cast<float>(i);
                                            -}
                                            -
                                            -EigenTensor<float, 3>::Type et = EigenTensor<float, 3>::From(t);
                                            -
                                            -
                                            -

                                            From是EigenTensor模板提供的一个接口,可以实现从paddle::framework::Tensor到对EigenTensor的转换。由于Tensor的rank是模板参数,因此在转换时需要显示的指定。

                                            -

                                            在Eigen中,不同rank的Tensor是不同类型,Vector是rank为1的Tensor。需要额外注意的是,EigenVector::From方法是把paddle中的一维Tensor转为Eigen的一维Tensor,在这里用EigenVector来表示;而EigenVector::Flatten方法是把paddle中的一个Tensor进行reshape操作,压扁成为Eigen的一维Tensor,类型仍然为EigenVector。

                                            -

                                            更多的转换方法请参考eigen_test.cc中的单元测试

                                            -
                                            -
                                            -

                                            实现计算

                                            -

                                            当需要完成计算时,我们需要等式左边的EigenTensor调用device接口。在这里需要注意的是,这里的EigenTensor之间的运算只是改变了原有Tensor中的数据,而不会改变原有Tensor的shape信息。

                                            -
                                            auto x = EigenVector<T>::Flatten(*input0);
                                            -auto y = EigenVector<T>::Flatten(*input1);
                                            -auto z = EigenVector<T>::Flatten(*output);
                                            -auto place = context.GetEigenDevice<Place>();
                                            -z.device(place) = x + y;
                                            -
                                            -
                                            -

                                            在这段代码中,input0/input1/output可以是任意维度的Tensor。我们调用了EigenVector的Flatten接口,把任意维度的Tensor转为了一维的EigenVector。而在计算结束之后,input0/input1/output的原有shape信息不变。如果想改变原有Tensor的shape信息,可以调用Resize接口进行改变。

                                            -

                                            由于Eigen Tensor模块的文档较少,我们可以参考TensorFlow的kernels模块下的相关OpKernel的计算代码。

                                            -
                                            -
                                            - - -
                                            -
                                            -
                                            - - -
                                            - -
                                            -

                                            - © Copyright 2016, PaddlePaddle developers. - -

                                            -
                                            - Built with Sphinx using a theme provided by Read the Docs. - -
                                            - -
                                            -
                                            - -
                                            - -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/dev/write_docs_cn.html b/develop/doc_cn/dev/write_docs_cn.html index ec59b7cafad..2abea256e42 100644 --- a/develop/doc_cn/dev/write_docs_cn.html +++ b/develop/doc_cn/dev/write_docs_cn.html @@ -37,7 +37,7 @@ - + - - - - - - - - - -
                                            - - - - -
                                            - - - - - - -
                                            -
                                            - - - - - - -
                                            - -
                                            -
                                            -
                                            -
                                            - -

                                            此教程会介绍如何使用Python的cProfile包、Python库yep、Google perftools来进行性能分析 (profiling) 与调优(performance tuning)。

                                            -

                                            Profling 指发现性能瓶颈。系统中的瓶颈可能和程序员开发过程中想象的瓶颈相去甚远。Tuning 指消除瓶颈。性能优化的过程通常是不断重复地 profiling 和 tuning。

                                            -

                                            PaddlePaddle 用户一般通过调用 Python API 编写深度学习程序。大部分 Python API 调用用 C++ 写的 libpaddle.so。所以 PaddlePaddle 的性能分析与调优分为两个部分:

                                            -
                                              -
                                            • Python 代码的性能分析
                                            • -
                                            • Python 与 C++ 混合代码的性能分析
                                            • -
                                            -
                                            -

                                            Python代码的性能分析

                                            -
                                            -

                                            生成性能分析文件

                                            -

                                            Python标准库中提供了性能分析的工具包,cProfile。生成Python性能分析的命令如下:

                                            -
                                            python -m cProfile -o profile.out main.py
                                            -
                                            -
                                            -

                                            其中 main.py 是我们要分析的程序,-o标识了一个输出的文件名,用来存储本次性能分析的结果。如果不指定这个文件,cProfile会打印到标准输出。

                                            -
                                            -
                                            -

                                            查看性能分析文件

                                            -

                                            cProfile 在main.py 运行完毕后输出profile.out。我们可以使用cprofilev来查看性能分析结果。cprofilev是一个Python的第三方库。使用它会开启一个HTTP服务,将性能分析结果以网页的形式展示出来:

                                            -
                                            cprofilev -a 0.0.0.0 -p 3214 -f profile.out main.py
                                            -
                                            -
                                            -

                                            其中-a标识HTTP服务绑定的IP。使用0.0.0.0允许外网访问这个HTTP服务。-p标识HTTP服务的端口。-f标识性能分析的结果文件。main.py标识被性能分析的源文件。

                                            -

                                            用Web浏览器访问对应网址,即可显示性能分析的结果:

                                            -
                                               ncalls  tottime  percall  cumtime  percall filename:lineno(function)
                                            -        1    0.284    0.284   29.514   29.514 main.py:1(<module>)
                                            -     4696    0.128    0.000   15.748    0.003 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/executor.py:20(run)
                                            -     4696   12.040    0.003   12.040    0.003 {built-in method run}
                                            -        1    0.144    0.144    6.534    6.534 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/v2/__init__.py:14(<module>)
                                            -
                                            -
                                            -

                                            每一列的含义是:

                                            -

                                            | 列名 | 含义 | -| — | — | -| ncalls | 函数的调用次数 | -| tottime | 函数实际使用的总时间。该时间去除掉本函数调用其他函数的时间 | -| percall | tottime的每次调用平均时间 | -| cumtime | 函数总时间。包含这个函数调用其他函数的时间 | -| percall | cumtime的每次调用平均时间 | -| filename:lineno(function) | 文件名, 行号,函数名 |

                                            -
                                            -
                                            -

                                            寻找性能瓶颈

                                            -

                                            通常tottimecumtime是寻找瓶颈的关键指标。这两个指标代表了某一个函数真实的运行时间。

                                            -

                                            将性能分析结果按照tottime排序,效果如下:

                                            -
                                                 4696   12.040    0.003   12.040    0.003 {built-in method run}
                                            -   300005    0.874    0.000    1.681    0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/v2/dataset/mnist.py:38(reader)
                                            -   107991    0.676    0.000    1.519    0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:219(__init__)
                                            -     4697    0.626    0.000    2.291    0.000 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:428(sync_with_cpp)
                                            -        1    0.618    0.618    0.618    0.618 /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/__init__.py:1(<module>)
                                            -
                                            -
                                            -

                                            可以看到最耗时的函数是C++端的run函数。这需要联合我们第二节PythonC++混合代码的性能分析来进行调优。而sync_with_cpp函数的总共耗时很长,每次调用的耗时也很长。于是我们可以点击sync_with_cpp的详细信息,了解其调用关系。

                                            -
                                            Called By:
                                            -
                                            -   Ordered by: internal time
                                            -   List reduced from 4497 to 2 due to restriction <'sync_with_cpp'>
                                            -
                                            -Function                                                                                                 was called by...
                                            -                                                                                                             ncalls  tottime  cumtime
                                            -/home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:428(sync_with_cpp)  <-    4697    0.626    2.291  /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:562(sync_with_cpp)
                                            -/home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:562(sync_with_cpp)  <-    4696    0.019    2.316  /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:487(clone)
                                            -                                                                                                                  1    0.000    0.001  /home/yuyang/perf_test/.env/lib/python2.7/site-packages/paddle/fluid/framework.py:534(append_backward)
                                            -
                                            -
                                            -Called:
                                            -
                                            -   Ordered by: internal time
                                            -   List reduced from 4497 to 2 due to restriction <'sync_with_cpp'>
                                            -
                                            -
                                            -

                                            通常观察热点函数间的调用关系,和对应行的代码,就可以了解到问题代码在哪里。当我们做出性能修正后,再次进行性能分析(profiling)即可检查我们调优后的修正是否能够改善程序的性能。

                                            -
                                            -
                                            -
                                            -

                                            Python与C++混合代码的性能分析

                                            -
                                            -

                                            生成性能分析文件

                                            -

                                            C++的性能分析工具非常多。常见的包括gprof, valgrind, google-perftools。但是调试Python中使用的动态链接库与直接调试原始二进制相比增加了很多复杂度。幸而Python的一个第三方库yep提供了方便的和google-perftools交互的方法。于是这里使用yep进行Python与C++混合代码的性能分析

                                            -

                                            使用yep前需要安装google-perftoolsyep包。ubuntu下安装命令为

                                            -
                                            apt update
                                            -apt install libgoogle-perftools-dev
                                            -pip install yep
                                            -
                                            -
                                            -

                                            安装完毕后,我们可以通过

                                            -
                                            python -m yep -v main.py
                                            -
                                            -
                                            -

                                            生成性能分析文件。生成的性能分析文件为main.py.prof

                                            -

                                            命令行中的-v指定在生成性能分析文件之后,在命令行显示分析结果。我们可以在命令行中简单的看一下生成效果。因为C++与Python不同,编译时可能会去掉调试信息,运行时也可能因为多线程产生混乱不可读的性能分析结果。为了生成更可读的性能分析结果,可以采取下面几点措施:

                                            -
                                              -
                                            1. 编译时指定-g生成调试信息。使用cmake的话,可以将CMAKE_BUILD_TYPE指定为RelWithDebInfo
                                            2. -
                                            3. 编译时一定要开启优化。单纯的Debug编译性能会和-O2或者-O3有非常大的差别。Debug模式下的性能测试是没有意义的。
                                            4. -
                                            5. 运行性能分析的时候,先从单线程开始,再开启多线程,进而多机。毕竟单线程调试更容易。可以设置OMP_NUM_THREADS=1这个环境变量关闭openmp优化。
                                            6. -
                                            -
                                            -
                                            -

                                            查看性能分析文件

                                            -

                                            在运行完性能分析后,会生成性能分析结果文件。我们可以使用pprof来显示性能分析结果。注意,这里使用了用Go语言重构后的pprof,因为这个工具具有web服务界面,且展示效果更好。

                                            -

                                            安装pprof的命令和一般的Go程序是一样的,其命令如下:

                                            -
                                            go get github.com/google/pprof
                                            -
                                            -
                                            -

                                            进而我们可以使用如下命令开启一个HTTP服务:

                                            -
                                            pprof -http=0.0.0.0:3213 `which python`  ./main.py.prof
                                            -
                                            -
                                            -

                                            这行命令中,-http指开启HTTP服务。which python会产生当前Python二进制的完整路径,进而指定了Python可执行文件的路径。./main.py.prof输入了性能分析结果。

                                            -

                                            访问对应的网址,我们可以查看性能分析的结果。结果如下图所示:

                                            -

                                            result

                                            -
                                            -
                                            -

                                            寻找性能瓶颈

                                            -

                                            与寻找Python代码的性能瓶颈类似,寻找Python与C++混合代码的性能瓶颈也是要看tottimecumtime。而pprof展示的调用图也可以帮助我们发现性能中的问题。

                                            -

                                            例如下图中,

                                            -

                                            kernel_perf

                                            -

                                            在一次训练中,乘法和乘法梯度的计算占用2%-4%左右的计算时间。而MomentumOp占用了17%左右的计算时间。显然,MomentumOp的性能有问题。

                                            -

                                            pprof中,对于性能的关键路径都做出了红色标记。先检查关键路径的性能问题,再检查其他部分的性能问题,可以更有次序的完成性能的优化。

                                            -
                                            -
                                            - - -
                                            -
                                            -
                                            - - -
                                            - -
                                            -

                                            - © Copyright 2016, PaddlePaddle developers. - -

                                            -
                                            - Built with Sphinx using a theme provided by Read the Docs. - -
                                            - -
                                            -
                                            - -
                                            - -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/howto/optimization/gpu_profiling_cn.html b/develop/doc_cn/howto/optimization/gpu_profiling_cn.html index 05d2b1aab0d..c3b8520dba1 100644 --- a/develop/doc_cn/howto/optimization/gpu_profiling_cn.html +++ b/develop/doc_cn/howto/optimization/gpu_profiling_cn.html @@ -144,6 +144,7 @@ var _hmt = _hmt || [];
                                          • 开发标准
                                          • FAQ
                                              diff --git a/develop/doc_cn/howto/read_source.html b/develop/doc_cn/howto/read_source.html deleted file mode 100644 index a957661475b..00000000000 --- a/develop/doc_cn/howto/read_source.html +++ /dev/null @@ -1,342 +0,0 @@ - - - - - - - - - - - - - PaddlePaddle Fluid Source Code Overview — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                              - - - - -
                                              - - - - - - -
                                              -
                                              - - - - - - -
                                              - -
                                              -
                                              -
                                              -
                                              - -
                                              -

                                              PaddlePaddle Fluid Source Code Overview

                                              -

                                              Examples: https://github.com/PaddlePaddle/Paddle/tree/develop/python/paddle/fluid/tests/book

                                              -

                                              Core: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/framework

                                              -

                                              Operator: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/operators

                                              -

                                              Memory: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/memory

                                              -

                                              Platform: https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/platform

                                              -
                                              -
                                              -

                                              Compile Time

                                              -

                                              The following defines the NN. The definition goes into this protocol buffer.

                                              -
                                              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_cost = fluid.layers.mean(x=cost)
                                              -
                                              -sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.001)
                                              -sgd_optimizer.minimize(avg_cost)
                                              -
                                              -
                                              - -
                                              -
                                              -

                                              Run Time

                                              -

                                              The following evaluates the NN. Instantiates all the variables, operators.

                                              -
                                              place = fluid.CPUPlace()
                                              -feeder = fluid.DataFeeder(place=place, feed_list=[x, y])
                                              -exe = fluid.Executor(place)
                                              -
                                              -# Allocate memory. Initialize Parameter.
                                              -exe.run(fluid.default_startup_program())
                                              -
                                              -# Allocate memory. Do computation.
                                              -exe.run(fluid.default_main_program(),
                                              -        feed=feeder.feed(data),
                                              -        fetch_list=[avg_cost])
                                              -
                                              -
                                              - -
                                              - - -
                                              -
                                              -
                                              - - -
                                              - -
                                              -

                                              - © Copyright 2016, PaddlePaddle developers. - -

                                              -
                                              - Built with Sphinx using a theme provided by Read the Docs. - -
                                              - -
                                              -
                                              - -
                                              - -
                                              - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/howto/rnn/hierarchical_layer_cn.html b/develop/doc_cn/howto/rnn/hierarchical_layer_cn.html index a6117bdc10f..10500f8ade8 100644 --- a/develop/doc_cn/howto/rnn/hierarchical_layer_cn.html +++ b/develop/doc_cn/howto/rnn/hierarchical_layer_cn.html @@ -144,6 +144,7 @@ var _hmt = _hmt || [];
                                            • 开发标准
                                            • FAQ
                                                diff --git a/develop/doc_cn/howto/rnn/hrnn_rnn_api_compare_cn.html b/develop/doc_cn/howto/rnn/hrnn_rnn_api_compare_cn.html index bf7450d9f7c..c395ce4fcbe 100644 --- a/develop/doc_cn/howto/rnn/hrnn_rnn_api_compare_cn.html +++ b/develop/doc_cn/howto/rnn/hrnn_rnn_api_compare_cn.html @@ -144,6 +144,7 @@ var _hmt = _hmt || [];
                                              • 开发标准
                                              • FAQ
                                                  @@ -219,10 +220,76 @@ var _hmt = _hmt || [];
                                                  • 本例中的原始数据一共有10个样本。每个样本由两部分组成,一个label(此处都为2)和一个已经分词后的句子。这个数据也被单层RNN网络直接使用。
                                                  +
                                                  2  	酒店 有 很 舒适 的 床垫 子 , 床上用品 也 应该 是 一人 一 换 , 感觉 很 利落 对 卫生 很 放心 呀 。
                                                  +2  	很 温馨 , 也 挺 干净 的 * 地段 不错 , 出来 就 有 全家 , 离 地铁站 也 近 , 交通 很方便 * 就是 都 不 给 刷牙 的 杯子 啊 , 就 第一天 给 了 一次性杯子 *
                                                  +2  	位置 方便 , 强烈推荐 , 十一 出去玩 的 时候 选 的 , 对面 就是 华润万家 , 周围 吃饭 的 也 不少 。
                                                  +2  	交通便利 , 吃 很 便利 , 乾 浄 、 安静 , 商务 房 有 电脑 、 上网 快 , 价格 可以 , 就 早餐 不 好吃 。 整体 是 不错 的 。 適 合 出差 來 住 。
                                                  +2  	本来 准备 住 两 晚 , 第 2 天 一早 居然 停电 , 且 无 通知 , 只有 口头 道歉 。 总体来说 性价比 尚可 , 房间 较 新 , 还是 推荐 .
                                                  +2  	这个 酒店 去过 很多 次 了 , 选择 的 主要原因 是 离 客户 最 便宜 相对 又 近 的 酒店
                                                  +2  	挺好 的 汉庭 , 前台 服务 很 热情 , 卫生 很 整洁 , 房间 安静 , 水温 适中 , 挺好 !
                                                  +2  	HowardJohnson 的 品质 , 服务 相当 好 的 一 家 五星级 。 房间 不错 、 泳池 不错 、 楼层 安排 很 合理 。 还有 就是 地理位置 , 简直 一 流 。 就 在 天一阁 、 月湖 旁边 , 离 天一广场 也 不远 。 下次 来 宁波 还会 住 。
                                                  +2  	酒店 很干净 , 很安静 , 很 温馨 , 服务员 服务 好 , 各方面 都 不错 *
                                                  +2  	挺好 的 , 就是 没 窗户 , 不过 对 得 起 这 价格
                                                  +
                                                  +
                                                  • 双层序列数据一共有4个样本。 每个样本间用空行分开,整体数据和原始数据完全一样。但于双层序列的LSTM来说,第一个样本同时encode两条数据成两个向量。这四条数据同时处理的句子数量为[2, 3, 2, 3]
                                                  +
                                                  2  	酒店 有 很 舒适 的 床垫 子 , 床上用品 也 应该 是 一人 一 换 , 感觉 很 利落 对 卫生 很 放心 呀 。
                                                  +2  	很 温馨 , 也 挺 干净 的 * 地段 不错 , 出来 就 有 全家 , 离 地铁站 也 近 , 交通 很方便 * 就是 都 不 给 刷牙 的 杯子 啊 , 就 第一天 给 了 一次性杯子 *
                                                  +
                                                  +2  	位置 方便 , 强烈推荐 , 十一 出去玩 的 时候 选 的 , 对面 就是 华润万家 , 周围 吃饭 的 也 不少 。
                                                  +2  	交通便利 , 吃 很 便利 , 乾 浄 、 安静 , 商务 房 有 电脑 、 上网 快 , 价格 可以 , 就 早餐 不 好吃 。 整体 是 不错 的 。 適 合 出差 來 住 。
                                                  +2  	本来 准备 住 两 晚 , 第 2 天 一早 居然 停电 , 且 无 通知 , 只有 口头 道歉 。 总体来说 性价比 尚可 , 房间 较 新 , 还是 推荐 .
                                                  +
                                                  +2  	这个 酒店 去过 很多 次 了 , 选择 的 主要原因 是 离 客户 最 便宜 相对 又 近 的 酒店
                                                  +2  	挺好 的 汉庭 , 前台 服务 很 热情 , 卫生 很 整洁 , 房间 安静 , 水温 适中 , 挺好 !
                                                  +
                                                  +2  	HowardJohnson 的 品质 , 服务 相当 好 的 一 家 五星级 。 房间 不错 、 泳池 不错 、 楼层 安排 很 合理 。 还有 就是 地理位置 , 简直 一 流 。 就 在 天一阁 、 月湖 旁边 , 离 天一广场 也 不远 。 下次 来 宁波 还会 住 。
                                                  +2  	酒店 很干净 , 很安静 , 很 温馨 , 服务员 服务 好 , 各方面 都 不错 *
                                                  +2  	挺好 的 , 就是 没 窗户 , 不过 对 得 起 这 价格
                                                  +
                                                  +

                                                  其次,对于两种不同的输入数据类型,不同DataProvider对比如下(sequenceGen.py):

                                                  +
                                                   1
                                                  + 2
                                                  + 3
                                                  + 4
                                                  + 5
                                                  + 6
                                                  + 7
                                                  + 8
                                                  + 9
                                                  +10
                                                  +11
                                                  +12
                                                  +13
                                                  +14
                                                  +15
                                                  +16
                                                  +17
                                                  +18
                                                  +19
                                                      settings.word_dict = dict_file
                                                  +    settings.input_types = [
                                                  +        integer_value_sequence(len(settings.word_dict)), integer_value(3)
                                                  +    ]
                                                  +    settings.logger.info('dict len : %d' % (len(settings.word_dict)))
                                                  +
                                                  +
                                                  +@provider(init_hook=hook, should_shuffle=False)
                                                  +def process(settings, file_name):
                                                  +    with open(file_name, 'r') as fdata:
                                                  +        for line in fdata:
                                                  +            label, comment = line.strip().split('\t')
                                                  +            label = int(''.join(label.split()))
                                                  +            words = comment.split()
                                                  +            words = [
                                                  +                settings.word_dict[w] for w in words if w in settings.word_dict
                                                  +            ]
                                                  +            yield words, label
                                                  +
                                                  +
                                                  +
                                                  • 这是普通的单层时间序列的DataProvider代码,其说明如下:
                                                    • DataProvider共返回两个数据,分别是words和label。即上述代码中的第19行。
                                                        @@ -233,6 +300,65 @@ var _hmt = _hmt || [];
                                                    +
                                                     1
                                                    + 2
                                                    + 3
                                                    + 4
                                                    + 5
                                                    + 6
                                                    + 7
                                                    + 8
                                                    + 9
                                                    +10
                                                    +11
                                                    +12
                                                    +13
                                                    +14
                                                    +15
                                                    +16
                                                    +17
                                                    +18
                                                    +19
                                                    +20
                                                    +21
                                                    +22
                                                    +23
                                                    +24
                                                    +25
                                                    +26
                                                    +27
                                                    +28
                                                    +29
                                                    def hook2(settings, dict_file, **kwargs):
                                                    +    settings.word_dict = dict_file
                                                    +    settings.input_types = [
                                                    +        integer_value_sub_sequence(len(settings.word_dict)),
                                                    +        integer_value_sequence(3)
                                                    +    ]
                                                    +    settings.logger.info('dict len : %d' % (len(settings.word_dict)))
                                                    +
                                                    +
                                                    +@provider(init_hook=hook2, should_shuffle=False)
                                                    +def process2(settings, file_name):
                                                    +    with open(file_name) as fdata:
                                                    +        labels = []
                                                    +        sentences = []
                                                    +        for line in fdata:
                                                    +            if (len(line)) > 1:
                                                    +                label, comment = line.strip().split('\t')
                                                    +                label = int(''.join(label.split()))
                                                    +                words = comment.split()
                                                    +                words = [
                                                    +                    settings.word_dict[w] for w in words
                                                    +                    if w in settings.word_dict
                                                    +                ]
                                                    +                labels.append(label)
                                                    +                sentences.append(words)
                                                    +            else:
                                                    +                yield sentences, labels
                                                    +                labels = []
                                                    +                sentences = []
                                                    +
                                                    +
                                                    • 对于同样的数据,双层时间序列的DataProvider的代码。其说明如下:
                                                      • DataProvider共返回两组数据,分别是sentences和labels。即在双层序列的原始数据中,每一组内的所有句子和labels
                                                      • @@ -245,6 +371,57 @@ var _hmt = _hmt || [];

                                                        模型配置的模型配置

                                                        首先,我们看一下单层RNN的配置。代码中9-15行(高亮部分)即为单层RNN序列的使用代码。这里使用了PaddlePaddle预定义好的RNN处理函数。在这个函数中,RNN对于每一个时间步通过了一个LSTM网络。

                                                        +
                                                         1
                                                        + 2
                                                        + 3
                                                        + 4
                                                        + 5
                                                        + 6
                                                        + 7
                                                        + 8
                                                        + 9
                                                        +10
                                                        +11
                                                        +12
                                                        +13
                                                        +14
                                                        +15
                                                        +16
                                                        +17
                                                        +18
                                                        +19
                                                        +20
                                                        +21
                                                        +22
                                                        +23
                                                        +24
                                                        +25
                                                        data = data_layer(name="word", size=dict_dim)
                                                        +
                                                        +emb = embedding_layer(input=data, size=word_dim)
                                                        +
                                                        +# (lstm_input + lstm) is equal to lstmemory 
                                                        +with mixed_layer(size=hidden_dim * 4) as lstm_input:
                                                        +    lstm_input += full_matrix_projection(input=emb)
                                                        +
                                                        +lstm = lstmemory_group(
                                                        +    input=lstm_input,
                                                        +    size=hidden_dim,
                                                        +    act=TanhActivation(),
                                                        +    gate_act=SigmoidActivation(),
                                                        +    state_act=TanhActivation())
                                                        +
                                                        +lstm_last = last_seq(input=lstm)
                                                        +
                                                        +with mixed_layer(
                                                        +        size=label_dim, act=SoftmaxActivation(), bias_attr=True) as output:
                                                        +    output += full_matrix_projection(input=lstm_last)
                                                        +
                                                        +outputs(
                                                        +    classification_cost(
                                                        +        input=output, label=data_layer(
                                                        +            name="label", size=1)))
                                                        +
                                                        +

                                                        其次,我们看一下语义相同的双层RNN的网络配置:

                                                        • PaddlePaddle中的许多layer并不在意输入是否是时间序列,例如embedding_layer。在这些layer中,所有的操作都是针对每一个时间步来进行的。
                                                        • @@ -256,6 +433,61 @@ var _hmt = _hmt || [];
                                                        • 与单层RNN的配置类似,我们只需要使用LSTM encode成的最后一个向量。所以对recurrent_group进行了last_seq操作。但和单层RNN不同,我们是对每一个子序列取最后一个元素,因此agg_level=AggregateLevel.TO_SEQUENCE
                                                        • 至此,lstm_last便和单层RNN配置中的lstm_last具有相同的结果了。
                                                        +
                                                         1
                                                        + 2
                                                        + 3
                                                        + 4
                                                        + 5
                                                        + 6
                                                        + 7
                                                        + 8
                                                        + 9
                                                        +10
                                                        +11
                                                        +12
                                                        +13
                                                        +14
                                                        +15
                                                        +16
                                                        +17
                                                        +18
                                                        +19
                                                        +20
                                                        +21
                                                        +22
                                                        +23
                                                        +24
                                                        +25
                                                        +26
                                                        +27
                                                        data = data_layer(name="word", size=dict_dim)
                                                        +
                                                        +emb_group = embedding_layer(input=data, size=word_dim)
                                                        +
                                                        +
                                                        +# (lstm_input + lstm) is equal to lstmemory 
                                                        +def lstm_group(lstm_group_input):
                                                        +    with mixed_layer(size=hidden_dim * 4) as group_input:
                                                        +        group_input += full_matrix_projection(input=lstm_group_input)
                                                        +
                                                        +    lstm_output = lstmemory_group(
                                                        +        input=group_input,
                                                        +        name="lstm_group",
                                                        +        size=hidden_dim,
                                                        +        act=TanhActivation(),
                                                        +        gate_act=SigmoidActivation(),
                                                        +        state_act=TanhActivation())
                                                        +    return lstm_output
                                                        +
                                                        +
                                                        +lstm_nest_group = recurrent_group(
                                                        +    input=SubsequenceInput(emb_group), step=lstm_group, name="lstm_nest_group")
                                                        +# hasSubseq ->(seqlastins) seq
                                                        +lstm_last = last_seq(
                                                        +    input=lstm_nest_group, agg_level=AggregateLevel.TO_SEQUENCE)
                                                        +
                                                        +# seq ->(expand) hasSubseq
                                                        +
                                                        +
                                                        @@ -271,6 +503,21 @@ var _hmt = _hmt || [];
                                                        • 单层RNN:过了一个很简单的recurrent_group。每一个时间步,当前的输入y和上一个时间步的输出rnn_state做了一个全链接。
                                                        +
                                                        def step(y):
                                                        +    mem = memory(name="rnn_state", size=hidden_dim)
                                                        +    out = fc_layer(input=[y, mem],
                                                        +                    size=hidden_dim,
                                                        +                    act=TanhActivation(),
                                                        +                    bias_attr=True,
                                                        +                    name="rnn_state")
                                                        +    return out
                                                        +
                                                        +out = recurrent_group(
                                                        +    name="rnn",
                                                        +    step=step,
                                                        +    input=emb)
                                                        +
                                                        +
                                                        • 双层RNN,外层memory是一个元素:
                                                          • 内层inner_step的recurrent_group和单层序列的几乎一样。除了boot_layer=outer_mem,表示将外层的outer_mem作为内层memory的初始状态。外层outer_step中,outer_mem是一个子句的最后一个向量,即整个双层group是将前一个子句的最后一个向量,作为下一个子句memory的初始状态。
                                                          • @@ -278,6 +525,36 @@ var _hmt = _hmt || [];
                                                        +
                                                        def outer_step(x):
                                                        +    outer_mem = memory(name="outer_rnn_state", size=hidden_dim)
                                                        +    def inner_step(y):
                                                        +        inner_mem = memory(name="inner_rnn_state",
                                                        +                           size=hidden_dim,
                                                        +                           boot_layer=outer_mem)
                                                        +        out = fc_layer(input=[y, inner_mem],
                                                        +                        size=hidden_dim,
                                                        +                        act=TanhActivation(),
                                                        +                        bias_attr=True,
                                                        +                        name="inner_rnn_state")
                                                        +        return out
                                                        +
                                                        +    inner_rnn_output = recurrent_group(
                                                        +        step=inner_step,
                                                        +        name="inner",
                                                        +        input=x)
                                                        +    last = last_seq(input=inner_rnn_output, name="outer_rnn_state")
                                                        +
                                                        +    # "return last" won't work, because recurrent_group only support the input 
                                                        +    # sequence type is same as return sequence type.
                                                        +    return inner_rnn_output
                                                        +
                                                        +out = recurrent_group(
                                                        +    name="outer",
                                                        +    step=outer_step,
                                                        +    input=SubsequenceInput(emb))
                                                        +
                                                        +
                                                        +

                                                        警告

                                                        PaddlePaddle目前只支持在每个时间步中,Memory的时间序列长度一致的情况。

                                                        @@ -300,9 +577,127 @@ var _hmt = _hmt || [];
                                                        • 单层RNN:
                                                        +
                                                         1
                                                        + 2
                                                        + 3
                                                        + 4
                                                        + 5
                                                        + 6
                                                        + 7
                                                        + 8
                                                        + 9
                                                        +10
                                                        +11
                                                        +12
                                                        +13
                                                        +14
                                                        +15
                                                        +16
                                                        +17
                                                        +18
                                                            def calrnn(y):
                                                        +        mem = memory(name='rnn_state_' + y.name, size=hidden_dim)
                                                        +        out = fc_layer(
                                                        +            input=[y, mem],
                                                        +            size=hidden_dim,
                                                        +            act=TanhActivation(),
                                                        +            bias_attr=True,
                                                        +            name='rnn_state_' + y.name)
                                                        +        return out
                                                        +
                                                        +    encoder1 = calrnn(x1)
                                                        +    encoder2 = calrnn(x2)
                                                        +    return [encoder1, encoder2]
                                                        +
                                                        +
                                                        +encoder1_rep, encoder2_rep = recurrent_group(
                                                        +    name="stepout", step=step, input=[emb1, emb2])
                                                        +
                                                        +
                                                        +
                                                        • 双层RNN:
                                                        +
                                                         1
                                                        + 2
                                                        + 3
                                                        + 4
                                                        + 5
                                                        + 6
                                                        + 7
                                                        + 8
                                                        + 9
                                                        +10
                                                        +11
                                                        +12
                                                        +13
                                                        +14
                                                        +15
                                                        +16
                                                        +17
                                                        +18
                                                        +19
                                                        +20
                                                        +21
                                                        +22
                                                        +23
                                                        +24
                                                        +25
                                                        +26
                                                        +27
                                                        +28
                                                        +29
                                                        +30
                                                        +31
                                                        +32
                                                        +33
                                                        +34
                                                        +35
                                                        +36
                                                        +37
                                                        +38
                                                        +39
                                                        +40
                                                        
                                                        +    def inner_step(ipt):
                                                        +        index[0] += 1
                                                        +        i = index[0]
                                                        +        outer_mem = memory(name="outer_rnn_state_%d" % i, size=hidden_dim)
                                                        +
                                                        +        def inner_step_impl(y):
                                                        +            inner_mem = memory(
                                                        +                name="inner_rnn_state_" + y.name,
                                                        +                size=hidden_dim,
                                                        +                boot_layer=outer_mem)
                                                        +            out = fc_layer(
                                                        +                input=[y, inner_mem],
                                                        +                size=hidden_dim,
                                                        +                act=TanhActivation(),
                                                        +                bias_attr=True,
                                                        +                name='inner_rnn_state_' + y.name)
                                                        +            return out
                                                        +
                                                        +        encoder = recurrent_group(
                                                        +            step=inner_step_impl, name='inner_%d' % i, input=ipt)
                                                        +        last = last_seq(name="outer_rnn_state_%d" % i, input=encoder)
                                                        +        return encoder, last
                                                        +
                                                        +    encoder1, sentence_last_state1 = inner_step(ipt=x1)
                                                        +    encoder2, sentence_last_state2 = inner_step(ipt=x2)
                                                        +
                                                        +    encoder1_expand = expand_layer(
                                                        +        input=sentence_last_state1, expand_as=encoder2)
                                                        +
                                                        +    return [encoder1_expand, encoder2]
                                                        +
                                                        +
                                                        +encoder1_rep, encoder2_rep = recurrent_group(
                                                        +    name="outer",
                                                        +    step=outer_step,
                                                        +    input=[SubsequenceInput(emb1), SubsequenceInput(emb2)],
                                                        +    targetInlink=emb2)
                                                        +
                                                        +encoder1_last = last_seq(input=encoder1_rep)
                                                        +
                                                        +

                                                        在上面代码中,单层和双层序列的使用和示例2中的示例类似,区别是同时处理了两个输入。而对于双层序列,两个输入的子序列长度也并不相同。但是,我们使用了targetInlink参数设置了外层recurrent_group的输出格式。所以外层输出的序列形状,和emb2的序列形状一致。

                                                        diff --git a/develop/doc_cn/howto/rnn/index_cn.html b/develop/doc_cn/howto/rnn/index_cn.html index b124a6a09b2..e373cd28ec5 100644 --- a/develop/doc_cn/howto/rnn/index_cn.html +++ b/develop/doc_cn/howto/rnn/index_cn.html @@ -144,6 +144,7 @@ var _hmt = _hmt || [];
                                                      • 开发标准
                                                      • FAQ
                                                          diff --git a/develop/doc_cn/howto/rnn/recurrent_group_cn.html b/develop/doc_cn/howto/rnn/recurrent_group_cn.html index f36a19826cf..369a74a3d62 100644 --- a/develop/doc_cn/howto/rnn/recurrent_group_cn.html +++ b/develop/doc_cn/howto/rnn/recurrent_group_cn.html @@ -144,6 +144,7 @@ var _hmt = _hmt || [];
                                                        • 开发标准
                                                        • FAQ
                                                            diff --git a/develop/doc_cn/howto/rnn/rnn_config_cn.html b/develop/doc_cn/howto/rnn/rnn_config_cn.html index 3e1893b0823..d321025d3db 100644 --- a/develop/doc_cn/howto/rnn/rnn_config_cn.html +++ b/develop/doc_cn/howto/rnn/rnn_config_cn.html @@ -144,6 +144,7 @@ var _hmt = _hmt || [];
                                                          • 开发标准
                                                          • FAQ
                                                              diff --git a/develop/doc_cn/index_cn.html b/develop/doc_cn/index_cn.html index ac742b05291..312d46458d7 100644 --- a/develop/doc_cn/index_cn.html +++ b/develop/doc_cn/index_cn.html @@ -142,6 +142,7 @@ var _hmt = _hmt || [];
                                                            • 开发标准
                                                            • FAQ
                                                                diff --git a/develop/doc_cn/mobile/cross_compiling_for_android_cn.html b/develop/doc_cn/mobile/cross_compiling_for_android_cn.html deleted file mode 100644 index ba4ee95e9e9..00000000000 --- a/develop/doc_cn/mobile/cross_compiling_for_android_cn.html +++ /dev/null @@ -1,442 +0,0 @@ - - - - - - - - - - - - - Android平台编译指南 — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                                - - - - -
                                                                - - - - - - -
                                                                -
                                                                - - - - - - -
                                                                - -
                                                                -
                                                                -
                                                                -
                                                                - -
                                                                -

                                                                Android平台编译指南

                                                                -

                                                                用户可通过如下两种方式,交叉编译Android平台上适用的PaddlePaddle库:

                                                                - -
                                                                -

                                                                基于Docker容器的编译方式

                                                                -

                                                                Docker能在所有主要操作系统(包括Linux,Mac OS X和Windows)上运行,因此,使用基于Docker容器的编译方式,用户可在自己熟悉的开发平台上编译Android平台上适用的PaddlePaddle库。

                                                                -
                                                                -

                                                                构建PaddlePaddle的Android开发镜像

                                                                -

                                                                我们把PaddlePaddle的交叉编译环境打包成一个镜像,称为开发镜像,里面涵盖了交叉编译Android版PaddlePaddle库需要的所有编译工具。

                                                                -
                                                                $ git clone https://github.com/PaddlePaddle/Paddle.git
                                                                -$ cd Paddle
                                                                -$ docker build -t username/paddle-android:dev . -f Dockerfile.android
                                                                -
                                                                -
                                                                -

                                                                用户也可以使用PaddlePaddle提供的官方开发镜像:

                                                                -
                                                                $ docker pull paddlepaddle/paddle:latest-dev-android
                                                                -
                                                                -
                                                                -

                                                                对于国内用户,我们提供了加速访问的镜像源:

                                                                -
                                                                $ docker pull docker.paddlepaddlehub.com/paddle:latest-dev-android
                                                                -
                                                                -
                                                                -
                                                                -
                                                                -

                                                                编译PaddlePaddle C-API库

                                                                -

                                                                构建好开发镜像后,即可使用开发镜像来编译Android版PaddlePaddle C-API库。 -Android的Docker开发镜像向用户提供两个可配置的参数:

                                                                - -- - - - - - - - - - - - - - - - - - - - - - - -
                                                                ArgumentOptional ValuesDefault
                                                                ANDROID_ABIarmeabi-v7a, arm64-v8aarmeabi-v7a
                                                                ANDROID_API>= 1621
                                                                  -
                                                                • 编译armeabi-v7aAndroid API 21的PaddlePaddle库
                                                                • -
                                                                -
                                                                $ docker run -it --rm -v $PWD:/paddle -e "ANDROID_ABI=armeabi-v7a" -e "ANDROID_API=21" username/paddle-android:dev
                                                                -
                                                                -
                                                                -
                                                                  -
                                                                • 编译arm64-v8aAndroid API 21的PaddlePaddle库
                                                                • -
                                                                -
                                                                $ docker run -it --rm -v $PWD:/paddle -e "ANDROID_ABI=arm64-v8a" -e "ANDROID_API=21" username/paddle-android:dev
                                                                -
                                                                -
                                                                -

                                                                执行上述docker run命令时,容器默认执行paddle/scripts/docker/build_android.sh脚本。该脚本中记录了交叉编译Android版PaddlePaddle库常用的CMake配置,并且会根据ANDROID_ABIANDROID_API自动构建独立工具链、进行编译和安装。由于arm64架构要求Android API不小于21。因此当ANDROID_ABI=arm64-v8aANDROID_API<21时,Docker容器中将默认使用Android API 21的编译工具链。用户可以参考下文配置交叉编译参数章节,根据个人的需求修改定制Docker容器所执行的脚本。编译安装结束之后,PaddlePaddle的C-API库将被安装到$PWD/install_android目录,所依赖的第三方库同时也被安装到$PWD/install_android/third_party目录。

                                                                -
                                                                -
                                                                -
                                                                -

                                                                基于Linux交叉编译环境的编译方式

                                                                -

                                                                本文档将以Linux x86-64平台为例,介绍交叉编译Android平台上适用的PaddlePaddle库的方法和步骤。

                                                                -
                                                                -

                                                                准备交叉编译环境

                                                                -

                                                                从源码交叉编译PaddlePaddle,用户需要提前准备好交叉编译环境。Android平台上使用的C/C++交叉编译工具链为Android NDK,用户可自行前往下载预编译好的版本,也可通过以下命令获取:

                                                                -
                                                                wget -q https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip
                                                                -unzip -q android-ndk-r14b-linux-x86_64.zip
                                                                -
                                                                -
                                                                -

                                                                Android NDK中包含了所有Android API级别、所有架构(arm/arm64/x86/mips)需要用到的编译工具和系统库。用户可根据自己的编译目标架构、所需支持的最低Android API级别,构建独立工具链

                                                                -
                                                                  -
                                                                • 构建armeabi-v7aAndroid API 21的独立工具链:
                                                                • -
                                                                -
                                                                your/path/to/android-ndk-r14b-linux-x86_64/build/tools/make-standalone-toolchain.sh \
                                                                -        --arch=arm --platform=android-21 --install-dir=your/path/to/arm_standalone_toolchain
                                                                -
                                                                -
                                                                -

                                                                此命令将在your/path/to/arm_standalone_toolchain目录生成一套独立编译工具链,面向架构为32位ARM架构,支持的最小的Android API级别为21,支持编译器arm-linux-androideabi-gcc (GCC) 4.9clang 3.8

                                                                -
                                                                  -
                                                                • 构建arm64-v8aAndroid API 21的独立工具链:
                                                                • -
                                                                -
                                                                your/path/to/android-ndk-r14b-linux-x86_64/build/tools/make-standalone-toolchain.sh \
                                                                -        --arch=arm64 --platform=android-21 --install-dir=your/path/to/arm64_standalone_toolchain
                                                                -
                                                                -
                                                                -

                                                                此命令将在your/path/to/arm64_standalone_toolchain目录生成一套独立编译工具链,面向架构为64位ARM64架构,支持的最小Android API级别为21,支持编译器arm-linux-androideabi-gcc (GCC) 4.9clang 3.8

                                                                -
                                                                -
                                                                -

                                                                配置交叉编译参数

                                                                -

                                                                CMake系统对交叉编译提供了支持cmake-toolchains。为了简化cmake配置,PaddlePaddle为交叉编译提供了工具链配置文档cmake/cross_compiling/android.cmake,以提供一些默认的编译器和编译参数相关配置。注意,从CMake 3.7版本开始,CMake官方对Android平台的交叉编译提供了通用的支持。PaddlePaddle若检测到用户使用的CMake版本不低于3.7时,将会将用户传进来的配置参数传递CMake系统,交由CMake系统本身来处理。有关参数配置的详细说明见cmake-toolchains

                                                                -

                                                                交叉编译Android版本的PaddlePaddle库时,有一些必须配置的参数:

                                                                -
                                                                  -
                                                                • CMAKE_SYSTEM_NAME,CMake编译的目标平台,必须设置为Android。在设置CMAKE_SYSTEM_NAME=Android后,PaddlePaddle的CMake系统才认为是在交叉编译Android系统的版本,并自动编译PaddlePaddle所需的所有第三方库。此外,还会强制设置一些PaddlePaddle参数的值(WITH_GPU=OFFWITH_AVX=OFFWITH_PYTHON=OFFWITH_RDMA=OFFWITH_MKL=OFFWITH_GOLANG=OFF)。
                                                                • -
                                                                • WITH_C_API,必须设置为ON。在Android平台上只支持使用C-API来预测。
                                                                • -
                                                                • WITH_SWIG_PY,必须设置为OFF。在Android平台上不支持通过swig调用来训练或者预测。
                                                                • -
                                                                -

                                                                Android平台可选配置参数:

                                                                -
                                                                  -
                                                                • ANDROID_STANDALONE_TOOLCHAIN,独立工具链所在的绝对路径,或者相对于构建目录的相对路径。PaddlePaddle的CMake系统将根据该值自动推导和设置需要使用的交叉编译器、sysroot、以及Android API级别;否则,用户需要在cmake时手动设置这些值。无默认值。
                                                                • -
                                                                • ANDROID_TOOLCHAIN,目标工具链。可设置gcc/clang,默认值为clang
                                                                    -
                                                                  • CMake 3.7以上,将会始终使用clang工具链;CMake 3.7以下,可设置ANDROID_TOOLCHAIN=gcc以使用gcc工具链。
                                                                  • -
                                                                  • Android官方提供的clang编译器要求系统支持GLIBC 2.15以上。
                                                                  • -
                                                                  -
                                                                • -
                                                                • ANDROID_ABI,目标架构ABI。目前支持armeabi-v7aarm64-v8a,默认值为armeabi-v7a
                                                                • -
                                                                • ANDROID_NATIVE_API_LEVEL,工具链的Android API级别。若没有显式设置,PaddlePaddle将根据ANDROID_STANDALONE_TOOLCHAIN的值自动推导得到。
                                                                • -
                                                                • ANROID_ARM_MODE,是否使用ARM模式。
                                                                    -
                                                                  • ANDROID_ABI=armeabi-v7a时,可设置ON/OFF,默认值为ON
                                                                  • -
                                                                  • ANDROID_ABI=arm64-v8a时,不需要设置。
                                                                  • -
                                                                  -
                                                                • -
                                                                • ANDROID_ARM_NEON,是否使用NEON指令。
                                                                    -
                                                                  • ANDROID_ABI=armeabi-v7a时,可设置ON/OFF,默认值为ON
                                                                  • -
                                                                  • ANDROID_ABI=arm64-v8a时,不需要设置。
                                                                  • -
                                                                  -
                                                                • -
                                                                -

                                                                其他配置参数:

                                                                -
                                                                  -
                                                                • USE_EIGEN_FOR_BLAS,是否使用Eigen库进行矩阵计算。可设置ON/OFF,默认值为OFF
                                                                • -
                                                                • HOST_C/CXX_COMPILER,宿主机的C/C++编译器。在编译宿主机版protoc可执行文件和目标机版OpenBLAS库时需要用到。默认设置成环境变量CC/CXX的值;若环境变量CC/CXX没有设置,则设置成cc/c++编译器。
                                                                • -
                                                                -

                                                                常用的cmake配置如下:

                                                                -
                                                                cmake -DCMAKE_SYSTEM_NAME=Android \
                                                                -      -DANDROID_STANDALONE_TOOLCHAIN=your/path/to/arm_standalone_toolchain \
                                                                -      -DANDROID_ABI=armeabi-v7a \
                                                                -      -DANDROID_ARM_NEON=ON \
                                                                -      -DANDROID_ARM_MODE=ON \
                                                                -      -DUSE_EIGEN_FOR_BLAS=ON \
                                                                -      -DCMAKE_INSTALL_PREFIX=your/path/to/install \
                                                                -      -DWITH_C_API=ON \
                                                                -      -DWITH_SWIG_PY=OFF \
                                                                -      ..
                                                                -
                                                                -
                                                                -
                                                                cmake -DCMAKE_SYSTEM_NAME=Android \
                                                                -      -DANDROID_STANDALONE_TOOLCHAIN=your/path/to/arm64_standalone_toolchain \
                                                                -      -DANDROID_ABI=arm64-v8a \
                                                                -      -DUSE_EIGEN_FOR_BLAS=OFF \
                                                                -      -DCMAKE_INSTALL_PREFIX=your/path/to/install \
                                                                -      -DWITH_C_API=ON \
                                                                -      -DWITH_SWIG_PY=OFF \
                                                                -      ..
                                                                -
                                                                -
                                                                -

                                                                用户还可根据自己的需求设置其他编译参数。

                                                                -
                                                                  -
                                                                • 设置CMAKE_BUILD_TYPEMinSizeRel,最小化生成的库的大小。
                                                                • -
                                                                • 设置CMAKE_BUILD_TYPERelease,获得最快的执行速度,
                                                                • -
                                                                • 用户亦可以通过手动设置CMAKE_C/CXX_FLAGS来影响PaddlePaddle的编译过程。
                                                                • -
                                                                -

                                                                性能TIPS,为了达到最快的计算速度,在CMake参数配置上,有以下建议:

                                                                -
                                                                  -
                                                                • 设置CMAKE_BUILD_TYPERelease
                                                                • -
                                                                • 使用clang编译工具链
                                                                • -
                                                                • armeabi-v7a时,设置USE_EIGEN_BLAS=ON,使用Eigen进行矩阵计算;arm64-v8a时,设置USE_EIGEN_FOR_BLAS=OFF,使用OpenBLAS进行矩阵计算
                                                                • -
                                                                -
                                                                -
                                                                -

                                                                编译和安装

                                                                -

                                                                CMake配置完成后,执行以下命令,PaddlePaddle将自动下载和编译所有第三方依赖库、编译和安装PaddlePaddle预测库。

                                                                -
                                                                make
                                                                -make install
                                                                -
                                                                -
                                                                -

                                                                注意:如果你曾经在源码目录下编译过其他平台的PaddlePaddle库,请先使用rm -rf命令删除third_party目录和build目录,以确保所有的第三方依赖库和PaddlePaddle代码都是针对新的CMake配置重新编译的。

                                                                -

                                                                执行完安装命令后,your/path/to/install目录中会包含includelibthird_party目录,其中include中包含C-API的头文件,lib中包含若干个不同Android ABI的PaddlePaddle库,third_party中包含所依赖的所有第三方库。自此,PaddlePaddle的已经安装完成,用户可将your/path/to/install目录下的生成文件用于深度学习相关Android App中,调用方法见C-API文档。

                                                                -
                                                                -
                                                                -
                                                                - - -
                                                                -
                                                                -
                                                                - - -
                                                                - -
                                                                -

                                                                - © Copyright 2016, PaddlePaddle developers. - -

                                                                -
                                                                - Built with Sphinx using a theme provided by Read the Docs. - -
                                                                - -
                                                                -
                                                                - -
                                                                - -
                                                                - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/mobile/cross_compiling_for_ios_cn.html b/develop/doc_cn/mobile/cross_compiling_for_ios_cn.html deleted file mode 100644 index b3b1f32ae0b..00000000000 --- a/develop/doc_cn/mobile/cross_compiling_for_ios_cn.html +++ /dev/null @@ -1,377 +0,0 @@ - - - - - - - - - - - - - iOS平台编译指南 — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                                - - - - -
                                                                - - - - - - -
                                                                -
                                                                - - - - - - -
                                                                - -
                                                                -
                                                                -
                                                                -
                                                                - -
                                                                -

                                                                iOS平台编译指南

                                                                -

                                                                交叉编译iOS平台上适用的PaddlePaddle库,需要在MacOS系统上进行。本文的将介绍在MacOS上,从源码交叉编译iOS平台上适用的PaddlePaddle库。

                                                                -
                                                                -

                                                                准备交叉编译环境

                                                                -

                                                                Apple官方为iOS开发提供了完整的交叉编译工具和集成开发环境,用户从App Store下载安装Xcode即可。也可自行前往官网下载,Xcode。安装完成之后,可在命令行执行xcodebuild -version,判断是否安装成功。

                                                                -
                                                                $ xcodebuild -version
                                                                -Xcode 9.0
                                                                -Build version 9A235
                                                                -
                                                                -
                                                                -
                                                                -
                                                                -

                                                                配置交叉编译参数

                                                                -

                                                                PaddlePaddle为交叉编译提供了工具链配置文档cmake/cross_compiling/ios.cmake,以提供一些默认的编译器和编译参数配置。

                                                                -

                                                                交叉编译iOS版本的PaddlePaddle库时,有一些必须配置的参数:

                                                                -
                                                                  -
                                                                • CMAKE_SYSTEM_NAME,CMake编译的目标平台,必须设置为iOS。在设置CMAKE_SYSTEM_NAME=iOS后,PaddlePaddle的CMake系统会自动编译所有的第三方依赖库,并且强制设置一些PaddlePaddle参数的值(WITH_C_API=ONWITH_GPU=OFFWITH_AVX=OFFWITH_PYTHON=OFFWITH_RDMA=OFF)。
                                                                • -
                                                                • WITH_C_API,是否编译C-API预测库,必须设置为ON。在iOS平台上只支持使用C-API来预测。
                                                                • -
                                                                • WITH_SWIG_PY,必须设置为OFF。在iOS平台上不支持通过swig调用来训练或者预测。
                                                                • -
                                                                -

                                                                iOS平台可选配置参数:

                                                                -
                                                                  -
                                                                • IOS_PLATFORM,可设置为OS(默认值)或SIMULATOR

                                                                  -
                                                                    -
                                                                  • OS,构建目标为arm架构的iPhone或者iPad等物理设备。
                                                                  • -
                                                                  • SIMULATOR,构建目标为x86架构的模拟器平台。
                                                                  • -
                                                                  -
                                                                • -
                                                                • IOS_ARCH,目标架构。针对不同的IOS_PLATFORM,可设置的目标架构如下表所示,默认编译所有架构:

                                                                  - - - - - - - - - - - - - - - - - - - - - -
                                                                  IOS_PLATFORMIOS_ARCH
                                                                  OSarmv7, armv7s, arm64
                                                                  SIMULATORi386, x86_64
                                                                • -
                                                                • IOS_DEPLOYMENT_TARGET,最小的iOS部署版本,默认值为7.0

                                                                  -
                                                                • -
                                                                • IOS_ENABLE_BITCODE,是否使能Bitcode,可设置ON/OFF,默认值为ON

                                                                  -
                                                                • -
                                                                • IOS_USE_VECLIB_FOR_BLAS,是否使用vecLib框架进行BLAS矩阵计算,可设置ON/OFF,默认值为OFF

                                                                  -
                                                                • -
                                                                • IOS_DEVELOPMENT_ROOTDeveloper目录,可显式指定为/path/to/platform/Developer。若未显式指定,PaddlePaddle将会根据IOS_PLATFORM自动选择Xcode对应platformDeveloper目录。

                                                                  -
                                                                • -
                                                                • IOS_SDK_ROOT,所使用SDK的根目录,可显式指定为/path/to/platform/Developer/SDKs/SDK。若未显式指定,PaddlePaddle将会自动选择IOS_DEVELOPMENT_ROOT目录下最新的SDK版本。

                                                                  -
                                                                • -
                                                                -

                                                                其他配置参数:

                                                                -
                                                                  -
                                                                • USE_EIGEN_FOR_BLAS,是否使用Eigen库进行矩阵计算,在IOS_USE_VECLIB_FOR_BLAS=OFF时有效。可设置ON/OFF,默认值为OFF
                                                                • -
                                                                • HOST_C/CXX_COMPILER,宿主机的C/C++编译器。默认值为环境变量CC/CXX的值;若环境变量CC/CXX未设置,则使用cc/c++编译器。
                                                                • -
                                                                -

                                                                常用的cmake配置如下:

                                                                -
                                                                cmake -DCMAKE_SYSTEM_NAME=iOS \
                                                                -      -DIOS_PLATFORM=OS \
                                                                -      -DIOS_ARCH="armv7;arm64" \
                                                                -      -DIOS_ENABLE_BITCODE=ON \
                                                                -      -DIOS_USE_VECLIB_FOR_BLAS=ON \
                                                                -      -DCMAKE_INSTALL_PREFIX=your/path/to/install \
                                                                -      -DWITH_C_API=ON \
                                                                -      -DWITH_TESTING=OFF \
                                                                -      -DWITH_SWIG_PY=OFF \
                                                                -      ..
                                                                -
                                                                -
                                                                -
                                                                cmake -DCMAKE_SYSTEM_NAME=iOS \
                                                                -      -DIOS_PLATFORM=SIMULATOR \
                                                                -      -DIOS_ARCH="x86_64" \
                                                                -      -DIOS_USE_VECLIB_FOR_BLAS=ON \
                                                                -      -DCMAKE_INSTALL_PREFIX=your/path/to/install \
                                                                -      -DWITH_C_API=ON \
                                                                -      -DWITH_TESTING=OFF \
                                                                -      -DWITH_SWIG_PY=OFF \
                                                                -      ..
                                                                -
                                                                -
                                                                -

                                                                用户还可根据自己的需求设置其他编译参数。比如希望最小化生成库的大小,可以设置CMAKE_BUILD_TYPEMinSizeRel;若希望得到最快的执行速度,则可设置CMAKE_BUILD_TYPERelease。亦可以通过手动设置CMAKE_C/CXX_FLAGS来影响PaddlePaddle的编译过程。

                                                                -

                                                                性能TIPS,为了达到最快的计算速度,在CMake参数配置上,有以下建议:

                                                                -
                                                                  -
                                                                • 设置CMAKE_BUILD_TYPERelease
                                                                • -
                                                                • 设置IOS_USE_VECLIB_FOR_BLAS=ON,调用vecLib框架提供的BLAS函数进行矩阵计算。
                                                                • -
                                                                -
                                                                -
                                                                -

                                                                编译和安装

                                                                -

                                                                CMake配置完成后,执行以下命令,PaddlePaddle将自动下载和编译所有第三方依赖库、编译和安装PaddlePaddle预测库。

                                                                -
                                                                $ make
                                                                -$ make install
                                                                -
                                                                -
                                                                -

                                                                注意:如果你曾在源码目录下编译过其他平台的PaddlePaddle库,请先使用rm -rf命令删除third_party目录和build目录,以确保所有的第三方依赖库和PaddlePaddle代码都是针对新的CMake配置重新编译的。

                                                                -

                                                                执行完安装命令后,your/path/to/install目录中会包含以下内容:

                                                                -
                                                                  -
                                                                • include目录,其中包含所有C-API的头文件
                                                                • -
                                                                • lib目录,其中包含PaddlePaddle的C-API静态库
                                                                • -
                                                                • third_party目录,其中包含所依赖的所有第三方库
                                                                • -
                                                                -

                                                                注意,如果PaddlePaddle库需要同时支持真机和模拟器,则需要分别编译真机和模拟器版本,然后使用lipo工具合并fat库。

                                                                -

                                                                自此,PaddlePaddle库已经安装完成,用户可将合成的fat库用于深度学习相关的iOS App中,调用方法见C-API文档。

                                                                -
                                                                -
                                                                - - -
                                                                -
                                                                -
                                                                - - -
                                                                - -
                                                                -

                                                                - © Copyright 2016, PaddlePaddle developers. - -

                                                                -
                                                                - Built with Sphinx using a theme provided by Read the Docs. - -
                                                                - -
                                                                -
                                                                - -
                                                                - -
                                                                - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/mobile/cross_compiling_for_raspberry_cn.html b/develop/doc_cn/mobile/cross_compiling_for_raspberry_cn.html deleted file mode 100644 index 140699b5519..00000000000 --- a/develop/doc_cn/mobile/cross_compiling_for_raspberry_cn.html +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - - - - - - Raspberry Pi平台编译指南 — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                                - - - - -
                                                                - - - - - - -
                                                                -
                                                                - - - - - - -
                                                                - -
                                                                -
                                                                -
                                                                -
                                                                - -
                                                                -

                                                                Raspberry Pi平台编译指南

                                                                -

                                                                通常有两个方法来构建基于 Rasspberry Pi 的版本:

                                                                -
                                                                  -
                                                                1. 通过ssh等方式登录到Raspberry Pi系统上来构建。所需的开发工具和第三方库可以参考 /Dockerfile
                                                                2. -
                                                                3. 另一个方法是交叉编译。这篇文档介绍在 Linux/x64 上交叉编译Raspberry Pi平台上适用的PaddlePaddle的方法和步骤。
                                                                4. -
                                                                -
                                                                -

                                                                安装交叉编译器

                                                                -

                                                                克隆下面 Github repo

                                                                -
                                                                git clone https://github.com/raspberrypi/tools.git
                                                                -
                                                                -
                                                                -

                                                                即可在 ./tools/tree/master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64 目录里找到交叉编译器 arm-linux-gnueabihf-gcc 4.8.3。运行该编译工具链需要一台 Linux x64 机器上以及 2.14版本以上的 glibc。

                                                                -
                                                                -
                                                                -

                                                                配置交叉编译参数

                                                                -

                                                                CMake支持交叉编译。PaddlePaddle for Raspberry Pi的配置信息在cmake/cross_compiling/raspberry_pi.cmake

                                                                -

                                                                交叉编译Raspberry Pi版本PaddlePaddle库时,有一些必须配置的参数:

                                                                -
                                                                  -
                                                                • CMAKE_SYSTEM_NAME:CMake编译的目标平台,必须配置为RPi。在设置CMAKE_SYSTEM_NAME=RPi后,PaddlePaddle的CMake系统才认为在是在交叉编译Raspberry Pi系统的版本,并自动编译宿主机版protoc可执行文件、目标机版protobuf库、以及目标机版OpenBLAS库。
                                                                • -
                                                                • RPI_TOOLCHAIN:编译工具链所在的绝对路径,或者相对于构建目录的相对路径。PaddlePaddle的CMake系统将根据该值自动设置需要使用的交叉编译器;否则,用户需要在cmake时手动设置这些值。无默认值。
                                                                • -
                                                                • RPI_ARM_NEON:是否使用NEON指令。目前必须设置成ON,默认值为ON
                                                                • -
                                                                • HOST_C/CXX_COMPILER,宿主机的C/C++编译器。在编译宿主机版protoc可执行文件和目标机版OpenBLAS库时需要用到。默认设置成环境变量CC的值;若环境变量CC没有设置,则设置成cc编译器。
                                                                • -
                                                                -

                                                                一个常用的CMake配置如下:

                                                                -
                                                                cmake -DCMAKE_SYSTEM_NAME=RPi \
                                                                -      -DRPI_TOOLCHAIN=your/path/to/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64 \
                                                                -      -DRPI_ARM_NEON=ON \
                                                                -      -DCMAKE_INSTALL_PREFIX=your/path/to/install \
                                                                -      -DWITH_GPU=OFF \
                                                                -      -DWITH_C_API=ON \
                                                                -      -DWITH_PYTHON=OFF \
                                                                -      -DWITH_SWIG_PY=OFF \
                                                                -      ..
                                                                -
                                                                -
                                                                -

                                                                其中WITH_C_API=ON表示需要构建推理库。

                                                                -

                                                                用户还可根据自己的需求设置其他编译参数。比如希望最小化生成的库的大小,可以设置CMAKE_BUILD_TYPEMinSizeRel;若希望最快的执行速度,则可设置CMAKE_BUILD_TYPERelease

                                                                -
                                                                -
                                                                -

                                                                编译和安装

                                                                -

                                                                CMake配置完成后,执行以下命令,PaddlePaddle将自动下载和编译所有第三方依赖库、编译和安装PaddlePaddle。

                                                                -
                                                                make
                                                                -make install
                                                                -
                                                                -
                                                                -

                                                                注意:如果你曾经在源码目录下编译过其他平台的PaddlePaddle库,请先使用rm -rf命令删除third_party目录和build目录,以确保所有的第三方依赖库和PaddlePaddle代码都是针对新的CMake配置重新编译的。

                                                                -

                                                                执行完安装命令后,your/path/to/install目录中会包含includelib目录,其中include中包含C-API的头文件,lib中包含一个Raspberry Pi版本的库。

                                                                -
                                                                -
                                                                - - -
                                                                -
                                                                -
                                                                - - -
                                                                - -
                                                                -

                                                                - © Copyright 2016, PaddlePaddle developers. - -

                                                                -
                                                                - Built with Sphinx using a theme provided by Read the Docs. - -
                                                                - -
                                                                -
                                                                - -
                                                                - -
                                                                - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/develop/doc_cn/objects.inv b/develop/doc_cn/objects.inv index 38801ebd29679cbfe21f2216798072176425a20d..5e8feb4e2833a4216fb1cc0a7c21cd313aeec694 100644 GIT binary patch delta 1738 zcmV;*1~vKL9I+0Ndw*C&T>~aDUp(FA7q2OGv7C}kJ*`# zw7emXU|kpKPcl_eHVUSMQP#4RFEwchX<6Y~cElL7jU0&Nl7D1HS^sRrE@%T1pb1n$ zpg)ihT4-dsM2bt~pQ*dIZ)XSZd{1g0-P)sOebK8gXNDYAQ$$HuL{+zJNz-y{WEdL- z(J~w?Q;N_c#gM5z{b__oWt;UC_h{97Iq4m*`?a+MHUJ$(xb@kSszaRfG)}!oyVt`> zQeE)3XZ_PvzkjlnK&a{p`lBaLONzlW$mZcnsvD+i_U%JlHtGP(Fe=Vqn6_%@R{T6% zVEqTe8KDIeJf0zq(tpQKm>a>wLQwh0sVp0rSLF#Y7`D6q(S2Xa$OT2zR2_-odM2G~ zDgmcdDj*x-__7bcoIte&rcKrw&H5|YRZ^UCOM8Cx#D8m4GxU_J8WI&`USXj)iV&i- ztyA;lnSZdJQPA%>+0bpQ4mmawZ3FC96s`SwbP?l+>CIHLQS$dI-cq$$--gQ(LMNTe z=r~tCo*>0F_vJj9p9|G=G$v}&INXU&)#zN5n^d2BD|_zxp7&(NYpi+oG6aVZZ49em zGeB4gaDTDMPG8*hdAG8i;WyNDG_BWmBwywMHY|h){>s0kxPB*GLG~AHX7@ZOmC1Cm z#fKgJYIGEUlz9wk9=>xIcHpQ*nf>ZJuRiVVE|Q}ttvF;DqgUn@LX=n>Tdk1?yHNwO z-++u;dJHB+`SYf8b$SXCWoPc+yz?vbIx{TY%YXG3OuI|6bHgsySy-hn)a8X*hBH?*@Mkr8PsA(tV51GEKMqmX!CB zmtJIy3Ubd;<Bm z3I-m(RI1m)5IDxI@ZUK!=v@t$0zk5Oj(=#Odk%sHzZ&crio5Y4*w}|KO73r*lh|qj zb*3Q~B{@T3B<{P{=L{?jzU=a-%C*n4XPI<{=Pw|cYvmyPrPtJbEOTw%O)hgPUQX^Ih-cPMgF43WebjGgKPY2SQ^5r+!Z`UAzDtbLFP#G zZR|?j+pT1I?qqqldALkgmlz-9QGdJ;>jp9Ug(XU3)&)qjCA0#Bt3IBQ9{H3=`>vw0qV=<7{t#f}vXwO4n7M7Vmk}c)#-Wa@o>qft3B&afbzS51Xt=by;x-V)QOR9cJ?x=1La(@#envR7P zch|*k6XZ$KN{wtyLvcr5orTL-h1`l$DcGs9(S#7vBmZ zN@9bchbYg4AJyEYNtW}lbgkJaHxG~46Az{Mk5oLQ?q;E%bmO%m% zE3P8?7|9OC^x@BA!!c8lI^{TKYdm|Cj`Qj~q6h9ltun0U)1jjxXMdLR0x-$HxL2_b z0dK;z3Vo>8;;C*Q#rXgq6{vEzLcK*ov+bU(w`2;YDrBGzPN*MEsBrkid1?G?gBOyt zjjAAckQAsX#(VK6G+hT^Oo$+`Ooc^Y-t(hc9c$P>I8|k9_er!|CVwsYJKJRLJ@1l6 z)Gy1_Qg81gV<@>)j6=d#;PPevr`e!9;lG)L3-32-Ugd4G{vktKPmqJymxrZ&rx1ZP gn_`E{LNp}BvDp|u3ae!}2SMc^c(#@KA0Q9Lz;#nvpa1{> delta 3590 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 MAR&hS50d1E3ROw;%m4rY diff --git a/develop/doc_cn/search.html b/develop/doc_cn/search.html index f14eb5e530b..04c7dcfb445 100644 --- a/develop/doc_cn/search.html +++ b/develop/doc_cn/search.html @@ -141,6 +141,7 @@ var _hmt = _hmt || [];
                                                              • 开发标准
                                                              • FAQ
                                                                  diff --git a/develop/doc_cn/searchindex.js b/develop/doc_cn/searchindex.js index db1564bd9bb..0ef8401c804 100644 --- a/develop/doc_cn/searchindex.js +++ b/develop/doc_cn/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["build_and_install/build_from_source_cn","build_and_install/docker_install_cn","build_and_install/index_cn","build_and_install/pip_install_cn","design/api","design/auto_gradient_check","design/backward","design/block","design/build_system/README","design/cluster_train/README","design/cluster_train/checkpointing","design/cluster_train/data_dispatch","design/cluster_train/large_model_dist_train","design/cluster_train/master_server","design/cluster_train/pserver_client","design/cluster_train/remote_parameter_updater","design/cluster_train/save_model","design/cluster_train/submit-job","design/concurrent_programming","design/cpp_data_feeding","design/csp","design/dist_refactor/distributed_architecture","design/dist_refactor/multi_cpu","design/dist_refactor/parameter_server","design/error_clip","design/evaluator","design/executor","design/file_manager/README","design/file_manager/pfs/pfsclient","design/float16","design/fluid","design/fluid_compiler","design/functions_operators_layers","design/gan_api","design/graph","design/graph_survey","design/if_else_op","design/infer_var_type","design/kernel_hint_design","design/kernel_selection","design/memory_optimization","design/mkl/mkl_packed","design/mkl/mkldnn","design/mkl/mkldnn_fluid","design/model_format","design/multi_language_interface/00.why_plain_c","design/multi_language_interface/01.inference_implementation","design/operator_kernel_type","design/ops/rnn","design/ops/sequence_decoder","design/optimizer","design/paddle_nccl","design/parallel_do","design/parameter_average","design/parameters_in_cpp","design/profiler","design/program","design/prune","design/python_api","design/reader/README","design/refactorization","design/register_grad_op","design/regularization","design/releasing_process","design/scope","design/selected_rows","design/simple_op_design","design/speech/deep_speech_2","design/support_new_device","design/switch","design/tensor_array","design/var_desc","dev/contribute_to_paddle_cn","dev/index_cn","dev/new_layer_cn","dev/new_op_cn","dev/use_eigen_cn","dev/write_docs_cn","faq/build_and_install/index_cn","faq/cluster/index_cn","faq/index_cn","faq/local/index_cn","faq/model/index_cn","faq/parameter/index_cn","getstarted/concepts/use_concepts_cn","getstarted/index_cn","getstarted/quickstart_cn","howto/capi/compile_paddle_lib_cn","howto/capi/index_cn","howto/capi/organization_of_the_inputs_cn","howto/capi/workflow_of_capi_cn","howto/cluster/cmd_argument_cn","howto/cluster/index_cn","howto/cluster/multi_cluster/fabric_cn","howto/cluster/multi_cluster/index_cn","howto/cluster/multi_cluster/k8s_aws_cn","howto/cluster/multi_cluster/k8s_cn","howto/cluster/multi_cluster/k8s_distributed_cn","howto/cluster/multi_cluster/openmpi_cn","howto/cluster/multi_cluster/src/k8s_data/README","howto/cluster/multi_cluster/src/k8s_train/README","howto/cluster/preparations_cn","howto/cmd_parameter/arguments_cn","howto/cmd_parameter/detail_introduction_cn","howto/cmd_parameter/index_cn","howto/cmd_parameter/use_case_cn","howto/index_cn","howto/optimization/cpu_profiling_cn","howto/optimization/gpu_profiling_cn","howto/read_source","howto/rnn/hierarchical_layer_cn","howto/rnn/hrnn_rnn_api_compare_cn","howto/rnn/index_cn","howto/rnn/recurrent_group_cn","howto/rnn/rnn_config_cn","index_cn","mobile/cross_compiling_for_android_cn","mobile/cross_compiling_for_ios_cn","mobile/cross_compiling_for_raspberry_cn","survey/cluster_bootstrapping_tools"],envversion:50,filenames:["build_and_install/build_from_source_cn.rst","build_and_install/docker_install_cn.rst","build_and_install/index_cn.rst","build_and_install/pip_install_cn.rst","design/api.md","design/auto_gradient_check.md","design/backward.md","design/block.md","design/build_system/README.md","design/cluster_train/README.md","design/cluster_train/checkpointing.md","design/cluster_train/data_dispatch.md","design/cluster_train/large_model_dist_train.md","design/cluster_train/master_server.md","design/cluster_train/pserver_client.md","design/cluster_train/remote_parameter_updater.md","design/cluster_train/save_model.md","design/cluster_train/submit-job.md","design/concurrent_programming.md","design/cpp_data_feeding.md","design/csp.md","design/dist_refactor/distributed_architecture.md","design/dist_refactor/multi_cpu.md","design/dist_refactor/parameter_server.md","design/error_clip.md","design/evaluator.md","design/executor.md","design/file_manager/README.md","design/file_manager/pfs/pfsclient.md","design/float16.md","design/fluid.md","design/fluid_compiler.md","design/functions_operators_layers.md","design/gan_api.md","design/graph.md","design/graph_survey.md","design/if_else_op.md","design/infer_var_type.md","design/kernel_hint_design.md","design/kernel_selection.md","design/memory_optimization.md","design/mkl/mkl_packed.md","design/mkl/mkldnn.md","design/mkl/mkldnn_fluid.md","design/model_format.md","design/multi_language_interface/00.why_plain_c.md","design/multi_language_interface/01.inference_implementation.md","design/operator_kernel_type.md","design/ops/rnn.md","design/ops/sequence_decoder.md","design/optimizer.md","design/paddle_nccl.md","design/parallel_do.md","design/parameter_average.md","design/parameters_in_cpp.md","design/profiler.md","design/program.md","design/prune.md","design/python_api.md","design/reader/README.md","design/refactorization.md","design/register_grad_op.md","design/regularization.md","design/releasing_process.md","design/scope.md","design/selected_rows.md","design/simple_op_design.md","design/speech/deep_speech_2.md","design/support_new_device.md","design/switch.md","design/tensor_array.md","design/var_desc.md","dev/contribute_to_paddle_cn.md","dev/index_cn.rst","dev/new_layer_cn.rst","dev/new_op_cn.md","dev/use_eigen_cn.md","dev/write_docs_cn.rst","faq/build_and_install/index_cn.rst","faq/cluster/index_cn.rst","faq/index_cn.rst","faq/local/index_cn.rst","faq/model/index_cn.rst","faq/parameter/index_cn.rst","getstarted/concepts/use_concepts_cn.rst","getstarted/index_cn.rst","getstarted/quickstart_cn.rst","howto/capi/compile_paddle_lib_cn.md","howto/capi/index_cn.rst","howto/capi/organization_of_the_inputs_cn.md","howto/capi/workflow_of_capi_cn.md","howto/cluster/cmd_argument_cn.md","howto/cluster/index_cn.rst","howto/cluster/multi_cluster/fabric_cn.md","howto/cluster/multi_cluster/index_cn.rst","howto/cluster/multi_cluster/k8s_aws_cn.md","howto/cluster/multi_cluster/k8s_cn.md","howto/cluster/multi_cluster/k8s_distributed_cn.md","howto/cluster/multi_cluster/openmpi_cn.md","howto/cluster/multi_cluster/src/k8s_data/README.md","howto/cluster/multi_cluster/src/k8s_train/README.md","howto/cluster/preparations_cn.md","howto/cmd_parameter/arguments_cn.md","howto/cmd_parameter/detail_introduction_cn.md","howto/cmd_parameter/index_cn.rst","howto/cmd_parameter/use_case_cn.md","howto/index_cn.rst","howto/optimization/cpu_profiling_cn.md","howto/optimization/gpu_profiling_cn.rst","howto/read_source.md","howto/rnn/hierarchical_layer_cn.rst","howto/rnn/hrnn_rnn_api_compare_cn.rst","howto/rnn/index_cn.rst","howto/rnn/recurrent_group_cn.md","howto/rnn/rnn_config_cn.rst","index_cn.rst","mobile/cross_compiling_for_android_cn.md","mobile/cross_compiling_for_ios_cn.md","mobile/cross_compiling_for_raspberry_cn.md","survey/cluster_bootstrapping_tools.md"],objects:{},objnames:{},objtypes:{},terms:{"00m":108,"01org":78,"03m":108,"0424m":108,"04\u4ee5\u4e0a":3,"04\u4ee5\u53camaco":86,"055ee37d":95,"0630u":108,"06u":108,"0810u":108,"0957m":108,"0\u53f7\u8bad\u7ec3\u8282\u70b9\u662f\u4e3b\u8bad\u7ec3\u8282\u70b9":103,"0\u5c42\u5e8f\u5217":110,"0_cudnn5":0,"0_cudnn5_avx_mkl":[1,3],"0_cudnn7_avx_mkl":3,"0rc1":63,"0rc2":63,"0x10f256d50":35,"0x7ffe4de00110":35,"100gi":95,"100m":81,"10g":17,"1150u":108,"11\u5b9e\u73b0\u4e86c":46,"11e6":96,"124n":108,"12\u4ee5\u4e0a":3,"12\u64cd\u4f5c\u7cfb\u7edf":78,"12gb":40,"13m":96,"1490u":108,"14\u7248\u672c\u4ee5\u4e0a\u7684":118,"14\u8fd9\u79cd\u5199\u6cd5\u5c06\u4f1a\u6d4b\u8bd5\u6a21\u578b":105,"1550u":108,"15\u884c":111,"16\u5b57\u8282\u8868\u793a\u4fdd\u5b58\u7684\u53c2\u6570\u603b\u4e2a\u6570":83,"16u":108,"173n":108,"1770u":108,"18ad":95,"18e457ce3d362ff5f3febf8e7f85ffec852f70f3b629add10aed84f930a68750":96,"197u":108,"1\u4e4b\u540e\u7684\u4efb\u4f55\u4e00\u4e2a\u7248\u672c\u6765\u7f16\u8bd1\u8fd0\u884c":0,"1\u7684\u5c42\u4e4b\u5916":105,"1\u7a00\u758f\u6570\u636e":74,"1\u8f6e\u5b58\u50a8\u7684\u6240\u6709\u6a21\u578b":105,"210u":108,"215n":108,"228u":108,"2520u":108,"2680u":108,"26\u884c":111,"279n":108,"27m":108,"285m":108,"2863m":108,"28m":108,"2977m":108,"2\u4e09\u7c7b\u7684\u6bd4\u4f8b\u4e3a":83,"2\u4e2a\u5b50\u5e8f\u5217":89,"2\u5206\u522b\u4ee3\u88683\u4e2a\u8282\u70b9\u7684trainer":97,"2\u610f\u5473\u77400\u53f7\u548c1\u53f7gpu\u5c06\u4f1a\u4f7f\u7528\u6570\u636e\u5e76\u884c\u6765\u8ba1\u7b97fc1\u548cfc2\u5c42":105,"2\u8fd9\u51e0\u4e2a\u76ee\u5f55\u8868\u793apaddlepaddle\u8282\u70b9\u4e0etrain":97,"2cbf7385":95,"302n":108,"30u":108,"328n":108,"32u":108,"331n":108,"3320u":108,"365e":95,"36u":108,"3710m":108,"3768m":108,"387u":108,"38u":108,"3920u":108,"39u":108,"3\u4ee5\u4e0a\u7684\u7b26\u53f7":3,"3\u53f7gpu":81,"4035m":108,"4090u":108,"4096mb":103,"4279m":108,"43u":108,"448a5b355b84":96,"4560u":108,"4563m":108,"45u":108,"4650u":108,"4726m":108,"473m":96,"4\u4e2a\u5e8f\u5217\u7684\u957f\u5ea6\u5206\u522b\u4e3a":89,"4\u5b57\u8282\u8868\u793apaddlepaddle\u7248\u672c\u4fe1\u606f":83,"4gb":103,"500m":81,"50bd":95,"50gi":95,"514u":108,"525n":108,"526u":108,"536u":108,"5460u":108,"5470u":108,"54u":108,"5690m":108,"573u":108,"578n":108,"5798m":108,"586u":108,"58s":96,"5969m":108,"5\u4f5c\u4e3a\u7f16\u8bd1\u73af\u5883":3,"5\u5373\u5c06\u505c\u6b62\u7ef4\u62a4":3,"5_cudnn5_avx_mkl":3,"5_cudnn5_avx_openbla":[3,86],"6080u":108,"6140u":108,"6305m":108,"639u":108,"64\u5e73\u53f0\u4e3a\u4f8b":116,"64m":44,"655u":108,"6780u":108,"6810u":108,"682u":108,"6970u":108,"6\u4e07\u4ebf\u6b21\u6d6e\u70b9\u8fd0\u7b97\u6bcf\u79d2":108,"6\u4ee5\u4e0a":[3,86],"6\u4f5c\u4e3a\u6807\u51c6\u7f16\u8bd1\u73af\u5883":3,"6ce9":95,"704u":108,"7090u":108,"72u":108,"73u":108,"75u":108,"760u":108,"767u":108,"783n":108,"784u":108,"78m":108,"7\u4ee5\u4e0a":116,"7\u4ee5\u4e0a\u7684\u7b26\u53f7":3,"7\u4ee5\u4e0b":116,"7\u548cpip":78,"7\u7248\u672c\u5f00\u59cb":116,"7\u7cfb\u5217":3,"7kb":96,"8000\u5c31\u53ef\u4ee5\u5728\u7f51\u9875\u4e0a\u751f\u6210\u9700\u8981\u7684\u6587\u6863":77,"8250u":108,"8300u":108,"830n":108,"849m":108,"861u":108,"8661m":108,"892m":108,"8\u5b57\u8282\u8868\u793a\u6bcf\u4e2a\u53c2\u6570\u5360\u7528\u7684\u5b57\u8282\u6570":83,"901n":108,"90u":108,"918u":108,"9247m":108,"924n":108,"9261m":108,"9330m":108,"94u":108,"9530m":108,"983m":108,"988u":108,"997u":108,"99u":108,"9a235":117,"9f18":96,"\u4e00\u4e2a":89,"\u4e00\u4e2a0\u5c42\u5e8f\u5217":110,"\u4e00\u4e2a0\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u6269\u5c55\u6210\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":110,"\u4e00\u4e2a\u4e0d\u5171\u4eab\u7684\u4f8b\u5b50\u662f":75,"\u4e00\u4e2a\u5178\u578b\u7684chunk\u5982\u4e0b\u6240\u793a":27,"\u4e00\u4e2a\u5206\u5e03\u5f0fpaddlepaddle\u8bad\u7ec3\u4efb\u52a1\u4e2d":96,"\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":110,"\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217\u6216\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":110,"\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u6269\u5c55\u6210\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":110,"\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217\u8fdb\u5165":113,"\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":110,"\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217\u6216\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":110,"\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u53d8\u6210\u4e00\u4e2a0\u5c42\u5e8f\u5217":110,"\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u53d8\u6210\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":110,"\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217\u8fdb\u5165":113,"\u4e00\u4e2a\u53cc\u5c42rnn\u7531\u591a\u4e2a\u5355\u5c42rnn\u7ec4\u6210":113,"\u4e00\u4e2a\u53ef\u8c03\u7528\u7684\u51fd\u6570":113,"\u4e00\u4e2a\u5e38\u7528\u7684cmake\u914d\u7f6e\u5982\u4e0b":118,"\u4e00\u4e2a\u6570\u636e\u96c6\u5927\u90e8\u5206\u5e8f\u5217\u957f\u5ea6\u662f100":81,"\u4e00\u4e2a\u662f\u6d6e\u70b9\u8ba1\u7b97\u91cf":108,"\u4e00\u4e2a\u72ec\u7acb\u7684\u5143\u7d20":110,"\u4e00\u4e2a\u72ec\u7acb\u7684\u8bcd\u8bed":110,"\u4e00\u4e2a\u795e\u7ecf\u7f51\u7edc\u7684\u6a21\u578b\u7531\u5927\u91cf\u7684\u53c2\u6570\u7ec4\u6210":10,"\u4e00\u4e2a\u7f51\u7edc\u5c42\u7684\u524d\u5411\u4f20\u64ad\u90e8\u5206\u628a\u8f93\u5165\u8f6c\u5316\u4e3a\u76f8\u5e94\u7684\u8f93\u51fa":74,"\u4e00\u4e2a\u7f51\u7edc\u5c42\u7684\u53c2\u6570\u662f\u5728":74,"\u4e00\u4e2a\u7f51\u7edc\u5c42\u7684c":74,"\u4e00\u4e2a\u8f93\u51fa\u6570\u636e\u540c\u6837\u88ab\u7ec4\u7ec7\u4e3a\u4e00\u4e2a":89,"\u4e00\u4e2a\u8f93\u51fa\u7ec4\u6210":75,"\u4e00\u4e2a\u91cd\u8981\u7684\u95ee\u9898\u662f\u9009\u62e9\u6b63\u786e\u7684learning_r":83,"\u4e00\u4e2achunk\u7531\u6240\u5728\u7684\u6587\u4ef6\u504f\u79fb":27,"\u4e00\u4e2agpu\u8bbe\u5907\u4e0a\u4e0d\u5141\u8bb8\u914d\u7f6e\u591a\u4e2a\u6a21\u578b":103,"\u4e00\u4e2agradientmachine\u7c7b\u7684\u5bf9\u8c61\u7ba1\u7406\u7740\u4e00\u7ec4\u8ba1\u7b97\u5c42":90,"\u4e00\u4e2alabel":111,"\u4e00\u4e2amemory\u5305\u542b":114,"\u4e00\u4e2aposix\u517c\u5bb9\u7684\u6587\u4ef6\u7cfb\u7edf":27,"\u4e00\u4e9b\u60c5\u51b5\u4e3a\u4e86\u4fbf\u4e8e\u53d1\u5e03":90,"\u4e00\u53e5\u8bdd\u662f\u7531\u8bcd\u8bed\u6784\u6210\u7684\u5e8f\u5217":113,"\u4e00\u53f0\u7535\u8111":0,"\u4e00\u662fbatch":81,"\u4e00\u6837\u7684\u65b9\u5f0f":0,"\u4e00\u7ef4\u6570\u7ec4":[89,90],"\u4e00\u7ef4\u6574\u578b\u6570\u7ec4":89,"\u4e00\u81f4":[110,111],"\u4e00\u822c\u4e0d\u5141\u8bb8\u518d\u4ece":63,"\u4e00\u822c\u4ece":72,"\u4e00\u822c\u5728paddlepaddle\u4e2d":111,"\u4e00\u822c\u662f\u7531\u4e8e\u76f4\u63a5\u4f20\u9012\u5927\u5b57\u5178\u5bfc\u81f4\u7684":83,"\u4e00\u822c\u6765\u8bf4":114,"\u4e00\u822c\u7531mkl":42,"\u4e00\u822c\u8868\u793a":111,"\u4e00\u822c\u8bbe\u7f6e":83,"\u4e00\u8282":90,"\u4e09\u79cd\u5e8f\u5217\u6a21\u5f0f":84,"\u4e0a":72,"\u4e0a\u4ea4\u53c9\u7f16\u8bd1raspberri":118,"\u4e0a\u4f20\u5230cloud\u6216\u8005\u4e0b\u8f7d\u5230\u672c\u5730\u7684\u65f6\u95f4\u53ef\u80fd\u6bd4\u8f83\u957f":27,"\u4e0a\u4f20\u65b9\u6cd5":63,"\u4e0a\u4f20\u8ba1\u7b97\u5f97\u51fa\u7684\u68af\u5ea6":92,"\u4e0a\u56fe\u4e2d\u7684":89,"\u4e0a\u56fe\u4e2d\u865a\u7ebf\u7684\u8fde\u63a5":111,"\u4e0a\u56fe\u63cf\u8ff0\u4e86\u4e00\u4e2a3\u8282\u70b9\u7684\u5206\u5e03\u5f0f\u8bad\u7ec3\u573a\u666f":97,"\u4e0a\u6ce8\u518c\u4e00\u4e0b":27,"\u4e0a\u7f16\u8bd1\u5f88\u6162":0,"\u4e0a\u8fd0\u884c":116,"\u4e0a\u8ff0\u4ee3\u7801\u5c06bias\u5168\u90e8\u521d\u59cb\u5316\u4e3a1":83,"\u4e0a\u8ff0\u547d\u4ee4\u4e2d":1,"\u4e0a\u8ff0\u547d\u4ee4\u628a\u5f53\u524d\u76ee\u5f55":0,"\u4e0a\u8ff0\u7684":82,"\u4e0a\u8ff0\u7684\u4ee3\u7801\u7247\u6bb5\u5305\u542b\u4e86\u4e24\u79cd\u65b9\u6cd5":108,"\u4e0a\u8ff0\u7b2c4\u6b65":0,"\u4e0a\u8ff0paddlepaddl":63,"\u4e0a\u9762\u7684\u4ee3\u7801\u5728":75,"\u4e0a\u9762\u7684\u4ee3\u7801\u9996\u5148\u5bfc\u5165\u4f9d\u8d56\u7684\u5305":75,"\u4e0b":[75,77],"\u4e0b\u4e00\u4e2awheel\u5305\u9700\u8981\u66f4\u65b0\u7248\u672c\u53f7\u624d\u53ef\u4ee5\u4e0a\u4f20":63,"\u4e0b\u4e00\u6b65\u5c31\u662f\u7528\u6a21\u578b\u6765\u505a\u9884\u6d4b":88,"\u4e0b\u4f1a\u770b\u5230\u5982\u4e0b\u76ee\u5f55\u7ed3\u6784":87,"\u4e0b\u540c":83,"\u4e0b\u56fe\u4e2d\u5c31\u5c55\u793a\u4e86\u4e00\u4e9b\u5173\u4e8e\u5185\u5b58\u6570\u636e\u8fc1\u5f99\u548c\u8ba1\u7b97\u8d44\u6e90\u5229\u7528\u7387\u7684\u5efa\u8bae":108,"\u4e0b\u56fe\u662f\u4e00\u4e2a\u5168\u8fde\u63a5\u5c42\u7684\u793a\u610f\u56fe":74,"\u4e0b\u56fe\u662fcsr\u5b58\u50a8\u7a00\u758f\u77e9\u9635\u7684\u793a\u610f\u56fe":89,"\u4e0b\u5b58\u653e\u516c\u5171\u6570\u636e\u96c6\u5408":11,"\u4e0b\u627e\u5230":87,"\u4e0b\u62c9\u6846\u4e2d\u627e\u5230\u751f\u6210\u76843\u4e2a\u4e8c\u8fdb\u5236\u6587\u4ef6":63,"\u4e0b\u6587\u4ee5nlp\u4efb\u52a1\u4e3a\u4f8b":113,"\u4e0b\u6587\u4f1a\u8be6\u7ec6\u8fdb\u884c\u4ecb\u7ecd":89,"\u4e0b\u6587\u4f7f\u7528":97,"\u4e0b\u6587\u5c31\u662f\u7528job\u7c7b\u578b\u7684\u8d44\u6e90\u6765\u8fdb\u884c\u8bad\u7ec3":96,"\u4e0b\u6587\u8be6\u7ec6\u89e3\u91ca":89,"\u4e0b\u7684":[90,97],"\u4e0b\u8868\u5217\u51fa\u4e86python\u7aef\u8bad\u7ec3\u63a5\u53e3\u66b4\u9732\u7684\u6570\u636e\u7c7b\u578b":89,"\u4e0b\u8f7d":27,"\u4e0b\u8f7d\u5230\u672c\u5730":27,"\u4e0b\u8f7d\u5b8c\u6570\u636e\u540e":96,"\u4e0b\u8f7d\u5f97\u5230":63,"\u4e0b\u8f7d\u6307\u5b9a\u7248\u672c\u7684docker\u955c\u50cf":1,"\u4e0b\u8f7dgpu\u7248\u672c":1,"\u4e0b\u9762":90,"\u4e0b\u9762\u4e3e\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50":108,"\u4e0b\u9762\u4ecb\u7ecd\u4ecb\u7ecd":75,"\u4e0b\u9762\u4ee5":91,"\u4e0b\u9762\u4ee5\u77e9\u9635\u4e58\u64cd\u4f5c":75,"\u4e0b\u9762\u4ee5addop\u4e3a\u4f8b\u8bf4\u660etensor\u7684\u4f7f\u7528\u8fc7\u7a0b":76,"\u4e0b\u9762\u5206\u522b\u4ecb\u7ecd\u67d0\u4e00\u7c7b\u6587\u4ef6\u7684\u5b9e\u73b0\u65b9\u5f0f":46,"\u4e0b\u9762\u5217\u51fa\u4e86":114,"\u4e0b\u9762\u5217\u51fa\u4e86\u5168\u8fde\u63a5\u5c42\u7684\u68af\u5ea6\u68c0\u67e5\u5355\u5143\u6d4b\u8bd5":74,"\u4e0b\u9762\u5c31\u6839\u636e\u8fd9\u51e0\u4e2a\u6b65\u9aa4\u5206\u522b\u4ecb\u7ecd":97,"\u4e0b\u9762\u6211\u4eec\u4f7f\u7528\u8fd9\u4e2a\u955c\u50cf\u6765\u4e0b\u8f7d\u6570\u636e\u5230docker":96,"\u4e0b\u9762\u662f":75,"\u4e0b\u9762\u662f\u5bf9":75,"\u4e0b\u9762\u662fc":90,"\u4e0b\u9762\u7684\u4ee3\u7801\u5c06\u968f\u673a\u751f\u6210\u7684\u77e9\u9635\u8f6c\u5316\u4e3a\u53ef\u4ee5\u88abpaddlepaddle\u52a0\u8f7d\u7684\u6a21\u578b\u53c2\u6570":83,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u4ecegithub\u62c9\u53d6\u6700\u65b0\u4ee3\u7801":87,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u521b\u5efa\u4e86\u4e00\u4e2a\u9ad8\u5ea6\u4e3a1":89,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u521b\u5efa\u4e86\u4e00\u4e2acpu\u4e0a\u7684\u4e8c\u503c\u7a00\u758f\u77e9\u9635":89,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u521b\u5efa\u4e86\u542b\u6709\u4e09\u4e2a\u5143\u7d20":89,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u5728\u521b\u5efa\u4e86\u4e00\u4e2acpu\u4e0a\u7684\u5e26\u5143\u7d20\u503c\u7684\u7a00\u758f\u77e9\u9635":89,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u5b9e\u73b0\u4e86":74,"\u4e0b\u9762\u7684\u70b9\u5b9e\u73b0\u4e86mulop\u7684\u5b9a\u4e49":75,"\u4e0b\u9762\u7ed9\u51fa\u4e86\u4e00\u4e2a\u4f8b\u5b50":74,"\u4e0b\u9762\u7ed9\u51fa\u5728\u4e09\u7ef4\u7a7a\u95f4\u4e2d\u4f7f\u7528\u7ebf\u6027\u56de\u5f52\u62df\u5408\u4e00\u6761\u76f4\u7ebf\u7684\u4f8b\u5b50":84,"\u4e0b\u9762\u8be6\u7ec6\u89e3\u91ca\u4ec0\u4e48\u662f":89,"\u4e0b\u9762\u8fd9\u4e9blayer\u80fd\u591f\u63a5\u53d7\u53cc\u5c42\u5e8f\u5217\u4f5c\u4e3a\u8f93\u5165":110,"\u4e0d\u4e00\u81f4\u7684\u7531pfsclient\u4e0b\u8f7d\u6216\u8005\u4f20\u8f93chunk\u5b8c\u6210":27,"\u4e0d\u4ec5\u8981\u63d0\u4f9b\u6bcf\u4e00\u4e2a\u5916\u5c42\u5e8f\u5217\u5728\u6574\u4e2a":89,"\u4e0d\u4f1a\u4fdd\u7559\u5728\u78c1\u76d8\u4e0a":0,"\u4e0d\u4f1a\u518d\u4ece":81,"\u4e0d\u4f1a\u865a\u62df\u4efb\u4f55\u786c\u4ef6":0,"\u4e0d\u4f7f\u7528\u9759\u6001\u5e93":45,"\u4e0d\u4f7f\u7528\u989d\u5916\u7a7a\u95f4":74,"\u4e0d\u4f7f\u7528c":45,"\u4e0d\u4f7f\u7528swig":45,"\u4e0d\u5141\u8bb8\u4e00\u4e2a\u6587\u4ef6\u4e2d\u5305\u542b\u591a\u4e2aop":75,"\u4e0d\u5171\u4eab\u5219\u4e0d\u52a0":75,"\u4e0d\u5171\u4eab\u7684\u4f8b\u5b50\u53ef\u4ee5\u53c2\u8003":75,"\u4e0d\u53ef\u4ee5\u66f4\u6539":63,"\u4e0d\u53ef\u518d\u8fdb\u884c\u62c6\u5206":89,"\u4e0d\u540c":42,"\u4e0d\u540c\u4e8e\u4e0a\u8ff0\u4ecb\u7ecd\u7684recurr":82,"\u4e0d\u540c\u4e8eop\u7684\u7f16\u8bd1\u6d4b\u8bd5":75,"\u4e0d\u540c\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u6570\u636e\u5927\u5c0f\u7684\u6700\u5927\u503c\u4e0e\u6700\u5c0f\u503c\u7684\u6bd4\u7387":103,"\u4e0d\u540c\u5e8f\u5217\u53ef\u80fd\u4f1a\u542b\u6709\u4e0d\u540c\u6570\u76ee\u4e2a\u5143\u7d20":89,"\u4e0d\u540c\u65f6\u95f4\u6b65\u7684\u8f93\u5165\u662f\u4e0d\u540c\u7684":114,"\u4e0d\u540c\u7248\u672c\u7684\u7f16\u8bd1\u5668\u4e4b\u95f4":45,"\u4e0d\u540c\u7684\u4f18\u5316\u7b97\u6cd5\u9700\u8981\u4f7f\u7528\u4e0d\u540c\u5927\u5c0f\u7684\u5185\u5b58":81,"\u4e0d\u540c\u7684\u5206\u5e03\u5f0f\u6587\u4ef6\u7cfb\u7edf":97,"\u4e0d\u540c\u7684\u6570\u636e\u7c7b\u578b\u548c\u5e8f\u5217\u6a21\u5f0f\u8fd4\u56de\u7684\u683c\u5f0f\u4e0d\u540c":84,"\u4e0d\u540c\u8ba1\u7b97\u5c42\u5bf9\u7a7a\u8f93\u5165\u7684\u5904\u7406\u7b56\u7565\u6709\u53ef\u80fd\u4e0d\u540c":89,"\u4e0d\u540c\u8bbe\u5907":75,"\u4e0d\u540c\u8bed\u8a00\u7684\u63a5\u53e3\u9002\u5e94\u4e0d\u540c\u8bed\u8a00\u7684\u7279\u6027":45,"\u4e0d\u540c\u8f93\u5165\u542b\u6709\u7684\u5b50\u53e5":113,"\u4e0d\u540c\u8f93\u5165\u5e8f\u5217\u542b\u6709\u7684\u8bcd\u8bed\u6570\u5fc5\u987b\u4e25\u683c\u76f8\u7b49":113,"\u4e0d\u540cdataprovider\u5bf9\u6bd4\u5982\u4e0b":111,"\u4e0d\u540crank\u7684tensor\u662f\u4e0d\u540c\u7c7b\u578b":76,"\u4e0d\u5728":46,"\u4e0d\u5bb9\u6613\u51fa\u9519":27,"\u4e0d\u5d4c\u5165\u5176\u4ed6\u8bed\u8a00\u89e3\u91ca\u5668":45,"\u4e0d\u5d4c\u5165python\u89e3\u91ca\u5668":45,"\u4e0d\u5e94\u8be5\u88ab\u62c6\u89e3":113,"\u4e0d\u6307\u5b9a\u65f6":113,"\u4e0d\u652f\u6301":89,"\u4e0d\u652f\u6301\u5e8f\u5217\u957f\u5ea6\u4e3a":89,"\u4e0d\u662f\u4e00\u6761\u5e8f\u5217":84,"\u4e0d\u662f\u771f\u6b63\u7684layer":82,"\u4e0d\u662f\u901a\u8fc7\u4e00\u822c\u7684\u65b9\u5f0f\u6765\u5b9e\u73b0\u5bf9\u8f93\u51fa\u7684\u6fc0\u6d3b":82,"\u4e0d\u663e\u793a\u7684\u5199\u6bcf\u4e2a\u7c7b\u5177\u4f53\u5305\u542b\u4ec0\u4e48":45,"\u4e0d\u6ee1\u8db3\u94a9\u5b50\u7684":72,"\u4e0d\u7528mount\u7684\u65b9\u5f0f\u6765\u8bbf\u95ee\u6570\u636e":11,"\u4e0d\u80fd\u4fee\u6539op\u7684\u6210\u5458\u53d8\u91cf":75,"\u4e0d\u80fd\u592a\u968f\u610f":72,"\u4e0d\u80fd\u88ab\u63d0\u4ea4\u5230":72,"\u4e0d\u8981\u5728\u6ce8\u91cd\u6027\u80fd\u7684\u8bad\u7ec3\u573a\u666f\u4e0b\u4f7f\u7528":81,"\u4e0d\u8bba\u5e8f\u5217\u4e2d\u7684\u5143\u7d20\u5728\u5185\u5b58\u4e2d\u5360\u7528\u591a\u5c11\u5b9e\u9645\u5b58\u50a8\u7a7a\u95f4":89,"\u4e0d\u8bba\u6570\u636e\u57df\u662f":89,"\u4e0d\u8bba\u662f\u4e00\u7ef4\u6574\u578b\u6570\u7ec4\u8fd8\u662f\u4e8c\u7ef4\u6d6e\u70b9\u6570\u77e9\u9635":89,"\u4e0d\u8bba\u662f\u5355\u5c42\u5e8f\u5217\u8fd8\u662f\u53cc\u5c42\u5e8f\u5217\u7684\u5e8f\u5217\u4fe1\u606f":89,"\u4e0d\u8fc7\u5b9e\u9645\u4e0a\u662f\u8fd0\u884c\u5728\u4e00\u4e2a":0,"\u4e0d\u9700\u5728\u4f7f\u7528c":90,"\u4e0d\u9700\u8981\u4f9d\u8d56\u5176\u4ed6\u4efb\u4f55\u8f6f\u4ef6\u4e86":0,"\u4e0d\u9700\u8981\u63d0\u4f9b\u5143\u7d20\u503c":89,"\u4e0d\u9700\u8981\u8bbe\u7f6e":116,"\u4e0e":[42,75,97,107],"\u4e0e\u4e4b\u76f8\u5bf9\u7684\u662flocal":27,"\u4e0e\u5176\u4ed6\u7b2c\u4e09\u65b9\u5e93\u4e00\u6837":42,"\u4e0e\u5176\u5b83":90,"\u4e0e\u529f\u80fd\u5206\u652f\u4e0d\u540c\u7684\u662f":63,"\u4e0e\u5355\u5c42rnn\u7684\u914d\u7f6e\u7c7b\u4f3c":111,"\u4e0e\u53ef\u80fd\u6709\u7684":63,"\u4e0e\u540c\u6b65sgd\u76f8\u6bd4":92,"\u4e0e\u5bfb\u627epython\u4ee3\u7801\u7684\u6027\u80fd\u74f6\u9888\u7c7b\u4f3c":107,"\u4e0e\u5f53\u524d\u7684\u8870\u51cf\u56e0\u5b50\u7684\u4e58\u79ef":83,"\u4e0e\u672c\u5730\u8bad\u7ec3\u76f8\u540c":93,"\u4e0e\u6b64\u4e0d\u540c\u7684\u662f":97,"\u4e0e\u8c03\u4f18":107,"\u4e0e\u8f93\u5165\u4e0d\u540c\u7684\u662f":90,"\u4e0e\u8fd9\u4e2a\u8bad\u7ec3\u6570\u636e\u4ea4\u4e92\u7684layer":81,"\u4e0ebatch":41,"\u4e0ejob":97,"\u4e0eoperator\u524d\u5411\u8ba1\u7b97\u7684\u8f93\u51fa\u8fdb\u884c\u5bf9\u6bd4":75,"\u4e0eoperator\u6ce8\u518c\u65f6\u6ce8\u518c\u7684\u7c7b\u578b\u4e00\u81f4":75,"\u4e0epython\u4e0d\u540c":107,"\u4e14\u4e0d\u6392\u9664commit\u4e4b\u95f4\u7684\u4fee\u6539\u5b58\u5728\u76f8\u4e92\u8986\u76d6\u7684\u60c5\u51b5":72,"\u4e14\u4f7f\u7528":87,"\u4e14\u589e\u52a0\u4e00\u4e2a\u7b2c\u4e09\u65b9\u8bed\u8a00":45,"\u4e14\u5c55\u793a\u6548\u679c\u66f4\u597d":107,"\u4e14\u5e8f\u5217\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20\u8fd8\u662f\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217":84,"\u4e14\u6bcf\u4e2a\u53e5\u5b50\u8868\u793a\u4e3a\u5bf9\u5e94\u7684\u8bcd\u8868\u7d22\u5f15\u6570\u7ec4":111,"\u4e14\u8c03\u7528\u65f6\u4e0d\u80fd\u629b\u51fa\u5f02\u5e38\u6216\u51fa\u73b0\u8fd0\u884c\u65f6\u9519\u8bef":46,"\u4e14c99\u652f\u6301bool\u7c7b\u578b\u548c\u5b9a\u957f\u6574\u6570":45,"\u4e14c99\u76f8\u5bf9\u4e8ec11\u4f7f\u7528\u66f4\u52a0\u5e7f\u6cdb":45,"\u4e24\u4e2a\u5b50\u76ee\u5f55\u4e0b":77,"\u4e24\u4e2a\u5d4c\u5957\u7684":113,"\u4e24\u4e2a\u64cd\u4f5c":108,"\u4e24\u4e2a\u8f93\u5165\u7684\u5b50\u5e8f\u5217\u957f\u5ea6\u4e5f\u5e76\u4e0d\u76f8\u540c":111,"\u4e24\u4e2a\u90e8\u5206":77,"\u4e24\u4e2a\u9690\u5c42\u7684\u7b80\u5355\u5168\u8fde\u63a5\u7f51\u7edc":90,"\u4e24\u6b21":89,"\u4e24\u79cd\u5e38\u7528\u7684\u6a21\u578b\u52a0\u8f7d\u65b9\u5f0f":90,"\u4e24\u79cd\u65b9\u6cd5\u7684\u533a\u522b":81,"\u4e24\u79cdblas\u5e93":0,"\u4e24\u8005\u90fd\u662f\u5bf9\u68af\u5ea6\u7684\u622a\u65ad":81,"\u4e25\u683c\u7684\u547d\u540d\u89c4\u8303pep":63,"\u4e2a\u5185\u5b58\u6c60\u5b9e\u9645\u4e0a\u51b3\u5b9a\u4e86shuffle\u7684\u7c92\u5ea6":81,"\u4e2a\u6027\u5316\u63a8\u8350":63,"\u4e2a\u6279\u6b21\u7684\u53c2\u6570\u5e73\u5747\u503c\u8fdb\u884c\u6d4b\u8bd5":103,"\u4e2a\u6a21\u578b\u6d4b\u8bd5\u6570\u636e":103,"\u4e2d":[41,42,45,46,74,75,76,81,89,97,107],"\u4e2d\u4e0d\u8981\u6dfb\u52a0\u5927\u6587\u4ef6\u7b49":72,"\u4e2d\u4f1a\u4f7f\u7528\u5230\u7684\u5b57\u5178\u6570\u636e\u6587\u4ef6":91,"\u4e2d\u4f1a\u63d0\u4f9b\u4e00\u4e9b\u5fc5\u8981\u7684\u63a5\u53e3\u548c\u51fd\u6570":42,"\u4e2d\u4f20\u5165\u53c2\u6570":91,"\u4e2d\u4f20\u5165\u7684\u53c2\u6570":91,"\u4e2d\u5143\u7d20\u4e2a\u6570\u603b\u662f\u7b49\u4e8e\u884c\u6570":89,"\u4e2d\u5143\u7d20\u7684\u4e2a\u6570\u7b49\u4e8e\u7f51\u7edc\u4e2d\u8f93\u51fa\u5c42\u7684\u4e2a\u6570":81,"\u4e2d\u5173\u4e8e\u65f6\u95f4\u9012\u5f52\u795e\u7ecf\u7f51\u7edc\u7684\u4ecb\u7ecd":111,"\u4e2d\u5199\u5165json\u5185\u5bb9":10,"\u4e2d\u5305\u542b\u4e00\u4e2araspberri":118,"\u4e2d\u5305\u542b\u6240\u4f9d\u8d56\u7684\u6240\u6709\u7b2c\u4e09\u65b9\u5e93":116,"\u4e2d\u5305\u542b\u82e5\u5e72\u4e2a\u4e0d\u540candroid":116,"\u4e2d\u5305\u542bc":[116,118],"\u4e2d\u5355\u5143\u6d4b\u8bd5\u7684\u4e00\u90e8\u5206":72,"\u4e2d\u5355\u5143\u6d4b\u8bd5\u80fd\u987a\u5229\u901a\u8fc7":72,"\u4e2d\u542b\u6709\u591a\u4e2a\u5e8f\u5217":89,"\u4e2d\u5b8c\u5168\u4e00\u81f4":45,"\u4e2d\u5b9a\u4e49":114,"\u4e2d\u5b9a\u4e49\u548c\u4f7f\u7528":113,"\u4e2d\u5b9e\u73b0\u4e86\u4e00\u4e2amerge\u7684\u65b9\u6cd5":42,"\u4e2d\u5b9e\u73b0\u7684\u7ed3\u6784\u4f53":46,"\u4e2d\u5bf9\u5e94\u7684layer\u5904":41,"\u4e2d\u5f15\u5165\u7684":41,"\u4e2d\u6253\u5370\u5176\u503c":81,"\u4e2d\u6307\u5b9a":103,"\u4e2d\u6307\u5b9a\u7684\u540d\u5b57":105,"\u4e2d\u63d0\u4f9b\u4e00\u4e2a\u4e0emkl\u6709\u5173\u7684\u603b\u5f00\u5173":42,"\u4e2d\u63d0\u4f9b\u4e86\u4e00\u4e9b\u5168\u5c40\u51fd\u6570\u7528\u6765\u5b9e\u73b0paddl":76,"\u4e2d\u641c\u7d22\u8fd9\u51e0\u4e2a\u5e93":0,"\u4e2d\u64cd\u4f5c":89,"\u4e2d\u6587\u6587\u6863":77,"\u4e2d\u6587\u6587\u6863\u76ee\u5f55":77,"\u4e2d\u6587\u7ef4\u57fa\u767e\u79d1\u9875\u9762":111,"\u4e2d\u6839\u636e":41,"\u4e2d\u6bcf\u4e2a\u5143\u7d20\u662f\u4e00\u4e2alayer\u7684\u8f93\u51fa\u7ed3\u679c\u77e9\u9635":81,"\u4e2d\u6bcf\u4e2apod\u7684ip\u5730\u5740":97,"\u4e2d\u6bcf\u5c42\u7684\u6570\u503c\u7edf\u8ba1":103,"\u4e2d\u6dfb\u52a0":41,"\u4e2d\u6dfb\u52a0\u4e00\u4e2a":42,"\u4e2d\u6dfb\u52a0\u4e24\u4e2a\u8f93\u5165":75,"\u4e2d\u7528\u4e8e\u5b58\u50a8\u6570\u636e\u7684":90,"\u4e2d\u7684":[76,90],"\u4e2d\u7684\u4e00\u884c":72,"\u4e2d\u7684\u4ee3\u7801\u4f5c\u4e3a\u5b9e\u4f8b":91,"\u4e2d\u7684\u504f\u79fb":89,"\u4e2d\u7684\u5bf9\u5e94\u5206\u652f\u5373\u53ef":72,"\u4e2d\u7684\u7248\u672c\u4fe1\u606f":63,"\u4e2d\u7684\u76f8\u5173\u811a\u672c":90,"\u4e2d\u7684\u8d77\u59cb\u504f\u79fb":89,"\u4e2d\u83b7\u53d6":97,"\u4e2d\u8bbe\u7f6e\u7684\u6240\u6709\u8282\u70b9":93,"\u4e2d\u8be6\u7ec6\u4ecb\u7ecd":74,"\u4e2d\u8c03\u7528":75,"\u4e2d\u8fd0\u884c\u4efb\u52a1\u7684\u89d2\u5ea6":11,"\u4e2d\u914d\u7f6e\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":114,"\u4e34\u65f6\u53d8\u91cf\u7b49\u7b49":81,"\u4e3a":[41,42,75,89,114,116,117,118],"\u4e3a\u4e86\u4f7f":75,"\u4e3a\u4e86\u4f7f\u8bc4\u5ba1\u4eba\u5728\u8bc4\u5ba1\u4ee3\u7801\u65f6\u66f4\u597d\u5730\u4e13\u6ce8\u4e8e\u4ee3\u7801\u672c\u8eab":72,"\u4e3a\u4e86\u4fdd\u8bc1\u6548\u7387":74,"\u4e3a\u4e86\u4fdd\u8bc1gpu\u9a71\u52a8\u80fd\u591f\u5728\u955c\u50cf\u91cc\u9762\u6b63\u5e38\u8fd0\u884c":1,"\u4e3a\u4e86\u51cf\u5c11\u751f\u6210\u94fe\u63a5\u5e93\u7684\u5927\u5c0f\u628a":87,"\u4e3a\u4e86\u548c\u7528\u6237\u7cfb\u7edf\u517c\u5bb9":88,"\u4e3a\u4e86\u5c01\u88c5\u80fd\u591f\u6b63\u786e\u5de5\u4f5c":74,"\u4e3a\u4e86\u5c3d\u53ef\u80fd\u5c11\u7684\u5728\u7236\u7c7blayer\u4e2d\u6dfb\u52a0\u53d8\u91cf\u6216\u8005\u51fd\u6570":42,"\u4e3a\u4e86\u5e94\u5bf9\u4ee5\u4e0a\u7684\u95ee\u9898":27,"\u4e3a\u4e86\u63cf\u8ff0\u65b9\u4fbf":113,"\u4e3a\u4e86\u65b9\u4fbf\u5927\u5bb6":72,"\u4e3a\u4e86\u65b9\u4fbf\u5927\u5bb6\u7684\u90e8\u7f72":94,"\u4e3a\u4e86\u66b4\u9732\u7684\u63a5\u53e3\u5c3d\u91cf\u7b80\u5355":46,"\u4e3a\u4e86\u66f4\u597d\u7684\u7b26\u5408paddlepaddle\u7684\u4ee3\u7801\u98ce\u683c":42,"\u4e3a\u4e86\u6700\u5927\u7a0b\u5ea6\u51cf\u5c11\u591a\u6b21\u8c03\u7528":41,"\u4e3a\u4e86\u751f\u6210\u66f4\u53ef\u8bfb\u7684\u6027\u80fd\u5206\u6790\u7ed3\u679c":107,"\u4e3a\u4e86\u7b80\u5316cmake\u914d\u7f6e":116,"\u4e3a\u4e86\u7f16\u8bd1paddlepaddl":0,"\u4e3a\u4e86\u8fbe\u5230\u6027\u80fd\u6700\u4f18":108,"\u4e3a\u4e86\u8fbe\u5230\u6700\u5feb\u7684\u8ba1\u7b97\u901f\u5ea6":[116,117],"\u4e3a\u4e86\u8fdb\u4e00\u6b65\u63d0\u5347paddlepaddle\u5728\u57fa\u672c\u6570\u5b66\u8fd0\u7b97\u7684\u8ba1\u7b97\u901f\u5ea6":42,"\u4e3a\u4ec0\u4e48\u7528":0,"\u4e3a\u4f7f\u7528c":90,"\u4e3a\u4f8b":[75,82],"\u4e3a\u4f8b\u6765\u4ecb\u7ecd\u5982\u4f55\u5199\u5e26kernel\u7684oper":75,"\u4e3a\u53c2\u6570\u77e9\u9635\u7684\u5bbd\u5ea6":83,"\u4e3a\u5b83\u4eec\u9644\u52a0\u4e0a\u5e8f\u5217\u4fe1\u606f\u5c06\u53d8\u6210\u5e8f\u5217\u8f93\u5165":89,"\u4e3a\u5bb9\u5668\u5185\u6267\u884c\u7684\u547d\u4ee4":1,"\u4e3a\u60a8\u505a\u6027\u80fd\u8c03\u4f18\u63d0\u4f9b\u4e86\u65b9\u5411":108,"\u4e3a\u65b9\u4fbf\u4f5c\u4e1a\u542f\u52a8\u63d0\u4f9b\u4e86\u4e24\u4e2a\u72ec\u7279\u7684\u547d\u4ee4\u9009\u9879":93,"\u4e3a\u6b64":96,"\u4e3a\u6bcf\u4e00\u4e2a":[89,90],"\u4e3a\u6bcf\u4e00\u4e2a\u8f93\u5165":[89,90],"\u4e3a\u6bcf\u4e2aop\u521b\u5efa\u5355\u72ec\u7684":75,"\u4e3a\u8f93\u51fa\u5206\u914d\u5185\u5b58":74,"\u4e3aconst\u51fd\u6570":75,"\u4e3aoutput_\u7533\u8bf7\u5185\u5b58":74,"\u4e3b\u8981\u4e3a\u5f00\u53d1\u8005\u4f7f\u7528":103,"\u4e3b\u8981\u529f\u80fd\u5305\u62ec":27,"\u4e3b\u8981\u5305\u62ec":42,"\u4e3b\u8981\u5305\u62ec\u4e86\u6df1\u5ea6\u5b66\u4e60\u76f8\u5173\u7684\u6570\u5b66\u539f\u8bed\u4e0e\u64cd\u4f5c":42,"\u4e3b\u8981\u5305\u62ec\u56db\u79cd\u7c7b\u578b":84,"\u4e3b\u8981\u539f\u56e0\u5305\u62ec\u4e24\u4e2a\u65b9\u9762":81,"\u4e3b\u8981\u7528\u4e8epython":75,"\u4e3b\u8981\u9488\u5bf9paddlepaddle\u5728\u91cd\u6784\u4e4b\u524d\u7684\u4ee3\u7801\u6846\u67b6\u4ee5\u53cav1\u7684api":42,"\u4e3e\u4e00\u4e2a\u4f8b\u5b50":83,"\u4e3e\u4f8b":81,"\u4e3e\u4f8b\u8bf4\u660e":111,"\u4e4b\u524d":72,"\u4e4b\u540e":[74,84,91],"\u4e4b\u540e\u4f7f\u7528":74,"\u4e4b\u540e\u4f7f\u7528\u77e9\u9635\u8fd0\u7b97\u51fd\u6570\u6765\u8ba1\u7b97":74,"\u4e4b\u540e\u518d\u7528\u7f51\u9875\u8fde\u5230http":77,"\u4e4b\u540e\u521d\u59cb\u5316\u6240\u6709\u7684\u6743\u91cd\u77e9\u9635":74,"\u4e4b\u540e\u624d\u80fd\u5f00\u59cb\u7f16\u8bd1\u7684\u6b65\u9aa4":0,"\u4e4b\u5916\u7684\u6240\u6709\u5934\u6587\u4ef6":46,"\u4e4b\u7c7b\u7684\u7a0b\u5e8f\u6765\u7f16\u8bd1\u6e90\u7801":0,"\u4e4b\u95f4\u7684\u8fd0\u7b97\u662f\u72ec\u7acb\u7684":113,"\u4e58\u4e0a\u8f93\u51fa\u7684\u68af\u5ea6":74,"\u4e58\u6cd5\u548c\u4e58\u6cd5\u68af\u5ea6\u7684\u8ba1\u7b97\u5360\u75282":107,"\u4e58\u9664\u7b49\u65f6\u5019":81,"\u4e5f\u4e0d\u4f7f\u7528\u5176\u4ed6\u52a8\u6001\u5e93":45,"\u4e5f\u4e0d\u5b58\u5728\u4e00\u4e2asubseq\u76f4\u63a5\u751f\u6210\u4e0b\u4e00\u4e2asubseq\u7684\u60c5\u51b5":113,"\u4e5f\u4e0d\u5e94\u8be5\u62a5\u9519":46,"\u4e5f\u4e0d\u751f\u6210":46,"\u4e5f\u4e0d\u80fd\u63a5\u6536\u5e8f\u5217\u6570\u636e\u4f5c\u4e3a\u8f93\u5165":82,"\u4e5f\u4f1a\u5360\u7528\u78c1\u76d8":0,"\u4e5f\u53ef\u4ee5\u4f7f\u7528":72,"\u4e5f\u53ef\u4ee5\u4f7f\u7528\u8fd9\u4e9b\u955c\u50cf":63,"\u4e5f\u53ef\u4ee5\u5229\u7528paddlepaddl":77,"\u4e5f\u53ef\u4ee5\u662f\u4e00\u4e2a\u8bcd\u8bed":113,"\u4e5f\u53ef\u4ee5\u662f\u5728\u4efb\u52a1\u542f\u52a8\u524d\u4e0b\u8f7d\u5230\u672c\u5730\u7684":91,"\u4e5f\u53ef\u4ee5\u76f4\u63a5\u5728\u7f51\u9875\u9884\u89c8\u6587\u6863":77,"\u4e5f\u53ef\u4ee5\u8bf4\u662f\u67d0\u4e9b\u7279\u5b9a\u6307\u4ee4\u7684\u4f7f\u7528\u60c5\u51b5":108,"\u4e5f\u53ef\u4ee5\u901a\u8fc7\u4fee\u6539":97,"\u4e5f\u53ef\u5199\u6210":75,"\u4e5f\u53ef\u81ea\u884c\u524d\u5f80\u5b98\u7f51\u4e0b\u8f7d":117,"\u4e5f\u53ef\u901a\u8fc7\u4ee5\u4e0b\u547d\u4ee4\u83b7\u53d6":116,"\u4e5f\u5c31\u662f":72,"\u4e5f\u5c31\u662f\u7a7a\u8f93\u5165":89,"\u4e5f\u5c31\u662f\u81ea\u5df1\u7528\u6237\u540d\u4e0b\u7684":72,"\u4e5f\u5c31\u662f\u8bf4":[89,103,105],"\u4e5f\u5c31\u662f\u8bf4\u8f93\u51fa\u7684\u7ed3\u679c\u4e0d\u4f1a\u5728\u539f\u6765\u7684\u6570\u636e\u4e0a\u7d2f\u52a0":42,"\u4e5f\u5c31\u662fpaddlepaddle\u4e2d\u7684\u4e00\u7ef4\u6574\u578b\u6570\u7ec4":89,"\u4e5f\u63cf\u8ff0\u4e86\u5bb9\u5668\u9700\u8981\u4f7f\u7528\u7684\u5b58\u50a8\u5377\u6302\u8f7d\u7684\u60c5\u51b5":97,"\u4e5f\u652f\u6301cpu\u7684\u6027\u80fd\u5206\u6790":108,"\u4e5f\u662f\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217":111,"\u4e5f\u662fdecoder\u5faa\u73af\u5c55\u5f00\u7684\u4f9d\u636e":113,"\u4e5f\u6ca1\u7528":78,"\u4e66\u5199":45,"\u4e86":0,"\u4e86\u89e3\u5176\u8c03\u7528\u5173\u7cfb":107,"\u4e86\u89e3\u60a8\u7684\u786c\u4ef6":108,"\u4e86\u89e3\u66f4\u591a\u7ec6\u8282":114,"\u4e86\u89e3\u66f4\u591a\u8be6\u7ec6\u4fe1\u606f":114,"\u4e8c\u7ef4\u6d6e\u70b9\u578b\u77e9\u9635":89,"\u4e8c\u7ef4\u6d6e\u70b9\u6570\u77e9\u9635":89,"\u4e8c\u7ef4\u77e9\u9635":90,"\u4e8c\u7ef4\u77e9\u9635\u53ef\u4ee5\u8868\u793a\u884c\u5411\u91cf\u548c\u5217\u5411\u91cf":89,"\u4e8c\u8005\u8bed\u610f\u4e0a\u5b8c\u5168\u4e00\u81f4":111,"\u4e8e\u662f":89,"\u4e8e\u662f\u6211\u4eec\u53ef\u4ee5\u70b9\u51fb":107,"\u4e8e\u662f\u8fd9\u91cc\u4f7f\u7528":107,"\u4ea4\u4e92\u7684\u65b9\u6cd5":107,"\u4ea4\u53c9\u7f16\u8bd1\u5de5\u5177\u94fe\u4e3a":116,"\u4ea4\u53c9\u7f16\u8bd1android\u5e73\u53f0\u4e0a\u9002\u7528\u7684paddlepaddle\u5e93":116,"\u4ea4\u53c9\u7f16\u8bd1android\u7248\u672c\u7684paddlepaddle\u5e93\u65f6":116,"\u4ea4\u53c9\u7f16\u8bd1ios\u5e73\u53f0\u4e0a\u9002\u7528\u7684paddlepaddle\u5e93":117,"\u4ea4\u53c9\u7f16\u8bd1ios\u7248\u672c\u7684paddlepaddle\u5e93\u65f6":117,"\u4ea4\u53c9\u7f16\u8bd1raspberri":118,"\u4ea4\u7531cmake\u7cfb\u7edf\u672c\u8eab\u6765\u5904\u7406":116,"\u4ea6\u53ef\u4ee5\u901a\u8fc7\u624b\u52a8\u8bbe\u7f6e":117,"\u4eab\u53d7\u60a8\u7684\u65c5\u7a0b":1,"\u4eba\u8138\u8bc6\u522b":11,"\u4ec0\u4e48\u662f":0,"\u4ec5\u4ec5\u4f7f\u7528":45,"\u4ec5\u4f1a\u5728\u652f\u6301avx2\u6307\u4ee4\u96c6\u53ca\u4ee5\u4e0a\u7684\u673a\u5668\u624d\u4f7f\u7528mkl":42,"\u4ec5\u5728\u8fdc\u7a0b\u7a00\u758f\u8bad\u7ec3\u65f6\u6709\u6548":74,"\u4ec5\u5bf9\u7a00\u758f\u6570\u636e\u6709\u6548":74,"\u4ec5\u652f\u6301\u6574\u578b\u503c":89,"\u4ec5\u7528\u4e8e\u5b58\u50a8\u6574\u578b\u503c":90,"\u4ecb\u7ecd\u4e86\u4e00\u79cd\u901a\u8fc7ssh\u8fdc\u7a0b\u5206\u53d1\u4efb\u52a1":97,"\u4ecb\u7ecd\u4ea4\u53c9\u7f16\u8bd1android\u5e73\u53f0\u4e0a\u9002\u7528\u7684paddlepaddle\u5e93\u7684\u65b9\u6cd5\u548c\u6b65\u9aa4":116,"\u4ecb\u7ecd\u4f7f\u7528paddlepaddl":91,"\u4ece":[63,79,108],"\u4ece0\u5230num":103,"\u4ece0\u5f00\u59cb\u7684\u6574\u6570":91,"\u4ece\u4e00\u4e2aword\u751f\u6210\u4e0b\u4e00\u4e2aword":113,"\u4ece\u5185\u6838\u51fd\u6570\u7684\u89d2\u5ea6":108,"\u4ece\u6a21\u578b\u6587\u4ef6\u5c06\u9884\u8bad\u7ec3\u53c2\u6570\u8f7d\u5165":83,"\u4ece\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65\u6765\u770b":111,"\u4ece\u6e90\u7801\u4e2d\u6784\u5efa\u7528\u4e8e\u7f16\u8bd1paddlepaddle\u7684docker\u955c\u50cf":0,"\u4ece\u6e90\u7801\u4ea4\u53c9\u7f16\u8bd1ios\u5e73\u53f0\u4e0a\u9002\u7528\u7684paddlepaddle\u5e93":117,"\u4ece\u6e90\u7801\u4ea4\u53c9\u7f16\u8bd1paddlepaddl":116,"\u4ece\u6e90\u7801\u7f16\u8bd1":2,"\u4ece\u78c1\u76d8\u52a0\u8f7d\u9884\u6d4b\u6a21\u578b":90,"\u4ece\u78c1\u76d8\u6587\u4ef6\u4e2d\u52a0\u8f7duuid\u6587\u4ef6\u540d\u7684\u68c0\u67e5\u70b9\u5feb\u7167\u6587\u4ef6":10,"\u4ece\u800c\u53ef\u4ee5\u505a\u4e00\u4e9b\u4e0e\u8ba1\u7b97\u91cd\u53e0\u7684\u5de5\u4f5c":74,"\u4ece\u800c\u5f15\u53d1\u5176\u4ed6\u8282\u70b9\u65e0\u6cd5\u8fde\u63a5\u5bfc\u81f4":79,"\u4ece\u800c\u907f\u514d\u4e86packing\u5197\u4f59":41,"\u4ece\u8bed\u4e49\u4e0a\u770b":113,"\u4ece\u8d77\u59cb\u7aef\u53e3\u76d1\u542c\u591a\u4e2a\u7aef\u53e3\u7528\u4e8e\u901a\u4fe1":91,"\u4ece\u8f93\u5165\u6570\u636e\u4e0a\u770b":111,"\u4ececmake":116,"\u4eceetcd\u4e2d\u8bfb\u53d6\u8282\u70b9":10,"\u4ecestart":103,"\u4ed3\u5e93\u7684\u8fdc\u7a0b\u4e3b\u673a":72,"\u4ed6\u4e3b\u8981\u5305\u542b\u4e86\u5b9e\u9645\u66b4\u9732\u7684\u7c7b\u578b\u7ed3\u6784":46,"\u4ed6\u4eec\u5206\u522b\u662f":111,"\u4ed6\u4eec\u5728\u81ea\u5df1\u7684":0,"\u4ed6\u4eec\u5728paddle\u7684\u6587\u6863\u548capi\u4e2d\u662f\u4e00\u4e2a\u6982\u5ff5":111,"\u4ed6\u662f\u5c06":46,"\u4ed6\u7684\u76ee\u6807\u662f\u4f7f\u7528c":45,"\u4ee3\u66ff":97,"\u4ee3\u7801\u4e2d9":111,"\u4ee3\u7801\u53c2\u8003":91,"\u4ee3\u7801\u5982\u4e0b":[81,82,83,114],"\u4ee3\u7801\u6ce8\u91ca\u8bf7\u9075\u5b88":72,"\u4ee3\u7801\u7247\u6bb5\u5982\u4e0b":89,"\u4ee3\u7801\u751f\u6210\u7684\u7b26\u53f7\u53ef\u80fd\u4e0d\u4e00\u81f4":45,"\u4ee3\u7801\u7684\u6027\u80fd\u5206\u6790":107,"\u4ee3\u7801\u793a\u4f8b\u5982\u4e0b":[75,90],"\u4ee3\u8868\u5bbf\u4e3b\u673a\u76ee\u5f55":97,"\u4ee3\u8868\u8fd9\u4e2alayer\u662f\u7528\u4e8e\u8dd1\u5728mkl":42,"\u4ee3\u8868\u8fd9\u4e2ashard\u7684\u6700\u5927index":11,"\u4ee3\u8868shard\u7684index":11,"\u4ee5":82,"\u4ee5\u4e0a":[72,116],"\u4ee5\u4e0a\u4e24\u79cd\u65b9\u5f0f\u53ea\u9700\u9009\u62e9\u5176\u4e00\u5373\u53ef":90,"\u4ee5\u4e0a\u4ee3\u7801\u7684reader\u8f93\u51fa\u7684data":11,"\u4ee5\u4e0a\u547d\u4ee4\u4f1a\u5728\u5f53\u524d\u76ee\u5f55\u4e0b\u751f\u6210100\u4e2a\u6587\u4ef6":11,"\u4ee5\u4e0b":11,"\u4ee5\u4e0b\u4ee3\u7801\u7247\u6bb5\u5b9a\u4e49":114,"\u4ee5\u4e0b\u5c06\u4e00\u4e00\u4ecb\u7ecd":94,"\u4ee5\u4e0b\u6307\u4ee4\u80fd\u68c0\u67e5linux\u7535\u8111\u662f\u5426\u652f\u6301avx":1,"\u4ee5\u4e0b\u6307\u5357\u4ecb\u7ecd\u4e86\u5982\u4f55\u4f7f\u7528openmpi\u6765\u642d\u5efapaddlepaddle\u7684\u96c6\u7fa4\u8bad\u7ec3\u4efb\u52a1":94,"\u4ee5\u4e0b\u6307\u5357\u5c55\u793a\u4e86paddlepaddle\u5bf9kubernetes\u7684\u652f\u6301":94,"\u4ee5\u4e0b\u64cd\u4f5c\u5747\u5728head\u8282\u70b9\u4e2d\u6267\u884c":98,"\u4ee5\u4e0b\u6559\u7a0b\u5c06\u6307\u5bfc\u60a8\u63d0\u4ea4\u4ee3\u7801":72,"\u4ee5\u4e0b\u7b80\u79f0rnn":41,"\u4ee5\u4ea4\u4e92\u5f0f\u7684\u65b9\u5f0f\u6267\u884c\u6216\u8c03\u8bd5\u60a8\u7684\u4ee3\u7801":1,"\u4ee5\u4f7f\u7528":116,"\u4ee5\u4f7f\u7528adam\u7b97\u6cd5\u4e3a\u4f8b":83,"\u4ee5\u4fbf\u6211\u4eec\u53ef\u4ee5\u628a\u66f4\u591a\u7684\u7cbe\u529b\u653e\u5230\u903b\u8f91\u672c\u8eab\u4e0a":27,"\u4ee5\u4fbf\u83b7\u5f97\u8bad\u7ec3\u6570\u636e\u7684\u4f4d\u7f6e\u548c\u83b7\u53d6\u73af\u5883\u53d8\u91cf\u914d\u7f6e":91,"\u4ee5\u4fdd\u8bc1\u68af\u5ea6\u7684\u6b63\u786e\u8ba1\u7b97":74,"\u4ee5\u4fdd\u8bc1\u68af\u5ea6\u8ba1\u7b97\u7684\u6b63\u786e\u6027":74,"\u4ee5\u4fdd\u8bc1\u7f16\u8bd1\u9ad8\u6548":0,"\u4ee5\u51cf\u5c0fsdk\u7684\u4f53\u79ef":88,"\u4ee5\u53ca":[41,74,89],"\u4ee5\u53ca\u4f7f\u7528\u5b50\u5e8f\u5217\u6765\u5b9a\u4e49\u5206\u7ea7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u67b6\u6784":114,"\u4ee5\u53ca\u5207\u6362\u673a\u5668\u65f6\u9700\u8981\u65b0\u5b89\u88c5\u7684\u8f9b\u82e6":0,"\u4ee5\u53ca\u53cc\u5c42\u5e8f\u5217":110,"\u4ee5\u53ca\u5982\u4f55\u89e3\u6790\u795e\u7ecf\u7f51\u7edc\u524d\u5411\u8ba1\u7b97\u7684\u8f93\u51fa\u7ed3\u679c":89,"\u4ee5\u53ca\u76ee\u6807\u673a\u7248openblas\u5e93":118,"\u4ee5\u53ca\u76f8\u5173\u7684\u5c5e\u6027\u53c2\u6570":75,"\u4ee5\u53ca\u7b2c\u4e09\u65b9\u4f9d\u8d56\u94fe\u63a5\u5e93\u548c\u5934\u6587\u4ef6":87,"\u4ee5\u53ca\u8ba1\u7b97\u903b\u8f91\u5728\u5e8f\u5217\u4e0a\u7684\u5faa\u73af\u5c55\u5f00":113,"\u4ee5\u53ca\u8f93\u5165\u7684\u68af\u5ea6":74,"\u4ee5\u53caandroid":116,"\u4ee5\u53canumpi":11,"\u4ee5\u53carelu":74,"\u4ee5\u5b9e\u73b0\u5bf9\u6a21\u578b\u8bad\u7ec3\u6216\u9884\u6d4b\u6d41\u7a0b\u7684\u63a7\u5236":104,"\u4ee5\u63d0\u4f9b\u4e00\u4e9b\u9ed8\u8ba4\u7684\u7f16\u8bd1\u5668\u548c\u7f16\u8bd1\u53c2\u6570\u76f8\u5173\u914d\u7f6e":116,"\u4ee5\u63d0\u4f9b\u4e00\u4e9b\u9ed8\u8ba4\u7684\u7f16\u8bd1\u5668\u548c\u7f16\u8bd1\u53c2\u6570\u914d\u7f6e":117,"\u4ee5\u6b64\u8fbe\u5230\u6700\u597d\u7684\u6027\u80fd":42,"\u4ee5\u786e\u4fdd\u6240\u6709\u7684\u7b2c\u4e09\u65b9\u4f9d\u8d56\u5e93\u548cpaddlepaddle\u4ee3\u7801\u90fd\u662f\u9488\u5bf9\u65b0\u7684cmake\u914d\u7f6e\u91cd\u65b0\u7f16\u8bd1\u7684":[116,117,118],"\u4ee5\u793a\u533a\u5206":[41,42],"\u4ee5\u8f93\u51fa":81,"\u4ee5\u9017\u53f7\u95f4\u9694":103,"\u4ee5\u907f\u514d\u94fe\u63a5\u4e0d\u5fc5\u8981\u7684\u5e93":87,"\u4ee5eigentensor\u4e3a\u4f8b":76,"\u4ee5embedding\u5c42\u4e3a\u4f8b":83,"\u4ee5lstm\u4e3a\u4f8b":82,"\u4efb\u4f55\u65f6\u5019\u5982\u679c\u9700\u8981\u6d6e\u70b9\u578b\u6570\u7ec4":89,"\u4efb\u52a1\u6765\u7ec8\u6b62\u96c6\u7fa4\u4f5c\u4e1a":93,"\u4efb\u610f\u5c06\u4e00\u4e9b\u6570\u636e\u7ec4\u5408\u6210\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217":111,"\u4efb\u610f\u65f6\u523b\u53ea\u53ef\u80fd\u540c\u65f6\u6709\u4e00\u53f0\u670d\u52a1\u5668\u6545\u969c":10,"\u4f18\u5316\u524d":41,"\u4f18\u5316\u540e":41,"\u4f18\u5316\u5668\u5219\u7528\u94fe\u5f0f\u6cd5\u5219\u6765\u5bf9\u6bcf\u4e2a\u53c2\u6570\u8ba1\u7b97\u635f\u5931\u51fd\u6570\u7684\u68af\u5ea6":74,"\u4f1a\u4ea7\u751f\u5f53\u524dpython\u4e8c\u8fdb\u5236\u7684\u5b8c\u6574\u8def\u5f84":107,"\u4f1a\u4ee5":[41,42],"\u4f1a\u4f7f\u7528":90,"\u4f1a\u4f7f\u7528\u76f8\u540c\u7684\u539f\u6570\u636e":41,"\u4f1a\u5148\u4e34\u65f6\u4fdd\u5b58\u5728":42,"\u4f1a\u5148\u8fdb\u884c\u53c2\u6570\u7684\u521d\u59cb\u5316\u4e0e\u89e3\u6790":97,"\u4f1a\u5171\u4eab\u53c2\u6570":83,"\u4f1a\u5173\u8054\u53c2\u6570":82,"\u4f1a\u52a0\u8f7d\u4e0a\u4e00\u8f6e\u7684\u53c2\u6570":103,"\u4f1a\u53d8\u6210\u8bcd\u8868\u4e2d\u7684\u4f4d\u7f6e":111,"\u4f1a\u542f\u52a8pserver\u4e0etrainer\u8fdb\u7a0b":97,"\u4f1a\u5728":[42,77],"\u4f1a\u5728\u5f53\u524d\u76ee\u5f55\u751f\u6210\u4e24\u4e2a\u5b50\u76ee\u5f55":77,"\u4f1a\u5728\u7f16\u8bd1paddlepaddle\u7684\u65f6\u5019\u4e0b\u8f7d\u5e76\u7f16\u8bd1mkl":42,"\u4f1a\u5927\u4e0d\u76f8\u540c":91,"\u4f1a\u5bf9\u6bcf\u4e00\u4e2a\u6fc0\u6d3b\u6682\u5b58\u4e00\u4e9b\u6570\u636e":81,"\u4f1a\u5bf9\u8bad\u7ec3\u6027\u80fd\u9020\u6210\u5f71\u54cd":81,"\u4f1a\u5bf9\u8fd9\u7c7b\u8f93\u5165\u8fdb\u884c\u62c6\u89e3":113,"\u4f1a\u5bfc\u81f4\u4e0d\u540c\u7248\u672cpython\u5728\u4e00\u4e2a\u8fdb\u7a0b\u91cc\u7684bug":45,"\u4f1a\u5c06\u6bcf\u4e2a\u65f6\u95f4\u6b65\u7684\u8f93\u51fa\u62fc\u63a5":113,"\u4f1a\u5c06\u7b2c\u4e00\u4e2a":81,"\u4f1a\u5f15\u5165":42,"\u4f1a\u6210\u4e3astep\u51fd\u6570\u7684\u8f93\u5165":113,"\u4f1a\u6253\u5370\u5230\u6807\u51c6\u8f93\u51fa":107,"\u4f1a\u6267\u884c":0,"\u4f1a\u628a\u8bad\u7ec3\u96c6\u548c\u6d4b\u8bd5\u96c6\u5206\u522b\u5206\u5272\u6210\u591a\u4e2a\u6587\u4ef6":91,"\u4f1a\u628acpu\u7684buffer\u5bf9\u9f50\u4e3a4096":42,"\u4f1a\u62a5\u5982\u4e0b\u7684\u9519\u8bef":81,"\u4f1a\u62a5\u9519":113,"\u4f1a\u6dfb\u52a0\u76f8\u5e94\u7684\u811a\u672c\u5728":42,"\u4f1a\u6dfb\u52a0\u76f8\u5e94\u7684\u811a\u672c\u7528\u4e8e\u6d4b\u8bd5\u548c\u5bf9\u6bd4\u5728\u4f7f\u7528mkl":41,"\u4f1a\u72ec\u7acb\u62e5\u6709\u4e00\u4efd\u8bad\u7ec3\u597d\u7684\u6a21\u578b":90,"\u4f1a\u751f\u6210\u6027\u80fd\u5206\u6790\u7ed3\u679c\u6587\u4ef6":107,"\u4f1a\u76f4\u63a5\u62a5\u9519\u9000\u51fa":45,"\u4f1a\u76f8\u5e94\u5730\u6539\u53d8\u8f93\u51fa\u7684\u5c3a\u5bf8":74,"\u4f1a\u81ea\u52a8\u4f7f\u7528mklml\u5e93\u4f5c\u4e3apaddlepaddle\u7684cblas\u548clapack\u5e93":42,"\u4f1a\u81ea\u52a8\u5173\u95ed\u5bf9\u5e94\u7684issu":72,"\u4f1a\u81ea\u52a8\u5728\u7f16\u8bd1\u65f6\u4e0b\u8f7d":0,"\u4f1a\u81ea\u52a8\u6839\u636e\u786c\u4ef6\u914d\u7f6e":42,"\u4f1a\u83b7\u53d6\u5f53\u524dnamespace\u4e0b\u7684\u6240\u6709pod":97,"\u4f1a\u88ab":91,"\u4f1a\u88ab\u62c6\u89e3\u4e3a\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":113,"\u4f1a\u88ab\u62c6\u89e3\u4e3a\u975e\u5e8f\u5217":113,"\u4f1a\u88abpickle\u5e8f\u5217\u5316\u6210\u5b57\u7b26\u4e32":11,"\u4f1a\u901a\u8fc7\u5224\u6570\u636e\u662f\u5426\u9644\u5e26\u6709\u5e8f\u5217\u4fe1\u606f\u6765\u5224\u65ad\u4e00\u4e2a\u5411\u91cf":89,"\u4f1a\u9020\u6210\u90ae\u4ef6\u707e\u96be":72,"\u4f20\u5165":11,"\u4f20\u7ed9dataprovider\u7684\u67d0\u4e00\u4e2aargs\u8fc7\u5927":83,"\u4f20\u9012\u7ed9\u914d\u7f6e\u6587\u4ef6\u7684\u53c2\u6570":103,"\u4f46":46,"\u4f46\u4e0d\u66b4\u9732":46,"\u4f46\u4e0d\u7528\u4e8e\u8ba1\u7b97\u68af\u5ea6":74,"\u4f46\u4e0d\u9700\u8981\u63d0\u524d\u521b\u5efa":103,"\u4f46\u4e8e\u53cc\u5c42\u5e8f\u5217\u7684lstm\u6765\u8bf4":111,"\u4f46\u53ef\u4ee5\u83b7\u53d6":81,"\u4f46\u548c\u5355\u5c42rnn\u4e0d\u540c":111,"\u4f46\u5b50\u53e5\u542b\u6709\u7684\u8bcd\u8bed\u6570\u53ef\u4ee5\u4e0d\u76f8\u7b49":113,"\u4f46\u5c3d\u91cf\u8bf7\u4fdd\u6301\u7f16\u8bd1\u548c\u8fd0\u884c\u4f7f\u7528\u7684cudnn\u662f\u540c\u4e00\u4e2a\u7248\u672c":0,"\u4f46\u5e76\u6ca1\u6709\u7ecf\u8fc7\u56de\u5f52\u6d4b\u8bd5":63,"\u4f46\u5e8f\u5217\u8f93\u51fa\u65f6":111,"\u4f46\u622a\u65ad\u65f6\u673a\u4e0d\u540c":81,"\u4f46\u6240\u6709fork\u7684\u7248\u672c\u5e93\u7684\u6240\u6709\u5206\u652f\u90fd\u76f8\u5f53\u4e8e\u7279\u6027\u5206\u652f":63,"\u4f46\u662f":[81,111],"\u4f46\u662f\u53c8\u8fc7\u4e8e\u7410\u788e":46,"\u4f46\u662f\u5728mkl":42,"\u4f46\u662f\u5728paddlepaddle\u4e2d":42,"\u4f46\u662f\u5927\u90e8\u5206\u53c2\u6570\u662f\u4e3a\u5f00\u53d1\u8005\u63d0\u4f9b\u7684":102,"\u4f46\u662f\u5b50\u5e8f\u5217\u7684\u6570\u76ee\u5fc5\u987b\u4e00\u6837":111,"\u4f46\u662f\u5e76\u4e0d\u80fd\u4fdd\u8bc1\u53c2\u6570\u540c\u6b65\u66f4\u65b0":92,"\u4f46\u662f\u652f\u6301avx\u6307\u4ee4\u96c6":72,"\u4f46\u662f\u6574\u4e2a\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u4e0d\u9700\u8981\u4efb\u4f55\u8f6c\u6362":42,"\u4f46\u662f\u6bcf\u4e2a\u6837\u672c\u4ec5\u5305\u542b\u51e0\u4e2a\u8bcd":105,"\u4f46\u662f\u6ce8\u610f\u7684\u662f":42,"\u4f46\u662f\u7a81\u7136\u6709\u4e00\u4e2a10000\u957f\u7684\u5e8f\u5217":81,"\u4f46\u662f\u865a\u62df\u7684\u4e0d\u4ec5\u4ec5\u662f":0,"\u4f46\u662f\u89e3\u91ca\u6027\u8bed\u8a00":45,"\u4f46\u662f\u8c03\u8bd5python\u4e2d\u4f7f\u7528\u7684\u52a8\u6001\u94fe\u63a5\u5e93\u4e0e\u76f4\u63a5\u8c03\u8bd5\u539f\u59cb\u4e8c\u8fdb\u5236\u76f8\u6bd4\u589e\u52a0\u4e86\u5f88\u591a\u590d\u6742\u5ea6":107,"\u4f46\u662fbatch":81,"\u4f46\u6709\u503c\u7684\u5730\u65b9\u5fc5\u987b\u4e3a1":84,"\u4f46\u6709\u503c\u7684\u90e8\u5206\u53ef\u4ee5\u662f\u4efb\u4f55\u6d6e\u70b9\u6570":84,"\u4f46\u7531\u4e8ecuda\u5e93\u901a\u5e38\u9700\u8981cento":3,"\u4f46\u9700\u6ce8\u610f\u53cd\u5411op\u6ca1\u6709":75,"\u4f46eigen":76,"\u4f5c\u4e3a\u4e0b\u4e00\u4e2a\u5b50\u53e5memory\u7684\u521d\u59cb\u72b6\u6001":111,"\u4f5c\u4e3a\u4f8b\u5b50\u6f14\u793a\u5982\u4f55\u914d\u7f6e\u590d\u6742\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u6a21\u578b":114,"\u4f5c\u4e3a\u53c2\u6570\u5c5e\u6027":75,"\u4f5c\u4e3a\u53c2\u6570\u7684id":83,"\u4f5c\u4e3a\u53e6\u4e00\u4e2a\u7b2c\u4e09\u65b9\u5e93\u96c6\u6210\u8fdbpaddlepaddl":42,"\u4f5c\u4e3a\u5b58\u50a8\u7cfb\u7edf":11,"\u4f5c\u4e3a\u5f53\u524d\u65f6\u523b\u8f93\u5165":113,"\u4f5c\u4e3a\u7c7b\u53e5\u67c4":45,"\u4f5c\u4e3a\u7edf\u8ba1\u7684\u57fa\u672c\u5355\u4f4d":89,"\u4f5c\u4e3a\u8c03\u7528":90,"\u4f5c\u4e3a\u8f93\u5165":89,"\u4f5c\u4e3a\u8f93\u51fa":114,"\u4f5c\u4e3aboot_layer\u4f20\u7ed9\u4e0b\u4e00\u4e2a\u5b50\u53e5\u7684memori":111,"\u4f5c\u7528":110,"\u4f60\u53ef\u4ee5\u5c06\u7f51\u7edc\u914d\u7f6e\u6210\u67d0\u4e9b\u5c42\u4f7f\u7528gpu\u8ba1\u7b97":105,"\u4f60\u8fd8\u53ef\u4ee5\u901a\u8fc7\u8fd0\u884cdjango\u6846\u67b6\u76f4\u63a5\u6fc0\u6d3b\u5de5\u5177\u7684\u670d\u52a1\u5668":77,"\u4f60\u9700\u8981\u4e00\u4e9b\u66f4\u590d\u6742\u7684\u5355\u5143\u6d4b\u8bd5\u6765\u4fdd\u8bc1\u4f60\u5b9e\u73b0\u7684\u7f51\u7edc\u5c42\u662f\u6b63\u786e\u7684":74,"\u4f60\u9700\u8981\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d\u6307\u5b9a\u8bbe\u5907\u7684id\u53f7":105,"\u4f60\u9700\u8981\u5728\u914d\u7f6ecmake\u65f6\u5c06":74,"\u4f60\u9700\u8981\u628a\u8be5\u6587\u4ef6\u52a0\u5165":74,"\u4f7f\u4e4b\u53d8\u4e3a\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217\u8f93\u5165":89,"\u4f7f\u4e4b\u53d8\u4e3a\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217\u8f93\u5165":89,"\u4f7f\u5f97\u5355\u5143\u6d4b\u8bd5\u6709\u4e00\u4e2a\u5e72\u51c0\u7684\u73af\u5883":78,"\u4f7f\u5f97\u642d\u6a21\u578b\u65f6\u66f4\u65b9\u4fbf":74,"\u4f7f\u68af\u5ea6\u7684\u63d0\u4ea4\u548c\u53c2\u6570\u7684\u66f4\u65b0\u6309\u7167\u987a\u5e8f\u65b9\u5f0f\u6267\u884c":92,"\u4f7f\u7528":[42,46,63,74,81,82,83,87,89,90,103,107,108,111,113,114,116],"\u4f7f\u75280\u53f7\u548c1\u53f7gpu\u8ba1\u7b97fc2\u5c42":105,"\u4f7f\u75280\u53f7gpu\u8ba1\u7b97fc2\u5c42":105,"\u4f7f\u75281\u53f7gpu\u8ba1\u7b97fc3\u5c42":105,"\u4f7f\u75282\u53f7\u548c3\u53f7gpu\u8ba1\u7b97fc3\u5c42":105,"\u4f7f\u7528\u4e00\u4e2a\u5c3a\u5ea6\u4e3a":74,"\u4f7f\u7528\u4e00\u4e2a\u8bcd\u524d\u4e24\u4e2a\u8bcd\u548c\u540e\u4e24\u4e2a\u8bcd":81,"\u4f7f\u7528\u4e0a\u6587\u521b\u5efa\u7684yaml\u6587\u4ef6\u521b\u5efakubernet":96,"\u4f7f\u7528\u4e0b\u9762\u547d\u4ee4":11,"\u4f7f\u7528\u4e0b\u9762\u7684\u547d\u4ee4\u6765\u8fd0\u884c\u5b83":77,"\u4f7f\u7528\u4e86\u540c\u6837\u7684parameter\u548cbia":83,"\u4f7f\u7528\u4ee5\u4e0a\u8bad\u7ec3\u597d\u7684\u6a21\u578b\u8fdb\u884c\u9884\u6d4b":84,"\u4f7f\u7528\u52a8\u6001\u5e93":45,"\u4f7f\u7528\u53c2\u6570":[0,91],"\u4f7f\u7528\u540c\u6837\u7684\u8bad\u7ec3\u6570\u636eblock":10,"\u4f7f\u7528\u57fa\u4e8edocker\u5bb9\u5668\u7684\u7f16\u8bd1\u65b9\u5f0f":116,"\u4f7f\u7528\u591a\u5757\u663e\u5361\u8bad\u7ec3":81,"\u4f7f\u7528\u591a\u7ebf\u7a0b\u8bad\u7ec3":81,"\u4f7f\u7528\u5b66\u4e60\u5b8c\u6210\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u6a21\u578b\u751f\u6210\u5e8f\u5217":114,"\u4f7f\u7528\u5b83\u4f1a\u5f00\u542f\u4e00\u4e2ahttp\u670d\u52a1":107,"\u4f7f\u7528\u5bb9\u5668\u65b9\u5f0f\u8fd0\u884c\u8bad\u7ec3\u4efb\u52a1\u7684kubernet":97,"\u4f7f\u7528\u6211\u4eec\u4e4b\u524d\u6784\u9020\u7684\u955c\u50cf":96,"\u4f7f\u7528\u6570\u503c\u6cd5\u68c0\u6d4b\u68af\u5ea6\u6b63\u786e\u6027\u548c\u7a33\u5b9a\u6027":75,"\u4f7f\u7528\u6587\u6863":75,"\u4f7f\u7528\u663e\u5361\u8bad\u7ec3":81,"\u4f7f\u7528\u667a\u80fd\u6307\u9488\u7684\u539f\u56e0\u662f":46,"\u4f7f\u7528\u6848\u4f8b":104,"\u4f7f\u7528\u73af\u5883\u53d8\u91cf":91,"\u4f7f\u7528\u7684\u53c2\u6570\u4e0epaddlepaddle\u7533\u8bf7\u7684buffer\u5171\u7528\u4e00\u5757\u5185\u5b58":42,"\u4f7f\u7528\u76f8\u5bf9\u8def\u5f84\u7684\u5f15\u7528\u65b9\u5f0f":46,"\u4f7f\u7528\u8005\u4e0d\u9700\u8981\u5173\u5fc3":103,"\u4f7f\u7528\u8005\u53ea\u9700\u8981\u5173\u6ce8\u4e8e\u8bbe\u8ba1rnn\u5728\u4e00\u4e2a\u65f6\u95f4\u6b65\u4e4b\u5185\u5b8c\u6210\u7684\u8ba1\u7b97":113,"\u4f7f\u7528\u8005\u65e0\u9700\u5173\u5fc3\u8fd9\u4e2a\u53c2\u6570":103,"\u4f7f\u7528\u8005\u901a\u5e38\u65e0\u9700\u5173\u5fc3":103,"\u4f7f\u7528\u8be5learning_rate_schedule\u65f6":83,"\u4f7f\u7528\u8fd9\u4e2a\u795e\u7ecf\u7f51\u7edc\u53ef\u4ee5\u5b8c\u6210\u5bf9\u65b0\u6570\u636e\u7684\u9884\u6d4b":10,"\u4f7f\u7528\u8fd9\u79cd\u65b9\u5f0f":[90,111],"\u4f7f\u7528\u8fdc\u7a0b\u7a00\u758f\u65b9\u5f0f\u8bad\u7ec3\u65f6":74,"\u4f7f\u7528\u9759\u6001\u5e93\u548c\u52a8\u6001\u5e93\u96be\u5ea6\u5dee\u4e0d\u591a":45,"\u4f7f\u7528c":[46,87],"\u4f7f\u7528c99\u505a\u63a5\u53e3":45,"\u4f7f\u7528c99\u800c\u4e0d\u4f7f\u7528c11\u7684\u539f\u56e0\u662f":45,"\u4f7f\u7528c99\u800c\u4e0d\u4f7f\u7528c89":45,"\u4f7f\u7528checkgrad\u6a21\u5f0f\u65f6\u7684\u53c2\u6570\u53d8\u5316\u5927\u5c0f":103,"\u4f7f\u7528cmake\u7684\u8bdd":107,"\u4f7f\u7528cpu\u4e24\u7ebf\u7a0b\u8ba1\u7b97fc4\u5c42":105,"\u4f7f\u7528cpu\u8ba1\u7b97fc4\u5c42":105,"\u4f7f\u7528docker":1,"\u4f7f\u7528docker\u5b89\u88c5\u548c\u8fd0\u884cpaddlepaddle\u53ef\u4ee5\u65e0\u9700\u8003\u8651":1,"\u4f7f\u7528docker\u5b89\u88c5\u8fd0\u884c":2,"\u4f7f\u7528docker\u5c31\u4e0d\u7528\u914d\u7f6e\u4ea4\u53c9\u7f16\u8bd1\u73af\u5883\u4e86":0,"\u4f7f\u7528docker\u6784\u5efapaddlepaddle\u7684\u6587\u6863":77,"\u4f7f\u7528eigen\u8fdb\u884c\u77e9\u9635\u8ba1\u7b97":116,"\u4f7f\u7528fabric\u542f\u52a8\u96c6\u7fa4\u8bad\u7ec3":94,"\u4f7f\u7528init":105,"\u4f7f\u7528lstm\u4f5c\u4e3aencod":111,"\u4f7f\u7528memory\u7684rnn\u5b9e\u73b0\u4fbf\u5982\u4e0b\u56fe\u6240\u793a":111,"\u4f7f\u7528model":105,"\u4f7f\u7528openblas\u7684\u955c\u50cf":1,"\u4f7f\u7528openblas\u8fdb\u884c\u77e9\u9635\u8ba1\u7b97":116,"\u4f7f\u7528paddlepaddl":[87,90],"\u4f7f\u7528pip\u5b89\u88c5":2,"\u4f7f\u7528rdma\u8fd8\u662ftcp\u4f20\u8f93\u534f\u8bae":103,"\u4f7f\u7528regress":63,"\u4f7f\u7528swig\u53ea\u652f\u6301cpython\u89e3\u91ca\u5668":45,"\u4f7f\u7528swig\u9700\u8981\u591a\u8bed\u8a00\u7ed1\u5b9a\u7684\u5f00\u53d1\u4eba\u5458\u719f\u7ec3\u638c\u63e1swig\u914d\u7f6e":45,"\u4f7f\u7528void":45,"\u4f7f\u8be5\u5c42\u7684\u53c2\u6570\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u4fdd\u6301\u4e0d\u53d8":83,"\u4f8b\u5982":[0,11,45,46,63,74,81,82,84,89,91,97,102,103,105,108,111,114],"\u4f8b\u5982\u4e0b\u56fe\u4e2d":107,"\u4f8b\u5982\u4e0b\u9762\u4ee3\u7801":81,"\u4f8b\u5982\u4e5f\u53ef\u5728\u7a0b\u5e8f\u8fd0\u884c\u8fc7\u7a0b\u4e2d\u518d\u52a0\u8f7d\u53e6\u5916\u4e00\u4e2a\u6a21\u578b":90,"\u4f8b\u5982\u4f7f\u7528":81,"\u4f8b\u5982\u542b\u6709\u591a\u4e2a\u901a\u9053\u7684\u56fe\u7247":89,"\u4f8b\u5982\u5728deepspeech2":41,"\u4f8b\u5982\u5bf9\u4e8ejava\u6216\u8005python":45,"\u4f8b\u5982\u5bf9\u4e8ejava\u6765\u8bf4":45,"\u4f8b\u5982\u5bf9\u4e8epython":45,"\u4f8b\u5982\u5c06\u7b2c\u4e00\u6761\u6570\u636e\u8f6c\u5316\u4e3a":111,"\u4f8b\u5982\u6587\u672c\u5206\u7c7b\u4e2d":111,"\u4f8b\u5982\u672c\u4f8b\u4e2d\u7684\u4e24\u4e2a\u7279\u5f81":111,"\u4f8b\u5982\u673a\u5668\u4e0a\u67094\u5757gpu":81,"\u4f8b\u5982c":45,"\u4f8b\u5982java\u4e0epython\u7684\u9519\u8bef\u5904\u7406\u662f\u76f4\u63a5\u6254\u51fa\u6765except":45,"\u4f8b\u5982output\u76ee\u5f55\u4e0b\u5c31\u5b58\u653e\u4e86\u8f93\u51fa\u7ed3\u679c":97,"\u4f8b\u5982python\u53ef\u4ee5\u4f7f\u7528":45,"\u4f8b\u5982python\u7684":45,"\u4f8b\u5982rnn":41,"\u4f8b\u5982sigmoid":74,"\u4f8b\u5b50\u4e2d\u4e3a3\u4e2a":91,"\u4f8b\u5b50\u4e2d\u662f":74,"\u4f8b\u5b50\u4e2d\u662f0":74,"\u4f8b\u5b50\u4e2d\u662f100":74,"\u4f8b\u5b50\u4e2d\u662f4096":74,"\u4f8b\u5b50\u4e2d\u662f8192":74,"\u4f8b\u5b50\u4e2d\u662ffc":74,"\u4f8b\u5b50\u4e2d\u662fsoftmax":74,"\u4f9bpaddlepaddle\u52a0\u8f7d":103,"\u4f9d\u636e\u662f\u5426\u5305\u542bkernel":75,"\u4f9d\u6b21\u7c7b\u63a8":63,"\u4f9d\u8d56":[0,3],"\u4f9d\u8d56\u73af\u5883\u5373\u53ef\u8fd0\u884c":1,"\u4f9d\u8d56libpython2":0,"\u4fbf\u548c\u5355\u5c42rnn\u914d\u7f6e\u4e2d\u7684":111,"\u4fbf\u662f\u5c06\u9759\u6001\u5e93\u52a0\u5165jvm\u4e2d":45,"\u4fdd\u5b58\u6a21\u578b\u53c2\u6570\u7684\u76ee\u5f55":103,"\u4fdd\u5b58\u7684\u53c2\u6570\u4e5f\u662ffloat\u7c7b\u578b":83,"\u4fdd\u5b58\u7f51\u7edc\u5c42\u8f93\u51fa\u7ed3\u679c\u7684\u76ee\u5f55":103,"\u4fdd\u5b58\u9884\u6d4b\u7ed3\u679c\u7684\u6587\u4ef6\u540d":103,"\u4fdd\u6301\u5c3d\u91cf\u5c11\u7684commit":72,"\u4fdd\u8bc1\u4f7f\u7528gpu\u8bad\u7ec3\u65f6\u4e5f\u53ef\u4ee5\u83b7\u5f97":81,"\u4fe1\u53f7\u6765\u81ea\u52a8\u7ec8\u6b62\u5b83\u542f\u52a8\u7684\u6240\u6709\u8fdb\u7a0b":93,"\u4fe1\u606f":89,"\u4fee\u590d\u6240\u6709bug\u540e":63,"\u4fee\u590ddocker\u7f16\u8bd1\u955c\u50cf\u95ee\u9898":63,"\u4fee\u6539":[42,63,96],"\u4fee\u6539\u542f\u52a8\u811a\u672c\u540e":96,"\u4fee\u6539\u6210":63,"\u4fee\u6539\u6210\u66f4\u5feb\u7684\u7248\u672c":108,"\u503c\u5f97\u6ce8\u610f\u7684\u662f":[72,111],"\u503c\u5f97\u6df1\u5165\u5206\u6790":108,"\u503c\u7c7b\u578b":105,"\u5047\u5982\u6211\u4eec\u662f\u4e09\u5206\u7c7b\u95ee\u9898":83,"\u5047\u8bbe":74,"\u5047\u8bbe\u60a8\u5df2\u7ecf\u5728\u5f53\u524d\u76ee\u5f55":1,"\u5047\u8bbe\u635f\u5931\u51fd\u6570\u662f":74,"\u5047\u8bbe\u7b2c\u4e00\u4e2alayer\u7684\u8f93\u51faa\u662f\u4e00\u4e2a":81,"\u504f\u7f6e\u53c2\u6570\u7684\u5927\u5c0f":74,"\u505a\u4e00\u4e2a\u4ecb\u7ecd":76,"\u505a\u53ea\u8bfb\u6302\u8f7d":11,"\u505a\u5982\u4e0b\u51e0\u4e2a\u64cd\u4f5c":63,"\u505a\u63a5\u53e3":45,"\u505a\u68af\u5ea6\u68c0\u6d4b":75,"\u505a\u68c0\u67e5":75,"\u505c\u6b62\u4fdd\u5b58\u68c0\u67e5\u70b9\u7684\u7ebf\u7a0b":10,"\u505c\u6b62\u52a0\u8f7d\u6570\u636e":103,"\u5141\u8bb8\u5916\u7f51\u8bbf\u95ee\u8fd9\u4e2ahttp\u670d\u52a1":107,"\u5143\u7d20":110,"\u5143\u7d20\u4e4b\u95f4\u7684\u987a\u5e8f\u662f\u5e8f\u5217\u6240\u643a\u5e26\u7684\u91cd\u8981\u4fe1\u606f":89,"\u5143\u7d20\u4e4b\u95f4\u7684\u987a\u5e8f\u662f\u91cd\u8981\u7684\u8f93\u5165\u4fe1\u606f":110,"\u5145\u5206\u53d1\u6325\u82f1\u7279\u5c14\u5e73\u53f0\u7684\u4f18\u52bf":41,"\u5145\u5206\u5c55\u73b0\u82f1\u7279\u5c14\u5e73\u53f0\u7684\u4f18\u52bf":42,"\u5148\u4ece\u5355\u7ebf\u7a0b\u5f00\u59cb":107,"\u5148\u5378\u8f7d\u4e4b\u524d\u7684\u7248\u672c":0,"\u5148\u5b8c\u6210\u5bf9\u6743\u91cd\u7684packing\u64cd\u4f5c":41,"\u5148\u5b9e\u73b0\u6a21\u578b\u63a8\u65ad\u7684api":46,"\u5148\u627e\u51fa\u53c2\u6570":82,"\u5148\u67e5\u770b\u4e00\u4e0b\u662f\u5426\u66fe\u7ecf\u5b89\u88c5\u8fc7paddl":78,"\u5148\u68c0\u67e5\u5173\u952e\u8def\u5f84\u7684\u6027\u80fd\u95ee\u9898":107,"\u514b\u9686\u4e0b\u9762":118,"\u5168\u8fde\u63a5\u5c42\u4ee5\u4e00\u4e2a\u7ef4\u5ea6\u4e3a":74,"\u5168\u8fde\u63a5\u5c42\u6ca1\u6709\u7f51\u7edc\u5c42\u914d\u7f6e\u7684\u8d85\u53c2\u6570":74,"\u5168\u8fde\u63a5\u5c42\u7684\u5b9e\u73b0\u4f4d\u4e8e":74,"\u5168\u8fde\u63a5\u5c42\u7684\u6bcf\u4e2a\u8f93\u51fa\u90fd\u8fde\u63a5\u5230\u4e0a\u4e00\u5c42\u7684\u6240\u6709\u7684\u795e\u7ecf\u5143\u4e0a":74,"\u5168\u8fde\u63a5\u5c42python\u5c01\u88c5\u7684\u4f8b\u5b50\u4e2d\u5305\u542b\u4e0b\u9762\u51e0\u6b65":74,"\u516c\u5f0f":1,"\u5171\u4eab\u4e00\u4e2aop\u5b9a\u4e49":75,"\u5171\u4eab\u5185\u5b58":42,"\u5171\u4eab\u540c\u4e00\u4e2a\u6743\u91cd":41,"\u5171\u4eab\u540c\u4e00\u4e2akernel\u65f6":75,"\u5171\u4eab\u5b58\u50a8\u6302\u5728\u7684\u8def\u5f84":97,"\u5173\u4e8e\u4ec0\u4e48\u662f":89,"\u5173\u4e8e\u5728paddlepaddle\u4e2d\u5982\u4f55\u4f7f\u7528eigen\u5e93":75,"\u5173\u4e8e\u65f6\u95f4\u5e8f\u5217":111,"\u5173\u4e8e\u6784\u5efa\u548c\u6d4b\u8bd5\u7684\u66f4\u591a\u4fe1\u606f":72,"\u5173\u4e8eavx":1,"\u5173\u4e8ec":88,"\u5173\u4e8eeigen":76,"\u5173\u4e8elstm":82,"\u5173\u4e8epaddlepaddle\u7684\u5206\u5e03\u5f0f\u8bad\u7ec3":97,"\u5173\u4e8epaddlepaddle\u7684\u66f4\u591a\u4f7f\u7528\u65b9\u6cd5\u8bf7\u53c2\u8003":84,"\u5173\u4e8eunbound":113,"\u5173\u952e\u8bcd\u5305\u62ec":72,"\u5176\u4e2d":[45,63,74,81,83,84,107,114,116,118],"\u5176\u4e2d\u5305\u542b\u4e86\u7528\u6237\u7684\u8bad\u7ec3\u7a0b\u5e8f":91,"\u5176\u4e2d\u5305\u542b\u6240\u4f9d\u8d56\u7684\u6240\u6709\u7b2c\u4e09\u65b9\u5e93":117,"\u5176\u4e2d\u5305\u542b\u6240\u6709c":117,"\u5176\u4e2d\u5305\u542bpaddlepaddle\u7684c":117,"\u5176\u4e2d\u6bcf\u4e2a\u5143\u7d20\u662f\u53cc\u5c42\u5e8f\u5217\u4e2d\u6bcf\u4e2asubseq\u6700\u540e\u4e00\u4e2a":110,"\u5176\u4e2dcheckgrad\u4e3b\u8981\u4e3a\u5f00\u53d1\u8005\u4f7f\u7528":103,"\u5176\u4e2dmean\u548cstd\u662f\u8bad\u7ec3\u914d\u7f6e\u4e2d\u7684\u53c2\u6570":103,"\u5176\u4e2dx\u8868\u793a\u8f93\u5165\u6570\u636e\u662f\u4e00\u4e2a\u7ef4\u5ea6\u4e3a2\u7684\u7a20\u5bc6\u5411\u91cf":84,"\u5176\u4e3b\u8981\u63a5\u53e3\u5982\u4e0b":76,"\u5176\u4ed6\u4eba\u53ef\u4ee5\u590d\u73b0\u95ee\u9898\u4ee5\u4fbf\u5e2e\u52a9":0,"\u5176\u4ed6\u5185\u5b58\u6742\u9879":81,"\u5176\u4ed6\u5185\u5b58\u6742\u9879\u662f\u6307paddlepaddle\u672c\u8eab\u6240\u7528\u7684\u4e00\u4e9b\u5185\u5b58":81,"\u5176\u4ed6\u51fd\u6570\u5747\u8fd4\u56de":46,"\u5176\u4ed6\u6240\u6709\u5c42\u90fd\u4f1a\u4f7f\u7528gpu\u8ba1\u7b97":105,"\u5176\u4ed6\u7528\u6237\u7684fork\u7248\u672c\u5e93\u5e76\u4e0d\u9700\u8981\u4e25\u683c\u9075\u5b88":63,"\u5176\u4ed6\u7684\u4f9d\u8d56\u8f6f\u4ef6":0,"\u5176\u4ed6\u914d\u7f6e\u53c2\u6570":[116,117],"\u5176\u4ed6\u9ad8\u7ea7\u529f\u80fd\u5305\u62ec\u5b9a\u4e49\u591a\u4e2amemori":114,"\u5176\u4f1a\u81ea\u52a8\u88ab\u52a0\u5165\u7f16\u8bd1\u5217\u8868":74,"\u5176\u547d\u4ee4\u5982\u4e0b":107,"\u5176\u5b83\u53ef\u9009\u7f16\u8bd1\u9009\u9879\u6309\u9700\u8fdb\u884c\u8bbe\u5b9a":87,"\u5176\u5b83layer\u7684\u8f93\u51fa":113,"\u5176\u5b9e\u4e5f\u662f\u548c\u6bcf\u4e2amini":81,"\u5176\u6b21":111,"\u5176\u8bf4\u660e\u5982\u4e0b":111,"\u5176\u8f6c\u6362\u6b21\u6570\u51cf\u5c11\u81f3":41,"\u5176\u8f93\u51fa\u88ab\u7528\u4f5cmemory\u7684\u521d\u59cb\u503c":114,"\u5176name\u7531\u53c2\u6570":82,"\u5177\u4f53\u4f7f\u7528\u65b9\u6cd5\u4e3a":[46,81],"\u5177\u4f53\u505a\u6cd5\u8bf7\u53c2\u8003":0,"\u5177\u4f53\u539f\u56e0\u53c2\u8003":46,"\u5177\u4f53\u53ef\u4ee5\u53c2\u8003":[74,81],"\u5177\u4f53\u53ef\u4ee5\u53c2\u8003mkl":42,"\u5177\u4f53\u53ef\u53c2\u8003\u6587\u6863":113,"\u5177\u4f53\u5b9e\u73b0\u65b9\u5f0f\u6bd4\u5982":[41,42],"\u5177\u4f53\u60c5\u51b5\u56e0\u4eba\u800c\u5f02":108,"\u5177\u4f53\u64cd\u4f5c\u5982\u4e0b":78,"\u5177\u4f53\u6b65\u9aa4\u5982\u4e0b":78,"\u5177\u4f53\u7684\u5b8c\u6210\u72b6\u6001\u53ef\u4ee5\u53c2\u89c1":42,"\u5177\u4f53\u7684\u89e3\u51b3\u65b9\u6cd5\u662f":78,"\u5177\u4f53\u8bf7\u53c2\u8003":[46,72],"\u5177\u4f53\u8bf7\u89c1":72,"\u5177\u6709\u76f8\u540c\u7684\u7ed3\u679c\u4e86":111,"\u5185":114,"\u5185\u5b58":108,"\u5185\u5b58\u4e0d\u8db3":79,"\u5185\u5b58\u5bb9\u9650\u9608\u503c":103,"\u5185\u5bb9":75,"\u5185\u5bb9\u5982\u4e0b":96,"\u5185\u5c42\u5e8f\u5217\u5728":89,"\u5185\u5c42inner_step\u7684recurrent_group\u548c\u5355\u5c42\u5e8f\u5217\u7684\u51e0\u4e4e\u4e00\u6837":111,"\u5185\u5df2\u7ecf\u5305\u542bpaddlepaddle\u7684\u6267\u884c\u7a0b\u5e8f\u4f46\u662f\u8fd8\u6ca1\u4e0a\u8ff0\u529f\u80fd":97,"\u5185\u7f6e\u7684":90,"\u5185\u90e8":[90,97],"\u5185\u90e8\u5b58\u50a8":42,"\u5185\u90e8\u7531":[89,90],"\u5185\u90e8\u9a71\u52a8python\u89e3\u91ca\u5668\u8fdb\u884c\u6a21\u578b\u914d\u7f6e\u89e3\u6790\u548c\u6570\u636e\u8bfb\u53d6":45,"\u518d\u4ee5":75,"\u518d\u505a\u4e00\u5b9a\u7684reshap":82,"\u518d\u5199\u5165\u7f51\u7edc\u53c2\u6570":83,"\u518d\u5728\u6bcf\u4e00\u4e2aapi\u4e2d\u81ea\u5df1\u68c0\u67e5\u7c7b\u578b":45,"\u518d\u57fa\u4e8e":63,"\u518d\u5b89\u88c5":[3,78],"\u518d\u5bf9\u6bcf\u4e00\u4e2a\u5355\u5c42\u65f6\u95f4\u5e8f\u5217\u8fdb\u884c\u5904\u7406":111,"\u518d\u5bf9\u6bcf\u4e00\u53e5\u8bdd\u7684\u7f16\u7801\u5411\u91cf\u7528lstm\u7f16\u7801\u6210\u4e00\u4e2a\u6bb5\u843d\u7684\u5411\u91cf":111,"\u518d\u5bf9\u8fd9\u4e2a\u6bb5\u843d\u5411\u91cf\u8fdb\u884c\u5206\u7c7b":111,"\u518d\u5c06\u66f4\u65b0\u540e\u7684\u53c2\u6570\u4e0b\u53d1\u5230\u6bcf\u4e2a\u8ba1\u7b97\u8282\u70b9":92,"\u518d\u5f00\u542f\u591a\u7ebf\u7a0b":107,"\u518d\u628a\u5df2\u8f6c\u6362\u4e3apacked\u683c\u5f0f\u7684\u6570\u636e\u4f20\u9012\u7ed9\u90a3\u4e9b\u590d\u7528\u540c\u4e00\u6570\u636e\u7684gemm":41,"\u518d\u6307\u5b9a":0,"\u518d\u68c0\u67e5\u5176\u4ed6\u90e8\u5206\u7684\u6027\u80fd\u95ee\u9898":107,"\u518d\u6b21\u5bf9\u4ee3\u7801\u8fdb\u884c\u6027\u80fd\u5206\u6790":108,"\u518d\u6b21\u8fdb\u884c\u6027\u80fd\u5206\u6790":107,"\u518d\u7528\u8fd9\u4e2a\u68af\u5ea6\u53bb\u548c":74,"\u518d\u901a\u8fc7\u51fd\u6570":97,"\u518d\u91cd\u65b0\u5b89\u88c5":0,"\u5199\u4ee3\u7801":45,"\u5199\u5165\u5feb\u7167\u6570\u636e":10,"\u5199\u5165\u6587\u4ef6\u4e2d":90,"\u5199\u68af\u5ea6\u68c0\u67e5\u5355\u5143\u6d4b\u8bd5\u662f\u4e00\u4e2a\u9a8c\u8bc1\u65b0\u5b9e\u73b0\u7684\u5c42\u662f\u5426\u6b63\u786e\u7684\u76f8\u5bf9\u7b80\u5355\u7684\u529e\u6cd5":74,"\u5199\u7684":107,"\u51c6\u5907\u60a8\u7684\u8ba1\u7b97\u96c6\u7fa4":101,"\u51c6\u5907\u8bad\u7ec3\u6570\u636e":98,"\u51c6\u5907\u8bad\u7ec3\u6570\u636e\u548c\u9a8c\u8bc1\u6570\u636e\u96c6":91,"\u51c6\u5907\u9884\u6d4b\u6a21\u578b\u548c":90,"\u51c6\u5907\u9884\u6d4b\u6a21\u578b\u90e8\u5206":90,"\u51cf\u5c0f\u5e8f\u5217\u7684\u957f\u5ea6":81,"\u51cf\u5c0f\u8fd9\u4e2a\u5185\u5b58\u6c60\u5373\u53ef\u51cf\u5c0f\u5185\u5b58\u5360\u7528":81,"\u51cf\u5c0fbatch":81,"\u51e0\u53f0\u5230\u51e0\u5343\u53f0\u89c4\u6a21":101,"\u51fa\u73b0":78,"\u51fa\u73b0\u4ee5\u4e0b\u9519\u8bef":83,"\u51fa\u73b0\u8be5\u9519\u8bef\u7684\u539f\u56e0\u4e00\u822c\u662f\u7528\u6237\u5bf9\u4e0d\u540clayer\u7684\u53c2\u6570":82,"\u51fa\u73b0\u8fd9\u4e2a\u95ee\u9898\u7684\u4e3b\u8981\u539f\u56e0\u662f":[3,78],"\u51fd\u6570":[41,42,74,89,107,108,114],"\u51fd\u6570\u4e2d\u64cd\u4f5c\u7684\u91cd\u8981\u53d8\u91cf\u7684\u8be6\u7ec6\u89e3\u91ca":75,"\u51fd\u6570\u5047\u8bbe":114,"\u51fd\u6570\u52a0\u5230\u4ee3\u7801\u4e2d":108,"\u51fd\u6570\u5373\u53ef\u5b8c\u6210\u8f6c\u6362":11,"\u51fd\u6570\u53ea\u5173\u6ce8\u4e8ernn\u4e00\u4e2a\u65f6\u95f4\u6b65\u4e4b\u5185\u7684\u8ba1\u7b97":113,"\u51fd\u6570\u540d":107,"\u51fd\u6570\u540d\u4e3a":46,"\u51fd\u6570\u547d\u540d":45,"\u51fd\u6570\u5b9a\u4e49\u8f93\u5165":75,"\u51fd\u6570\u5b9e\u9645\u4f7f\u7528\u7684\u603b\u65f6\u95f4":107,"\u51fd\u6570\u5f97\u5230\u7684\u68af\u5ea6\u53bb\u5bf9\u6bd4":74,"\u51fd\u6570\u5fc5\u987b\u5148\u8c03\u7528\u57fa\u7c7b\u4e2d\u7684\u51fd\u6570":74,"\u51fd\u6570\u5fc5\u987b\u8fd4\u56de\u4e00\u4e2a\u6216\u591a\u4e2alayer\u7684\u8f93\u51fa":113,"\u51fd\u6570\u603b\u65f6\u95f4":107,"\u51fd\u6570\u6307\u51fa\u4e86\u5728\u8bad\u7ec3\u65f6\u9700\u8981\u4ece\u53c2\u6570\u670d\u52a1\u5668\u53d6\u51fa\u7684\u884c":74,"\u51fd\u6570\u6765\u5c06\u4fe1\u606f\u8f93\u51fa\u5230\u754c\u9762\u4e2d":108,"\u51fd\u6570\u7684\u5b9e\u73b0\u662f\u6b63\u786e\u7684":74,"\u51fd\u6570\u7684\u5f00\u5934\u5fc5\u987b\u8c03\u7528":74,"\u51fd\u6570\u7684\u603b\u5171\u8017\u65f6\u5f88\u957f":107,"\u51fd\u6570\u7684\u8c03\u7528\u6b21\u6570":107,"\u51fd\u6570\u80fd\u591f\u5c06\u4f7f\u7528":90,"\u51fd\u6570\u91cc\u5b9e\u73b0":75,"\u5206\u4e3a":90,"\u5206\u522b\u4e3a\u6570\u636e\u8f93\u5165\u6dfb\u52a0\u5916\u5c42\u5e8f\u5217\u548c\u5185\u5c42\u5e8f\u5217\u7684\u5e8f\u5217\u4fe1\u606f":89,"\u5206\u522b\u4ece\u8bcd\u8bed\u548c\u53e5\u5b50\u7ea7\u522b\u7f16\u7801\u8f93\u5165\u6570\u636e":113,"\u5206\u522b\u4ee3\u8868\u8f93\u5165\u6570\u636e":42,"\u5206\u522b\u4f7f\u7528\u5355\u53cc\u5c42rnn\u4f5c\u4e3a\u7f51\u7edc\u914d\u7f6e\u7684\u6a21\u578b":111,"\u5206\u522b\u5b9a\u4e49\u5b50\u53e5\u7ea7\u522b\u548c\u8bcd\u8bed\u7ea7\u522b\u4e0a\u9700\u8981\u5b8c\u6210\u7684\u8fd0\u7b97":113,"\u5206\u522b\u5bf9\u5e94capi":63,"\u5206\u522b\u662f":110,"\u5206\u522b\u662frnn\u72b6\u6001\u548c\u8f93\u5165\u7684\u53d8\u6362\u77e9\u9635":114,"\u5206\u522b\u662fsentences\u548clabel":111,"\u5206\u522b\u662fwords\u548clabel":111,"\u5206\u522b\u8ba1\u7b97\u6bcf\u4e2a\u53c2\u6570\u7684\u68af\u5ea6":74,"\u5206\u522b\u8fdb\u884c\u5e8f\u5217\u64cd\u4f5c":111,"\u5206\u5e03\u5f0f\u5b58\u50a8\u670d\u52a1":10,"\u5206\u5e03\u5f0f\u8bad\u7ec3":106,"\u5206\u5e03\u5f0f\u8bad\u7ec3\u67b6\u6784\u5982\u4e0b\u56fe\u6240\u793a":92,"\u5206\u652f":[63,72],"\u5206\u652f\u4e00\u65e6\u5efa\u7acb":63,"\u5206\u652f\u4e0a":72,"\u5206\u652f\u4e0a\u521b\u5efa\u65b0\u5206\u652f":72,"\u5206\u652f\u4e2d":63,"\u5206\u652f\u4e3a\u5f00\u53d1":63,"\u5206\u652f\u4e3a\u6bcf\u4e00\u6b21release\u65f6\u5efa\u7acb\u7684\u4e34\u65f6\u5206\u652f":63,"\u5206\u652f\u4e3a\u7a33\u5b9a":63,"\u5206\u652f\u529f\u80fd\u7684\u5c01\u95ed":63,"\u5206\u652f\u5408\u5165":63,"\u5206\u652f\u5408\u5165master\u5206\u652f":63,"\u5206\u652f\u540c\u6b65\u4e3b\u7248\u672c\u5e93\u7684":63,"\u5206\u652f\u540d":72,"\u5206\u652f\u540d\u4e3a":63,"\u5206\u652f\u5b58\u5728\u7684\u65f6\u5019":63,"\u5206\u652f\u6d3e\u751f\u51fa\u65b0\u7684\u5206\u652f":63,"\u5206\u652f\u7528\u6765\u6d4b\u8bd5\u53ea\u9700\u8981\u8ba1\u7b97\u4e00\u4e2a\u8f93\u5165\u68af\u5ea6\u7684\u60c5\u51b5":75,"\u5206\u652f\u7684\u7248\u672c\u90fd\u662f\u7ecf\u8fc7\u5355\u5143\u6d4b\u8bd5\u548c\u56de\u5f52\u6d4b\u8bd5\u7684\u7248\u672c":63,"\u5206\u652f\u7684\u7248\u672c\u90fd\u7ecf\u8fc7\u5355\u5143\u6d4b\u8bd5":63,"\u5206\u652f\u89c4\u8303":72,"\u5206\u6790\u5f97\u5230\u7684\u4fe1\u606f\u7528\u4e8e\u534f\u52a9\u8fdb\u884c\u7a0b\u5e8f\u7684\u4f18\u5316":108,"\u5206\u7247":10,"\u5206\u7c7b\u4efb\u52a1\u4e2d\u7c7b\u522b\u6807\u7b7e":89,"\u5206\u914d\u5230\u5f53\u524d\u6570\u636e\u5757\u6837\u672c\u6570\u7684\u56db\u5206\u4e4b\u4e00":103,"\u5207\u6362\u5230":72,"\u5207\u6362\u5230\u6240\u5efa\u5206\u652f":72,"\u5217\u5143\u7d20\u6392\u5217\u6210\u7684\u77e9\u5f62\u9635\u5217":89,"\u5217\u540d":107,"\u5217\u8868\u5982\u4e0b":84,"\u5219\u4e0d\u9700\u8981\u91cd\u5199\u8be5\u51fd\u6570":74,"\u5219\u4f1a\u4f7f\u7528openblas\u4f5c\u4e3ablas\u5e93":0,"\u5219\u4f7f\u7528":117,"\u5219\u4f7f\u7528\u540c\u6b65\u8bad\u7ec3":103,"\u5219\u4f7f\u7528\u542f\u52a8\u53c2\u6570\u5b9a\u4e49\u7684\u521d\u59cb\u5316\u65b9\u6cd5\u521d\u59cb\u5316\u53c2\u6570":10,"\u5219\u4f7f\u7528\u8be5\u53c2\u6570\u4f5c\u4e3a\u9ed8\u8ba4\u503c":103,"\u5219\u53ef\u8bbe\u7f6e":[117,118],"\u5219\u5e76\u4e0d\u4f1a\u7b49\u5f85\u6240\u6709trainer\u63d0\u4ea4\u68af\u5ea6\u624d\u66f4\u65b0\u53c2\u6570":92,"\u5219\u5ffd\u7565":10,"\u5219\u603b\u4f1a\u663e\u793a\u963b\u9694\u6458\u8981\u4fe1\u606f":103,"\u5219\u628a\u53e6\u4e00\u4e2a\u6162\u901f\u7684kill\u6389":10,"\u5219\u662f\u5e26gui\u7684nvidia\u53ef\u89c6\u5316\u6027\u80fd\u5206\u6790\u5de5\u5177":108,"\u5219\u663e\u793a\u963b\u9694\u6027\u80fd\u7684\u6458\u8981\u4fe1\u606f":103,"\u5219\u76f4\u63a5\u5f15\u5165\u53e6\u4e00\u79cd\u7c7b\u578b\u7684\u5934\u6587\u4ef6":46,"\u5219\u8bbe\u7f6e\u6210":[116,118],"\u5219\u9700\u8981\u4f7f\u7528\u7b49\u4e8e\u6743\u91cd\u53c2\u6570\u89c4\u6a21\u5927\u7ea65\u500d\u7684\u5185\u5b58":81,"\u5219\u9700\u8981\u5206\u522b\u7f16\u8bd1\u771f\u673a\u548c\u6a21\u62df\u5668\u7248\u672c":117,"\u5219\u9700\u8981\u56de\u6eda\u5230\u4e0a\u4e00\u4e2a\u68c0\u67e5\u70b9":10,"\u5219\u9700\u8981\u5728\u672c\u673a\u5b89\u88c5\u4e0b\u9762\u7ae0\u8282\u5217\u51fa\u7684":0,"\u5219\u9700\u8981\u624b\u52a8\u62f7\u8d1d\u5c5e\u4e8e\u6bcf\u4e2atrainer\u8282\u70b9\u7684\u8bad\u7ec3\u6570\u636e\u5230\u5bf9\u5e94\u7684\u8282\u70b9\u4e0a":91,"\u521b\u5efa":[42,89,90],"\u521b\u5efa\u4e00\u4e2a":86,"\u521b\u5efa\u4e00\u4e2akubernet":97,"\u521b\u5efa\u5e76\u5207\u6362\u5230\u65b0\u5206\u652f":72,"\u521b\u5efa\u6210\u529f\u540e":97,"\u521b\u5efa\u65e5\u5fd7\u76ee\u5f55":98,"\u521b\u5efa\u7a00\u758f\u77e9\u9635\u65f6\u9700\u8981\u663e\u793a\u5730\u6307\u5b9a\u77e9\u9635\u7684":89,"\u521b\u5efaissu":2,"\u521d\u59cb\u5316\u504f\u7f6e\u5411\u91cf":74,"\u521d\u59cb\u5316\u6743\u91cd\u8868":74,"\u521d\u59cb\u5316\u6a21\u578b\u7684\u8def\u5f84":103,"\u521d\u59cb\u5316\u7236\u7c7b":74,"\u521d\u59cb\u5316biases_":74,"\u521d\u59cb\u72b6\u6001":113,"\u5220\u9664":72,"\u5220\u9664\u78c1\u76d8\u76ee\u5f55\u4e2d\u4e0d\u662f\u5f53\u524duuid\u7684\u5feb\u7167\u6587\u4ef6":10,"\u5224\u65ad\u662f\u5426\u5b89\u88c5\u6210\u529f":117,"\u5229\u7528\u5206\u5e03\u5f0f\u8bad\u7ec3\u9a7e\u9a6d\u66f4\u591a\u7684\u8ba1\u7b97\u8d44\u6e90":81,"\u5229\u7528\u66f4\u591a\u7684\u8ba1\u7b97\u8d44\u6e90\u53ef\u4ee5\u5206\u4e3a\u4ee5\u4e0b\u51e0\u4e2a\u65b9\u5f0f\u6765\u8fdb\u884c":81,"\u5229\u7528\u8fd9\u79cd\u7279\u6027":113,"\u522b\u4eba\u5e2e\u4e86\u5fd9":72,"\u522b\u5fd8\u4e86":0,"\u5230":[10,78,114],"\u5230\u6307\u5b9a\u6587\u4ef6\u4e2d":90,"\u5230\u672c\u5730":72,"\u5230\u6b64":75,"\u5230\u7b2c\u4e8c\u6b65":63,"\u5236\u4f5c\u65b0\u955c\u50cf\u6765\u5b8c\u6210\u4ee5\u4e0a\u7684\u5de5\u4f5c":97,"\u5236\u4f5cpaddlepaddle\u955c\u50cf":97,"\u524d\u4e00\u7bc7\u6587\u7ae0\u4ecb\u7ecd\u4e86\u5982\u4f55\u5728kubernetes\u96c6\u7fa4\u4e0a\u542f\u52a8\u4e00\u4e2a\u5355\u673apaddlepaddle\u8bad\u7ec3\u4f5c\u4e1a":97,"\u524d\u540e\u7684\u7f51\u7edc\u6027\u80fd":41,"\u524d\u5411\u4f20\u64ad":74,"\u524d\u5411\u4f20\u64ad\u7ed9\u5b9a\u8f93\u5165":74,"\u524d\u5411\u548c\u540e\u5411":74,"\u524d\u5411\u8ba1\u7b97\u4e4b\u540epaddlepaddle\u5185\u90e8\u5df2\u7ecf\u5206\u914d":90,"\u524d\u5411op\u5b9e\u73b0\u5b8c\u6210":75,"\u524d\u8005\u5728":81,"\u524d\u8005\u5b58\u50a8op\u7684\u8f93\u5165\u8f93\u51fa\u548c\u53c2\u6570\u5c5e\u6027":75,"\u524d\u8005\u622a\u65ad\u53ef\u5b66\u4e60\u53c2\u6570\u7684\u68af\u5ea6":81,"\u524d\u8005op\u7684\u5b9a\u4e49\u7ee7\u627f\u81ea":75,"\u524d\u81ea\u52a8\u68c0\u67e5\u4e00\u4e9b\u57fa\u672c\u4e8b\u5b9c":72,"\u524d\u9700\u8981\u5b89\u88c5":107,"\u524d\u9988":92,"\u529f\u80fd":27,"\u529f\u80fd\u7684\u6b63\u786e\u6027\u5305\u62ec\u9a8c\u8bc1paddlepaddle\u76ee\u524d\u7684":63,"\u52a0\u4e0a\u504f\u7f6e\u5411\u91cf":74,"\u52a0\u5165":108,"\u52a0\u6743\u548c\u7528\u6765\u751f\u6210":114,"\u52a0\u6743\u7f16\u7801\u5411\u91cf":114,"\u52a0\u8f7d\u5177\u4f53\u7f51\u7edc\u53c2\u6570":83,"\u52a0\u8f7d\u6a21\u578b\u53ef\u5176\u5b83\u591a\u79cd\u65b9\u5f0f":90,"\u52a0\u8f7d\u6a21\u578b\u9700\u540c\u65f6\u6307\u5b9a":90,"\u52a0\u8f7d\u9884\u6d4b\u6a21\u578b":90,"\u52a0\u8f7d\u9884\u8bad\u7ec3\u53c2\u6570":83,"\u52a0\u8f7dtest":103,"\u52a0\u901f\u7f16\u8bd1":0,"\u52a0\u901fpaddlepaddle\u8bad\u7ec3\u53ef\u4ee5\u8003\u8651\u4ece\u4ee5\u4e0b\u51e0\u4e2a\u65b9\u9762":81,"\u52a8\u6001\u5e93":[45,87],"\u52a9\u624b":74,"\u5305":107,"\u5305\u542b\u4e86\u67d0\u79cd\u7c7b\u578b\u7684\u7c7b\u578b\u5b9a\u4e49\u548c\u66b4\u9732\u7684\u5168\u90e8\u51fd\u6570":46,"\u5305\u542b\u4f46\u4e0d\u9650\u4e8e":0,"\u5305\u542b\u6d4b\u8bd5\u6570\u636e\u96c6\u7684\u76ee\u5f55":91,"\u5305\u542b\u8bad\u7ec3\u6570\u636e\u7684\u76ee\u5f55":91,"\u5305\u542b\u8fd9\u4e2a\u51fd\u6570\u8c03\u7528\u5176\u4ed6\u51fd\u6570\u7684\u65f6\u95f4":107,"\u5305\u542bkernel\u7684op\u548c\u4e0d\u5305\u542bkernel\u7684op":75,"\u5305\u62ec":[11,41,42,87,103],"\u5305\u62ec\u4e86\u7f16\u8bd1\u51fa\u7684paddlepaddle\u5934\u6587\u4ef6\u548c\u94fe\u63a5\u5e93":87,"\u5305\u62ec\u5b57\u7b26\u4e32\u5206\u914d":81,"\u5305\u62ec\u6743\u91cdw\u548c\u504f\u7f6eb":10,"\u5305\u62ec\u751f\u6210cpu":0,"\u5305\u62ec\u795e\u7ecf\u7f51\u7edc\u62d3\u6251\u7ed3\u6784":84,"\u5305\u62ecbool":105,"\u5305\u62eclinux":116,"\u5305\u62ecmkl":42,"\u5305\u7684\u65b9\u6cd5\u662f":78,"\u533a\u522b\u662f\u540c\u65f6\u5904\u7406\u4e86\u4e24\u4e2a\u8f93\u5165":111,"\u533a\u522b\u662frnn\u4f7f\u7528\u4e24\u5c42\u5e8f\u5217\u6a21\u578b":111,"\u534f\u540c\u5b8c\u6210releas":63,"\u5355\u4e2a\u503c":11,"\u5355\u4f4d\u662fmb":103,"\u5355\u5143\u6d4b\u8bd5":76,"\u5355\u5143\u6d4b\u8bd5\u4f1a\u5f15\u7528site":78,"\u5355\u5143\u6d4b\u8bd5\u4f1a\u88ab\u81ea\u52a8\u52a0\u5165\u5de5\u7a0b\u8fdb\u884c\u7f16\u8bd1":75,"\u5355\u5143\u6d4b\u8bd5checkgrad_ep":102,"\u5355\u53cc\u5c42\u5e8f\u5217\u7684\u53e5\u5b50\u662f\u4e00\u6837\u7684":111,"\u5355\u53cc\u5c42rnn":112,"\u5355\u5c42":113,"\u5355\u5c42\u4e0d\u7b49\u957frnn":111,"\u5355\u5c42\u548c\u53cc\u5c42\u5e8f\u5217\u7684\u4f7f\u7528\u548c\u793a\u4f8b2\u4e2d\u7684\u793a\u4f8b\u7c7b\u4f3c":111,"\u5355\u5c42\u5e8f\u5217":[89,110],"\u5355\u5c42\u5e8f\u5217\u7684\u6bcf\u4e2a\u5143\u7d20":110,"\u5355\u5c42\u5e8f\u5217\u7b2ci\u4e2a\u5143\u7d20":110,"\u5355\u5c42\u6216\u53cc\u5c42":110,"\u5355\u5c42\u65f6\u95f4\u5e8f\u5217":111,"\u5355\u5c42rnn":[111,113],"\u5355\u5c42rnn\u548c\u53cc\u5c42rnn\u7684\u7f51\u7edc\u914d\u7f6e":111,"\u5355\u673acpu\u8bad\u7ec3":81,"\u5355\u673agpu\u8bad\u7ec3":81,"\u5355\u6b65\u51fd\u6570":114,"\u5355\u6b65\u51fd\u6570\u548c\u8f93\u51fa\u51fd\u6570\u5728":114,"\u5355\u6b65\u51fd\u6570\u548c\u8f93\u51fa\u51fd\u6570\u90fd\u975e\u5e38\u7b80\u5355":114,"\u5355\u6b65\u51fd\u6570\u7684\u5b9e\u73b0\u5982\u4e0b\u6240\u793a":114,"\u5355\u6d4b\u5305\u62ec\u5bf9\u6bd4\u524d\u5411op\u4e0d\u540c\u8bbe\u5907":75,"\u5355\u70b9\u6545\u969c":10,"\u5355\u7eaf\u7684":107,"\u5355\u8fdb\u5355\u51fa":113,"\u5360\u7528\u4e8617":107,"\u5373":[46,75,77,81,82,97],"\u5373\u4e0a\u8ff0\u4ee3\u7801\u4e2d\u7684\u7b2c19\u884c":111,"\u5373\u4e0b\u8f7d\u5931\u8d25":78,"\u5373\u4e0d\u5141\u8bb8\u5728":75,"\u5373\u4e0d\u9700\u8981\u4f7f\u7528memori":111,"\u5373\u4e3a\u4e00\u4e2a\u65f6\u95f4\u6b65":111,"\u5373\u4e3a\u5355\u5c42rnn\u5e8f\u5217\u7684\u4f7f\u7528\u4ee3\u7801":111,"\u5373\u4e3a\u65f6\u95f4\u5e8f\u5217\u7684\u8f93\u5165":111,"\u5373\u4e3a\u8fd9\u4e2a\u53cc\u5c42rnn\u7684\u7f51\u7edc\u7ed3\u6784":111,"\u5373\u4e8c\u7ef4\u6570\u7ec4":111,"\u5373\u4f7f\u7528":[46,82],"\u5373\u4f7f\u7528\u6237\u76f4\u63a5\u5f15\u7528\u67d0\u79cd\u7c7b\u578b\u7684\u5934\u6587\u4ef6":46,"\u5373\u4f7f\u95f4\u9694\u5f88\u5c0f":103,"\u5373\u4f7fc":46,"\u5373\u4f8b\u5982":46,"\u5373\u4fbf\u662f":0,"\u5373\u4fbf\u8bbe\u7f6e":78,"\u5373\u4fbfpaddl":46,"\u5373\u521d\u59cb\u72b6\u6001\u4e3a0":113,"\u5373\u5355\u65f6\u95f4\u6b65\u6267\u884c\u7684\u51fd\u6570":114,"\u5373\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217":111,"\u5373\u53cc\u5c42rnn\u7684\u6bcf\u4e2a\u72b6\u6001":113,"\u5373\u53ef":72,"\u5373\u53ef\u4ee5\u6781\u5927\u7684\u52a0\u901f\u6570\u636e\u8f7d\u5165\u6d41\u7a0b":81,"\u5373\u53ef\u4f7f\u7528\u5f00\u53d1\u955c\u50cf\u6765\u7f16\u8bd1android\u7248paddlepaddl":116,"\u5373\u53ef\u5728":118,"\u5373\u53ef\u5f00\u59cb\u4e0b\u8f7d":3,"\u5373\u53ef\u5f00\u59cb\u4e0b\u9762\u7684\u6b65\u9aa4":1,"\u5373\u53ef\u663e\u793a\u6027\u80fd\u5206\u6790\u7684\u7ed3\u679c":107,"\u5373\u53ef\u68c0\u67e5\u6211\u4eec\u8c03\u4f18\u540e\u7684\u4fee\u6b63\u662f\u5426\u80fd\u591f\u6539\u5584\u7a0b\u5e8f\u7684\u6027\u80fd":107,"\u5373\u5728\u53cc\u5c42\u5e8f\u5217\u7684\u539f\u59cb\u6570\u636e\u4e2d":111,"\u5373\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d":81,"\u5373\u5927\u90e8\u5206\u503c\u4e3a0":84,"\u5373\u5b8c\u6210\u67d0\u4e00\u4e2a\u4efb\u52a1\u7684\u6700\u5c11\u51fd\u6570":46,"\u5373\u5c06\u4e00\u6bb5\u8bdd\u8fdb\u884c\u5206\u7c7b":111,"\u5373\u5c06nchw\u8f6c\u6362\u6210nhwc":82,"\u5373\u5f53\u524d\u65f6\u95f4\u6b65\u4e0b\u7684\u795e\u7ecf\u7f51\u7edc\u4f9d\u8d56\u524d\u4e00\u4e2a\u65f6\u95f4\u6b65\u795e\u7ecf\u7f51\u7edc\u4e2d\u67d0\u4e00\u4e2a\u795e\u7ecf\u5143\u8f93\u51fa":111,"\u5373\u6211\u4eec\u53ef\u4ee5\u5148\u5b9a\u4e49\u4e00\u4e2atensor":76,"\u5373\u628a\u5355\u5c42rnn\u751f\u6210\u540e\u7684subseq\u7ed9\u62fc\u63a5\u6210\u4e00\u4e2a\u65b0\u7684\u53cc\u5c42seq":113,"\u5373\u6574\u4e2a\u53cc\u5c42group\u662f\u5c06\u524d\u4e00\u4e2a\u5b50\u53e5\u7684\u6700\u540e\u4e00\u4e2a\u5411\u91cf":111,"\u5373\u6574\u4e2a\u8f93\u5165\u5e8f\u5217":110,"\u5373\u6574\u6570\u6570\u7ec4":111,"\u5373\u65f6\u95f4\u9012\u5f52\u795e\u7ecf\u7f51\u7edc":111,"\u5373\u662f\u8de8\u8d8a\u65f6\u95f4\u6b65\u7684\u7f51\u7edc\u8fde\u63a5":111,"\u5373\u66b4\u9732":46,"\u5373\u7279\u5f81\u7684\u6570\u7ec4":111,"\u5373\u7f51\u5361\u540d":97,"\u5373\u8868\u793a\u4e0d\u9700\u8981\u8f6c\u6362":42,"\u5373\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u51fa\u73b0nan\u6216\u8005inf":81,"\u5373\u8bbe\u7f6e":81,"\u5373\u8fd0\u884c\u8bad\u7ec3\u7a0b\u5e8f":1,"\u5373\u8fd9\u4e2a\u52a8\u6001\u5e93\u662f\u4e0d\u4f9d\u8d56\u4e8e\u5176\u4ed6\u4efb\u4f55\u6587\u4ef6\u7684":45,"\u5373define_py_data_sources2\u5e94\u6539\u4e3a":83,"\u5373input":113,"\u5373rnn\u4e4b\u95f4\u6709\u4e00\u6b21\u5d4c\u5957\u5173\u7cfb":111,"\u5378\u8f7dpaddlepaddle\u5305":78,"\u538b\u6241\u6210\u4e3aeigen\u7684\u4e00\u7ef4tensor":76,"\u538b\u7f29\u6210\u4e00\u4e2a\u5411\u91cf":111,"\u539f\u56e0":[72,78],"\u539f\u56e0\u5728\u4e8e\u6ca1\u6709\u628a\u673a\u5668\u4e0acuda\u76f8\u5173\u7684\u9a71\u52a8\u548c\u5e93\u6620\u5c04\u5230\u5bb9\u5668\u5185\u90e8":78,"\u539f\u56e0\u662f\u6bcf\u4e2a\u56de\u590d\u90fd\u4f1a\u53d1\u9001\u4e00\u5c01\u90ae\u4ef6":72,"\u539f\u6765\u7684\u65b9\u6848":42,"\u53c2\u6570":[0,45,74,81,90,91,97,102],"\u53c2\u6570\u4e3a":75,"\u53c2\u6570\u5171\u4eab\u7684\u914d\u7f6e\u793a\u4f8b\u4e3a":83,"\u53c2\u6570\u548c\u73af\u5883\u53d8\u91cf":91,"\u53c2\u6570\u670d\u52a1\u5668":[92,102],"\u53c2\u6570\u670d\u52a1\u5668\u4e4b\u95f4\u4e0d\u76f8\u4e92\u4f9d\u8d56":92,"\u53c2\u6570\u670d\u52a1\u5668\u4e5f\u4e0d\u4f1a\u7b49\u5f85\u8ba1\u7b97\u8282\u70b9\u5168\u90e8\u90fd\u63d0\u4ea4\u68af\u5ea6\u4e4b\u540e\u624d\u5f00\u59cb\u4e0b\u4e00\u6b65":92,"\u53c2\u6570\u670d\u52a1\u5668\u63a5\u6536\u4ece\u8ba1\u7b97\u8282\u70b9\u4e0a\u4f20\u7684\u68af\u5ea6":92,"\u53c2\u6570\u670d\u52a1\u5668\u7684\u53c2\u6570\u5206\u5757\u5927\u5c0f":103,"\u53c2\u6570\u670d\u52a1\u5668\u7684\u76d1\u542c\u7aef\u53e3":103,"\u53c2\u6570\u670d\u52a1\u5668\u7684\u7f51\u7edc\u8bbe\u5907\u540d\u79f0":103,"\u53c2\u6570\u670d\u52a1\u5668\u7684ip\u5730\u5740":103,"\u53c2\u6570\u670d\u52a1\u5668\u7a00\u758f\u66f4\u65b0\u7684\u53c2\u6570\u5206\u5757\u5927\u5c0f":103,"\u53c2\u6570\u6765\u63a7\u5236\u7f13\u5b58\u65b9\u6cd5":81,"\u53c2\u6570\u6982\u8ff0":104,"\u53c2\u6570\u7684\u4e2a\u6570\u548c\u53c2\u6570\u5217\u8868":90,"\u53c2\u6570\u7684\u89e3\u6790":97,"\u53c2\u6570\u8bbe\u7f6e":80,"\u53c2\u6570\u8bbe\u7f6e\u4e86\u5916\u5c42":111,"\u53c2\u6570\u8bf4\u660e":91,"\u53c2\u6570\u8bf4\u660e\u5bb9\u5668\u5df2\u4ea4\u4e92\u5f0f\u8fd0\u884c":1,"\u53c2\u6570\u8f93\u5165":81,"\u53c2\u6570\u9700\u8981\u5b9e\u73b0":114,"\u53c2\u7167\u4e0a\u8ff0\u6b65\u9aa4\u66f4\u65b0":72,"\u53c2\u8003":[1,27,45],"\u53c2\u8003\u4e0b\u56fe":63,"\u53c2\u8003\u4e0b\u8ff0\u53ef\u9009\u6b65\u9aa4":0,"\u53c2\u8003\u5f3a\u8c03\u90e8\u5206":108,"\u53c2\u8003\u65f6\u95f4\u5e8f\u5217":111,"\u53c2\u8003\u6837\u4f8b\u6570\u636e\u51c6\u5907\u811a\u672c":91,"\u53c2\u8003\u955c\u50cf\u7684":97,"\u53c8\u53ef\u4ee5\u907f\u514d\u4e0d\u5fc5\u8981\u7684\u8f6c\u6362":42,"\u53c8\u662f\u4e00\u4e2a\u5355\u5c42\u7684\u5e8f\u5217":110,"\u53c8\u8981\u4fdd\u8bc1\u6570\u636e\u662f\u968f\u673a\u7684":81,"\u53ca":74,"\u53cc\u5411\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u9690\u85cf\u72b6\u6001":114,"\u53cc\u5411\u9a8c\u8bc1":27,"\u53cc\u5c42":113,"\u53cc\u5c42\u4e0d\u7b49\u957frnn":111,"\u53cc\u5c42\u5e8f\u5217":[89,110],"\u53cc\u5c42\u5e8f\u5217\u5728\u5904\u7406\u957f\u5e8f\u5217\u7684\u4efb\u52a1\u6216\u662f\u6784\u5efa\u5c42\u7ea7\u6a21\u578b\u65f6\u4f1a\u53d1\u6325\u4f5c\u7528":89,"\u53cc\u5c42\u5e8f\u5217\u6216\u5355\u5c42\u5e8f\u5217":110,"\u53cc\u5c42\u5e8f\u5217\u6570\u636e\u4e00\u5171\u67094\u4e2a\u6837\u672c":111,"\u53cc\u5c42\u5e8f\u5217\u662f\u4e00\u4e2a\u5d4c\u5957\u7684\u5e8f\u5217":110,"\u53cc\u5c42\u5e8f\u5217\u662fpaddlepaddle\u652f\u6301\u7684\u4e00\u79cd\u975e\u5e38\u7075\u6d3b\u7684\u6570\u636e\u7ec4\u7ec7\u65b9\u5f0f":113,"\u53cc\u5c42\u5e8f\u5217\u6bcf\u4e2asubseq\u4e2d\u6bcf\u4e2a\u5143\u7d20":110,"\u53cc\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u53d8\u6210\u4e00\u4e2a0\u5c42\u5e8f\u5217":110,"\u53cc\u5c42\u5e8f\u5217\u9700\u8981\u8bbe\u7f6e\u5206\u522b\u4e3a\u5916\u5c42\u5e8f\u5217\u548c\u5185\u5c42\u5e8f\u5217\u5206\u522b\u8bbe\u7f6e":89,"\u53cc\u5c42\u6216\u8005\u5355\u5c42":110,"\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217\u7684dataprovider\u7684\u4ee3\u7801":111,"\u53cc\u5c42rnn":113,"\u53cc\u5c42rnn\u6570\u636e\u968f\u610f\u52a0\u4e86\u4e00\u4e9b\u9694\u65ad":111,"\u53cc\u5c42rnn\u987e\u540d\u601d\u4e49":111,"\u53cc\u8fdb\u5355\u51fa":113,"\u53cc\u8fdb\u53cc\u51fa":113,"\u53cd\u5411\u4f20\u64ad":74,"\u53cd\u5411\u4f20\u64ad\u6839\u636e\u8f93\u51fa\u7684\u68af\u5ea6":74,"\u53cd\u5411\u8ba1\u7b97\u5df2\u7ecf\u81ea\u52a8\u96c6\u6210\u8fdb\u6d4b\u8bd5\u6846\u67b6":75,"\u53cd\u5411op\u7684\u68af\u5ea6\u6d4b\u8bd5":75,"\u53cd\u5411op\u7c7b":75,"\u53cd\u5411op\u7c7b\u7684\u5b9a\u4e49":75,"\u53cd\u5411opkernel\u7684\u5b9a\u4e49\u4e0e\u524d\u5411op\u7c7b\u4f3c":75,"\u53d1\u578b\u7248":63,"\u53d1\u5e03\u5230dockerhub":63,"\u53d1\u5e03docker\u955c\u50cf\u53ea\u9700\u8981\u5bf9\u81ea\u52a8push\u7684\u955c\u50cf\u6253\u4e0a":63,"\u53d1\u6563\u5230\u4e86\u4e00\u4e2a\u6570\u503c\u7279\u522b\u5927\u7684\u5730\u65b9":81,"\u53d1\u884c\u548c\u7ef4\u62a4":72,"\u53d1\u9001\u53c2\u6570\u7684\u7aef\u53e3\u53f7":103,"\u53d6\u503c\u76f8\u540c\u7684layer":82,"\u53d6\u5176\u4e2d\u4e00\u4e2a\u6a21\u578bparams_pass_90":84,"\u53d6\u51b3\u4e8e":75,"\u53d8\u6362\u77e9\u9635":74,"\u53d8\u91cf\u6765\u533a\u5206layer\u7684\u5c5e\u6027":42,"\u53e5\u5b50\u662f\u7531\u8bcd\u8bed\u6784\u6210\u7684\u5e8f\u5217":89,"\u53e6\u4e00\u4e2a\u65b9\u6cd5\u662f\u4ea4\u53c9\u7f16\u8bd1":118,"\u53e6\u4e00\u4e2a\u662f\u5185\u5b58\u64cd\u4f5c\u91cf":108,"\u53e6\u4e00\u4e2a\u662f\u6bcf\u6761\u5e8f\u5217":81,"\u53e6\u4e00\u79cd\u65b9\u5f0f\u662f\u5c06\u7f51\u7edc\u5c42\u5212\u5206\u5230\u4e0d\u540c\u7684gpu\u4e0a\u53bb\u8ba1\u7b97":105,"\u53e6\u5916":[0,111],"\u53e6\u5916\u6700\u65b0\u7684pip\u5b98\u65b9\u6e90\u4e2d\u7684\u5b89\u88c5\u5305\u9ed8\u8ba4\u662fmanylinux1\u6807\u51c6":3,"\u53ea\u4f5c\u4e3aread":113,"\u53ea\u4fdd\u5b58\u6700\u540e\u4e00\u8f6e\u7684\u53c2\u6570":103,"\u53ea\u5728\u7b2c\u4e00\u6b21cmake\u7684\u65f6\u5019\u6709\u6548":0,"\u53ea\u5bf9\u7279\u6b8a\u5728\u7ebf\u7cfb\u7edf\u8003\u8651\u4e24\u53f0\u4ee5\u4e0a\u540c\u65f6\u6545\u969c\u7684\u5bb9\u707e":10,"\u53ea\u5bf9\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u8fdb\u884c\u5e8f\u5217\u5316":90,"\u53ea\u5c06\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u8fdb\u884c\u5e8f\u5217\u5316":90,"\u53ea\u662f\u53cc\u5c42\u5e8f\u5217\u5c06\u5176\u53c8\u505a\u4e86\u5b50\u5e8f\u5217\u5212\u5206":111,"\u53ea\u66b4\u9732\u6982\u5ff5\u7684\u63a5\u53e3":46,"\u53ea\u6709\u5f53\u8bbe\u7f6e\u4e86spars":103,"\u53ea\u7528\u4e8e\u5728\u5e8f\u5217\u751f\u6210\u4efb\u52a1\u4e2d\u6307\u5b9a\u8f93\u5165\u6570\u636e":113,"\u53ea\u7559\u4e0b\u6838\u5fc3\u8ba1\u7b97\u5c42":90,"\u53ea\u80fd\u5728recurrent_group\u4e2d\u4f5c\u4e3astep":82,"\u53ea\u80fd\u6309\u884c\u8ba1\u7b97":82,"\u53ea\u80fd\u6d4b\u8bd5\u5355\u4e2a\u6a21\u578b":105,"\u53ea\u80fd\u8bbf\u95ee\u5b83\u4eec\u7684\u8f93\u51fa\u503c":82,"\u53ea\u80fd\u8c03\u7528paddle\u7684\u52a8\u6001\u5e93":45,"\u53ea\u8981\u4e00\u7cfb\u5217\u7279\u5f81\u6570\u636e\u4e2d\u7684":111,"\u53ea\u8981\u51fa\u73b0\u6d6e\u70b9\u6570\u5f02\u5e38":81,"\u53ea\u8bfbmemory\u8f93\u5165":113,"\u53ea\u9488\u5bf9\u5185\u5b58":81,"\u53ea\u9700\u4e2d\u65ad":93,"\u53ea\u9700\u5728\u7f16\u8bd1\u65f6\u9700\u914d\u5236\u4e0b\u9762\u8fd9\u4e9b\u7f16\u8bd1\u9009\u9879":87,"\u53ea\u9700\u7528\u60a8\u5b9a\u4e49\u7684\u76ee\u5f55\u4fee\u6539":93,"\u53ea\u9700\u8981":114,"\u53ea\u9700\u8981\u6062\u590d\u8fd9\u53f0\u8282\u70b9":10,"\u53ea\u9700\u8981\u8bbe\u7f6e\u884c\u504f\u79fb":89,"\u53ea\u9700\u8981\u94fe\u63a5":87,"\u53ea\u9700\u8fdb\u884c\u524d\u5411\u8ba1\u7b97\u800c\u65e0\u9700\u8c03\u7528\u53cd\u5411\u8ba1\u7b97":90,"\u53ef\u4ee5":[1,63,72,77],"\u53ef\u4ee5\u4ece":1,"\u53ef\u4ee5\u4ece\u6211\u4eec\u7684ci\u7cfb\u7edf\u4e2d\u4e0b\u8f7d\u6700\u65b0\u7684whl\u5b89\u88c5\u5305\u548cc":3,"\u53ef\u4ee5\u4f30\u8ba1\u51fa\u5982\u679c\u6a21\u578b\u91c7\u7528\u4e0d\u53d8\u7684\u8f93\u51fa\u6700\u5c0f\u7684cost0\u662f\u591a\u5c11":83,"\u53ef\u4ee5\u4f7f\u7528":[83,90],"\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u7684\u547d\u4ee4\u66f4\u65b0\u60a8\u7684pip":3,"\u53ef\u4ee5\u4f7f\u7528\u5982\u4e0b\u4ee3\u7801":83,"\u53ef\u4ee5\u4f7f\u7528\u76f8\u5e94\u6570\u636e\u7c7b\u578b\u7684":83,"\u53ef\u4ee5\u4f7f\u7528\u8be5\u53c2\u6570":103,"\u53ef\u4ee5\u4f7f\u7528kubernetes\u7684\u547d\u4ee4\u884c\u5de5\u5177\u521b\u5efajob":97,"\u53ef\u4ee5\u5148\u4f7f\u7528":82,"\u53ef\u4ee5\u51cf\u5c0f\u7cfb\u7edf\u590d\u6742\u6027":10,"\u53ef\u4ee5\u51cf\u5c11\u7f13\u5b58\u6c60\u7684\u5927\u5c0f":81,"\u53ef\u4ee5\u521b\u5efa\u4e00\u4e2a":96,"\u53ef\u4ee5\u521b\u5efa\u975e":75,"\u53ef\u4ee5\u52a0\u901fpaddlepaddle\u7684\u8ba1\u7b97":1,"\u53ef\u4ee5\u53c2\u8003":[0,1,72,111,114],"\u53ef\u4ee5\u53c2\u8003\u4e0b\u9762\u7684\u6b65\u9aa4\u6392\u67e5":79,"\u53ef\u4ee5\u53c2\u8003paddlepaddl":84,"\u53ef\u4ee5\u540c\u65f6\u5728cpu":76,"\u53ef\u4ee5\u542b\u6709\u4e00\u6761\u6216\u591a\u6761\u6837\u672c":89,"\u53ef\u4ee5\u544a\u8bc9\u60a8\u67d0\u4e2a\u64cd\u4f5c\u5230\u5e95\u82b1\u4e86\u591a\u957f\u65f6\u95f4":108,"\u53ef\u4ee5\u5728":[0,93],"\u53ef\u4ee5\u5728\u4efb\u4f55\u673a\u5668\u4e0a\u6267\u884c\u7684":45,"\u53ef\u4ee5\u5728\u5171\u4eab\u5b58\u50a8\u4e0a\u67e5\u770b\u8f93\u51fa\u7684\u65e5\u5fd7\u548c\u6a21\u578b":97,"\u53ef\u4ee5\u5728\u6b64\u9875\u9762\u7684":63,"\u53ef\u4ee5\u5728\u8fd9\u4e2a":72,"\u53ef\u4ee5\u5728event_handler\u4e2d":81,"\u53ef\u4ee5\u5b8c\u6210\u795e\u7ecf\u7f51\u7edc\u7684sgd\u65b9\u6cd5\u7684\u8bad\u7ec3":92,"\u53ef\u4ee5\u5b9e\u73b0\u4ecepaddl":76,"\u53ef\u4ee5\u5c06cmake":107,"\u53ef\u4ee5\u5c06memory\u7406\u89e3\u4e3a\u4e00\u4e2a\u65f6\u5ef6\u64cd\u4f5c":113,"\u53ef\u4ee5\u5c06op\u5206\u4e3a\u4e24\u79cd":75,"\u53ef\u4ee5\u5c1d\u8bd5\u4ee5\u4e0b\u7684\u65b9\u6cd5":1,"\u53ef\u4ee5\u5e2e\u60a8\u63d0\u4f9b\u4e00\u4e9b\u5b9a\u4f4d\u6027\u80fd\u74f6\u9888\u7684\u5efa\u8bae":108,"\u53ef\u4ee5\u5e76\u884c\u7f16\u8bd1\u5417":0,"\u53ef\u4ee5\u5feb\u901f\u5728\u672c\u5730\u542f\u52a8\u4e00\u4e2a\u5305\u542b\u4e86paddlepaddle\u5b98\u65b9book\u6559\u7a0b\u7684jupyt":1,"\u53ef\u4ee5\u6267\u884c":[3,78],"\u53ef\u4ee5\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\u7f16\u8bd1\u751f\u6210\u6587\u6863":77,"\u53ef\u4ee5\u628a\u5b83\u60f3\u8c61\u4e3a\u4e00\u4e2a\u7c7b\u4f3c":0,"\u53ef\u4ee5\u628a\u672c\u5730\u7684\u6570\u636e\u4e0a\u4f20\u5230\u5b58\u50a8\u96c6\u7fa4\u4e2d":11,"\u53ef\u4ee5\u6307\u5b9a\u540c\u65f6\u6267\u884cgpu\u4e0a\u7684\u5355\u5143\u6d4b\u8bd5":0,"\u53ef\u4ee5\u6307\u5b9a\u54ea\u4e00\u4e2a\u8f93\u5165\u548c\u8f93\u51fa\u5e8f\u5217\u4fe1\u606f\u4e00\u81f4":111,"\u53ef\u4ee5\u6307\u5b9a\u5f00\u542f\u81ea\u52a8\u68c0\u6d4bsm\u67b6\u6784":0,"\u53ef\u4ee5\u6309\u7167\u4e0b\u9762\u7684\u65b9\u6cd5":0,"\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":[110,113],"\u53ef\u4ee5\u662f\u4e00\u4e2a\u975e\u5e8f\u5217":113,"\u53ef\u4ee5\u662f\u4ece\u5206\u5e03\u5f0f\u5b58\u50a8\u6302\u8f7d\u8fc7\u6765\u7684":91,"\u53ef\u4ee5\u662f\u4ee5\u4e0b\u51e0\u79cd":74,"\u53ef\u4ee5\u662f\u6574\u578b":89,"\u53ef\u4ee5\u663e\u793a\u5730\u6307\u5b9a\u4e00\u4e2alayer\u7684\u8f93\u51fa\u7528\u4e8e\u521d\u59cb\u5316memori":113,"\u53ef\u4ee5\u66f4\u6709\u6b21\u5e8f\u7684\u5b8c\u6210\u6027\u80fd\u7684\u4f18\u5316":107,"\u53ef\u4ee5\u6709\u4ee5\u4e0b\u4e24\u79cd":113,"\u53ef\u4ee5\u6709\u6548\u51cf\u5c0f\u7f51\u7edc\u7684\u963b\u585e":103,"\u53ef\u4ee5\u6709\u6548\u7684\u907f\u514dparamet":10,"\u53ef\u4ee5\u67e5\u770b":97,"\u53ef\u4ee5\u67e5\u770b\u6b64pod\u8fd0\u884c\u7684\u5bbf\u4e3b\u673a":96,"\u53ef\u4ee5\u6d4b\u8bd5\u591a\u4e2a\u6a21\u578b":105,"\u53ef\u4ee5\u7528":[0,27],"\u53ef\u4ee5\u7528\u4ee5\u4e0b\u6307\u4ee4":11,"\u53ef\u4ee5\u7528\u5982\u4e0b\u547d\u4ee4":72,"\u53ef\u4ee5\u7528\u6765\u8ba1\u7b97cpu\u51fd\u6570\u6216cuda\u5185\u6838\u7684\u65f6\u95f4\u6d88\u8017":108,"\u53ef\u4ee5\u76f4\u63a5\u8fd0\u884c":90,"\u53ef\u4ee5\u7701\u7565\u6b65\u9aa43\u4e2d":0,"\u53ef\u4ee5\u770b\u4f5c\u662f\u4e00\u4e2a\u975e\u5e8f\u5217\u8f93\u5165":110,"\u53ef\u4ee5\u770b\u51fa":92,"\u53ef\u4ee5\u770b\u5230\u6700\u8017\u65f6\u7684\u51fd\u6570\u662fc":107,"\u53ef\u4ee5\u7cbe\u786e\u8bf4\u660e\u4e00\u4e2a\u957f\u8017\u65f6\u64cd\u4f5c\u7684\u5177\u4f53\u539f\u56e0":108,"\u53ef\u4ee5\u7ee7\u7eed\u5728\u81ea\u5df1\u7684\u529f\u80fd\u5206\u652f\u63d0\u4ea4\u4ee3\u7801":63,"\u53ef\u4ee5\u8003\u8651\u4f7f\u7528\u4e00\u4e9b\u4f18\u5316\u7b97\u6cd5":81,"\u53ef\u4ee5\u8054\u7cfbop":79,"\u53ef\u4ee5\u8054\u7cfbop\u662f\u5426\u53ef\u4ee5\u66f4\u6362\u96c6\u7fa4\u6216\u5347\u7ea7\u5f53\u524d\u96c6\u7fa4":79,"\u53ef\u4ee5\u83b7\u53d6\u7f51\u7edc\u4e2d\u5b9a\u4e49\u7684\u4efb\u610f\u591a\u4e2a":90,"\u53ef\u4ee5\u88c5\u7684\u662f":0,"\u53ef\u4ee5\u8bbe\u7f6e":[107,117,118],"\u53ef\u4ee5\u8bbf\u95ee\u7531recurr":82,"\u53ef\u4ee5\u8c03\u7528resize\u63a5\u53e3\u8fdb\u884c\u6539\u53d8":76,"\u53ef\u4ee5\u8f7b\u677e\u5730\u5b8c\u6210\u795e\u7ecf\u7f51\u7edc\u914d\u7f6e":84,"\u53ef\u4ee5\u8fd0\u884c":91,"\u53ef\u4ee5\u9009\u5728\u5728\u5f53\u524d\u673a\u5668\u5b89\u88c5\u4e5f\u53ef\u4ee5\u62f7\u8d1d\u5230\u76ee\u6807\u673a\u5668\u5b89\u88c5":0,"\u53ef\u4ee5\u9009\u62e9\u662f\u5426\u4f7f\u7528\u53c2\u6570":105,"\u53ef\u4ee5\u901a\u8fc7":72,"\u53ef\u4ee5\u901a\u8fc7\u4fee\u6539\u8fd9\u4e24\u4e2a\u51fd\u6570\u6765\u5b9e\u73b0\u590d\u6742\u7684\u7f51\u7edc\u914d\u7f6e":114,"\u53ef\u4ee5\u901a\u8fc7\u5728":81,"\u53ef\u4ee5\u901a\u8fc7\u7f51\u9875\u6d4f\u89c8":1,"\u53ef\u4ee5\u901a\u8fc7\u8fd9\u4e2a\u8f93\u51fa\u6765\u5b8c\u6210\u81ea\u5b9a\u4e49\u7684\u8bc4\u4f30\u6307\u6807\u8ba1\u7b97\u7b49\u529f\u80fd":81,"\u53ef\u4ee5\u901a\u8fc7\u9636\u6bb5\u6027\u7684\u4fdd\u5b58\u6bcf\u4e2aparamet":10,"\u53ef\u4ee5\u91c7\u53d6\u4e0b\u9762\u51e0\u70b9\u63aa\u65bd":107,"\u53ef\u4ee5\u91cd\u547d\u540d\u8fd9\u4e2awhl\u5305\u4e3a":[3,78],"\u53ef\u53c2\u8003":90,"\u53ef\u5728":87,"\u53ef\u5728\u547d\u4ee4\u884c\u6267\u884c":117,"\u53ef\u663e\u5f0f\u6307\u5b9a\u4e3a":117,"\u53ef\u7528\u4e8e\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d\u89e3\u6790\u8fd9\u4e9b\u53c2\u6570":105,"\u53ef\u76f4\u63a5\u8fd0\u884c":90,"\u53ef\u80fd\u4f1a\u5bfc\u81f4\u51fa\u9519":97,"\u53ef\u80fd\u4f1a\u9020\u6210\u7f51\u7edc\u62e5\u585e":10,"\u53ef\u80fd\u7684\u4ee3\u7801\u4e3a":81,"\u53ef\u80fd\u7684\u539f\u56e0\u662f":83,"\u53ef\u80fd\u7684\u60c5\u51b5\u4e0b":108,"\u53ef\u80fd\u9700\u8981\u6ce8\u610f\u7ed9\u8fd9\u4e2a\u865a\u62df\u673a\u591a\u5206\u914d\u4e00\u4e9b":0,"\u53ef\u89c1\u8be5\u8ba1\u7b97\u7531\u4e24\u4e2a\u8f93\u5165":75,"\u53ef\u8bbe\u7f6e":[116,117],"\u53ef\u8bbe\u7f6e\u4e3a":117,"\u53ef\u8bbe\u7f6e\u7684\u76ee\u6807\u67b6\u6784\u5982\u4e0b\u8868\u6240\u793a":117,"\u53ef\u9009":[0,74,90,91],"\u53ef\u9009\u6b65\u9aa4":0,"\u53ef\u9009\u7684\u4e0d\u540c\u7f16\u8bd1\u73af\u5883docker\u955c\u50cf":0,"\u53ef\u9009\u914d\u7f6e\u9009\u9879":87,"\u53ef\u901a\u8fc7pip\u4e00\u952e\u5b89\u88c5":2,"\u53ef\u914d\u7f6e\u4e3a":87,"\u53ef\u91c7\u7528\u7b2c\u4e8c\u79cd\u65b9\u5f0f":82,"\u53f3\u4fa7\u7684":63,"\u5404\u6b21\u524d\u5411\u4e4b\u95f4\u4e5f\u90fd\u4f7f\u7528\u4e86\u76f8\u540c\u7684\u6743\u91cd":41,"\u5404\u9879\u66f4\u52a0\u5177\u4f53\u7684\u5355\u5143\u6d4b\u8bd5\u5728":75,"\u5408\u5e76\u5165\u4e00\u4e2a\u6587\u4ef6":90,"\u5408\u5e76\u6a21\u578b\u6587\u4ef6":90,"\u540c\u4e00\u6b21\u524d\u5411":41,"\u540c\u65f6":[41,42,78,81,108],"\u540c\u65f6\u4e5f\u4f1a\u8bfb\u53d6\u76f8\u5173\u8def\u5f84\u53d8\u91cf\u6765\u8fdb\u884c\u641c\u7d22":0,"\u540c\u65f6\u4e5f\u53ef\u4ee5\u52a0\u901f\u5f00\u59cb\u8bad\u7ec3\u524d\u6570\u636e\u8f7d\u5165\u7684\u8fc7\u7a0b":81,"\u540c\u65f6\u4e5f\u53ef\u4ee5\u901a\u8fc7":72,"\u540c\u65f6\u4e5f\u80fd\u591f\u5f15\u5165\u66f4\u52a0\u590d\u6742\u7684\u8bb0\u5fc6\u673a\u5236":113,"\u540c\u65f6\u4f1a\u5f00\u542fintel":42,"\u540c\u65f6\u5176\u5185\u90e8\u5b9e\u73b0\u53ef\u4ee5\u907f\u514d\u7eafcpu\u7248\u672cpaddlepaddle\u5728\u6267\u884c\u672c\u8bed\u53e5\u65f6\u53d1\u751f\u5d29\u6e83":108,"\u540c\u65f6\u518d\u5c06":63,"\u540c\u65f6\u53c8\u5c3d\u53ef\u80fd\u5c11\u7684\u727a\u7272mkl":42,"\u540c\u65f6\u5728\u5185\u5b58\u91cc\u76f4\u63a5\u968f\u5373\u9009\u53d6\u6570\u636e\u6765\u505ashuffl":81,"\u540c\u65f6\u5c06\u53c2\u6570\u521d\u59cb\u5316\u4e3a":83,"\u540c\u65f6\u63d0\u8d77":63,"\u540c\u65f6\u6570\u636e\u683c\u5f0f\u5c31\u662f":42,"\u540c\u65f6\u7528\u6237\u9700\u8981\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d\u6307\u5b9a":105,"\u540c\u65f6\u8bbe\u7f6e\u5185\u5b58\u7f13\u5b58\u529f\u80fd":81,"\u540c\u65f6\u8f93\u51fa\u5e8f\u5217\u5c42\u548c\u975e\u5e8f\u5217\u5c42":81,"\u540c\u6837":84,"\u540c\u6837\u4e5f\u53ef\u4ee5\u5728\u6d4b\u8bd5\u6a21\u5f0f\u4e2d\u6307\u5b9a\u6a21\u578b\u8def\u5f84":103,"\u540c\u6837\u53ef\u4ee5\u6269\u5c55\u5230\u53cc\u5c42\u5e8f\u5217\u7684\u5904\u7406\u4e0a":113,"\u540c\u6837\u53ef\u83b7\u53d6\u5230\u8f93\u5165\u8f93\u51fa\u548c\u5c5e\u6027\u53c2\u6570":75,"\u540c\u6b65\u6267\u884c\u64cd\u4f5c\u7684\u7ebf\u7a0b\u6570":103,"\u540c\u7406":75,"\u540d\u5b57\u4fee\u9970":45,"\u540e":[0,72,83,97,116,117,118],"\u540e\u5411":41,"\u540e\u5411\u4f20\u64ad":74,"\u540e\u5411\u4f20\u64ad\u7ed9\u5b9a\u8f93\u51fa\u7684\u68af\u5ea6":74,"\u540e\u5411\u65f6\u590d\u7528\u5df2\u7ecf\u8f6c\u6362\u8fc7\u7684\u6743\u91cd":41,"\u540e\u7f00\u4e3a":91,"\u540e\u8005\u5728\u6fc0\u6d3b\u51fd\u6570\u53cd\u5411\u8ba1\u7b97\u65f6\u88ab\u8c03\u7528":81,"\u540e\u8005\u622a\u65ad\u56de\u4f20\u7ed9\u524d\u5c42\u7684\u68af\u5ea6":81,"\u540e\u8005\u7528\u4e8e\u68c0\u67e5\u53c2\u6570\u5c5e\u6027\u7684\u5408\u6cd5\u6027":75,"\u540e\u8005\u7ee7\u627f\u81ea":75,"\u540e\u9762\u7684gradient":91,"\u540e\u9988":92,"\u5411\u6307\u5b9a\u7684\u76ee\u5f55\u4e2d\u4e00\u4e2a\u65b0\u7684\u6587\u4ef6":10,"\u5411\u91cf":89,"\u5411\u91cfenable_parallel_vector":102,"\u5411paddlepaddle\u7684\u4e3b\u7248\u672c\u5e93\u63d0\u4ea4":63,"\u5417":0,"\u5426\u5219":[75,116,118],"\u5426\u5219\u4f1a\u628a":72,"\u5426\u5219\u4f7f\u7528\u591a\u673a\u8bad\u7ec3":103,"\u5426\u5219\u4f7f\u7528cpu\u6a21\u5f0f":103,"\u5426\u5219\u4f7f\u7528gpu":105,"\u5426\u5219\u5b83\u4ee5\u4e00\u4e2a\u5e8f\u5217\u8f93\u5165":114,"\u5426\u5219\u5f97\u628apaddle\u9759\u6001\u5e93\u94fe\u63a5\u5230\u89e3\u91ca\u5668\u91cc":45,"\u5426\u5219\u9891\u7e41\u7684\u591a\u8282\u70b9\u5de5\u4f5c\u7a7a\u95f4\u90e8\u7f72\u53ef\u80fd\u4f1a\u5f88\u9ebb\u70e6":93,"\u542b\u4e49":107,"\u542b\u6709\u5e8f\u5217\u4fe1\u606f\u548c\u5b50\u5e8f\u5217\u4fe1\u606f\u7684\u7a20\u5bc6\u5411\u91cf":74,"\u542b\u6709\u5e8f\u5217\u4fe1\u606f\u7684\u6574\u6570":74,"\u542b\u6709\u5e8f\u5217\u4fe1\u606f\u7684\u7a20\u5bc6\u5411\u91cf":74,"\u542f\u52a8\u4e00\u4e2a\u65b0\u7684\u7ebf\u7a0b\u5f00\u59cb\u4fdd\u5b58\u68c0\u67e5\u70b9":10,"\u542f\u52a8\u4e00\u4e2a\u6d4b\u8bd5\u96c6\u7fa4":93,"\u542f\u52a8\u53c2\u6570\u8bf4\u660e":92,"\u542f\u52a8\u5bb9\u5668\u5f00\u59cb\u8bad\u7ec3":97,"\u542f\u52a8\u5e76\u884c\u5411\u91cf\u7684\u9608\u503c":103,"\u542f\u52a8\u5feb\u901f\u5e94\u7b54":103,"\u542f\u52a8\u8bad\u7ec3\u4efb\u52a1":98,"\u542f\u7528\u68af\u5ea6\u53c2\u6570\u7684\u9608\u503c":103,"\u547d\u4ee4\u4e3a":[78,96],"\u547d\u4ee4\u521b\u5efa\u65b0\u955c\u50cf":96,"\u547d\u4ee4\u5220\u9664":[116,117,118],"\u547d\u4ee4\u53ef\u4ee5\u8bbe\u7f6e":0,"\u547d\u4ee4\u65f6":116,"\u547d\u4ee4\u6709\u65f6\u5019\u4f1a\u4ea7\u751f\u4e00\u4e9b\u4e2d\u95f4\u7ed3\u679c":0,"\u547d\u4ee4\u770b\u5230\u505c\u6b62\u540e\u4f46\u662f\u6ca1\u6709\u5220\u9664\u7684":0,"\u547d\u4ee4\u7f16\u8bd1\u6e90\u7801\u5373\u53ef":0,"\u547d\u4ee4\u884c\u4e2d\u7684":107,"\u547d\u4ee4\u884c\u53c2\u6570\u8bbe\u7f6e":106,"\u547d\u4ee4\u8bbe\u7f6e\u8be5\u7c7b\u7f16\u8bd1\u9009\u9879":0,"\u547d\u4ee4\u9009\u9879\u5e76\u4e14":93,"\u547d\u4ee4\u91cc\u90fd\u7528\u4e86":0,"\u547d\u540d\u4e3a":72,"\u547d\u540d\u89c4\u8303":75,"\u547d\u540d\u8bf7\u9075\u5b88":75,"\u548c":[0,11,41,42,45,46,63,72,74,75,76,77,81,82,83,87,89,91,92,93,105,107,108,111,114,116,118],"\u548c\u4e00\u4e2a\u5df2\u7ecf\u5206\u8bcd\u540e\u7684\u53e5\u5b50":111,"\u548c\u4e09\u79cd\u5e8f\u5217\u6a21\u5f0f":84,"\u548c\u4e0b\u9762\u5c06\u8981\u4ecb\u7ecd\u7684\u6ce8\u518c\u51fd\u6570\u4e00\u8d77\u653e\u5728":75,"\u548c\u4e2d\u6587\u6587\u6863":77,"\u548c\u4e4b\u524d\u51cf\u5c0f\u901a\u8fc7\u51cf\u5c0f\u7f13\u5b58\u6c60\u6765\u51cf\u5c0f\u5185\u5b58\u5360\u7528\u7684\u539f\u7406\u4e00\u81f4":81,"\u548c\u504f\u7f6e\u5411\u91cf":74,"\u548c\u5185\u5b58":0,"\u548c\u5217\u53f7":89,"\u548c\u53cc\u5c42\u5e8f\u5217\u542b\u6709subseq":110,"\u548c\u5bf9\u5e94\u884c\u7684\u4ee3\u7801":107,"\u548c\u5e8f\u5217\u4e2d\u542b\u6709\u5143\u7d20\u7684\u6570\u76ee\u540c":110,"\u548c\u5f02\u6b65\u968f\u673a\u68af\u5ea6\u4e0b\u964d":92,"\u548c\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u8f93\u5165":114,"\u548c\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u76f4\u63a5\u8fd0\u884c\u7684":0,"\u548c\u672a\u6765\u53ef\u80fd\u8fd8\u4f1a\u7528\u5230":42,"\u548c\u793a\u4f8b2\u4e2d\u7684\u914d\u7f6e\u7c7b\u4f3c":111,"\u548c\u79bb\u7ebf\u6570\u636e\u7684\u65b9\u5f0f":11,"\u548c\u90e8\u5206layer":113,"\u548cpool":110,"\u548cpserver\u4e4b\u95f4\u7528\u4e8e\u7a00\u758f\u7c7b\u578b\u53c2\u6570\u901a\u4fe1\u7684\u7aef\u53e3\u4e2a\u6570":91,"\u54ea\u4e2atrainer\u5148\u5b8c\u6210block\u7684\u8bad\u7ec3":10,"\u54ea\u4e9b\u4e0d\u662f":111,"\u56db\u79cd\u6570\u636e\u7c7b\u578b":84,"\u56e0\u4e3a\u4e0a\u8ff0\u7279\u70b9":88,"\u56e0\u4e3a\u5168\u8fde\u63a5\u5c42\u7684\u6fc0\u6d3b\u53ef\u4ee5\u662fsoftmax":74,"\u56e0\u4e3a\u53c2\u6570":105,"\u56e0\u4e3a\u5b83\u4eec\u7684\u8ba1\u7b97\u6548\u7387\u6bd4":114,"\u56e0\u4e3a\u5b83\u6bd4":114,"\u56e0\u4e3a\u5b98\u65b9\u955c\u50cf":97,"\u56e0\u4e3a\u6211\u4eec\u4f1a\u628a\u6240\u6709\u7f16\u8bd1\u5de5\u5177\u90fd\u5b89\u88c5\u8fdb\u4e00\u4e2a":0,"\u56e0\u4e3a\u6e90\u7801\u5c31\u5728\u672c\u673a\u4e0a":0,"\u56e0\u4e3a\u8f93\u5165\u6570\u636e\u53ef\u80fd\u6709\u591a\u79cd\u7ed3\u6784":88,"\u56e0\u4e3a\u8fd9\u4e2a\u5de5\u5177\u5177\u6709web\u670d\u52a1\u754c\u9762":107,"\u56e0\u4e3a\u8fd9\u6837\u505a\u4e5f\u6ca1\u6cd5\u4fdd\u8bc1\u6d88\u9664\u968f\u673a\u6027":10,"\u56e0\u4e3ac":107,"\u56e0\u4e3apython\u7684\u641c\u7d22\u8def\u5f84\u662f\u4f18\u5148\u5df2\u7ecf\u5b89\u88c5\u7684python\u5305":78,"\u56e0\u4e3aswig\u5728\u7b2c\u4e09\u65b9\u8bed\u8a00\u4e2d\u66b4\u9732\u7684\u51fd\u6570\u540d":45,"\u56e0\u6b64":[41,74,111,113,116],"\u56e0\u6b64\u53cc\u5c42\u5e8f\u5217\u7684\u914d\u7f6e\u4e2d":111,"\u56e0\u6b64\u53ef\u80fd\u6d4b\u8bd5\u4e0d\u591f\u5b8c\u5907":76,"\u56e0\u6b64\u5728\u8f6c\u6362\u65f6\u9700\u8981\u663e\u793a\u7684\u6307\u5b9a":76,"\u56e0\u6b64\u5b83\u662finteger_value_sub_sequ":111,"\u56e0\u6b64\u5f53":116,"\u56e0\u6b64\u6211\u4eec\u91c7\u7528\u8f93\u51fa\u7684\u52a0\u6743\u548c":74,"\u56e0\u6b64\u7528\u6237\u5e76\u4e0d\u9700\u8981\u5173\u5fc3\u5b83\u4eec":102,"\u56e0\u6b64\u9519\u8bef\u7684\u4f7f\u7528\u4e8c\u8fdb\u5236\u53d1\u884c\u7248\u53ef\u80fd\u4f1a\u5bfc\u81f4\u8fd9\u79cd\u9519\u8bef":78,"\u56fd\u5185\u7528\u6237\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u7684\u955c\u50cf\u6e90\u6765\u52a0\u901f\u8bbf\u95ee":1,"\u56fe1":[89,90],"\u56fe2":89,"\u56fe\u50cf\u5206\u7c7b":63,"\u56fe\u8868":1,"\u5728":[0,41,42,46,63,72,75,89,90,91,107,110,114,117],"\u5728\u4e00\u4e2a\u4e0d\u53ef\u4e2d\u65ad\u5e76\u7f3a\u5c11\u5907\u4efd\u7684\u8bad\u7ec3\u4efb\u52a1\u4e2d":10,"\u5728\u4e00\u4e2a\u529f\u80fd\u9f50\u5168\u7684kubernetes\u673a\u7fa4\u91cc":96,"\u5728\u4e00\u4e2a\u53c2\u6570\u7684\u68af\u5ea6\u88ab\u66f4\u65b0\u540e":74,"\u5728\u4e00\u4e9b\u5206\u5e03\u5f0f\u7cfb\u7edf\u4e2d":91,"\u5728\u4e00\u6b21\u8bad\u7ec3\u4e2d":107,"\u5728\u4e00\u8f6e\u4e2d\u6bcfsave":103,"\u5728\u4e0a\u56fe\u4e2d\u663e\u793a\u4e86\u5728\u4e00\u4e2a\u5b9e\u9645\u751f\u4ea7\u73af\u5883\u4e2d\u7684\u5e94\u7528":11,"\u5728\u4e0a\u9762\u4ee3\u7801\u4e2d":111,"\u5728\u4e0a\u9762\u7684\u4ee3\u7801\u4e2d":75,"\u5728\u4e0b\u4e00\u7bc7\u4e2d":96,"\u5728\u4e0d\u540c\u96c6\u7fa4\u4e2d\u8fd0\u884c":92,"\u5728\u4e4b\u540e\u7684":81,"\u5728\u4e86\u89e3docker\u7684\u57fa\u672c\u4f7f\u7528\u65b9\u6cd5\u4e4b\u540e":1,"\u5728\u4efb\u610f\u65f6\u95f4\u67d0\u4e00\u53f0\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u4fdd\u5b58\u7684\u53c2\u6570\u53ef\u80fd\u6bd4\u53e6\u4e00\u53f0\u8981\u66f4\u65b0":92,"\u5728\u4f7f\u7528\u4e0d\u540c\u7684\u5206\u5e03\u5f0f\u8ba1\u7b97\u5e73\u53f0\u65f6":91,"\u5728\u4f7f\u7528\u540c\u6b65sgd\u8bad\u7ec3\u795e\u7ecf\u7f51\u7edc\u65f6":92,"\u5728\u4f7f\u7528\u65f6":82,"\u5728\u4f7f\u7528\u8be5\u6587\u6863\u4e4b\u524d":84,"\u5728\u4f7f\u7528c":87,"\u5728\u4f7f\u7528paddlepaddl":87,"\u5728\u4f7f\u7528twine\u4e0a\u4f20\u4e4b\u524d":63,"\u5728\u5168\u8fde\u63a5\u5c42\u4e2d":74,"\u5728\u5177\u4f53\u7684\u8ba1\u7b97\u4e2d":76,"\u5728\u51c6\u5907\u53d1\u8d77":72,"\u5728\u51fa\u73b0\u5355\u70b9\u6545\u969c\u65f6":10,"\u5728\u51fd\u6570":97,"\u5728\u5206\u5e03\u5f0f\u73af\u5883\u4e2d\u6d4b\u8bd5":103,"\u5728\u5206\u5e03\u5f0f\u8bad\u7ec3\u4e2d":103,"\u5728\u521b\u5efaparameters\u540e":83,"\u5728\u5355\u5c42\u6570\u636e\u7684\u57fa\u7840\u4e0a":111,"\u5728\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u52a0\u8f7d\u548c\u4fdd\u5b58\u53c2\u6570":103,"\u5728\u53c2\u6570\u670d\u52a1\u5668\u7ec8\u7aef\u6bcflog":103,"\u5728\u53cc\u5c42rnn\u4e2d\u7684\u7ecf\u5178\u60c5\u51b5\u662f\u5c06\u5185\u5c42\u7684\u6bcf\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217\u6570\u636e":111,"\u5728\u53cd\u5411\u4f20\u9012\u7684\u65f6\u5019":81,"\u5728\u53d8\u6362\u65f6\u9700\u8981\u5c06\u8f93\u5165\u5e8f\u5217\u4f20\u5165":111,"\u5728\u542f\u52a8job\u4e4b\u524d":97,"\u5728\u547d\u4ee4\u884c\u663e\u793a\u5206\u6790\u7ed3\u679c":107,"\u5728\u56de\u590d\u8bc4\u5ba1\u4eba\u610f\u89c1\u65f6":72,"\u5728\u56fe\u50cf\u4efb\u52a1\u4e2d":82,"\u5728\u591acpu\u8bad\u7ec3\u65f6\u5171\u4eab\u8be5\u53c2\u6570":103,"\u5728\u5b8c\u6210\u4e00\u5b9a\u91cf\u6570\u636e\u7684\u8bad\u7ec3\u540e":92,"\u5728\u5b8c\u6210\u795e\u7ecf\u7f51\u7edc\u7684\u642d\u5efa\u4e4b\u540e":84,"\u5728\u5b9a\u4e49\u8f93\u5165layer\u4e4b\u540e":84,"\u5728\u5b9e\u73b0\u6bcf\u4e2a\u5b50\u7c7b\u7684\u65f6\u5019\u5c31\u4e0d\u9700\u8981\u5173\u5fc3\u5206\u652f\u7684\u4e8b\u60c5\u4e86":42,"\u5728\u5b9e\u73b0\u8fc7\u7a0b\u4e2d":46,"\u5728\u5b9e\u9645\u5e94\u7528\u4e2d":82,"\u5728\u5bb9\u5668\u4e2d\u7f16\u8f91\u4ee3\u7801":1,"\u5728\u5bb9\u5668\u521b\u5efa\u540e":97,"\u5728\u5bf9\u5bb9\u5668\u7684\u63cf\u8ff0":97,"\u5728\u5bf9\u5e94\u7684":41,"\u5728\u5c42\u4e2d\u6307\u5b9a":105,"\u5728\u5c42\u521d\u59cb\u5316\u7684\u65f6\u5019":41,"\u5728\u5e8f\u5217\u751f\u6210\u4efb\u52a1\u4e2d":113,"\u5728\u5f00\u59cb\u8bad\u7ec3\u4e4b\u524d":11,"\u5728\u5f02\u6784\u96c6\u7fa4\u4e2d":10,"\u5728\u5f02\u6b65sgd\u4e2d":92,"\u5728\u5f15\u5165\u5176\u4ed6\u7c7b\u578b\u7684\u5934\u6587\u4ef6\u65f6":46,"\u5728\u5f53\u524d":81,"\u5728\u5f53\u524d\u7684\u5b9e\u73b0\u65b9\u5f0f\u4e0b":74,"\u5728\u5f97\u5230":97,"\u5728\u5feb\u7167\u5199\u5165\u5b8c\u6210\u540e":10,"\u5728\u60a8\u7684\u5b9e\u9645\u73af\u5883\u4e2d":10,"\u5728\u6211\u4eec\u7684\u4f8b\u5b50\u4e2d":114,"\u5728\u6267\u884c\u65f6":76,"\u5728\u63d0\u4ea4":72,"\u5728\u642d\u5efa\u795e\u7ecf\u7f51\u7edc\u7684\u8fc7\u7a0b\u4e2d":84,"\u5728\u65e0\u7279\u6b8a\u9700\u6c42\u60c5\u51b5\u4e0b":87,"\u5728\u6709\u666e\u901a\u7684cpu":42,"\u5728\u672c\u4f8b\u4e2d":[72,105,111],"\u5728\u672c\u6559\u7a0b\u4e2d":114,"\u5728\u672c\u6587\u6863\u4e2d":27,"\u5728\u672c\u793a\u4f8b\u4e2d":111,"\u5728\u672c\u8282\u4e2d":114,"\u5728\u673a\u7fa4\u4e0a\u8fd0\u884c\u8f6c\u6362\u7a0b\u5e8f":11,"\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b":81,"\u5728\u6811\u7684\u6bcf\u4e00\u5c42\u4e0a":103,"\u5728\u6837\u4f8b\u4e2d":46,"\u5728\u6b64":[102,105],"\u5728\u6bcf\u4e2a\u65f6\u95f4\u6b65\u4e2d":114,"\u5728\u6bcf\u4e2a\u65f6\u95f4\u6b65\u7684\u5b50\u5e8f\u5217\u957f\u5ea6\u53ef\u4ee5\u4e0d\u76f8\u7b49":111,"\u5728\u6bcf\u4e2a\u65f6\u95f4\u6b65\u957f":114,"\u5728\u6bcf\u4e2apod\u4e0a\u90fd\u901a\u8fc7volume\u65b9\u5f0f\u6302\u8f7d\u5206\u5e03\u5f0f\u6587\u4ef6\u7cfb\u7edf\u7684\u4e00\u4e2a\u76ee\u5f55\u7528\u4e8e\u4fdd\u5b58\u8bad\u7ec3\u6570\u636e\u548c\u8f93\u51fa\u7ed3\u679c":97,"\u5728\u6d4b\u8bd5\u9636\u6bb5":103,"\u5728\u6e90\u7801\u76ee\u5f55\u6811\u7684\u6839\u76ee\u5f55\u4e2d\u8fd0\u884c":72,"\u5728\u751f\u6210\u65f6":114,"\u5728\u7528\u6237\u4f7f\u7528c":46,"\u5728\u76f8\u5e94\u7684\u4f18\u5316\u7b97\u6cd5\u91cc\u8bbe\u7f6elearning_rate_schedule\u53ca\u76f8\u5173\u53c2\u6570":83,"\u5728\u76f8\u5e94layer\u7684":82,"\u5728\u795e\u7ecf\u7f51\u7edc\u4e2d\u7b49\u4e8e\u4e00\u6b21\u9884\u6d4b\u5904\u7406\u7684\u6837\u672c\u6570":89,"\u5728\u7a0b\u5e8f\u5b9e\u73b0\u4e2d\u90fd\u4f1a\u8f6c\u5316\u4e3a\u4e8c\u7ef4\u77e9\u9635":89,"\u5728\u7b2c\u4e8c\u4e2atab":63,"\u5728\u7ebf\u4e0a\u7cfb\u7edf\u4e2d":91,"\u5728\u7ebf\u6a21\u578b\u9884\u6d4b\u670d\u52a1":11,"\u5728\u7ec4\u5408\u65f6":84,"\u5728\u7ec4\u7ec7\u795e\u7ecf\u7f51\u7edc\u8f93\u5165":90,"\u5728\u7ec4\u7ec7\u795e\u7ecf\u7f51\u7edc\u8f93\u5165\u65f6":89,"\u5728\u7ec8\u7aef\u6267\u884c":90,"\u5728\u7f16\u8bd1\u5bbf\u4e3b\u673a\u7248protoc\u53ef\u6267\u884c\u6587\u4ef6\u548c\u76ee\u6807\u673a\u7248openblas\u5e93\u65f6\u9700\u8981\u7528\u5230":[116,118],"\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d":74,"\u5728\u81ea\u7136\u8bed\u8a00\u5904\u7406\u4efb\u52a1\u4e2d":110,"\u5728\u8bad\u7ec3\u4e2d":114,"\u5728\u8bad\u7ec3\u4e4b\u524d":97,"\u5728\u8bad\u7ec3\u65f6":96,"\u5728\u8bad\u7ec3\u7ed3\u675f\u7684\u65f6\u5019\u518d\u4fdd\u5b58\u4e3apaddlepaddle\u7684\u683c\u5f0f":42,"\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d":97,"\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u6bcfshow":103,"\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u83b7\u5f97\u53c2\u6570\u7684\u6743\u91cd\u548c\u68af\u5ea6":81,"\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u83b7\u5f97\u67d0\u4e00\u4e2alayer\u7684output":81,"\u5728\u8bbe\u7f6e":[116,117,118],"\u5728\u8bc4\u5ba1\u8fc7\u7a0b\u4e2d":63,"\u5728\u8be5\u793a\u4f8b\u4e2d":83,"\u5728\u8be5\u914d\u7f6e\u76847":111,"\u5728\u8c03\u7528":90,"\u5728\u8c03\u7528c":90,"\u5728\u8f6f\u4ef6\u5de5\u7a0b\u7684\u8303\u7574\u91cc":108,"\u5728\u8f93\u51fa\u7684\u8fc7\u7a0b\u4e2d":113,"\u5728\u8fd0\u884c\u5b8c\u6027\u80fd\u5206\u6790\u540e":107,"\u5728\u8fd0\u884c\u65f6\u5c06\u795e\u7ecf\u7f51\u7edc\u7684\u591a\u4e2a\u53ef\u5b66\u4e60\u53c2\u6570\u653e\u5728\u540c\u4e00\u4e2a\u76ee\u5f55\u4e2d":90,"\u5728\u8fd0\u884c\u795e\u7ecf\u7f51\u7edc\u8ba1\u7b97\u56fe\u65f6":76,"\u5728\u8fd9\u4e00\u90e8\u5206":104,"\u5728\u8fd9\u4e2a":63,"\u5728\u8fd9\u4e2a\u4f8b\u5b50\u91cc":[74,96],"\u5728\u8fd9\u4e2a\u51fd\u6570\u4e2d":111,"\u5728\u8fd9\u4e2a\u52a8\u6001\u5e93\u4e2d\u4e0d\u5d4c\u5165\u4efb\u4f55\u5176\u4ed6\u8bed\u8a00\u7684\u89e3\u91ca\u5668":45,"\u5728\u8fd9\u4e2a\u6559\u7a0b\u4e2d":108,"\u5728\u8fd9\u4e2a\u6a21\u578b\u4e2d":114,"\u5728\u8fd9\u4e2a\u9636\u6bb5\u7684\u4ee3\u7801\u6b63\u5728\u7ecf\u5386\u56de\u5f52\u6d4b\u8bd5":63,"\u5728\u8fd9\u4e9b\u5934\u6587\u4ef6\u4e2d":46,"\u5728\u8fd9\u4e9b\u6587\u4ef6\u4e2d":46,"\u5728\u8fd9\u4e9blayer\u4e2d":111,"\u5728\u8fd9\u65f6\u771f\u6b63\u7684\u5206\u914d\u5185\u5b58":76,"\u5728\u8fd9\u6bb5\u4ee3\u7801\u4e2d":76,"\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b":[74,114],"\u5728\u8fd9\u79cd\u7ed3\u6784\u4e2d":113,"\u5728\u8fd9\u7bc7\u6587\u6863\u91cc":96,"\u5728\u8fd9\u7bc7\u6587\u7ae0\u91cc":97,"\u5728\u8fd9\u91cc":113,"\u5728\u8fd9\u91cc\u6211\u4eec\u4f7f\u7528\u5168\u8fde\u63a5\u5c42\u4f5c\u4e3a\u4f8b\u5b50\u6765\u5c55\u793a\u5b9e\u73b0\u65b0\u7f51\u7edc\u5c42\u6240\u9700\u8981\u7684\u56db\u4e2a\u6b65\u9aa4":74,"\u5728\u8fd9\u91cc\u7528eigenvector\u6765\u8868\u793a":76,"\u5728\u8fd9\u91cc\u9700\u8981\u6ce8\u610f\u7684\u662f":76,"\u5728\u8fdb\u884c\u5206\u5e03\u5f0f\u8bad\u7ec3\u65f6":91,"\u5728\u8fdb\u884c\u7f51\u7edc\u914d\u7f6e\u4e4b\u524d":84,"\u5728\u91c7\u7528sgd":83,"\u5728\u91cd\u6784\u524d\u7684paddlepaddle\u4e2d":42,"\u5728\u95ee\u9898\u672c\u8eab\u7684\u8ba1\u7b97\u91cf\u6bd4\u8f83\u5c0f\u7684\u65f6\u5019":41,"\u5728\u96c6\u7fa4\u4e0a\u8bad\u7ec3\u4e00\u4e2a\u7a00\u758f\u6a21\u578b\u9700\u8981\u52a0\u4e0a\u4e0b\u9762\u7684\u53c2\u6570":105,"\u5728\u975e\u5e8f\u5217\u8f93\u5165\u65f6":81,"\u5728android\u5e73\u53f0\u4e0a\u4e0d\u652f\u6301\u901a\u8fc7swig\u8c03\u7528\u6765\u8bad\u7ec3\u6216\u8005\u9884\u6d4b":116,"\u5728android\u5e73\u53f0\u4e0a\u53ea\u652f\u6301\u4f7f\u7528c":116,"\u5728batch":41,"\u5728build\u76ee\u5f55\u4e0b\u6267\u884c":78,"\u5728c":[45,89],"\u5728c\u7684\u5934\u6587\u4ef6":45,"\u5728cmake\u53c2\u6570\u914d\u7f6e\u4e0a":[116,117],"\u5728cmake\u7684\u547d\u4ee4\u884c\u4e2d":0,"\u5728eigen\u4e2d":76,"\u5728hpc\u9886\u57df\u4f7f\u7528\u975e\u5e38\u7684\u5e7f\u6cdb":94,"\u5728ios\u5e73\u53f0\u4e0a\u4e0d\u652f\u6301\u901a\u8fc7swig\u8c03\u7528\u6765\u8bad\u7ec3\u6216\u8005\u9884\u6d4b":117,"\u5728ios\u5e73\u53f0\u4e0a\u53ea\u652f\u6301\u4f7f\u7528c":117,"\u5728main":107,"\u5728openmpi\u96c6\u7fa4\u4e2d\u542f\u52a8\u8bad\u7ec3":94,"\u5728packing\u4e0a\u7684\u8017\u65f6":41,"\u5728paddl":97,"\u5728paddle\u4e2d":105,"\u5728paddle\u4e4b\u4e0a\u8fd0\u884c\u7684\u6df1\u5ea6\u5b66\u4e60\u8bad\u7ec3\u8f93\u51fa\u7684\u6a21\u578b\u4f1a\u63d0\u4f9b\u7ed9\u5728\u7ebf\u4eba\u8138\u8bc6\u522b\u7684\u5e94\u7528\u4f7f\u7528":11,"\u5728paddlepaddl":89,"\u5728paddlepaddle\u4e2d":[84,113],"\u5728paddlepaddle\u4e2d\u4f7f\u7528dropout\u6709\u4e24\u79cd\u65b9\u5f0f":82,"\u5728paddlepaddle\u4e2d\u5305\u542b\u4ee5\u4e0b":82,"\u5728paddlepaddle\u5185\u90e8":[89,90],"\u5728paddlepaddle\u7684\u6587\u6863\u4e2d":111,"\u5728paramet":10,"\u5728python\u811a\u672c\u4e2d\u5b9e\u73b0\u4e0e\u524d\u5411operator\u76f8\u540c\u7684\u8ba1\u7b97\u903b\u8f91":75,"\u5728rnn\u7684\u60c5\u51b5\u4e0b":41,"\u5728step\u51fd\u6570\u4e2d\u5b9a\u4e49":113,"\u5728step\u51fd\u6570\u4e2d\u5b9a\u4e49memori":113,"\u5728trainer":105,"\u5728trainer\u4e2d\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u53d6\u6a21\u7684\u65b9\u6cd5\u4e3a\u6bcf\u4e2atrainer\u5206\u914d\u8bad\u7ec3\u6570\u636e\u6587\u4ef6":91,"\u5747\u4f1a\u5b58\u653e\u4e8e":87,"\u5747\u4f1a\u88ab\u5b89\u88c5\u5230includ":46,"\u5747\u5300\u5206\u5e03":83,"\u5747\u5300\u5206\u5e03\u7684\u8303\u56f4\u662f":103,"\u5747\u662f\u5728":46,"\u5747\u6709\u4e09\u4e2a\u5b50\u5e8f\u5217":111,"\u5747\u6709\u4e24\u7ec4\u7279\u5f81":111,"\u57fa\u4e8e\u53cc\u5c42\u5e8f\u5217\u8f93\u5165":113,"\u57fa\u4e8e\u7c98\u6027\u4f1a\u8bdd\u7684\u8d1f\u8f7d\u5747\u8861\u529f\u80fd":27,"\u57fa\u672c\u4f7f\u7528\u6982\u5ff5":[85,90],"\u57fa\u7840\u4e0a":89,"\u57fa\u7c7b":75,"\u586b\u5199":72,"\u589e\u52a0":75,"\u589e\u52a0\u4e86\u4e00\u6761cd\u547d\u4ee4":96,"\u589e\u52a0\u4e86\u8bbe\u5907\u7c7b\u578b":75,"\u589e\u52a0\u5982\u4e0b\u53c2\u6570":105,"\u589e\u52a0\u68af\u5ea6\u68c0\u6d4b\u7684\u5355\u5143\u6d4b\u8bd5":74,"\u5904\u7406\u5668\u6709\u4e24\u4e2a\u5173\u952e\u6027\u80fd\u9650\u5236":108,"\u5904\u7406\u7684\u8f93\u5165\u5e8f\u5217\u4e3b\u8981\u5206\u4e3a\u4ee5\u4e0b\u4e09\u79cd\u7c7b\u578b":113,"\u5907\u6ce8":108,"\u590d\u6742\u5ea6\u6216\u65f6\u95f4\u590d\u6742\u5ea6":108,"\u5916\u5c42\u5e8f\u5217\u5728":89,"\u5916\u5c42memory\u662f\u4e00\u4e2a\u5143\u7d20":111,"\u5916\u5c42outer_step\u4e2d":111,"\u5916\u90e8\u5b58\u50a8":42,"\u591a\u4e2a":90,"\u591a\u4e2a\u503c":11,"\u591a\u4e2a\u5c42\u7684\u8f93\u51fa\u77e9\u9635\u7684\u9ad8\u5ea6\u4e0d\u4e00\u81f4\u5bfc\u81f4\u62fc\u63a5\u5931\u8d25":81,"\u591a\u4e2a\u6392\u6210\u4e00\u5217\u7684\u5143\u7d20":89,"\u591a\u4e2a\u8f93\u51fa\u5c42\u5904\u7406\u591a\u4e2a\u4e0d\u540c\u957f\u5ea6\u7684\u5e8f\u5217":81,"\u591a\u4e2aip\u4f7f\u7528":91,"\u591a\u4e2aparamet":10,"\u591a\u53e5\u8bdd\u8fdb\u4e00\u6b65\u6784\u6210\u4e86\u6bb5\u843d":113,"\u591a\u673a\u8bad\u7ec3":81,"\u591a\u6b21\u8c03\u7528":41,"\u591a\u7528\u4e8e\u81ea\u7136\u8bed\u8a00\u5904\u7406\u4efb\u52a1":90,"\u591a\u8f6e\u5bf9\u8bdd\u7b49\u66f4\u4e3a\u590d\u6742\u7684\u8bed\u8a00\u6570\u636e":113,"\u5927\u4e8e\u7b49\u4e8e\u4e00\u4e2a":90,"\u5927\u591a\u6570\u5c42\u4e0d\u9700\u8981\u8fdc\u7a0b\u7a00\u758f\u8bad\u7ec3\u51fd\u6570":74,"\u5927\u591a\u6570\u5c42\u9700\u8981\u8bbe\u7f6e\u4e3a":74,"\u5927\u591a\u6570\u7f51\u7edc\u5c42\u4e0d\u9700\u8981\u652f\u6301\u8fdc\u7a0b\u7a00\u758f\u66f4\u65b0":74,"\u5927\u591a\u6570\u8bed\u8a00\u90fd\u652f\u6301\u4f7f\u7528c\u8bed\u8a00api":45,"\u5927\u5bb6\u53ef\u4ee5\u7528\u628a\u5f00\u53d1\u5de5\u5177\u5b89\u88c5\u8fdb\u5165":0,"\u5927\u5bb6\u53ef\u4ee5\u901a\u8fc7\u5b83\u9605\u8bfb\u6559\u7a0b":1,"\u5927\u5c0f\u4e0d\u4e00\u6837\u65f6":81,"\u5927\u6982\u82b1\u5341\u5206\u949f\u770b\u4e00\u4e0b":0,"\u5927\u90e8\u5206":107,"\u5934\u4fe1\u606f\u4e2d":83,"\u5934\u6587\u4ef6\u4e2d\u628a\u53c2\u6570\u5b9a\u4e49\u4e3a\u7c7b\u7684\u6210\u5458\u53d8\u91cf":74,"\u5934\u6587\u4ef6\u5982\u4e0b":74,"\u5982":[72,75,105,114],"\u5982\u4e0a\u4e00\u5c0f\u8282\u6240\u793a":76,"\u5982\u4e0b":91,"\u5982\u4e0b\u56fe\u6240\u793a":[108,111],"\u5982\u4e0b\u6240\u793a":105,"\u5982\u4f55\u8d21\u732e\u4ee3\u7801":73,"\u5982\u4f55\u8d21\u732e\u6587\u6863":73,"\u5982\u56fe\u4e2dtrainer":10,"\u5982\u6709":75,"\u5982\u679c\u4e00\u4e2a\u7f51\u7edc\u5c42\u9700\u8981\u914d\u7f6e\u7684\u8bdd":74,"\u5982\u679c\u4e0a\u9762\u4e24\u6b65\u51fa\u73b0\u9519\u8bef":10,"\u5982\u679c\u4e0d\u4e3a0":103,"\u5982\u679c\u4e0d\u4f7f\u7528\u5206\u5e03\u5f0f\u5b58\u50a8":91,"\u5982\u679c\u4e0d\u60f3\u4f7f\u7528":77,"\u5982\u679c\u4e0d\u6307\u5b9a\u8fd9\u4e2a\u6587\u4ef6":107,"\u5982\u679c\u4e0d\u6536\u655b":83,"\u5982\u679c\u4e0d\u9700\u8981\u5916\u90e8\u5b58\u50a8\u7528\u4e8e\u8f6c\u6362":42,"\u5982\u679c\u4e3a0":103,"\u5982\u679c\u4e3a\u5426\u5219\u662f\u7528openbla":0,"\u5982\u679c\u4e3afals":103,"\u5982\u679c\u4e3atrue":103,"\u5982\u679c\u4e4b\u540e\u60f3\u8981\u91cd\u65b0\u8bbe\u7f6e":0,"\u5982\u679c\u4ec5\u4ec5\u4fee\u6539\u4e00\u4e2a\u6587\u4ef6\u4f46\u63d0\u4ea4\u4e86\u5341\u51e0\u4e2acommit":72,"\u5982\u679c\u4ecd\u7136\u5b58\u5728\u95ee\u9898":3,"\u5982\u679c\u4ed4\u7ec6\u8bbe\u7f6e\u7684\u8bdd":103,"\u5982\u679c\u4f60\u53ea\u9700\u8981\u4f7f\u7528\u7b80\u5355\u7684rnn":114,"\u5982\u679c\u4f60\u60f3\u4f7f\u7528\u8fd9\u4e9b\u7279\u6027":105,"\u5982\u679c\u4f60\u60f3\u8981\u4fdd\u5b58\u67d0\u4e9b\u5c42\u7684\u7279\u5f81\u56fe":103,"\u5982\u679c\u4f60\u66fe\u5728\u6e90\u7801\u76ee\u5f55\u4e0b\u7f16\u8bd1\u8fc7\u5176\u4ed6\u5e73\u53f0\u7684paddlepaddle\u5e93":117,"\u5982\u679c\u4f60\u66fe\u7ecf\u5728\u6e90\u7801\u76ee\u5f55\u4e0b\u7f16\u8bd1\u8fc7\u5176\u4ed6\u5e73\u53f0\u7684paddlepaddle\u5e93":[116,118],"\u5982\u679c\u4f60\u6b63\u5728\u5904\u7406\u5e8f\u5217\u6807\u8bb0\u4efb\u52a1":114,"\u5982\u679c\u4f60\u8981\u4e3a\u4e86\u6d4b\u8bd5\u800c\u589e\u52a0\u65b0\u7684\u6587\u4ef6":74,"\u5982\u679c\u4f7f\u7528":90,"\u5982\u679c\u4f7f\u7528\u81ea\u884c":0,"\u5982\u679c\u4f7f\u7528mkl\u5e76\u4e14\u673a\u5668\u542b\u6709avx2\u6307\u4ee4\u96c6":0,"\u5982\u679c\u4f7f\u7528swig\u6211\u4eec\u9700\u8981\u5c06\u5728interface\u6587\u4ef6\u91cc":45,"\u5982\u679c\u5173\u95edmkl":0,"\u5982\u679c\u51fa\u73b0\u4ee5\u4e0bpython\u76f8\u5173\u7684\u5355\u5143\u6d4b\u8bd5\u90fd\u8fc7\u4e0d\u4e86\u7684\u60c5\u51b5":78,"\u5982\u679c\u53c2\u6570\u4fdd\u5b58\u4e0b\u6765\u7684\u6a21\u578b\u76ee\u5f55":81,"\u5982\u679c\u53d1\u73b0\u6700\u65e9\u7684\u62a5\u9519\u5c31\u662f\u7f51\u7edc\u901a\u4fe1\u7684\u95ee\u9898":79,"\u5982\u679c\u540c\u65f6\u4f7f\u7528":91,"\u5982\u679c\u5728\u4f7f\u7528mkl":42,"\u5982\u679c\u5728\u5b89\u88c5\u8fc7\u7a0b\u4e2d\u9047\u5230\u4e86\u95ee\u9898":2,"\u5982\u679c\u5728\u70b9\u51fb\u4e0b\u9762\u94fe\u63a5\u65f6\u51fa\u73b0\u5982\u4e0b\u767b\u9646\u754c\u9762":3,"\u5982\u679c\u5728\u7f16\u8bd1":87,"\u5982\u679c\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d\u672a\u8bbe\u7f6easync":103,"\u5982\u679c\u5728\u8bad\u7ec3\u671f\u95f4\u540c\u65f6\u53d1\u8d77\u53e6\u5916\u4e00\u4e2a\u8fdb\u7a0b\u8fdb\u884c\u6d4b\u8bd5":103,"\u5982\u679c\u5728\u8bad\u7ec3\u914d\u7f6e\u4e2d\u8bbe\u7f6ebatch":103,"\u5982\u679c\u5728\u8bad\u7ec3nlp\u76f8\u5173\u6a21\u578b\u65f6":83,"\u5982\u679c\u591a\u4e2aop\u4f9d\u8d56\u4e00\u4e9b\u5171\u7528\u7684\u51fd\u6570":75,"\u5982\u679c\u5931\u8d25":63,"\u5982\u679c\u5b58\u5728\u6570\u636e\u6392\u5217\u683c\u5f0f\u4e0d\u4e00\u6837\u7684\u60c5\u51b5\u65f6":42,"\u5982\u679c\u5b58\u5728\u67d0\u4e9btrainer\u6267\u884c\u901f\u5ea6\u8fc7\u6162\u4f1a\u5f71\u54cd\u6574\u4f53\u96c6\u7fa4\u7684\u901f\u5ea6":10,"\u5982\u679c\u5c06\u8fd9\u4e2a\u5185\u5b58\u6c60\u51cf\u5c0f":81,"\u5982\u679c\u5c0f\u4e8e75m":78,"\u5982\u679c\u5df2\u7ecf\u6709pod\u8fd0\u884c":97,"\u5982\u679c\u5df2\u7ecf\u6b63\u5728\u6267\u884c\u4fdd\u5b58\u68c0\u67e5\u70b9\u7684\u7ebf\u7a0b":10,"\u5982\u679c\u5e0c\u671b\u53ef\u4ee5\u5728\u540e\u53f0\u8fd0\u884cpserver\u7a0b\u5e8f":91,"\u5982\u679c\u5f53\u524dmpi\u96c6\u7fa4\u5e76\u4e0d\u652f\u6301\u4efb\u52a1\u72ec\u5360\u6a21\u5f0f":79,"\u5982\u679c\u60a8\u5728\u4f7f\u7528window":1,"\u5982\u679c\u60a8\u60f3\u8981\u66f4\u6df1\u5165\u4e86\u89e3deep":1,"\u5982\u679c\u60a8\u671f\u671b\u5728\u7f16\u8bd1\u5b8c\u6210\u540e\u7acb\u5373\u6267\u884c\u6240\u6709\u7684\u5355\u5143\u6d4b\u8bd5":0,"\u5982\u679c\u60a8\u6ca1\u6709\u542c\u8bf4":0,"\u5982\u679c\u60a8\u7684\u7535\u8111\u4e0d\u652f\u6301avx":1,"\u5982\u679c\u60a8\u7684\u95ee\u9898\u672a\u5728\u6b64\u5904":80,"\u5982\u679c\u60a8\u7684gpu\u7406\u8bba\u53ef\u4ee5\u8fbe\u52306":108,"\u5982\u679c\u60a8\u9009\u62e9\u4e0d\u4f7f\u7528docker\u955c\u50cf":0,"\u5982\u679c\u60f3\u4f7f\u7528\u53ef\u89c6\u5316\u7684\u5206\u6790\u5668":108,"\u5982\u679c\u60f3\u5f88\u597d\u7684\u7406\u89e3\u7a0b\u5e8f\u7684\u884c\u4e3a":108,"\u5982\u679c\u60f3\u6539\u53d8\u539f\u6709tensor\u7684shape\u4fe1\u606f":76,"\u5982\u679c\u60f3\u8981\u4e86\u89e3\u53cc\u5c42rnn\u5728\u5177\u4f53\u95ee\u9898\u4e2d\u7684\u4f7f\u7528":111,"\u5982\u679c\u60f3\u8981\u542f\u7528paddlepaddle\u7684\u5185\u7f6e\u5b9a\u65f6\u5668":108,"\u5982\u679c\u60f3\u8be6\u7ec6\u4e86\u89e3":94,"\u5982\u679c\u6211\u77e5\u9053\u5185\u6838\u82b1\u4e8610ms\u6765\u79fb\u52a81gb\u6570\u636e":108,"\u5982\u679c\u6307\u5b9a\u4e862\u4e2alayer\u4f5c\u4e3a\u8f93\u51fa\u5c42":81,"\u5982\u679c\u63d0\u793a\u6b63\u786e":77,"\u5982\u679c\u652f\u6301\u589e\u52a0\u6b64\u53c2\u6570\u63d0\u4ea4":79,"\u5982\u679c\u662f\u4e00\u4e2a\u5e8f\u5217\u8f93\u5165":89,"\u5982\u679c\u662f\u5176\u5b83\u7c7b\u578b":11,"\u5982\u679c\u662f\u7528\u7f16\u8bd1\u65f6\u6307\u5b9acpu\u7248\u672c":87,"\u5982\u679c\u6709\u591a\u4e2a\u8f93\u5165":113,"\u5982\u679c\u6709\u591a\u4e2a\u8f93\u5165\u5e8f\u5217":113,"\u5982\u679c\u6709\u9700\u8981\u4fee\u6539\u7684\u5730\u65b9":72,"\u5982\u679c\u6709bugfix\u7684\u884c\u4e3a":63,"\u5982\u679c\u671f\u671b\u6267\u884c\u5176\u4e2d\u4e00\u4e2a\u5355\u5143\u6d4b\u8bd5":0,"\u5982\u679c\u672a\u8bbe\u7f6e":103,"\u5982\u679c\u672a\u8bbe\u7f6egpu":105,"\u5982\u679c\u673a\u5668\u4e2d\u5df2\u7ecf\u5b89\u88c5\u8fc7paddlepaddl":0,"\u5982\u679c\u67d0\u4e00\u4e2a\u7c7b\u578b\u9700\u8981\u5f15\u7528\u53e6\u4e00\u4e2a\u7c7b\u578b":46,"\u5982\u679c\u67d0\u4e00\u4e2apaddl":46,"\u5982\u679c\u67d0\u4e00\u4e2apaddle\u6982\u5ff5\u5fc5\u987b\u8981\u66b4\u9732":46,"\u5982\u679c\u67d0\u4e00\u5757\u6839\u672c\u5c31\u4e0d\u600e\u4e48\u8017\u65f6":108,"\u5982\u679c\u68c0\u67e5\u5230\u5206\u914d\u5728\u4e0d\u540c\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u7684\u53c2\u6570\u7684\u5206\u5e03\u4e0d\u5747\u5300\u6b21\u6570\u5927\u4e8echeck":103,"\u5982\u679c\u6ca1\u6709\u5b89\u88c5nvidia":1,"\u5982\u679c\u6ca1\u6709\u5b9a\u4e49memori":113,"\u5982\u679c\u6ca1\u8fc7":72,"\u5982\u679c\u6d88\u606f\u6570\u636e\u592a\u5c0f":103,"\u5982\u679c\u6ee1\u8db3\u6761\u4ef6":10,"\u5982\u679c\u7528\u516c\u7528\u7684\u7535\u8111\u5f00\u53d1":0,"\u5982\u679c\u7528\u6237\u4e0d\u9700\u8981\u8bbf\u95eelstm\u7684\u4e2d\u95f4\u53d8\u91cf":82,"\u5982\u679c\u7528\u6237\u60f3\u8981\u81ea\u5b9a\u4e49\u521d\u59cb\u5316\u65b9\u5f0f":83,"\u5982\u679c\u7528\u6237\u8981\u628apaddle\u7684\u9759\u6001\u5e93":45,"\u5982\u679c\u7528\u81ea\u5df1\u7684\u7535\u8111\u5f00\u53d1":0,"\u5982\u679c\u771f\u60f3\u6316\u6398\u5185\u6838\u6df1\u5904\u7684\u67d0\u4e2a\u79d8\u5bc6":108,"\u5982\u679c\u795e\u7ecf\u7f51\u7edc\u6709\u591a\u4e2a\u8f93\u5165\u6216\u8005\u591a\u4e2a\u8f93\u51fa":[89,90],"\u5982\u679c\u7a0b\u5e8f\u5d29\u6e83\u4f60\u4e5f\u53ef\u4ee5\u624b\u52a8\u7ec8\u6b62":93,"\u5982\u679c\u7cfb\u7edf\u5b89\u88c5\u4e86\u591a\u4e2apython\u7248\u672c":78,"\u5982\u679c\u7cfb\u7edf\u652f\u6301":[3,78],"\u5982\u679c\u7cfb\u7edf\u652f\u6301\u7684\u662f":[3,78],"\u5982\u679c\u7f16\u8bd1\u65f6\u6307\u5b9a\u7f16\u8bd1cpu\u7248\u672c":87,"\u5982\u679c\u7f16\u8bd1\u65f6\u6307\u5b9a\u7f16\u8bd1gpu\u7248\u672c":87,"\u5982\u679c\u7f51\u7edc\u5c42\u4e0d\u9700\u8981\u8fdc\u7a0b\u7a00\u758f\u66f4\u65b0":74,"\u5982\u679c\u7f51\u7edc\u67b6\u6784\u7b80\u5355":114,"\u5982\u679c\u8981\u4e0a\u4f20gpu\u7248\u672c\u7684\u5305":63,"\u5982\u679c\u8981\u542f\u7528gpu":101,"\u5982\u679c\u8981\u8fd0\u884c\u6240\u6709\u7684\u5355\u5143\u6d4b\u8bd5":72,"\u5982\u679c\u89e3\u51b3\u4e86\u67d0\u4e2aissue\u7684\u95ee\u9898":72,"\u5982\u679c\u8bad\u7ec3\u4e00\u4e2apass":83,"\u5982\u679c\u8bad\u7ec3\u8fc7\u7a0b\u7684\u7684cost\u660e\u663e\u9ad8\u4e8e\u8fd9\u4e2a\u5e38\u6570\u8f93\u51fa\u7684cost":83,"\u5982\u679c\u8bbe\u7f6e\u8be5\u53c2\u6570":103,"\u5982\u679c\u8bc4\u5ba1\u610f\u89c1\u6bd4\u8f83\u591a":72,"\u5982\u679c\u8c03\u7528\u9759\u6001\u5e93\u53ea\u80fd\u5c06\u9759\u6001\u5e93\u4e0e\u89e3\u91ca\u5668\u94fe\u63a5":45,"\u5982\u679c\u8f93\u5165\u662f\u5e8f\u5217\u6570\u636e":89,"\u5982\u679c\u8f93\u51fa\u662f\u4e00\u4e2a\u5e8f\u5217":89,"\u5982\u679c\u8f93\u51fa\u662fno":1,"\u5982\u679c\u8fd0\u884c":78,"\u5982\u679c\u8fd8\u4e0d\u884c":78,"\u5982\u679c\u95ee\u9898\u6ca1\u6709\u5f97\u5230\u89e3\u51b3":2,"\u5982\u679c\u9700\u8981":87,"\u5982\u679c\u9700\u8981\u5728c\u7ef4\u5ea6\u8ba1\u7b97softmax":82,"\u5982\u679c\u9700\u8981\u5b89\u88c5\u652f\u6301gpu\u7684\u7248\u672c":[3,86],"\u5982\u679c\u9700\u8981\u624b\u52a8\u7f16\u8bd1":63,"\u5982\u679c\u9700\u8981\u6269\u5927\u77e9\u9635":74,"\u5982\u679c\u9700\u8981\u7f29\u51cf\u77e9\u9635":74,"\u5982\u679c\u9700\u8981\u83b7\u53d6":3,"\u5982\u679ccuda":75,"\u5982\u679clearning_rate\u592a\u5927":83,"\u5982\u679clearning_rate\u592a\u5c0f":83,"\u5982\u679cmkl":42,"\u5982\u679cop\u6ca1\u6709\u5b9e\u73b0cuda":75,"\u5982\u679cop\u7684\u67d0\u4e2a\u8f93\u5165\u4e0d\u53c2\u4e0e\u53cd\u5411\u68af\u5ea6\u7684\u8ba1\u7b97":75,"\u5982\u679cpaddlepaddle\u5305\u5df2\u7ecf\u5728python\u7684sit":78,"\u5982\u679cpaddlepaddle\u5e93\u9700\u8981\u540c\u65f6\u652f\u6301\u771f\u673a\u548c\u6a21\u62df\u5668":117,"\u5982\u679cparamet":10,"\u5982\u6bcf\u4e2a\u6587\u4ef6\u53ea\u6709\u4e00\u4e2a":72,"\u5982\u795e\u7ecf\u5143\u6fc0\u6d3b\u503c\u7b49":81,"\u5982\u8981build\u8fd9\u4e2a\u5f00\u53d1\u955c\u50cf":72,"\u5982\u9ad8\u4eae\u90e8\u5206":108,"\u5982train":91,"\u5b50\u53e5":113,"\u5b50\u53e5\u7684\u5355\u8bcd\u6570\u548c\u6307\u5b9a\u7684\u4e00\u4e2a\u8f93\u5165\u5e8f\u5217\u4e00\u81f4":113,"\u5b50\u7c7b\u53ea\u9700\u8981\u4f7f\u7528\u5b9a\u4e49\u597d\u7684\u63a5\u53e3":42,"\u5b57\u6bb5\u4e2d":97,"\u5b57\u6bb5\u4e3a\u4f8b":81,"\u5b57\u6bb5\u7684\u53d6\u503c":89,"\u5b57\u6bb5\u8868\u793a\u5bb9\u5668\u7684\u73af\u5883\u53d8\u91cf":97,"\u5b57\u6bb5\u8868\u793a\u8fd9\u4e2ajob\u4f1a\u540c\u65f6\u5f00\u542f3\u4e2apaddlepaddle\u8282\u70b9":97,"\u5b57\u6bb5\u8bbe\u4e3a":63,"\u5b57\u7b26\u4e32":11,"\u5b58\u50a8":[11,89,90],"\u5b58\u50a8\u6d6e\u70b9\u7c7b\u578b\u8f93\u5165":90,"\u5b58\u50a8\u7684\u538b\u7f29\u6587\u4ef6":90,"\u5b58\u6570\u6570\u636e":89,"\u5b66\u4e60":0,"\u5b66\u4e60\u6210\u672c\u9ad8":45,"\u5b66\u4e60\u7387\u4e3a":83,"\u5b83\u4eec\u4e3b\u8981\u662f\u7528\u4e8e":42,"\u5b83\u4eec\u7684\u6587\u4ef6\u540d\u662f":11,"\u5b83\u5305\u542b\u4ee5\u4e0b\u51e0\u6b65":74,"\u5b83\u5305\u542b\u4ee5\u4e0b\u53c2\u6570":74,"\u5b83\u53ea\u4f1a\u5305\u62ec\u751f\u6210\u597d\u7684\u52a8\u6001\u5e93\u548c\u5934\u6587\u4ef6":42,"\u5b83\u53eb\u505a":114,"\u5b83\u53ef\u4ee5\u5e2e\u52a9\u51cf\u5c11\u5206\u53d1\u5ef6\u8fdf":93,"\u5b83\u53ef\u4ee5\u5e2e\u52a9\u6211\u4eec\u683c\u5f0f\u5316\u6e90\u4ee3\u7801":72,"\u5b83\u53ef\u4ee5\u6307\u6d4b\u91cf\u4e00\u4e2a\u7a0b\u5e8f\u7684\u7a7a\u95f4":108,"\u5b83\u53ef\u80fd\u6709\u4e0d\u6b62\u4e00\u4e2a\u6743\u91cd":74,"\u5b83\u5b9a\u4e49\u4e86":114,"\u5b83\u5b9a\u4e49\u89e3\u7801\u7f51\u7edc\u7684":114,"\u5b83\u5c06\u88ab\u5206\u53d1\u5230":93,"\u5b83\u5e76\u4e0d\u662f\u4e00\u4e2a\u5b8c\u6574\u7684recurr":82,"\u5b83\u5e94\u8be5\u6253\u5370\u51fa\u9884\u6d4b\u4f4f\u623f\u6570\u636e\u7684\u6e05\u5355":86,"\u5b83\u652f\u6301\u591a\u7ebf\u7a0b\u66f4\u65b0":74,"\u5b83\u662finteger_value\u7c7b\u578b\u7684":111,"\u5b83\u662finteger_value_sequence\u7c7b\u578b\u7684":111,"\u5b83\u6709\u52a9\u4e8e\u5e2e\u52a9\u9891\u7e41\u4fee\u6539\u548c\u8bbf\u95ee\u5de5\u4f5c\u533a\u6587\u4ef6\u7684\u7528\u6237\u51cf\u5c11\u8d1f\u62c5":93,"\u5b83\u7684":114,"\u5b83\u7684\u529f\u80fd\u662f":75,"\u5b83\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20":110,"\u5b83\u7684\u8f93\u5165\u4e0e\u7ecf\u8fc7\u5b66\u4e60\u7684\u53c2\u6570\u505a\u5185\u79ef\u5e76\u52a0\u4e0a\u504f\u7f6e":74,"\u5b83\u8d1f\u8d23\u51b3\u5b9a\u7f16\u8bd1\u65f6\u662f\u5426\u4f7f\u7528mklml\u548cmkl":42,"\u5b83\u9996\u5148\u8c03\u7528\u57fa\u6784\u9020\u51fd\u6570":74,"\u5b89\u88c5":107,"\u5b89\u88c5\u4e0e\u7f16\u8bd1":115,"\u5b89\u88c5\u4e0e\u7f16\u8bd1c":88,"\u5b89\u88c5\u540e":1,"\u5b89\u88c5\u540e\u7684\u76ee\u5f55\u7ed3\u6784\u4e3a":46,"\u5b89\u88c5\u597ddocker\u4e4b\u540e\u53ca\u53ef\u7528\u4ee5\u4e0b\u547d\u4ee4\u542f\u52a8\u5de5\u5177":77,"\u5b89\u88c5\u597ddocker\u4e4b\u540e\u53ef\u4ee5\u4f7f\u7528\u6e90\u7801\u76ee\u5f55\u4e0b\u7684\u811a\u672c\u6784\u5efa\u6587\u6863":77,"\u5b89\u88c5\u5b8c\u6210\u4e4b\u540e":[101,117],"\u5b89\u88c5\u5b8c\u6bd5\u540e":107,"\u5b89\u88c5\u6587\u6863":84,"\u5b89\u88c5\u65b9\u5f0f\u6765\u5feb\u901f\u5b89\u88c5paddlepaddl":101,"\u5b8c\u6210":72,"\u5b8c\u6210\u4e00\u4e2a\u4f20\u8f93\u52a8\u4f5c\u5b8c\u6210\u7684\u65f6\u95f4\u4e5f\u6bd4\u8f83\u77ed":27,"\u5b8c\u6210\u4e0a\u8ff0\u51c6\u5907\u4e4b\u540e":90,"\u5b8c\u6210\u4efb\u610f\u7684\u8fd0\u7b97\u903b\u8f91":113,"\u5b8c\u6210\u540evolume\u4e2d\u7684\u6587\u4ef6\u5185\u5bb9\u5927\u81f4\u5982\u4e0b":97,"\u5b8c\u6210\u5728windows\u4e0a\u5b89\u88c5\u548c\u4f7f\u7528dock":1,"\u5b8c\u6210\u5b89\u88c5":3,"\u5b8c\u6210\u5e38\u7528layer\u7684mkl":42,"\u5b8c\u6210\u5e38\u89c1\u6df1\u5ea6\u795e\u7ecf\u7f51\u7edcvgg":42,"\u5b8c\u6210\u6570\u636e\u7684\u9884\u5904\u7406":11,"\u5b8c\u6210\u76f8\u5e94\u7684\u8ba1\u7b97":110,"\u5b8c\u6210\u81ea\u52a8\u5316\u4e8c\u8fdb\u5236\u7f16\u8bd1":63,"\u5b8c\u6210paddlepaddle\u7684\u5b89\u88c5":84,"\u5b8c\u6574\u4ee3\u7801\u53ef\u4ee5\u53c2\u8003\u793a\u4f8b":81,"\u5b8c\u6574\u4ee3\u7801\u53ef\u4ee5\u67e5\u770b":90,"\u5b8c\u6574\u6e90\u7801\u53ef\u53c2\u8003":83,"\u5b8c\u6574\u7684\u53c2\u6570\u77e9\u9635\u88ab\u5206\u5e03\u5728\u4e0d\u540c\u7684\u53c2\u6570\u670d\u52a1\u5668\u4e0a":74,"\u5b8c\u6574\u7684\u914d\u7f6e\u6587\u4ef6\u5728":114,"\u5b98\u65b9\u6587\u6863":0,"\u5b9a\u4e49":42,"\u5b9a\u4e49\u4e00\u4e2a\u65f6\u95f4\u6b65\u4e4b\u5185rnn\u5355\u5143\u5b8c\u6210\u7684\u8ba1\u7b97":113,"\u5b9a\u4e49\u4e00\u4e9b\u9664\u4e86layer\u548cmemory\u76f8\u5173\u7684\u7c7b\u548c\u51fd\u6570":42,"\u5b9a\u4e49\u4e86\u4e00\u4e2a\u53ea\u8bfb\u7684memori":113,"\u5b9a\u4e49\u4e86lstm\u5355\u5143\u5728\u4e00\u4e2a\u65f6\u95f4\u6b65\u5185\u7684\u8ba1\u7b97\u8fc7\u7a0b":82,"\u5b9a\u4e49\u4f4d\u7f6e":75,"\u5b9a\u4e49\u5728\u5916\u5c42":113,"\u5b9a\u4e49\u5f02\u6b65\u8bad\u7ec3\u7684\u957f\u5ea6":103,"\u5b9a\u4e49\u6e90\u8bed\u53e5\u7684\u6570\u636e\u5c42":114,"\u5b9a\u4e49\u7684\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784":90,"\u5b9a\u4e49\u7c7b\u578b":75,"\u5b9a\u4e49\u89e3\u7801\u5668\u7684memori":114,"\u5b9a\u4e49\u8f93\u5165":75,"\u5b9a\u4e49\u8f93\u51fa":75,"\u5b9a\u4e49\u8f93\u51fa\u51fd\u6570":114,"\u5b9a\u4e49\u95e8\u63a7\u5faa\u73af\u5355\u5143\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u5355\u6b65\u51fd\u6570":114,"\u5b9d\u5854\u7684\u5e95\u7aef\u9700\u8981\u575a\u5b9e\u7684\u57fa\u5ea7\u6765\u652f\u6491":84,"\u5b9e\u73b0\u4e24\u4e2a\u5b8c\u5168\u7b49\u4ef7\u7684\u5168\u8fde\u63a5rnn":111,"\u5b9e\u73b0\u5177\u4f53\u7684\u51fd\u6570\u529f\u80fd\u5373\u53ef":42,"\u5b9e\u73b0\u524d\u5411\u4f20\u64ad\u7684\u90e8\u5206\u6709\u4e0b\u9762\u51e0\u4e2a\u6b65\u9aa4":74,"\u5b9e\u73b0\u5355\u6b65\u51fd\u6570":114,"\u5b9e\u73b0\u540e\u5411\u4f20\u64ad\u7684\u90e8\u5206\u6709\u4e0b\u9762\u51e0\u4e2a\u6b65\u9aa4":74,"\u5b9e\u73b0\u5728":75,"\u5b9e\u73b0\u5bf9":76,"\u5b9e\u73b0\u65b0\u7684op\u90fd\u6dfb\u52a0\u81f3\u76ee\u5f55":75,"\u5b9e\u73b0\u6784\u9020\u51fd\u6570":74,"\u5b9e\u73b0\u7684":82,"\u5b9e\u73b0\u7b80\u5355":45,"\u5b9e\u73b0\u7ec6\u8282":74,"\u5b9e\u73b0\u7f51\u7edc\u5c42\u7684\u524d\u5411\u4f20\u64ad":74,"\u5b9e\u73b0\u7f51\u7edc\u5c42\u7684\u540e\u5411\u4f20\u64ad":74,"\u5b9e\u73b0\u8bcd\u8bed\u548c\u53e5\u5b50\u4e24\u4e2a\u7ea7\u522b\u7684\u53cc\u5c42rnn\u7ed3\u6784":113,"\u5b9e\u73b0\u8be5\u5c42\u7684c":74,"\u5b9e\u9645\u4e0a\u4f7f\u7528\u4e86":82,"\u5b9e\u9645\u4e0a\u9700\u8981\u7684\u8f93\u51fa\u7ed3\u679c\u662f\u4e24\u4e2a\u77e9\u9635":81,"\u5bb9\u5668\u8fd0\u884c\u90fd\u8fd0\u884c":97,"\u5bb9\u5668\u9ed8\u8ba4\u6267\u884c":116,"\u5bbd\u5ea6":89,"\u5bbd\u5ea6\u4e3a":89,"\u5bbd\u5ea6\u7b49\u4e8e\u914d\u7f6e\u4e2dlayer\u7684s":81,"\u5bbf\u4e3b\u673a\u7684c":[116,117,118],"\u5bc4\u5b58\u5668\u4f7f\u7528\u60c5\u51b5\u548c\u5171\u4eab\u5185\u5b58\u4f7f\u7528\u60c5\u51b5\u80fd\u8ba9\u6211\u4eec\u5bf9gpu\u7684\u6574\u4f53\u4f7f\u7528\u6709\u66f4\u597d\u7684\u7406\u89e3":108,"\u5bf9":90,"\u5bf9\u4e00\u4e2a5\u7ef4\u975e\u5e8f\u5217\u7684\u7a00\u758f01\u5411\u91cf":84,"\u5bf9\u4e00\u4e2a5\u7ef4\u975e\u5e8f\u5217\u7684\u7a00\u758f\u6d6e\u70b9\u5411\u91cf":84,"\u5bf9\u4e8e":114,"\u5bf9\u4e8e\u4e0d\u540c\u7684\u8bad\u7ec3\u4efb\u52a1":91,"\u5bf9\u4e8e\u4e0d\u540c\u8bed\u8a00":45,"\u5bf9\u4e8e\u4e24\u79cd\u4e0d\u540c\u7684\u8f93\u5165\u6570\u636e\u7c7b\u578b":111,"\u5bf9\u4e8e\u4e60\u60ef\u4f7f\u7528windows\u548cmacos\u7684\u5f00\u53d1\u8005\u6765\u8bf4":0,"\u5bf9\u4e8e\u5355\u5c42rnn":111,"\u5bf9\u4e8e\u5355\u5c42rnn\u7684\u6570\u636e\u4e00\u5171\u6709\u4e24\u4e2a\u6837\u672c":111,"\u5bf9\u4e8e\u53cc\u5c42rnn":111,"\u5bf9\u4e8e\u540c\u4e00\u6bb5c":45,"\u5bf9\u4e8e\u540c\u6837\u7684\u6570\u636e":111,"\u5bf9\u4e8e\u540c\u6837\u8bbe\u7f6e\u7684\u7f51\u7edc\u6a21\u578b":41,"\u5bf9\u4e8e\u56fd\u5185\u7528\u6237":[1,116],"\u5bf9\u4e8e\u591a\u8bed\u8a00\u63a5\u53e3":45,"\u5bf9\u4e8e\u5927\u591a\u6570\u8bed\u8a00":45,"\u5bf9\u4e8e\u5e8f\u5217\u957f\u5ea6":41,"\u5bf9\u4e8e\u6027\u80fd\u7684\u5173\u952e\u8def\u5f84\u90fd\u505a\u51fa\u4e86\u7ea2\u8272\u6807\u8bb0":107,"\u5bf9\u4e8e\u6211\u4eec\u652f\u6301\u7684\u5168\u90e8\u77e9\u9635\u64cd\u4f5c":74,"\u5bf9\u4e8e\u6709\u53c2\u6570\u7684\u5c42":42,"\u5bf9\u4e8e\u6709\u5b9a\u5236\u5316\u4e8c\u8fdb\u5236\u6587\u4ef6\u9700\u6c42\u7684\u7528\u6237":2,"\u5bf9\u4e8e\u672c\u6837\u4f8b\u4ee3\u7801":91,"\u5bf9\u4e8e\u6bb5\u843d\u7684\u6587\u672c\u5206\u7c7b":111,"\u5bf9\u4e8e\u6bcf\u4e00\u4e2a\u5355\u5c42rnn\u7684\u6570\u636e":111,"\u5bf9\u4e8e\u6bcf\u4e00\u4e2a\u65b0\u52a0\u7684rnn":41,"\u5bf9\u4e8e\u6bcf\u79cd\u7c7b\u578b":46,"\u5bf9\u4e8e\u6bcf\u79cdc":46,"\u5bf9\u4e8e\u8fd9\u6837\u7684\u9700\u6c42":90,"\u5bf9\u4e8e\u914d\u5907\u6709\u6ce8\u610f\u529b\u673a\u5236\u7684\u89e3\u7801\u5668":114,"\u5bf9\u4e8enchw":82,"\u5bf9\u4ee3\u7801\u8fdb\u884c\u6027\u80fd\u5206\u6790":108,"\u5bf9\u4f7f\u7528\u7684\u4e2d\u95f4\u53d8\u91cf\u548c\u8d44\u6e90\u8fdb\u884c\u6e05\u7406\u548c\u91ca\u653e":90,"\u5bf9\u5168\u8fde\u63a5\u5c42\u6765\u8bf4":74,"\u5bf9\u52a0\u8f7d\u9884\u8bad\u7ec3\u53c2\u6570\u7684\u5c42":83,"\u5bf9\u53cc\u5c42\u5e8f\u5217\u6765\u8bb2":89,"\u5bf9\u5df2\u7ecfpush\u5230\u8fdc\u7a0b\u4ed3\u5e93\u7684\u591a\u4e2acommit":72,"\u5bf9\u5e94":117,"\u5bf9\u5e94\u4e00\u4e2a\u5b50\u53e5":113,"\u5bf9\u5e94\u4e00\u4e2a\u8bcd":113,"\u5bf9\u5e94\u4e8e\u8c03\u7528c":89,"\u5bf9\u5e94\u7684\u68af\u5ea6op\u8ba1\u7b97\u4e4b\u4e2d":75,"\u5bf9\u5e94\u7740\u4e0a\u6587\u63d0\u5230\u7684\u4e00\u7ef4\u6574\u578b\u6570\u7ec4":89,"\u5bf9\u5e94\u7740\u4e0a\u6587\u63d0\u5230\u7684\u4e8c\u7ef4\u6d6e\u70b9\u578b\u77e9\u9635":89,"\u5bf9\u63a8\u8350\u914d\u7f6e\u4e2d\u7684\u9009\u9879\u5efa\u8bae\u6309\u7167\u8bbe\u7f6e":87,"\u5bf9\u65b0\u7684\u6743\u91cd\u8fdb\u884c\u8f6c\u6362\u7528\u4e8e\u4e0b\u6b21\u8fed\u4ee3":41,"\u5bf9\u6bcf\u4e2a\u8f93\u5165":74,"\u5bf9\u6bcf\u4e2a\u8f93\u5165\u4e58\u4e0a\u53d8\u6362\u77e9\u9635":74,"\u5bf9\u6bd4":45,"\u5bf9\u6bd4\u4f18\u5316\u540elayer\u4e0e\u76f8\u5bf9\u5e94\u7684paddlepaddle\u539f\u6709lay":41,"\u5bf9\u6bd4\u4f18\u5316\u540elayer\u81ea\u8eab":41,"\u5bf9\u6bd4\u53cd\u5411op\u4e0d\u540c\u8bbe\u5907":75,"\u5bf9\u6fc0\u6d3b\u6c42\u5bfc":74,"\u5bf9\u795e\u7ecf\u7f51\u7edc\u6765\u8bf4":89,"\u5bf9\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u8fdb\u884c\u5e8f\u5217\u5316":90,"\u5bf9\u8bc4\u5ba1\u610f\u89c1\u4e0d\u540c\u610f\u7684":72,"\u5bf9\u8bc4\u5ba1\u610f\u89c1\u540c\u610f\u4e14\u6309\u5176\u4fee\u6539\u5b8c\u7684":72,"\u5bf9\u8c61":83,"\u5bf9\u8c61\u5206\u914d\u7a7a\u95f4":90,"\u5bf9\u8f93\u5165\u53c2\u6570\u7684\u5b89\u5168\u6027\u8fdb\u884c\u4e86\u5fc5\u8981\u7684\u5224\u65ad":46,"\u5bf9\u8f93\u5165\u6570\u636e\u7684\u683c\u5f0f\u505a\u6e05\u6670\u7b80\u6d01\u7684\u5c01\u88c5":88,"\u5bf9\u8f93\u51fa\u7684\u5408\u5e76":113,"\u5bf9\u8fd9\u4e2a\u7248\u672c\u7684\u63d0\u4ea4":63,"\u5bf9sparse_binary_vector\u548csparse_float_vector":84,"\u5bfb\u627e\u6709\u6ca1\u6709\u5176\u4ed6\u53ef\u4ee5\u4f18\u5316\u7684\u53ef\u80fd":42,"\u5bfb\u627epython\u4e0ec":107,"\u5bfc\u51fa\u8fd9\u4e9b\u63a5\u53e3":46,"\u5bfc\u81f4\u4e86\u6d6e\u70b9\u6570\u6ea2\u51fa":81,"\u5bfc\u81f4\u53c2\u6570\u6536\u655b\u5230\u4e86\u4e00\u4e9b\u5947\u5f02\u7684\u60c5\u51b5":81,"\u5bfc\u81f4\u53c2\u6570\u7d2f\u52a0":81,"\u5bfc\u81f4\u7f16\u8bd1paddlepaddle\u5931\u8d25":78,"\u5bfc\u81f4\u8bad\u7ec3\u65f6\u95f4\u8fc7\u957f":83,"\u5bfc\u81f4mklml\u5e93\u4e0b\u8f7d\u4e0d\u6210\u529f":78,"\u5c01\u88c5\u4e86":108,"\u5c01\u88c5\u8be5\u5c42\u7684python\u63a5\u53e3":74,"\u5c06":[63,83,108],"\u5c06\u4e00\u4e2a\u795e\u7ecf\u7f51\u7edc\u53c2\u6570\u62c6\u5206\u6210\u591a\u4efd":10,"\u5c06\u4e0a\u4e00\u65f6\u95f4\u6b65\u6240\u751f\u6210\u7684\u8bcd\u7684\u5411\u91cf\u6765\u4f5c\u4e3a\u5f53\u524d\u65f6\u95f4\u6b65\u7684\u8f93\u5165":114,"\u5c06\u4f1a\u4f18\u5148\u4f7f\u7528":91,"\u5c06\u4f1a\u59cb\u7ec8\u4f7f\u7528":116,"\u5c06\u4f1a\u5c06\u7528\u6237\u4f20\u8fdb\u6765\u7684\u914d\u7f6e\u53c2\u6570\u4f20\u9012cmake\u7cfb\u7edf":116,"\u5c06\u4f1a\u81ea\u52a8\u8ba1\u7b97\u51fa\u4e00\u4e2a\u5408\u9002\u7684\u503c":103,"\u5c06\u4f1a\u88ab\u629b\u5f03":91,"\u5c06\u5176\u8bbe\u7f6e\u6210":81,"\u5c06\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217\u6570\u636e\u5148\u53d8\u6362\u6210\u5355\u5c42\u65f6\u95f4\u5e8f\u5217\u6570\u636e":111,"\u5c06\u542b\u6709\u5b50\u53e5":113,"\u5c06\u542b\u6709\u8bcd\u8bed\u7684\u53e5\u5b50\u5b9a\u4e49\u4e3a\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":113,"\u5c06\u56fe\u7247\u5206\u7c7b\u5230":90,"\u5c06\u591a\u53e5\u8bdd\u770b\u6210\u4e00\u4e2a\u6574\u4f53\u540c\u65f6\u4f7f\u7528encoder\u538b\u7f29":111,"\u5c06\u591a\u53f0\u673a\u5668\u7684\u6d4b\u8bd5\u7ed3\u679c\u5408\u5e76":103,"\u5c06\u5927\u91cf\u7684":45,"\u5c06\u5b57\u5178\u7684\u5730\u5740\u4f5c\u4e3aargs\u4f20\u7ed9dataprovid":83,"\u5c06\u5b83\u4eec\u653e\u5728\u540c\u4e00\u76ee\u5f55\u4e2d":90,"\u5c06\u5bf9\u5e94\u6570\u636e\u5c42\u7684\u7ef4\u6570\u8bbe\u7f6e\u6210\u4e00\u4e2a\u5927\u4e8e\u8f93\u5165\u6570\u636e\u7ef4\u6570\u7684\u503c\u7528\u4e8e\u5360\u4f4d\u5373\u53ef":82,"\u5c06\u5e8f\u5217\u5316\u7ed3\u679c\u5199\u5165\u4e00\u4e2a\u6587\u4ef6\u5185":90,"\u5c06\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u524d\u5411\u548c\u53cd\u5411\u90e8\u5206\u6df7\u5408\u5728\u4e00\u8d77":114,"\u5c06\u6027\u80fd\u5206\u6790\u7ed3\u679c\u4ee5\u7f51\u9875\u7684\u5f62\u5f0f\u5c55\u793a\u51fa\u6765":107,"\u5c06\u6027\u80fd\u5206\u6790\u7ed3\u679c\u6309\u7167tottime\u6392\u5e8f":107,"\u5c06\u6570\u636e\u5207\u5206\u6210\u591a\u4efd":91,"\u5c06\u65b0\u5206\u652f\u7684\u7248\u672c\u6253\u4e0atag":63,"\u5c06\u65b0\u5efa\u7684\u6743\u91cd\u52a0\u5165\u6743\u91cd\u8868":74,"\u5c06\u660e\u6587\u53c2\u6570\u8f6c\u5316\u4e3apaddlepaddle\u53ef\u52a0\u8f7d\u7684\u6a21\u578b\u53c2\u6570\u65f6":83,"\u5c06\u672c\u5730\u7684\u4fee\u6539\u63a8\u9001\u5230":72,"\u5c06\u6b64\u76ee\u5f55\u6302\u8f7d\u4e3a\u5bb9\u5668\u7684":97,"\u5c06\u73af\u5883\u53d8\u91cf\u8f6c\u6362\u6210paddle\u7684\u547d\u4ee4\u884c\u53c2\u6570":97,"\u5c06\u7528\u4e8epython":75,"\u5c06\u7ed3\u679c\u4fdd\u5b58\u5230\u6b64\u76ee\u5f55\u91cc":97,"\u5c06\u7f51\u7edc\u7ed3\u6784\u5b9a\u4e49\u548c\u8bad\u7ec3\u7ed3\u675f\u5b58\u50a8\u4e0b\u6765\u7684\u6a21\u578b\u53c2\u6570\u6587\u4ef6":90,"\u5c06\u8bad\u7ec3\u6587\u4ef6\u4e0e\u5207\u5206\u597d\u7684\u6570\u636e\u4e0a\u4f20\u5230\u5171\u4eab\u5b58\u50a8":97,"\u5c06\u8df3\u8fc7\u5206\u53d1\u9636\u6bb5\u76f4\u63a5\u542f\u52a8\u6240\u6709\u8282\u70b9\u7684\u96c6\u7fa4\u4f5c\u4e1a":93,"\u5c06\u8fd9\u79cd\u8de8\u8d8a\u65f6\u95f4\u6b65\u7684\u8fde\u63a5\u7528\u4e00\u4e2a\u7279\u6b8a\u7684\u795e\u7ecf\u7f51\u7edc\u5355\u5143\u5b9e\u73b0":111,"\u5c06\u8fdc\u7a0b\u4ed3\u5e93":72,"\u5c06\u900f\u660e":93,"\u5c06\u9700\u8981\u8f93\u51fa\u7684\u5c42\u4f5c\u4e3a":81,"\u5c06cuda\u5e93\u548clinux\u8bbe\u5907\u6302\u8f7d\u5230docker\u5bb9\u5668\u5185":1,"\u5c06ip\u6392\u5e8f\u751f\u6210\u7684\u5e8f\u53f7\u4f5c\u4e3atrain":97,"\u5c06master\u5206\u652f\u7684\u5408\u5165commit\u6253\u4e0atag":63,"\u5c06node\u8282\u70b9\u7684ip\u5730\u5740\u4fdd\u5b58\u5230machines\u6587\u4ef6\u4e2d":98,"\u5c06paddlepaddle\u4fdd\u5b58\u7684\u6a21\u578b\u53c2\u6570\u8fd8\u539f\u56de\u660e\u6587\u65f6":83,"\u5c06recurr":82,"\u5c0f\u4e8e\u67d0\u4e2a\u6bd4\u8f83\u5c0f\u7684\u9608\u503c\u8ba4\u4e3a\u901a\u8fc7":42,"\u5c31\u4f1a\u5728\u5b8c\u6210\u7f16\u8bd1\u4e4b\u540e":0,"\u5c31\u53ef\u4ee5\u4e86\u89e3\u5230\u95ee\u9898\u4ee3\u7801\u5728\u54ea\u91cc":107,"\u5c31\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u7684\u547d\u4ee4\u5f00\u59cb\u6267\u884c\u8bad\u7ec3":1,"\u5c31\u53ef\u4ee5\u6309":0,"\u5c31\u5c06\u8fd9\u4e9b\u5c42\u52a0\u5165\u4e00\u4e2apython":90,"\u5c31\u5f88\u5bb9\u6613\u5bfc\u81f4\u5185\u5b58\u8d85\u9650":81,"\u5c31\u662f\u7528\u4e8e\u5c55\u793a\u4e0a\u8ff0\u5206\u6790\u5de5\u5177\u7684\u7528\u6cd5":108,"\u5c31\u662fpaddlepaddle\u4e2d\u6240\u6307\u7684":89,"\u5c31\u8fd9\u4e48\u7b80\u5355":1,"\u5c31\u901a\u5e38\u7684gpu\u6027\u80fd\u5206\u6790\u6765\u8bf4":108,"\u5c31\u9700\u8981\u5bf9\u8fd9\u4e2a\u7b2c\u4e09\u65b9\u8bed\u8a00\u589e\u52a0\u4e00\u4e9b\u5b9a\u4e49":45,"\u5c31\u9700\u8981\u9009\u62e9\u4f7f\u7528no":1,"\u5c3d\u65e9\u62a5\u9519":75,"\u5c42\u524d\u5411\u8ba1\u7b97\u7684\u7ed3\u679c":90,"\u5c42\u548c\u8f93\u5165\u7684\u914d\u7f6e":74,"\u5c42\u6b21\u5316\u7684rnn":113,"\u5c42\u7684\u540d\u79f0\u4e0e":114,"\u5c42\u7684\u5927\u5c0f":74,"\u5c42\u7684\u7c7b\u578b":74,"\u5c42\u7684\u8f93\u51fa\u88ab\u7528\u4f5c\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684":114,"\u5c55\u793a\u4e86\u4e00\u4e2a\u542b\u67094\u4e2a\u5e8f\u5217\u7684":89,"\u5c55\u793a\u4e86\u90e8\u5206\u547d\u4ee4\u884c\u53c2\u6570\u7684\u4f7f\u7528":104,"\u5c55\u793a\u7684\u8c03\u7528\u56fe\u4e5f\u53ef\u4ee5\u5e2e\u52a9\u6211\u4eec\u53d1\u73b0\u6027\u80fd\u4e2d\u7684\u95ee\u9898":107,"\u5c5e\u4e8e\u8fd9\u4e00\u7c7b\u7684\u5b9e\u73b0":82,"\u5c5e\u6027":75,"\u5de5\u4f5c\u6a21\u5f0f":103,"\u5de5\u4f5c\u7a7a\u95f4\u4e2d\u7684":93,"\u5de5\u4f5c\u7a7a\u95f4\u5e94\u5982\u4e0b\u6240\u793a":91,"\u5de5\u5177\u4e0a\u4f20\u5373\u53ef":63,"\u5de5\u5177\u5408\u5e76fat\u5e93":117,"\u5de5\u5177\u670d\u52a1\u5668\u5c06\u8bfb\u53d6\u73af\u5883\u53d8\u91cf":77,"\u5de5\u5177\u6765\u7ba1\u7406":72,"\u5de5\u5177\u6765\u7f16\u8bd1\u6587\u6863":77,"\u5de5\u5177\u94fe":116,"\u5de5\u5177\u94fe\u7684android":116,"\u5de6\u53f3\u7684\u8ba1\u7b97\u65f6\u95f4":107,"\u5df2\u6253\u5f00":72,"\u5df2\u7ecf\u5728\u96c6\u7fa4\u63d0\u4ea4\u73af\u5883\u4e2d\u5b8c\u6210\u8bbe\u7f6e":103,"\u5e02\u9762\u4e0a\u5df2\u7ecf\u6709nvidia\u6216\u7b2c\u4e09\u65b9\u63d0\u4f9b\u7684\u4f17\u591a\u5de5\u5177":108,"\u5e0c\u671b\u80fd\u591f\u5c06\u5e8f\u5217\u5316\u540e\u7684\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u548c\u8bad\u7ec3\u597d\u7684\u6a21\u578b\u53c2\u6570\u6253\u5305\u8fdb\u4e00\u4e2a\u6587\u4ef6":90,"\u5e26\u6709\u4e0b\u9762\u4e24\u4e2a\u6a21\u677f\u53c2\u6570":75,"\u5e2e\u52a9\u6211\u4eec\u5b8c\u6210\u5bf9\u8f93\u5165\u5e8f\u5217\u7684\u62c6\u5206":113,"\u5e2e\u52a9\u6211\u4eec\u66f4\u597d\u5730\u63cf\u8ff0\u6bb5\u843d":113,"\u5e2e\u52a9\u6211\u4eec\u6784\u9020\u4e00\u4e9b\u590d\u6742\u7684\u8f93\u5165\u4fe1\u606f":110,"\u5e38\u5e38\u51fa\u73b0":78,"\u5e38\u7528\u4e8e\u81ea\u7136\u8bed\u8a00\u5904\u7406\u4efb\u52a1":89,"\u5e38\u7528\u7684cmake\u914d\u7f6e\u5982\u4e0b":[116,117],"\u5e38\u89c1\u7684\u5305\u62ec":107,"\u5e38\u89c1\u95ee\u9898\u89e3\u7b54":2,"\u5e73\u5747\u6545\u969c\u4fee\u590d\u65f6\u95f4":10,"\u5e73\u5747\u6545\u969c\u7387":10,"\u5e76\u4e0d\u4fdd\u8bc1":74,"\u5e76\u4e0d\u662f\u4f7f\u7528\u53cc\u5c42rnn\u89e3\u51b3\u5b9e\u9645\u7684\u95ee\u9898":111,"\u5e76\u4e0d\u662fkubernetes\u4e2d\u7684node\u6982\u5ff5":97,"\u5e76\u4e0d\u771f\u6b63":[89,90],"\u5e76\u4e0d\u771f\u6b63\u7684\u548c":111,"\u5e76\u4e0d\u96be":0,"\u5e76\u4e14":114,"\u5e76\u4e14\u4e5f\u53ef\u4ee5\u5728windows\u7684docker\u4e2d\u8fd0\u884c":1,"\u5e76\u4e14\u4e66\u5199\u4e00\u4efd\u4ee3\u7801":76,"\u5e76\u4e14\u4f1a\u5199\u597d":42,"\u5e76\u4e14\u4f1a\u6839\u636e":116,"\u5e76\u4e14\u4f7f\u7528":46,"\u5e76\u4e14\u5185\u5c42\u7684\u5e8f\u5217\u64cd\u4f5c\u4e4b\u95f4\u72ec\u7acb\u65e0\u4f9d\u8d56":111,"\u5e76\u4e14\u52a0\u4e0a\u4e0b\u9762\u7684\u547d\u4ee4\u884c\u53c2\u6570":105,"\u5e76\u4e14\u5305\u62ecunit":72,"\u5e76\u4e14\u53ea\u9700\u8981\u5728\u5fc5\u8981\u7684\u65f6\u5019\u8f6c\u6362\u8fd9\u79cd\u683c\u5f0f":42,"\u5e76\u4e14\u53ef\u80fd\u4f1a\u52a0\u901f\u8bad\u7ec3\u8fc7\u7a0b":81,"\u5e76\u4e14\u542f\u52a8\u8bad\u7ec3":97,"\u5e76\u4e14\u5728\u5e38\u89c1\u7684\u5e73\u53f0\u4e0a":45,"\u5e76\u4e14\u5c55\u793a\u4e86\u5982\u4f55\u5229\u7528paddlepaddle\u6765\u89e3\u51b3\u4e00\u4e2a\u7ecf\u5178\u7684\u7ebf\u6027\u56de\u5f52\u95ee\u9898":84,"\u5e76\u4e14\u5f3a\u5236\u8bbe\u7f6e\u4e00\u4e9bpaddlepaddle\u53c2\u6570\u7684\u503c":117,"\u5e76\u4e14\u5f53\u7f16\u8bd1\u65f6":41,"\u5e76\u4e14\u628a\u7cfb\u7edf\u751f\u6210\u7684ca":27,"\u5e76\u4e14\u628a\u7ed3\u679c\u8fd4\u56depfsclient\u7aef":27,"\u5e76\u4e14\u67e5\u8be2paddlepaddle\u5355\u5143\u6d4b\u8bd5\u7684\u65e5\u5fd7":78,"\u5e76\u4e14\u7f16\u8bd1\u65f6\u9700\u8981\u6253\u5f00":75,"\u5e76\u4e14\u7f16\u8bd1\u80fd\u901a\u8fc7\u4ee3\u7801\u6837\u5f0f\u68c0\u67e5":72,"\u5e76\u4e14\u8ba9\u63a5\u53e3\u8131\u79bb\u5b9e\u73b0\u7ec6\u8282":45,"\u5e76\u4e14\u8bbe\u7f6e\u9ed8\u8ba4\u503c\u4e3a1":75,"\u5e76\u4e14\u8f93\u5165\u8f93\u51fa\u90fd\u662f\u5171\u7528\u4e00\u5757\u5185\u5b58":42,"\u5e76\u4e14\u8f93\u51fa\u4e00\u4e2a":72,"\u5e76\u4e14\u9700\u8981\u91cd\u5199\u57fa\u7c7b\u4e2d\u7684\u4ee5\u4e0b\u51e0\u4e2a\u865a\u51fd\u6570":74,"\u5e76\u4e14cpu":75,"\u5e76\u4e14softmax\u5c42\u7684\u4e24\u4e2a\u8f93\u5165\u4e5f\u4f7f\u7528\u4e86\u540c\u6837\u7684\u53c2\u6570":83,"\u5e76\u4f7f\u7528":93,"\u5e76\u4fdd\u5b58\u8f93\u51fa\u5230\u4e00\u4e2a\u65e5\u5fd7\u6587\u4ef6":91,"\u5e76\u5177\u5907\u4ee5\u4e0b\u7279\u70b9":88,"\u5e76\u521b\u5efa\u4e86\u4e00\u4e2a\u65b0\u6587\u4ef6":72,"\u5e76\u521b\u5efaoptim":84,"\u5e76\u521d\u59cb\u5316":75,"\u5e76\u5220\u9664":63,"\u5e76\u5220\u9664\u66f4\u65e9\u7684\u5feb\u7167":10,"\u5e76\u52a0\u8f7d\u5176\u4e2d\u7684\u53c2\u6570":10,"\u5e76\u53d1\u5e03\u5230pypi":63,"\u5e76\u53ef\u4ee5\u5728\u5927\u591a\u6570\u4e3b\u6d41\u7684linux\u64cd\u4f5c\u7cfb\u7edf\u4ee5\u53camacos\u4e0a\u6267\u884c":3,"\u5e76\u548c\u53c2\u6570\u670d\u52a1\u5668\u901a\u4fe1":92,"\u5e76\u5728\u4e58\u79ef\u7ed3\u679c\u4e0a\u518d\u52a0\u4e0a\u7ef4\u5ea6\u4e3a":74,"\u5e76\u5728\u6700\u5f00\u59cb\u521d\u59cb\u5316\u4e3a\u8d77\u59cb\u8bcd":114,"\u5e76\u5728\u6bcf\u6b21\u6743\u91cd\u66f4\u65b0\u540e":41,"\u5e76\u5728\u7c7b\u6784\u5efa\u51fd\u6570\u4e2d\u628a\u5b83\u653e\u5165\u4e00\u4e2a\u7c7b\u6210\u5458\u53d8\u91cf\u91cc":74,"\u5e76\u5728\u8be5layer\u91cc\u91c7\u7528\u7b2c\u4e00\u79cd\u65b9\u5f0f\u8bbe\u7f6e":82,"\u5e76\u5728\u96c6\u7fa4\u4e2d\u8fd0\u884c\u591a\u4e2a\u5206\u5e03\u5f0f\u6570\u636e\u5904\u7406\u4efb\u52a1":11,"\u5e76\u5728python\u811a\u672c\u4e2d\u5b8c\u6210\u4e0eoperator\u540c\u6837\u7684\u8ba1\u7b97\u903b\u8f91":75,"\u5e76\u5904\u7406\u4e0e\u4e4b\u76f8\u5173\u7684\u6240\u6709\u7ec6\u8282":90,"\u5e76\u5b89\u88c5\u4e86python":78,"\u5e76\u5b89\u88c5\u6700\u65b0":3,"\u5e76\u5b89\u88c5\u6709python2":86,"\u5e76\u5b8c\u6210\u53c2\u6570\u4f18\u5316\u66f4\u65b0":92,"\u5e76\u5bf9\u6bd4\u662f\u5426\u548c\u6b63\u5728\u5b89\u88c5\u7684\u540e\u7f00\u4e00\u81f4":78,"\u5e76\u5bf9\u76f8\u5e94\u7684\u53c2\u6570\u8c03\u7528":74,"\u5e76\u5c06":63,"\u5e76\u5c06\u5176\u6295\u5c04\u5230":114,"\u5e76\u5c06\u8be5layer\u4e0a\u4e00\u65f6\u95f4\u6b65\u7684\u8f93\u51fa\u4f5c\u4e3a\u81ea\u8eab\u5f53\u524d\u65f6\u95f4\u6b65\u7684\u8f93\u51fa":82,"\u5e76\u5c06c":46,"\u5e76\u624b\u52a8\u751f\u6210download\u6210\u529f\u6807\u7b7e":78,"\u5e76\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4":1,"\u5e76\u628a\u5feb\u7167\u4fdd\u5b58\u5230\u8fd9\u4e2a\u76ee\u5f55\u4e0b":10,"\u5e76\u628a\u7ed3\u679c\u653e\u5230\u5f53\u524d\u5c42\u7684":42,"\u5e76\u628a\u8fd9\u4e2a\u5305\u542b\u4e86\u8bad\u7ec3\u6570\u636e\u7684container\u4fdd\u5b58\u4e3a\u4e00\u4e2a\u65b0\u7684\u955c\u50cf":96,"\u5e76\u66f4\u6362job":79,"\u5e76\u6839\u636e\u5206\u5e03\u5f0f\u8bad\u7ec3\u5e76\u53d1\u6570":91,"\u5e76\u68c0\u67e5\u548c\u9700\u5b89\u88c5\u7684\u5305\u662f\u5426\u5339\u914d":3,"\u5e76\u6ca1\u6709paddle\u7279\u522b\u9700\u8981\u7684\u7279\u6027":45,"\u5e76\u6dfb\u52a0\u5934\u6587\u4ef6":41,"\u5e76\u6dfb\u52a0\u6ce8\u91ca":75,"\u5e76\u7279\u5316\u6a21\u677f\u53c2\u6570\u4e3a":75,"\u5e76\u7c98\u8d34\u6b64python\u4ee3\u7801":86,"\u5e76\u81ea\u52a8\u4e0b\u8f7d\u5b89\u88c5\u4f9d\u8d56\u8f6f\u4ef6":3,"\u5e76\u81ea\u52a8\u7f16\u8bd1\u5bbf\u4e3b\u673a\u7248protoc\u53ef\u6267\u884c\u6587\u4ef6":118,"\u5e76\u81ea\u52a8\u7f16\u8bd1paddlepaddle\u6240\u9700\u7684\u6240\u6709\u7b2c\u4e09\u65b9\u5e93":116,"\u5e76\u884c\u5730\u6267\u884c\u6a21\u578b\u7684\u8bad\u7ec3":92,"\u5e76\u884c\u5730\u63a5\u6536\u68af\u5ea6\u548c\u66f4\u65b0\u53c2\u6570":92,"\u5e76\u88ab\u5b58\u50a8\u5728\u8bf8\u5982hadoop":11,"\u5e76\u89c2\u5bdf\u7ed3\u679c":108,"\u5e76\u89e3\u91ca\u4e86\u5404\u81ea\u542b\u4e49":75,"\u5e76\u8bb0\u5f55\u5b83\u7684\u7f16\u53f7":72,"\u5e76\u8fdb\u884c\u521d\u59cb\u5316\u64cd\u4f5c":84,"\u5e76\u9002\u5e94github\u7684\u7279\u6027\u505a\u4e86\u4e00\u4e9b\u533a\u522b":63,"\u5e76\u91cd\u65b0\u6253\u5305wheel\u5305":63,"\u5e76\u94fe\u63a5\u5230\u751f\u6210\u7684lib\u5e93\u4e2d":75,"\u5e78\u800cpython\u7684\u4e00\u4e2a\u7b2c\u4e09\u65b9\u5e93":107,"\u5e8f\u5217\u4e2d\u542b\u6709\u5143\u7d20\u7684\u6570\u76ee\u540c":110,"\u5e8f\u5217\u4e2d\u7684\u4e00\u4e2a\u5143\u7d20":89,"\u5e8f\u5217\u4e2d\u7684\u5143\u7d20\u662f\u8bcd\u8bed":89,"\u5e8f\u5217\u4e2d\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20\u53c8\u662f\u4e00\u4e2a\u5e8f\u5217":89,"\u5e8f\u5217\u4e2d\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u975e\u5e8f\u5217":89,"\u5e8f\u5217\u4fe1\u606f":89,"\u5e8f\u5217\u5316\u795e\u7ecf\u7f51\u7edc\u6a21\u578b\u914d\u7f6e":90,"\u5e8f\u5217\u5316\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u65f6":90,"\u5e8f\u5217\u5316\u7ed3\u679c\u4f1a\u5199\u5165\u5f53\u524d\u8fd0\u884c\u76ee\u5f55\u4e0b\u7684":90,"\u5e8f\u5217\u6570\u636e\u662f\u81ea\u7136\u8bed\u8a00\u5904\u7406\u4efb\u52a1\u9762\u5bf9\u7684\u4e00\u79cd\u4e3b\u8981\u8f93\u5165\u6570\u636e\u7c7b\u578b":113,"\u5e8f\u5217\u662f\u4e00\u79cd\u5e38\u89c1\u7684\u6570\u636e\u7c7b\u578b":110,"\u5e8f\u5217\u751f\u6210\u4efb\u52a1\u5927\u591a\u9075\u5faaencod":113,"\u5e8f\u5217\u751f\u6210\u4efb\u52a1\u7684\u8f93\u5165":113,"\u5e8f\u5217\u7684\u6bcf\u4e2a\u5143\u7d20\u662f\u539f\u6765\u53cc\u5c42\u5e8f\u5217\u6bcf\u4e2asubseq\u5143\u7d20\u7684\u5e73\u5747\u503c":110,"\u5e8f\u5217\u8f93\u5165":89,"\u5e8f\u5217\u8f93\u5165\u65f6\u7b49\u4e8e":81,"\u5e8f\u5217\u8f93\u5165\u793a\u610f\u56fe":89,"\u5e93\u6709\u81ea\u5df1\u72ec\u7acb\u7684\u52a8\u6001\u5e93\u6587\u4ef6":87,"\u5e94\u7528\u524d\u5411\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":114,"\u5e94\u7528\u53cd\u5411\u9012\u5f52\u795e\u7ecf\u7f51\u7edc":114,"\u5e94\u80fd\u53cd\u6620\u5f53\u524dcommit\u7684\u5185\u5bb9":72,"\u5e94\u8be5\u4e0e\u5b83\u7684memory\u540d\u5b57\u76f8\u540c":114,"\u5e94\u8be5\u8bf4\u8c22\u8c22":72,"\u5e94\u8be5\u964d\u4f4e\u5b66\u4e60\u7387":83,"\u5e95\u5c42\u8fdb\u7a0b":93,"\u5efa\u7acb\u4e00\u4e2a":72,"\u5efa\u8bae":[63,72],"\u5efa\u8bae\u5c06\u8be5\u53c2\u6570\u8bbe\u4e3atrue":103,"\u5f00\u53d1\u4e86\u6a21\u578b\u9884\u6d4b\u7684\u6837\u4f8b\u4ee3\u7801":46,"\u5f00\u53d1\u4eba\u5458\u4f7f\u7528":72,"\u5f00\u53d1\u5206\u652f":3,"\u5f00\u53d1\u6807\u51c6":115,"\u5f00\u53d1\u8005\u4f7f\u7528":0,"\u5f00\u53d1\u8005\u4fee\u6539\u81ea\u5df1\u7684\u4ee3\u7801":63,"\u5f00\u53d1\u8005fork\u7684\u7248\u672c\u5e93\u4e2d":63,"\u5f00\u53d1\u8005fork\u7684\u7248\u672c\u5e93\u4f7f\u7528":63,"\u5f00\u53d1\u955c\u50cf":72,"\u5f00\u53d1\u9884\u6d4b\u5e8f":90,"\u5f00\u53d1\u9884\u6d4b\u7a0b\u5e8f\u94fe\u63a5":87,"\u5f00\u542f":0,"\u5f00\u5934":[41,42],"\u5f00\u5934\u7684\u90e8\u5206":91,"\u5f00\u5934\u90e8\u5206\u6307\u5b9a":91,"\u5f00\u59cb\u63d0\u4f9b\u670d\u52a1":10,"\u5f00\u59cb\u6807\u8bb0":114,"\u5f00\u59cb\u795e\u7ecf\u7f51\u7edc\u7684":92,"\u5f00\u59cb\u9636\u6bb5":108,"\u5f02\u6b65\u968f\u673a\u68af\u5ea6\u4e0b\u964d":102,"\u5f02\u6b65sgd\u66f4\u65b0\u7684\u6b65\u957f\u63a7\u5236":91,"\u5f15\u5165\u4e86\u4ee5\u4e0b\u56db\u4e2aapi":41,"\u5f15\u5165\u4e86\u7c7b\u578b\u7684\u5934\u6587\u4ef6":46,"\u5f15\u5bfc\u5c42":114,"\u5f15\u7528memory\u5f97\u5230\u8fd9layer\u4e0a\u4e00\u65f6\u523b\u8f93\u51fa":113,"\u5f39\u51fa\u4e0b\u9762\u7684\u9009\u62e9\u6846":63,"\u5f52\u4e00\u5316\u6982\u7387\u5411\u91cf":114,"\u5f53":105,"\u5f53\u4e00\u4e2a":89,"\u5f53\u4e0a\u8ff0\u63a5\u53e3\u7b2c4\u4e2a\u53c2\u6570":89,"\u5f53\u4f60\u6267\u884c\u547d\u4ee4":74,"\u5f53\u4fdd\u5b58\u7684\u7f51\u7edc\u53c2\u6570\u4e3afloat\u7c7b\u578b\u65f6\u4e3a4":83,"\u5f53\u524d\u65f6\u95f4\u6b65\u5904\u7684memory\u7684\u8f93\u51fa\u4f5c\u4e3a\u4e0b\u4e00\u65f6\u95f4\u6b65memory\u7684\u8f93\u5165":114,"\u5f53\u524d\u7684\u5b66\u4e60\u7387\u4e3a\u6240\u8bbe\u7f6e":83,"\u5f53\u524d\u7684\u5b9e\u73b0\u65b9\u5f0f\u4e0b":74,"\u5f53\u524d\u7684\u8f93\u5165y\u548c\u4e0a\u4e00\u4e2a\u65f6\u95f4\u6b65\u7684\u8f93\u51farnn_state\u505a\u4e86\u4e00\u4e2a\u5168\u94fe\u63a5":111,"\u5f53\u524d\u8bad\u7ec3\u4efb\u52a1\u542f\u52a8\u7684pserver\u7684ip\u5217\u8868":91,"\u5f53\u524d\u8bad\u7ec3\u4efb\u52a1pserver\u603b\u6570":91,"\u5f53\u524d\u8bad\u7ec3\u4efb\u52a1trainer\u603b\u6570":91,"\u5f53\u524dtrainer\u7684\u7ebf\u7a0b\u6570\u76ee":91,"\u5f53\u529f\u80fd\u5206\u652f\u5f00\u53d1\u5b8c\u6bd5\u540e":63,"\u5f53\u53ea\u505a\u63a8\u65ad":41,"\u5f53\u5728\u7f51\u7edc\u5c42\u914d\u7f6e\u4e2d\u8bbe\u7f6e":103,"\u5f53\u5728\u8bad\u7ec3\u914d\u7f6e\u4e2d\u8bbe\u7f6e":103,"\u5f53\u5df2\u8bad\u7ec3\u6837\u672c\u6570\u5927\u4e8e1000\u5c0f\u4e8e\u7b49\u4e8e2000\u65f6":83,"\u5f53\u5df2\u8bad\u7ec3\u6837\u672c\u6570\u5927\u4e8e2000\u65f6":83,"\u5f53\u5df2\u8bad\u7ec3\u6837\u672c\u6570\u5c0f\u4e8e\u7b49\u4e8e1000\u65f6":83,"\u5f53\u5df2\u8bad\u7ec3pass\u6570\u5927\u4e8e1\u5c0f\u4e8e\u7b49\u4e8e2\u65f6":83,"\u5f53\u5df2\u8bad\u7ec3pass\u6570\u5927\u4e8e2\u65f6":83,"\u5f53\u5df2\u8bad\u7ec3pass\u6570\u5c0f\u4e8e\u7b49\u4e8e1\u65f6":83,"\u5f53\u5f00\u542f":42,"\u5f53\u6211\u4eec\u505a\u51fa\u6027\u80fd\u4fee\u6b63\u540e":107,"\u5f53\u6211\u4eec\u8bad\u7ec3\u5b8c\u4e00\u4e2a\u795e\u7ecf\u7f51\u7edc\u6a21\u578b\u4e4b\u540e":88,"\u5f53\u6240\u6709pod\u90fd\u5904\u4e8erunning\u72b6\u6001":97,"\u5f53\u6253\u5f00":42,"\u5f53\u6570\u636e\u683c\u5f0f\u4e0epaddlepaddle\u9ed8\u8ba4\u7684":42,"\u5f53\u6a21\u578b\u53c2\u6570\u4e0d\u5b58\u5728\u65f6":103,"\u5f53\u6a21\u5f0f\u4e3a":103,"\u5f53\u7136":[1,108],"\u5f53\u7136\u53ef\u4ee5":0,"\u5f53\u7136\u8fd9\u4e24\u8005\u4e5f\u53ef\u4ee5\u76f8\u7b49":42,"\u5f53\u7528\u6237\u4f7f\u7528\u5b8c\u8fd9\u4e2a\u53c2\u6570\u540e":46,"\u5f53\u7528\u6237\u6ca1\u6709\u663e\u5f0f\u8bbe\u5b9a\u65f6":82,"\u5f53\u7f51\u7edc\u51fa\u73b0\u5206\u652f\u4e14\u5728":42,"\u5f53\u7f51\u7edc\u5c42\u7528\u4e00\u4e2a\u6279\u6b21\u505a\u8bad\u7ec3\u65f6":74,"\u5f53\u89e3\u8bfb\u6bcf\u4e00\u4e2a":114,"\u5f53\u8d85\u8fc7\u8be5\u9608\u503c\u65f6":103,"\u5f53\u8f93\u5165\u662f\u7ef4\u5ea6\u5f88\u9ad8\u7684\u7a00\u758f\u6570\u636e\u65f6":105,"\u5f53\u9700\u8981\u5b8c\u6210\u8ba1\u7b97\u65f6":76,"\u5f53\u975e\u5e8f\u5217\u8f93\u5165\u65f6":89,"\u5f53destination\u6587\u4ef6\u4e0d\u5b58\u5728\u6216\u8005\u5927\u5c0f\u548csource\u6587\u4ef6\u4e0d\u4e00\u81f4\u65f6":27,"\u5f53n1":81,"\u5f62\u6210recurr":113,"\u5f62\u6210recurrent\u8fde\u63a5":113,"\u5f88\u591a":0,"\u5f88\u6709\u53ef\u80fd\u5b9e\u9645\u5e94\u7528\u5c31\u662f\u6ca1\u6709\u6309\u7167\u60a8\u7684\u9884\u671f\u60c5\u51b5\u8fd0\u884c":108,"\u5f88\u6709\u53ef\u80fd\u662f\u975e\u72ec\u5360\u65b9\u5f0f\u6267\u884c\u5bfc\u81f4\u7684\u7aef\u53e3\u51b2\u7a81":79,"\u5f88\u96be\u4fdd\u8bc1\u591a\u8bed\u8a00\u4ee3\u7801\u98ce\u683c\u7684\u4e00\u81f4\u6027":45,"\u5f97\u4f7f\u7528":45,"\u5f97\u5230\u8f93\u51fa\u503c":75,"\u5f97\u5230\u9884\u6d4b\u7ed3\u679c\u7684\u8fc7\u7a0b":88,"\u5faa\u73af\u5c55\u5f00\u7684\u6bcf\u4e2a\u65f6\u95f4\u6b65\u603b\u662f\u80fd\u591f\u5f15\u7528\u6240\u6709\u8f93\u5165":113,"\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u4e2d":114,"\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u4f5c\u4e3a\u4f7f\u7528":114,"\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u548c":114,"\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u5728\u6bcf\u4e2a\u65f6\u95f4\u6b65\u9aa4\u987a\u5e8f\u5730\u5904\u7406\u5e8f\u5217":114,"\u5faa\u73af\u7f51\u7edc\u4ece":114,"\u5fc5\u8981":46,"\u5fc5\u9009":91,"\u5fc5\u987b":74,"\u5fc5\u987b\u5148\u6267\u884c\u7b2c2\u6b65":0,"\u5fc5\u987b\u5206\u522b\u4e0e":42,"\u5fc5\u987b\u5c06\u524d\u4e00\u4e2a\u5b50\u53e5\u7684\u6700\u540e\u4e00\u4e2a\u5143\u7d20":111,"\u5fc5\u987b\u6307\u5411\u4e00\u4e2apaddlepaddle\u5b9a\u4e49\u7684lay":113,"\u5fc5\u987b\u6307\u5b9a\u4e3a":90,"\u5fc5\u987b\u662f\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":113,"\u5fc5\u987b\u662f\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":110,"\u5fc5\u987b\u7531\u53ea\u8bfbmemory\u7684":114,"\u5fc5\u987b\u8bbe\u7f6e\u4e3a":[116,117],"\u5fc5\u987b\u8bbe\u7f6e\u4e3aon":117,"\u5fc5\u987b\u914d\u7f6e\u4e3a":[87,118],"\u5fc5\u987b\u914d\u7f6e\u9009\u9879":87,"\u5feb\u901f\u5f00\u59cb":85,"\u6027\u80fd\u4f18\u5316\u7684\u8fc7\u7a0b\u901a\u5e38\u662f\u4e0d\u65ad\u91cd\u590d\u5730":107,"\u6027\u80fd\u5206\u6790":108,"\u6027\u80fd\u5206\u6790\u5de5\u5177\u662f\u7528\u4e8e\u7ed9\u5e94\u7528\u7a0b\u5e8f\u7684\u6027\u80fd\u505a\u5b9a\u91cf\u5206\u6790\u7684":108,"\u6027\u80fd\u5206\u6790\u662f\u6027\u80fd\u4f18\u5316\u7684\u5173\u952e\u4e00\u6b65":108,"\u6027\u80fd\u548c\u628a\u7f16\u8bd1\u5de5\u5177\u5b89\u88c5\u5728\u672c\u673a\u8fd0\u884c\u4e00\u6837":0,"\u6027\u80fd\u8c03\u4f18":102,"\u6027\u80fdtip":[116,117],"\u60a8\u4e5f\u53ef\u4ee5\u8fdb\u5165\u5230docker\u5bb9\u5668\u4e2d":1,"\u60a8\u4f1a\u5728\u63a5\u4e0b\u6765\u7684\u90e8\u5206\u4e2d\u83b7\u5f97\u66f4\u591a\u7684\u7ec6\u8282\u4ecb\u7ecd":108,"\u60a8\u53ef\u4ee5\u4ece\u4e0b\u9762\u7684\u8868\u683c\u4e2d\u627e\u5230\u9700\u8981\u7684\u7248\u672c":3,"\u60a8\u53ef\u4ee5\u4efb\u610f\u4f7f\u7528\u4e00\u4e2a\u6216\u4e24\u4e2a\u6765\u5bf9\u611f\u5174\u8da3\u7684\u4ee3\u7801\u6bb5\u505a\u6027\u80fd\u5206\u6790":108,"\u60a8\u53ef\u4ee5\u5728":[1,94],"\u60a8\u53ef\u4ee5\u5728\u5bb9\u5668\u4e2d\u6267\u884c":1,"\u60a8\u53ef\u4ee5\u5bfc\u5165":108,"\u60a8\u53ef\u4ee5\u6309\u7167\u4e0b\u9762\u7684\u6b65\u9aa4\u5728openmpi\u96c6\u7fa4\u4e2d\u63d0\u4ea4paddle\u8bad\u7ec3\u4efb\u52a1":98,"\u60a8\u53ef\u4ee5\u91c7\u7528\u4e0b\u9762\u4e94\u4e2a\u6b65\u9aa4":108,"\u60a8\u53ef\u80fd\u9700\u8981\u4fee\u6539":91,"\u60a8\u5c06\u4e86\u89e3\u5982\u4f55":114,"\u60a8\u5c31\u80fd\u83b7\u5f97\u5982\u4e0b\u7684\u5206\u6790\u7ed3\u679c":108,"\u60a8\u6309\u5982\u4e0b\u6b65\u9aa4\u64cd\u4f5c\u5373\u53ef":108,"\u60a8\u6700\u597d\u5148\u786e\u8ba4":108,"\u60a8\u9996\u5148\u9700\u8981\u5728\u76f8\u5173\u4ee3\u7801\u6bb5\u4e2d\u52a0\u5165":108,"\u60c5\u611f\u5206\u6790":63,"\u60f3\u4e86\u89e3\u66f4\u591apaddlepaddl":77,"\u610f\u5473\u7740\u4e0d\u540c\u65f6\u95f4\u6b65\u7684\u8f93\u5165\u90fd\u662f\u76f8\u540c\u7684\u503c":114,"\u610f\u601d\u662f\u4e0d\u4f7f\u7528\u5e73\u5747\u53c2\u6570\u6267\u884c\u6d4b\u8bd5":103,"\u610f\u601d\u662f\u4e0d\u4fdd\u5b58\u7ed3\u679c":103,"\u610f\u601d\u662f\u4f7f\u7528\u7b2ctest":103,"\u610f\u601d\u662f\u5728gpu\u6a21\u5f0f\u4e0b\u4f7f\u75284\u4e2agpu":103,"\u6210\u529f\u7f16\u8bd1\u540e":87,"\u6210\u529f\u8bad\u7ec3\u4e14\u9000\u51fa\u7684pod\u6570\u76ee\u4e3a3\u65f6":97,"\u6210\u5458":75,"\u6211\u4eec\u4e0d\u80fd\u901a\u8fc7\u5e38\u89c4\u7684\u68af\u5ea6\u68c0\u67e5\u7684\u65b9\u5f0f\u6765\u8ba1\u7b97\u68af\u5ea6":74,"\u6211\u4eec\u4e3b\u8981\u4f1a\u4ecb\u7ecdnvprof\u548cnvvp":108,"\u6211\u4eec\u4e5f\u53ef\u4ee5\u786e\u5b9a\u6bcf\u4e00\u4e2a\u53c2\u6570\u7684\u7c7b\u578b":46,"\u6211\u4eec\u4e5f\u5c06mklml\u5373":42,"\u6211\u4eec\u4e5f\u652f\u6301\u5728aws\u4e0a\u90e8\u7f72paddlepaddl":94,"\u6211\u4eec\u4ec5\u4ec5\u5bf9\u795e\u7ecf\u7f51\u7edc\u7684\u8f93\u5165\u8fdb\u884c\u4e86\u63cf\u8ff0":84,"\u6211\u4eec\u4ec5\u6709\u4e00\u4e2a\u8f93\u5165":74,"\u6211\u4eec\u4ecb\u7ecd\u5982\u4f55\u5728":96,"\u6211\u4eec\u4ecb\u7ecd\u5982\u4f55\u5728kubernetes\u96c6\u7fa4\u4e0a\u8fdb\u884c\u5206\u5e03\u5f0fpaddlepaddle\u8bad\u7ec3\u4f5c\u4e1a":97,"\u6211\u4eec\u4ee5\u624b\u5199\u6570\u5b57\u8bc6\u522b\u4efb\u52a1\u4e3a\u4f8b\u8fdb\u884c\u4ecb\u7ecd":90,"\u6211\u4eec\u4f1a\u4fdd\u8bc1":42,"\u6211\u4eec\u4f1a\u53ca\u65f6\u8fdb\u884c\u56de\u590d":80,"\u6211\u4eec\u4f1a\u5728\u7f51\u7edc\u8bad\u7ec3\u4e4b\u524d\u628a\u683c\u5f0f\u8f6c\u6362\u4e3amkl":42,"\u6211\u4eec\u4f1a\u5bf9\u6bcf\u4e2a\u8bad\u7ec3\u4efb\u52a1\u90fd\u4f1a\u5728\u6bcf\u4e2a\u8282\u70b9\u4e0a\u521b\u5efa\u4e00\u4e2a\u5de5\u4f5c\u7a7a\u95f4":91,"\u6211\u4eec\u4f1a\u5bf9\u6bd4\u5982\u4e0b2\u4e2a\u65b9\u9762":41,"\u6211\u4eec\u4f1a\u628amkl":42,"\u6211\u4eec\u4f1a\u6dfb\u52a0":[41,42],"\u6211\u4eec\u4f1a\u7ee7\u7eed\u4f7f\u7528\u73b0\u6709\u7684\u5185\u5b58\u5757":74,"\u6211\u4eec\u4f1a\u91cd\u65b0\u5206\u914d\u5185\u5b58":74,"\u6211\u4eec\u4f7f\u7528":74,"\u6211\u4eec\u4f7f\u7528\u4e0d\u540c\u7684layer\u8fdb\u884c\u7ec4\u5408":84,"\u6211\u4eec\u4f7f\u7528\u4e86":111,"\u6211\u4eec\u4f7f\u7528\u52a8\u6001\u5e93\u6765\u5206\u53d1paddl":45,"\u6211\u4eec\u4f7f\u7528paddl":91,"\u6211\u4eec\u5047\u8bbe\u4e00\u53f0\u673a\u5668\u4e0a\u67094\u4e2agpu":105,"\u6211\u4eec\u5148\u8c03\u7528\u6bcf\u4e2a":76,"\u6211\u4eec\u51b3\u5b9a\u4f7f\u7528\u5df2\u6709\u7684":42,"\u6211\u4eec\u5373\u53ef\u5b8c\u6210\u795e\u7ecf\u7f51\u7edc\u7684\u642d\u5efa":84,"\u6211\u4eec\u53ea\u6f14\u793a\u4e00\u4e2a\u5355\u673a\u4f5c\u4e1a":96,"\u6211\u4eec\u53ea\u9700\u8981\u4f7f\u7528lstm":111,"\u6211\u4eec\u53ea\u9700\u8981\u8fd0\u884c\u4e0b\u9762\u547d\u4ee4\u628a\u7f16\u8bd1\u597d\u7684paddlepaddle\u6253\u5305\u6210\u4e00\u4e2a":72,"\u6211\u4eec\u53ea\u9700\u8981\u914d\u7f6e":0,"\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528":107,"\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u5176\u4ed6layer\u8fdb\u884c\u7ec4\u5408":84,"\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u5b83\u6765\u751f\u6210\u5e8f\u5217":114,"\u6211\u4eec\u53ef\u4ee5\u5148\u5b8c\u6210\u5bf9\u539f\u6570\u636e\u7684packing\u64cd\u4f5c":41,"\u6211\u4eec\u53ef\u4ee5\u521b\u5efatrainer\u6765\u5bf9\u7f51\u7edc\u8fdb\u884c\u8bad\u7ec3":84,"\u6211\u4eec\u53ef\u4ee5\u53c2\u8003tensorflow\u7684":76,"\u6211\u4eec\u53ef\u4ee5\u5728":72,"\u6211\u4eec\u53ef\u4ee5\u5728\u547d\u4ee4\u884c\u4e2d\u7b80\u5355\u7684\u770b\u4e00\u4e0b\u751f\u6210\u6548\u679c":107,"\u6211\u4eec\u53ef\u4ee5\u5b9a\u4e49\u5982\u4e0b\u7684layer\u7ec4\u5408":84,"\u6211\u4eec\u53ef\u4ee5\u5b9a\u4e49\u5982\u4e0blayer\u6765\u63cf\u8ff0\u795e\u7ecf\u7f51\u7edc\u7684\u8f93\u5165":84,"\u6211\u4eec\u53ef\u4ee5\u6309\u7167\u5982\u4e0b\u5c42\u6b21\u5b9a\u4e49\u975e\u5e8f\u5217":110,"\u6211\u4eec\u53ef\u4ee5\u67e5\u770b\u6027\u80fd\u5206\u6790\u7684\u7ed3\u679c":107,"\u6211\u4eec\u53ef\u4ee5\u8bbe\u8ba1\u642d\u5efa\u4e00\u4e2a\u7075\u6d3b\u7684":113,"\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7":107,"\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u65e5\u5fd7\u67e5\u770b\u5bb9\u5668\u8bad\u7ec3\u7684\u60c5\u51b5":97,"\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u8bbe\u7f6e":91,"\u6211\u4eec\u540c\u6837\u63d0\u4f9b\u4e86\u4ece\u6e90\u7801\u7f16\u8bd1\u5b89\u88c5paddlepaddle\u7684\u65b9\u6cd5":2,"\u6211\u4eec\u5728":76,"\u6211\u4eec\u5728\u51fd\u6570\u7684\u7ed3\u5c3e\u8fd4\u56de":114,"\u6211\u4eec\u5bf9\u6a21\u578b\u8fdb\u884c\u4e86\u4ee5\u4e0b\u66f4\u6539":114,"\u6211\u4eec\u5c06":97,"\u6211\u4eec\u5c06\u4e00\u6bb5\u8bdd\u770b\u6210\u53e5\u5b50\u7684\u6570\u7ec4":111,"\u6211\u4eec\u5c06\u4ecb\u7ecd\u5982\u4f55\u542f\u52a8\u5206\u5e03\u5f0f\u8bad\u7ec3\u4f5c\u4e1a":96,"\u6211\u4eec\u5c06\u4f7f\u7528":114,"\u6211\u4eec\u5c06\u4f7f\u7528\u7b80\u5355\u7684":114,"\u6211\u4eec\u5c06\u539f\u59cb\u6570\u636e\u7684\u6bcf\u4e00\u7ec4":111,"\u6211\u4eec\u5c06\u5b83\u4eec\u5212\u5206\u4e3a\u4e0d\u540c\u7684\u7c7b\u522b":102,"\u6211\u4eec\u5c06\u795e\u7ecf\u7f51\u7edc\u4e00\u6b21\u8ba1\u7b97\u63a5\u53d7\u7684\u6240\u6709\u8f93\u5165\u6837\u672c\u79f0\u4e4b\u4e3a\u4e00\u4e2a":89,"\u6211\u4eec\u5c06\u8bad\u7ec3\u7ed3\u675f\u540e\u5b58\u50a8\u4e0b\u6765\u7684\u6a21\u578b\u8f6c\u6362\u6210\u9884\u6d4b\u6a21\u578b":90,"\u6211\u4eec\u5c31\u5b8c\u6210\u4e86\u4e00\u6b21\u4ee3\u7801\u8d21\u732e\u7684\u8fc7\u7a0b":72,"\u6211\u4eec\u5df2\u7ecf\u5b9e\u73b0\u4e86\u5927\u591a\u6570\u5e38\u7528\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u67b6\u6784":114,"\u6211\u4eec\u5efa\u8bae\u4f60\u4e3a\u4f60\u7684python\u5c01\u88c5\u5b9e\u73b0\u4e00\u4e2a":74,"\u6211\u4eec\u5efa\u8bae\u4f60\u5728\u5199\u65b0\u7f51\u7edc\u5c42\u65f6\u628a\u6d4b\u8bd5\u4ee3\u7801\u653e\u5165\u65b0\u7684\u6587\u4ef6\u4e2d":74,"\u6211\u4eec\u5efa\u8bae\u4f7f\u7528\u7b2c\u4e8c\u7c7b\u5b9e\u73b0":82,"\u6211\u4eec\u603b\u7ed3\u51fa\u4e00\u4e9b\u7279\u522b\u9700\u8981\u6ce8\u610f\u7684\u70b9":42,"\u6211\u4eec\u628apaddlepaddle\u7684\u4ea4\u53c9\u7f16\u8bd1\u73af\u5883\u6253\u5305\u6210\u4e00\u4e2a\u955c\u50cf":116,"\u6211\u4eec\u63a8\u8350\u4f7f\u7528":[1,101],"\u6211\u4eec\u63a8\u8350\u4f7f\u7528\u6700\u65b0\u7248\u672c\u7684cudnn":0,"\u6211\u4eec\u63a8\u8350\u5728docker\u4e2d\u8fd0\u884cpaddlepaddl":2,"\u6211\u4eec\u63d0\u4f9b\u4e24\u4e2a\u8f6c\u6362\u65b9\u5f0f":11,"\u6211\u4eec\u63d0\u4f9b\u4e86\u4f7f\u7528fabric":94,"\u6211\u4eec\u63d0\u4f9b\u4e86\u52a0\u901f\u8bbf\u95ee\u7684\u955c\u50cf\u6e90":[1,116],"\u6211\u4eec\u63d0\u4f9b\u4e86\u591a\u79cd\u7684\u96c6\u7fa4\u90e8\u7f72\u65b9\u5f0f":94,"\u6211\u4eec\u63d0\u4f9b\u4e86\u5982\u4e0b\u6307\u5357":88,"\u6211\u4eec\u63d0\u4f9b\u53ef\u4ee5\u76f4\u63a5\u8fd0\u884cpaddlepaddl":1,"\u6211\u4eec\u63d0\u51fa\u4e86chunk\u7684\u6982\u5ff5":27,"\u6211\u4eec\u662f\u5bf9\u6bcf\u4e00\u4e2a\u5b50\u5e8f\u5217\u53d6\u6700\u540e\u4e00\u4e2a\u5143\u7d20":111,"\u6211\u4eec\u6700\u7ec8\u7684\u52a8\u6001\u5e93\u4e2d\u4e0d\u5d4c\u5165python\u6216\u8005\u5176\u4ed6\u4efb\u4f55\u8bed\u8a00\u7684\u89e3\u91ca\u5668":45,"\u6211\u4eec\u6709\u4e00\u4e2a\u5e8f\u5217\u4f5c\u4e3a\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u72b6\u6001":114,"\u6211\u4eec\u7684":0,"\u6211\u4eec\u7684\u6807\u51c6\u5f00\u53d1\u6d41\u7a0b\u662f\u628a\u8fd9\u4e9b\u5de5\u5177\u90fd\u88c5\u8fdb\u4e00\u4e2adocker":72,"\u6211\u4eec\u770b\u4e00\u4e0b\u5355\u5c42rnn\u7684\u914d\u7f6e":111,"\u6211\u4eec\u770b\u4e00\u4e0b\u8bed\u4e49\u76f8\u540c\u7684\u53cc\u5c42rnn\u7684\u7f51\u7edc\u914d\u7f6e":111,"\u6211\u4eec\u771f\u8bda\u5730\u611f\u8c22\u60a8\u7684\u8d21\u732e":72,"\u6211\u4eec\u79f0\u4e4b\u4e3a\u4e00\u4e2a0\u5c42\u7684\u5e8f\u5217":110,"\u6211\u4eec\u8ba1\u5212\u5c06":41,"\u6211\u4eec\u8ba1\u5212\u5c06\u82f1\u7279\u5c14\u6df1\u5ea6\u795e\u7ecf\u7f51\u7edc\u6570\u5b66\u5e93":42,"\u6211\u4eec\u8bbe\u8ba1\u8bf4\u660e\u4e86\u540d\u4e3afilemanager\u7cfb\u7edf":27,"\u6211\u4eec\u8c03\u7528\u4e86eigenvector\u7684flatten\u63a5\u53e3":76,"\u6211\u4eec\u8fd8\u53ef\u4ee5\u767b\u5f55\u5230\u5bbf\u4e3b\u673a\u4e0a\u67e5\u770b\u8bad\u7ec3\u7ed3\u679c":96,"\u6211\u4eec\u8fd8\u5c06\u7f16\u7801\u5411\u91cf\u6295\u5c04\u5230":114,"\u6211\u4eec\u9009\u53d6\u5355\u53cc\u5c42\u5e8f\u5217\u914d\u7f6e\u4e2d\u7684\u4e0d\u540c\u90e8\u5206":111,"\u6211\u4eec\u9009\u62e9":11,"\u6211\u4eec\u901a\u5e38\u501f\u52a9":75,"\u6211\u4eec\u901a\u5e38\u5c06\u4e00\u53e5\u8bdd\u7406\u89e3\u6210\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217":111,"\u6211\u4eec\u901a\u8fc7\u4f7f\u7528\u65b0\u5f15\u5165\u7684gemm":41,"\u6211\u4eec\u901a\u8fc7\u8bfb\u53d6":97,"\u6211\u4eec\u90fd\u63d0\u4f9bpython\u7684\u8f6c\u6362\u5e93":11,"\u6211\u4eec\u9700\u8981":0,"\u6211\u4eec\u9700\u8981\u5148\u628a\u8f93\u5165tensor\u548c\u8f93\u51fatensor\u8f6c\u6362\u4e3aeigen\u652f\u6301\u7684\u683c\u5f0f":76,"\u6211\u4eec\u9700\u8981\u5236\u4f5c\u4e00\u4e2a\u5305\u542b\u8bad\u7ec3\u6570\u636e\u7684paddlepaddle\u955c\u50cf":96,"\u6211\u4eec\u9700\u8981\u5728\u96c6\u7fa4\u7684\u6240\u6709\u8282\u70b9\u4e0a\u5b89\u88c5":101,"\u6211\u4eec\u9700\u8981\u7b49\u5f0f\u5de6\u8fb9\u7684eigentensor\u8c03\u7528device\u63a5\u53e3":76,"\u6211\u4eec\u9700\u8981\u8ba1\u7b97":74,"\u6211\u4eec\u9996\u5148\u9700\u8981\u6839\u636e\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u6765\u521b\u5efa\u6240\u9700\u8981\u4f18\u5316\u7684paramet":84,"\u6211\u5220\u9664\u4e86":72,"\u6211\u53ef\u4ee5\u7528":0,"\u6211\u53ef\u4ee5\u9009\u62e9\u4e0d\u7528docker\u5417":0,"\u6216":[89,108,117],"\u6216\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":110,"\u6216\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u53d8\u6210\u4e00\u4e2a0\u5c42\u5e8f\u5217":110,"\u6216\u4e00\u4e2a\u5411\u91cf":113,"\u6216\u5355\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u53d8\u6210\u4e00\u4e2a0\u5c42\u5e8f\u5217":110,"\u6216\u662f\u5728\u81ea\u7136\u8bed\u8a00\u5904\u7406\u4efb\u52a1\u4e2d\u8868\u793a\u8bcd\u8bed\u5728\u5b57\u5178\u4e2d\u7684\u5e8f\u53f7":89,"\u6216\u6700\u5927\u503c":110,"\u6216\u79f0\u4f5cweight":81,"\u6216\u7b2c\u4e00\u4e2a":110,"\u6216\u7b2c\u4e00\u4e2a\u5143\u7d20":110,"\u6216\u7f16\u5199\u7a0b\u5e8f\u65f6":91,"\u6216\u8005":[0,42,45,46,72,75,81,89,107,108,110,111],"\u6216\u8005\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":113,"\u6216\u8005\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":[110,113],"\u6216\u8005\u4e5f\u53ef\u4ee5\u4f7f\u7528\u4e3a\u4e0a\u8ff0\u53ef\u9009\u6b65\u9aa4\u6784\u5efa\u7684\u955c\u50cf":0,"\u6216\u8005\u4ece\u5de5\u5177\u7684\u754c\u9762\u91cc\u8fd0\u884c\u60a8\u7684\u5e94\u7528":108,"\u6216\u8005\u5236\u4f5c\u548c\u5206\u4eab\u5e26\u6709\u4ee3\u7801":1,"\u6216\u8005\u53cd\u5411\u5730\u4ece":114,"\u6216\u8005\u53ef\u88abdns\u89e3\u6790\u7684\u4e3b\u673a\u540d":101,"\u6216\u8005\u5728cpu\u6a21\u5f0f\u4e0b\u4f7f\u75284\u4e2a\u7ebf\u7a0b":103,"\u6216\u8005\u5c06\u8fd9\u53f0\u8282\u70b9\u8fc1\u79fb\u5230\u53e6\u4e00\u4e2a\u8282\u70b9\u5e76\u542f\u52a8\u5373\u53ef\u6062\u590d\u8bad\u7ec3\u4efb\u52a1":10,"\u6216\u8005\u5df2\u7ecf\u5728\u96c6\u7fa4\u63d0\u4ea4\u73af\u5883\u4e2d\u81ea\u52a8\u8bbe\u7f6e":102,"\u6216\u8005\u5f15\u8d77\u884c\u65f6\u9519\u8bef":89,"\u6216\u8005\u6570\u7ec4\u7684\u6570\u7ec4\u8fd9\u4e2a\u6982\u5ff5":111,"\u6216\u8005\u662f\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":110,"\u6216\u8005\u662f\u51fd\u6570\u8c03\u7528\u7684\u9891\u7387\u548c\u8017\u65f6\u7b49":108,"\u6216\u8005\u66f4\u65e9":83,"\u6216\u8005\u6bcf\u4e00\u4e2a\u7cfb\u5217\u91cc\u7684\u7279\u5f81\u6570\u636e":111,"\u6216\u8005\u7528tuple\u8868\u793a\u7684\u591a\u4e2a\u503c":11,"\u6216\u8005\u7531\u5b83\u4eec\u7ec4\u6210\u7684list":11,"\u6216\u8005\u76f4\u63a5\u6254\u6389\u975e\u5e38\u957f\u7684\u5e8f\u5217":81,"\u6216\u8005\u76f8\u5bf9\u4e8e\u6784\u5efa\u76ee\u5f55\u7684\u76f8\u5bf9\u8def\u5f84":[116,118],"\u6216\u8005\u8f93\u5165\u6570\u636e\u5c3a\u5ea6\u8fc7\u5927":81,"\u6216\u8005\u8fd0\u884c":78,"\u6216\u8005\u91c7\u7528\u5e76\u884c\u8ba1\u7b97\u6765\u52a0\u901f\u67d0\u4e9b\u5c42\u7684\u66f4\u65b0":105,"\u6216activ":42,"\u6216gpu":103,"\u622a\u65ad\u5bf9\u8c61\u4e0d\u540c":81,"\u6240\u4ee5":[1,42,63,81,107],"\u6240\u4ee5\u4e00\u4e2a\u7248\u672c\u53f7\u7684wheel\u5305\u53d1\u5e03\u4e4b\u540e":63,"\u6240\u4ee5\u4e0d\u5b58\u5728\u8fd9\u4e2a\u95ee\u9898":42,"\u6240\u4ee5\u4e0d\u80fd\u91c7\u7528\u7b2c\u4e00\u79cd\u65b9\u5f0f\u5728\u8fd9\u51e0\u4e2alayer\u91cc\u8bbe\u7f6e":82,"\u6240\u4ee5\u505a\u6cd5\u53ef\u4ee5\u6709\u4e24\u79cd":81,"\u6240\u4ee5\u53ef\u4ee5\u7b80\u5316\u5bf9\u73af\u5883\u7684\u8981\u6c42":96,"\u6240\u4ee5\u5728":42,"\u6240\u4ee5\u5728\u5199\u5165\u5feb\u7167\u7684\u8fc7\u7a0b\u4e2d":10,"\u6240\u4ee5\u5916\u5c42\u8f93\u51fa\u7684\u5e8f\u5217\u5f62\u72b6":111,"\u6240\u4ee5\u5bf9":111,"\u6240\u4ee5\u5f00\u53d1\u8005\u9700\u8981\u6839\u636e\u81ea\u5df1\u8bad\u7ec3\u4efb\u52a1\u7684\u5b9e\u9645\u573a\u666f\u5b8c\u6210\u8bad\u7ec3\u6570\u636e\u7684\u5206\u5272\u548c":91,"\u6240\u4ee5\u6027\u80fd\u4e5f\u5c31\u9010\u6b65\u53d8\u6210\u4e86\u6df1\u5ea6\u5b66\u4e60\u9886\u57df\u6700\u91cd\u8981\u7684\u6307\u6807":108,"\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u5728\u8fd9\u4e2a\u57fa\u7840\u4e0a":97,"\u6240\u4ee5\u6211\u4eec\u5b9a\u4e49\u4e86\u4e00\u4e2a":42,"\u6240\u4ee5\u6211\u4eec\u786e\u4fdd\u53d1\u5e03\u7684\u4e8c\u8fdb\u5236\u5305\u53ef\u4ee5\u652f\u6301\u4e3b\u6d41\u7684linux\u64cd\u4f5c\u7cfb\u7edf":3,"\u6240\u4ee5\u6211\u4eec\u9700\u8981\u5c06\u8f93\u5165\u6570\u636e\u6807\u8bb0\u6210":111,"\u6240\u4ee5\u6211\u4eec\u9ed8\u8ba4\u4f7f\u7528cento":3,"\u6240\u4ee5\u6574\u4f53\u4e0a":42,"\u6240\u4ee5\u6dfb\u52a0\u4e86\u5bf9\u5e94\u7684":42,"\u6240\u4ee5\u7528\u6237\u9700\u8981\u9996\u5148\u5728":27,"\u6240\u4ee5\u76f8\u6bd4\u4e8erecurr":82,"\u6240\u4ee5\u8fd9\u4e00\u6b65\u662f\u5fc5\u8981\u7684":74,"\u6240\u4ee5\u9700\u8981\u5f15\u5165\u4e00\u4e2a\u8f6c\u6362\u65b9\u6cd5":42,"\u6240\u4f7f\u7528":117,"\u6240\u4f9d\u8d56\u7684\u7b2c\u4e09\u65b9\u5e93\u540c\u65f6\u4e5f\u88ab\u5b89\u88c5\u5230":116,"\u6240\u5bf9\u5e94\u7684\u8bcd\u8868index\u6570\u7ec4":111,"\u6240\u6709\u4e0e\u7c7b\u578b\u76f8\u5173\u7684\u51fd\u6570":46,"\u6240\u6709\u4ee3\u7801\u5fc5\u987b\u5177\u6709\u5355\u5143\u6d4b\u8bd5":72,"\u6240\u6709\u53c2\u6570\u7f6e\u4e3a\u96f6":103,"\u6240\u6709\u547d\u4ee4\u884c\u9009\u9879\u53ef\u4ee5\u8bbe\u7f6e\u4e3a":93,"\u6240\u6709\u5916\u90e8\u7684\u8f6c\u6362\u5de5\u4f5c\u90fd\u4f1a\u5728reset\u7cfb\u5217\u51fd\u6570\u4e2d\u90fd\u51c6\u5907\u597d":42,"\u6240\u6709\u67b6\u6784":116,"\u6240\u6709\u7684":[41,72,74],"\u6240\u6709\u7684\u5355\u6d4b\u90fd\u4f1a\u88ab\u6267\u884c\u4e00\u6b21":74,"\u6240\u6709\u7684\u63a5\u53e3\u5747\u4e3ac\u63a5\u53e3":46,"\u6240\u6709\u7684\u64cd\u4f5c\u90fd\u662f\u9488\u5bf9\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65\u6765\u8fdb\u884c\u7684":111,"\u6240\u6709\u7684python\u5c01\u88c5\u90fd\u4f7f\u7528":74,"\u6240\u6709\u7684python\u5c01\u88c5\u90fd\u5728":74,"\u6240\u6709\u76f8\u5173\u7684":41,"\u6240\u6709\u7c7b\u578b\u540d\u4e3a":46,"\u6240\u6709\u7f51\u7edc\u5c42\u7684\u68af\u5ea6\u68c0\u67e5\u5355\u6d4b\u90fd\u4f4d\u4e8e":74,"\u6240\u6709\u8f93\u5165\u5e8f\u5217\u5e94\u8be5\u6709\u76f8\u540c\u7684\u957f\u5ea6":114,"\u6240\u6709mkl":42,"\u6240\u9700\u652f\u6301\u7684\u6700\u4f4eandroid":116,"\u6240\u9700\u7684\u5f00\u53d1\u5de5\u5177\u548c\u7b2c\u4e09\u65b9\u5e93\u53ef\u4ee5\u53c2\u8003":118,"\u624b\u5199\u591a\u8bed\u8a00\u7ed1\u5b9a":45,"\u624b\u5199\u6570\u5b57\u8bc6\u522b":90,"\u624b\u5199\u6570\u5b57\u8bc6\u522b\u4efb\u52a1\u5b9a\u4e49\u4e86\u4e00\u4e2a\u542b\u6709":90,"\u624b\u52a8\u4e0b\u8f7d\u4e14\u89e3\u538b\u7f29":78,"\u624b\u52a8\u4e0b\u8f7d\u5e76\u5b89\u88c5":78,"\u624d\u53ef\u4ee5\u5b89\u88c5":3,"\u624d\u80fd\u4fdd\u8bc1\u548c\u5355\u5c42\u5e8f\u5217\u7684\u914d\u7f6e\u4e2d":111,"\u624d\u80fd\u53d1\u6325\u5176\u5168\u90e8\u80fd\u529b":108,"\u624d\u80fd\u66f4\u597d\u7684\u53d1\u6325mkl":42,"\u6253\u5f00":108,"\u6253\u5f00\u6d4f\u89c8\u5668\u8bbf\u95ee\u5bf9\u5e94\u76ee\u5f55\u4e0b\u7684index":77,"\u6253\u5f00\u8fd9\u4e2a\u7f16\u8bd1\u9009\u9879":46,"\u6267\u884c":[63,86,87,93],"\u6267\u884c\u4e0a\u8ff0":116,"\u6267\u884c\u4e0a\u8ff0\u4ee3\u7801\u751f\u6210makefile\u6587\u4ef6\u540e":87,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u4ee5\u542f\u52a83\u4e2a\u8282\u70b9\u7684openmpi\u96c6\u7fa4\u548c\u4e00\u4e2a":98,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u5373\u53ef\u5728\u5f53\u524d\u673a\u5668\u4e0a\u5b89\u88c5paddlepaddle\u7684\u8fd0\u884c\u65f6\u73af\u5883":3,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u53ef\u4ee5\u67e5\u770b\u5df2\u7ecf\u5b89\u88c5\u7684\u7248\u672c":101,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u5b8c\u6210\u5feb\u901f\u5b89\u88c5":86,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u6765\u8fd0\u884c\u5355\u5143\u6d4b\u8bd5":75,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u7f16\u8bd1cpu":0,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u83b7\u53d6\u6700\u65b0\u7684paddlepaddl":1,"\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4":[116,117,118],"\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\u542f\u52a8\u4f7f\u7528python\u7f16\u5199\u7684trainer\u7a0b\u5e8f":91,"\u6267\u884c\u4ee5\u4e0b\u64cd\u4f5c":114,"\u6267\u884c\u4ee5\u4e0b\u7684\u547d\u4ee4\u542f\u52a8\u4e00\u4e2a\u53c2\u6570\u670d\u52a1\u5668\u5e76\u7b49\u5f85\u548c\u8ba1\u7b97\u8282\u70b9\u7684\u6570\u636e\u4ea4\u4e92":91,"\u6267\u884c\u5b8c\u5b89\u88c5\u547d\u4ee4\u540e":[116,117,118],"\u6267\u884c\u60a8\u7684\u4ee3\u7801":108,"\u627e\u5230":[0,114],"\u627e\u5230\u4ee5\u4e0a\u76f8\u5173\u7684\u4f8b\u5b50":94,"\u627e\u5230\u6700\u65e9\u62a5\u9519\u7684\u5730\u65b9":79,"\u627e\u5230\u8fd0\u884c\u6162\u7684\u539f\u56e0":108,"\u627e\u5230\u8fd0\u884c\u6162\u7684\u90e8\u5206":108,"\u628a":[11,74],"\u628a\u4e4b\u524d\u793a\u4f8b\u4e2d\u8f6c\u6362\u5b8c\u6bd5\u7684random":11,"\u628a\u4efb\u610f\u7ef4\u5ea6\u7684tensor\u8f6c\u4e3a\u4e86\u4e00\u7ef4\u7684eigenvector":76,"\u628a\u5de5\u5177\u548c\u914d\u7f6e\u90fd\u5b89\u88c5\u5728\u4e00\u4e2a":0,"\u628a\u8bad\u7ec3\u6570\u636e\u76f4\u63a5\u653e\u5728":96,"\u628a\u8fd9\u4e9b\u5de5\u5177\u5b89\u88c5\u5230\u672c\u673a":0,"\u6295\u5c04\u53cd\u5411rnn\u7684\u7b2c\u4e00\u4e2a\u5b9e\u4f8b\u5230":114,"\u6295\u5c04\u7f16\u7801\u5411\u91cf\u5230":114,"\u62c6\u6210\u4ee5\u4e0a\u4e24\u4e2a\u9759\u6001\u94fe\u63a5\u5e93":87,"\u62c6\u89e3":113,"\u62c6\u89e3\u6210\u7684\u6bcf\u4e00\u53e5\u8bdd\u518d\u901a\u8fc7\u4e00\u4e2alstm\u7f51\u7edc":111,"\u62f7\u8d1d\u5230numpi":81,"\u62f7\u8d1d\u5fc5\u8981\u7684\u6587\u4ef6\u5230head\u8282\u70b9":98,"\u62f7\u8d1d\u8bad\u7ec3\u6570\u636e\u5230\u5404\u81ea\u7684\u8282\u70b9":98,"\u62f7\u8d1d\u8bad\u7ec3\u6587\u4ef6\u5230\u5bb9\u5668\u5185":97,"\u62f7\u8d1d\u8bad\u7ec3\u7a0b\u5e8f\u548c\u5b57\u5178\u6587\u4ef6\u5230\u6bcf\u53f0mpi\u8282\u70b9":98,"\u62fc\u63a5":81,"\u6302\u8f7d\u5230\u5bb9\u5668\u5185\u90e8\u7684":1,"\u6302\u8f7d\u6216\u4e0b\u8f7d\u7684\u8bad\u7ec3\u6570\u636e\u5206\u7247":91,"\u6307\u53d1\u73b0\u6027\u80fd\u74f6\u9888":107,"\u6307\u5411\u4e00\u4e2alayer":113,"\u6307\u5b9a":[81,82,113,114],"\u6307\u5b9a\u4e00\u53f0\u673a\u5668\u4e0a\u4f7f\u7528\u7684\u7ebf\u7a0b\u6570":103,"\u6307\u5b9a\u4e3a":89,"\u6307\u5b9a\u4f7f\u75282":81,"\u6307\u5b9a\u524d\u5411\u7f51\u7edc\u6700\u7ec8\u7684\u8f93\u51fa\u76ee\u6807\u53d8\u91cf":75,"\u6307\u5b9a\u52a0\u8f7d\u7684\u65b9\u5f0f":103,"\u6307\u5b9a\u5728\u751f\u6210\u6027\u80fd\u5206\u6790\u6587\u4ef6\u4e4b\u540e":107,"\u6307\u5b9a\u5bf9\u8f93\u5165\u53d8\u91cf":75,"\u6307\u5b9a\u5c06\u5f53\u524d\u8def\u5f84":1,"\u6307\u5b9a\u68c0\u6d4b\u68af\u5ea6\u65f6\u80fd\u5bb9\u5fcd\u7684\u6700\u5927\u9519\u8bef\u503c":75,"\u6307\u5b9a\u7684\u5185\u5bb9\u5b58\u50a8\u5e93\u8fd0\u884c\u547d\u4ee4":77,"\u6307\u5b9a\u7684\u8f93\u5165\u4e0d\u4f1a\u88ab":113,"\u6307\u5b9a\u8981\u8f93\u51fa\u7684\u5b57\u6bb5\u8fdb\u884c\u8f93\u51fa":81,"\u6307\u5b9a\u9700\u8981\u4f7f\u7528\u7684\u5bb9\u5668":1,"\u6307\u5b9acudnn\u7684\u6700\u5927\u5de5\u4f5c\u7a7a\u95f4\u5bb9\u9650":103,"\u6307\u5bf9\u4e8e\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217\u8f93\u5165\u6570\u636e":111,"\u6307\u5f00\u542fhttp\u670d\u52a1":107,"\u6307\u6d88\u9664\u74f6\u9888":107,"\u6307\u6df1\u5ea6\u5b66\u4e60\u8bad\u7ec3\u4e4b\u540e\u5f97\u5230\u7684\u6240\u6709\u53c2\u6570":10,"\u6307\u793a\u4f7f\u7528\u54ea\u4e2agpu\u6838":103,"\u6307\u793a\u5728\u7b80\u5355\u7684recurrentlayer\u5c42\u7684\u8ba1\u7b97\u4e2d\u662f\u5426\u4f7f\u7528\u6279\u5904\u7406\u65b9\u6cd5":103,"\u6307\u793a\u5f53\u6307\u5b9a\u8f6e\u7684\u6d4b\u8bd5\u6a21\u578b\u4e0d\u5b58\u5728\u65f6":103,"\u6307\u793a\u662f\u5426\u4f7f\u7528\u591a\u7ebf\u7a0b\u6765\u8ba1\u7b97\u4e00\u4e2a\u795e\u7ecf\u7f51\u7edc":103,"\u6307\u793a\u662f\u5426\u5f00\u542f\u53c2\u6570\u670d\u52a1\u5668":103,"\u6307\u793a\u662f\u5426\u663e\u793a\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u7684\u7a00\u758f\u53c2\u6570\u5206\u5e03\u7684\u65e5\u5fd7\u7ec6\u8282":103,"\u6307\u793a\u662f\u5426\u68c0\u67e5\u6240\u6709\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u7684\u7a00\u758f\u53c2\u6570\u7684\u5206\u5e03\u662f\u5747\u5300\u7684":103,"\u6309\u542f\u53d1\u5f0f\u635f\u5931\u7684\u5927\u5c0f\u9012\u589e\u6392\u5e8f":103,"\u6309\u7167\u4e0b\u9762\u6b65\u9aa4\u5373\u53ef":97,"\u6309\u7167\u5177\u4f53\u5b9e\u73b0\u65b9\u5f0f\u53ef\u4ee5\u5f52\u7eb3\u4e3a2\u7c7b":82,"\u6309\u7167\u57fa\u672c\u6570\u636e\u7c7b\u578b\u5728paddlepaddle\u5185\u90e8\u7684\u5b9a\u4e49\u548c\u5b9e\u73b0":89,"\u6309\u94ae":[63,72],"\u635f\u5931\u51fd\u6570\u5c42":90,"\u6392\u6210\u4e00\u5217\u7684\u591a\u4e2a\u5143\u7d20":110,"\u63a5\u4e0a\u4e00\u4e2a\u5168\u8fde\u63a5\u5c42":84,"\u63a5\u4e0a\u5e73\u65b9\u8bef\u5dee\u5c42":84,"\u63a5\u4e0b\u6765":75,"\u63a5\u4e0b\u6765\u53ef\u4ee5\u8003\u8651\u4e0b\u65f6\u95f4\u7ebf\u7684\u5206\u6790":108,"\u63a5\u4e0b\u6765\u5c31\u53ef\u4ee5\u4f7f\u7528":108,"\u63a5\u4e0b\u6765\u6211\u4eec\u521b\u5efa\u4e00\u4e2a\u539f\u59cb":72,"\u63a5\u4e0b\u6765\u6211\u4eec\u53d6\u6d88\u5bf9":72,"\u63a5\u4e0b\u6765\u7b49\u5f85":72,"\u63a5\u53d7\u4e00\u4e2a\u8f93\u5165\u53c2\u6570":75,"\u63a5\u53e3":[45,46,75,76,90],"\u63a5\u53e3\u4f1a\u88ab\u8c03\u7528":76,"\u63a5\u53e3\u5b8c\u6210\u795e\u7ecf\u7f51\u7edc\u7684\u524d\u5411\u8ba1\u7b97":90,"\u63a5\u53e3\u5bf9\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u548c\u8bad\u7ec3\u597d\u7684\u53c2\u6570\u8fdb\u884c\u5e8f\u5217\u5316":90,"\u63a5\u53e3\u5c42\u505a\u8fc7\u591a\u5c01\u88c5":46,"\u63a5\u53e3\u662f":11,"\u63a5\u53e3\u6700\u7ec8\u4f1a\u8c03\u7528\u5bf9\u5e94":76,"\u63a5\u53e3\u6709\u4e00\u4e2a":81,"\u63a5\u53e3\u7684":81,"\u63a5\u53e3\u8bf4\u660e\u8bf7\u67e5\u770b":89,"\u63a5\u6536\u5230\u8db3\u591f\u7684gradient":91,"\u63a5\u6536\u5904\u7406pfsclient\u7aef\u7684\u6587\u4ef6\u7ba1\u7406\u8bf7\u6c42":27,"\u63a5\u7740\u5bf9\u6240\u6709\u53c2\u6570\u7684\u4f7f\u7528\u573a\u5408\u8fdb\u884c\u6982\u8ff0\u548c\u5206\u7c7b":104,"\u63a5\u7740\u7f16\u8bd1\u5373\u53ef":78,"\u63a7\u5236":103,"\u63a7\u5236\u662f\u5426\u4f7f\u7528mkl":42,"\u63a7\u5236\u662f\u5426\u4f7f\u7528mklml\u5e93":42,"\u63a7\u5236\u7528\u6237\u6743\u9650":11,"\u63a8\u5bfc\u8be5\u5c42\u524d\u5411\u548c\u540e\u5411\u4f20\u9012\u7684\u65b9\u7a0b":74,"\u63a8\u8350\u4f7f\u7528\u6b64\u65b9\u5f0f":87,"\u63a8\u8350\u4f7f\u7528centos\u7684devtools2":0,"\u63a8\u8350\u6e05\u7406\u6574\u4e2a\u7f16\u8bd1\u76ee\u5f55":0,"\u63a8\u8350\u8bbe\u7f6e\u4e3a":87,"\u63a8\u8350\u914d\u7f6e\u4e3a":87,"\u63a8\u8350\u914d\u7f6e\u9009\u9879":87,"\u63a8\u9001\u5230\u8fdc\u7a0b\u4ed3\u5e93":72,"\u63cf\u8ff0\u7684\u9ed8\u8ba4\u5165\u53e3\u7a0b\u5e8f":0,"\u63cf\u8ff0\u8be5op\u7684\u8f93\u5165":75,"\u63cf\u8ff0\u95ee\u9898":72,"\u63d0\u4ea4\u65b9\u5f0f\u53c2\u89c1":77,"\u63d0\u4ea4pull":72,"\u63d0\u4f9b":93,"\u63d0\u4f9b\u4e03\u5c42\u534f\u8bae\u7684\u53cd\u5411\u4ee3\u7406":27,"\u63d0\u4f9b\u4e86\u4e00\u4e2a\u542f\u52a8\u811a\u672c":97,"\u63d0\u4f9b\u4e86\u547d\u4ee4\u6837\u4f8b\u6765\u8fd0\u884c":93,"\u63d0\u4f9b\u4e86\u65b9\u4fbf\u7684\u548c":107,"\u63d0\u4f9b\u4e86\u81ea\u52a8\u5316\u811a\u672c\u6765\u542f\u52a8\u4e0d\u540c\u8282\u70b9\u4e2d\u7684\u6240\u6709":93,"\u63d0\u4f9b\u51e0\u4e4e\u6240\u6709\u8bad\u7ec3\u7684\u5185\u90e8\u8f93\u51fa\u65e5\u5fd7":93,"\u63d0\u4f9b\u5e38\u7528\u7684\u547d\u4ee4\u884c\u7ba1\u7406\u547d\u4ee4\u7ba1\u7406\u6587\u4ef6\u548c\u76ee\u5f55":27,"\u63d0\u4f9b\u6269\u5c55\u7684\u957f\u5ea6\u4fe1\u606f":110,"\u63d0\u4f9b\u7528\u6237\u7ba1\u7406\u6587\u4ef6\u7684\u547d\u4ee4":27,"\u63d0\u4f9b\u7ed9paddle\u4f5c\u4e3a\u8bad\u7ec3\u6570\u636e":11,"\u63d0\u4f9b\u8bad\u7ec3\u8fc7\u7a0b\u7684":93,"\u63d0\u793a":78,"\u641c\u7d22\u4ee3\u7801\u5e93":77,"\u642d\u5efa\u795e\u7ecf\u7f51\u7edc\u5c31\u50cf\u4f7f\u7528\u79ef\u6728\u642d\u5efa\u5b9d\u5854\u4e00\u6837":84,"\u64cd\u4f5c":111,"\u64cd\u4f5c\u7cfb\u7edf":[0,3],"\u652f\u6301\u4e24\u79cd\u5e8f\u5217\u7c7b\u578b":89,"\u652f\u6301\u4ea4\u53c9\u7f16\u8bd1":118,"\u652f\u6301\u53cc\u5c42\u5e8f\u5217\u4f5c\u4e3a\u8f93\u5165\u7684layer":[112,113],"\u652f\u6301\u5927\u6587\u4ef6\u7684\u65ad\u70b9\u4e0a\u4f20":27,"\u652f\u6301\u5927\u89c4\u6a21\u96c6\u7fa4\u751f\u4ea7\u73af\u5883\u7684\u5b8c\u6574\u96c6\u7fa4\u65b9\u6848":94,"\u652f\u6301\u7684\u6700\u5c0f\u7684android":116,"\u652f\u6301\u7684\u6700\u5c0fandroid":116,"\u652f\u6301\u7ef4\u6570\u53ef\u53d8\u7684\u6570\u636e\u8f93\u5165":82,"\u652f\u6301\u7f16\u8bd1\u5668":116,"\u6539\u53d8\u7ef4\u5ea6\u987a\u5e8f":82,"\u653e\u5728\u8fd9\u4e2a\u76ee\u5f55\u91cc\u7684\u6587\u4ef6\u5176\u5b9e\u662f\u4fdd\u5b58\u5230\u4e86mfs\u4e0a":97,"\u6545\u800c\u662f\u4e00\u4e2a\u5355\u5c42\u65f6\u95f4\u5e8f\u5217":111,"\u6548\u679c\u5982\u4e0b":107,"\u6559\u7a0b":1,"\u6570":113,"\u6570\u5b66\u5e93":87,"\u6570\u5fc5\u987b\u4e25\u683c\u76f8\u7b49":113,"\u6570\u636e":[27,89,90],"\u6570\u636e\u4e2d0":83,"\u6570\u636e\u5206\u7247":92,"\u6570\u636e\u63d0\u4f9b\u5668":102,"\u6570\u636e\u8bfb\u53d6\u5747\u4ea4\u7531\u5176\u4ed6\u8bed\u8a00\u5b8c\u6210":45,"\u6570\u636e\u8f93\u5165":[89,113],"\u6570\u636e\u957f\u5ea6\u53ca\u6821\u9a8c\u503c\u7ec4\u6210":27,"\u6570\u636e\u96c6":90,"\u6570\u636e\u96c6\u9700\u8981\u9884\u5148\u88ab\u8f6c\u6362\u6210paddlepaddle\u5206\u5e03\u5f0f\u8bad\u7ec3\u4f7f\u7528\u7684\u5b58\u50a8\u683c":11,"\u6570\u636e\u9884\u5904\u7406\u4efb\u52a1":11,"\u6570\u76ee":105,"\u6574\u4e2a\u5b89\u88c5\u8fc7\u7a0b\u8017\u65f6\u8f83\u957f":2,"\u6574\u4f53\u4f7f\u7528\u6d41\u7a0b":90,"\u6574\u4f53\u6570\u636e\u548c\u539f\u59cb\u6570\u636e\u5b8c\u5168\u4e00\u6837":111,"\u6574\u4f53\u7684\u7ed3\u6784\u56fe\u5982\u4e0b":97,"\u6574\u578b\u6570\u7ec4":89,"\u6574\u6570":74,"\u6574\u6570\u6807\u7b7e":84,"\u6587\u4ef6":[45,72,75,89,96],"\u6587\u4ef6\u4e2d":[75,90,97],"\u6587\u4ef6\u4e2d\u6ce8\u518c\u524d\u5411":75,"\u6587\u4ef6\u4e2d\u6ce8\u518c\u8be5op\u548ckernel":75,"\u6587\u4ef6\u4e2d\u6ce8\u518ccuda":75,"\u6587\u4ef6\u4e3a":81,"\u6587\u4ef6\u4e4b\u5916":72,"\u6587\u4ef6\u4f20\u8f93\u7684\u7684\u5173\u952e\u5728\u4e8e\u9700\u8981pfsclient\u7aef\u5bf9\u6bd4source\u548cdestination\u7684\u6587\u4ef6chunks\u7684checksum\u662f\u5426\u4fdd\u6301\u4e00\u81f4":27,"\u6587\u4ef6\u5185\u5bb9\u4e3a":45,"\u6587\u4ef6\u540d":107,"\u6587\u4ef6\u540d\u4e3a\u4efb\u610f\u6587\u4ef6\u540d":91,"\u6587\u4ef6\u540d\u4e3a\u6b64uuid":10,"\u6587\u4ef6\u547d\u540d\u4ee5":75,"\u6587\u4ef6\u59390":97,"\u6587\u4ef6\u5bf9\u5e94\u7684data":11,"\u6587\u4ef6\u5de5\u5177\u662f\u4f7f\u7528docker":77,"\u6587\u4ef6\u7684\u4e0a\u4f20\u548c\u4e0b\u8f7d\u90fd\u662f\u901a\u8fc7\u5bf9chunk\u7684\u64cd\u4f5c\u6765\u5b9e\u73b0\u7684":27,"\u6587\u4ef6\u7684\u6539\u53d8":72,"\u6587\u4ef6\u7684\u8def\u5f84\u6765\u52a0\u8f7d\u9884\u6d4b\u6a21\u578b":90,"\u6587\u4ef6model":105,"\u6587\u5b57\u7684\u4ea4\u4e92\u5f0f\u6587\u6863":1,"\u6587\u6863":78,"\u6587\u68631":76,"\u6587\u68632":76,"\u6587\u6863\u8f83\u5c11":76,"\u6587\u6863\u90fd\u662f\u901a\u8fc7":77,"\u6587\u7ae0":97,"\u65b0\u5efa\u4e00\u4e2a\u6743\u91cd":74,"\u65b0\u624b\u5165\u95e8":115,"\u65b0\u624b\u5165\u95e8\u7ae0\u8282":63,"\u65b0\u7248\u672c":42,"\u65b9\u4fbf\u4f7f\u7528":88,"\u65b9\u4fbf\u5206\u4eab\u8fd0\u884c\u65f6\u73af\u5883":2,"\u65b9\u4fbf\u6392\u67e5\u4ee5\u53ca\u5feb\u901f\u5b9a\u4f4d\u95ee\u9898":81,"\u65b9\u4fbf\u63d0\u4ea4\u96c6\u7fa4\u8bad\u7ec3\u4efb\u52a1":94,"\u65b9\u4fbf\u6d4b\u8bd5\u4eba\u5458\u6d4b\u8bd5paddlepaddle\u7684\u884c\u4e3a":63,"\u65b9\u4fbf\u7528\u6237\u4e0a\u4f20\u81ea\u5df1\u7684\u8bad\u7ec3\u6570\u636e\u4ee5\u8fdb\u884c\u5206\u5e03\u5f0f\u8bad\u7ec3":27,"\u65b9\u4fbf\u7528\u6237\u5728python\u7aef\u9009\u62e9\u662f\u5426\u542f\u7528\u8fd9\u4e2a\u529f\u80fd":41,"\u65b9\u4fbf\u7528\u6237\u9009\u62e9\u4f7f\u7528mkl":42,"\u65b9\u5f0f1":81,"\u65b9\u5f0f2":81,"\u65b9\u5f0f\u5c06\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u548c\u8bad\u7ec3\u597d\u7684\u53c2\u6570\u5e8f\u5217\u5316\u5230\u4e00\u4e2a\u6587\u4ef6":90,"\u65b9\u5f0f\u7c7b\u4f3c\u4e8e":42,"\u65b9\u6cd5\u4e00":105,"\u65b9\u6cd5\u4e09":105,"\u65b9\u6cd5\u4e8c":105,"\u65e0\u5ef6\u8fdf":103,"\u65e0\u6cd5\u505a\u5230\u5bf9\u4e8e\u5404\u79cd\u8bed\u8a00\u9519\u8bef\u5904\u7406\u65b9\u5f0f\u7684\u9002\u914d":45,"\u65e0\u8bba\u5728\u672c\u5730\u8fd8\u662f\u5728\u4e91\u7aef":11,"\u65e0\u8bba\u662f\u4ece":11,"\u65e0\u8bba\u662f\u5728\u672c\u5730\u6216\u662f\u4e91\u7aef\u8f6c\u6362":11,"\u65e0\u8bba\u662f\u91cd\u6784\u524d\u7684layer\u8fd8\u662f\u91cd\u6784\u540e\u7684op":42,"\u65e0\u9700\u5173\u5fc3\u548c\u5904\u7406\u5e8f\u5217\u4fe1\u606f":89,"\u65e0\u9700\u5355\u72ec\u5b89\u88c5\u7b2c\u4e09\u65b9\u4f9d\u8d56":2,"\u65e0\u9700\u63d0\u4f9b\u975e\u96f6\u5143\u7684\u503c":89,"\u65e0\u9700\u9644\u52a0\u5e8f\u5217\u4fe1\u606f":89,"\u65e0\u9ed8\u8ba4\u503c":[116,118],"\u65e5\u5fd7\u62a5\u9519\u4e3a\u7f51\u7edc\u901a\u4fe1\u7c7b\u9519\u8bef":79,"\u65f6":[10,41,42,74,81,83,87,89,97,103,110,114,116],"\u65f6\u4e00\u8d77\u66f4\u65b0":42,"\u65f6\u4f7f\u7528openblas\u6570\u5b66\u5e93":87,"\u65f6\u5982\u4f55\u7ec4\u7ec7\u8f93\u5165\u6570\u636e":89,"\u65f6\u6709\u6548":117,"\u65f6\u88ab\u8bad\u7ec3\u7684":74,"\u65f6\u8bbe\u5907id\u53f7\u7684\u5206\u914d":105,"\u65f6\u95f4":111,"\u65f6\u95f4\u6b65\u7684\u6982\u5ff5":111,"\u65f6\u987b\u4ece\u7b2c17\u5b57\u8282\u5f00\u59cb":83,"\u6613\u4e8e\u95ee\u9898\u7684\u590d\u73b0":2,"\u6620\u5c04\u4e3a":0,"\u6620\u5c04\u5230\u4e00\u4e2a\u7ef4\u5ea6\u4e3a":74,"\u662f":[3,27,42,78],"\u662f\u4e00\u4e2a\u51681\u7684\u5411\u91cf":74,"\u662f\u4e00\u4e2a\u5185\u7f6e\u7684\u5b9a\u65f6\u5668\u5c01\u88c5":108,"\u662f\u4e00\u4e2a\u52a8\u6001\u7a0b\u5e8f\u5206\u6790\u7684\u672f\u8bed":108,"\u662f\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":110,"\u662f\u4e00\u4e2a\u53cc\u5c42\u7684\u5e8f\u5217":110,"\u662f\u4e00\u4e2a\u591a\u8bed\u8a00\u63a5\u53e3\u7684\u4ee3\u7801\u751f\u6210\u5668":45,"\u662f\u4e00\u4e2a\u5c01\u88c5\u5bf9\u8c61":108,"\u662f\u4e00\u4e2a\u5f88\u6709\u7528\u7684\u53c2\u6570":105,"\u662f\u4e00\u4e2a\u65b9\u4fbf\u7684\u7a0b\u5e8f\u90e8\u7f72\u548c\u7ba1\u7406\u5de5\u5177":94,"\u662f\u4e00\u4e2a\u7c7b\u578b\u7684\u6807\u5fd7":46,"\u662f\u4e00\u4e2a\u975e\u7ebf\u6027\u7684":74,"\u662f\u4e00\u4e2apython\u7684\u7b2c\u4e09\u65b9\u5e93":107,"\u662f\u4e00\u4e2aunbound":113,"\u662f\u4e00\u6761\u65f6\u95f4\u5e8f\u5217":84,"\u662f\u4e00\u6b21\u9884\u6d4b\u63a5\u53d7\u7684\u6837\u672c\u6570\u76ee":89,"\u662f\u4e00\u79cd\u4efb\u610f\u590d\u6742\u7684rnn\u5355\u5143":113,"\u662f\u4e0d\u5305\u62ec\u6e90\u7801\u7684":96,"\u662f\u4e0d\u5e38\u89c1\u7684\u505a\u6cd5":45,"\u662f\u4f7f\u5f97\u8981\u5171\u4eab\u7684\u53c2\u6570\u4f7f\u7528\u540c\u6837\u7684":83,"\u662f\u4f7f\u7528mkl\u6570\u5b66\u5e93":87,"\u662f\u504f\u5dee":114,"\u662f\u5404\u4e2a\u5b9e\u73b0\u4e2d\u5171\u4eab\u7684\u5934\u6587\u4ef6":46,"\u662f\u5411\u91cf":74,"\u662f\u5426\u4e3a\u5f02\u6b65sgd\u66f4\u65b0\u6a21\u5f0f":91,"\u662f\u5426\u4ec5\u7f16\u8bd1capi":0,"\u662f\u5426\u4ee5\u9006\u5e8f\u5904\u7406\u8f93\u5165\u5e8f\u5217":113,"\u662f\u5426\u4f7f\u7528":117,"\u662f\u5426\u4f7f\u7528\u53cc\u7cbe\u5ea6\u6d6e\u70b9\u6570":0,"\u662f\u5426\u4f7f\u7528\u65e7\u7684remoteparameterupdat":103,"\u662f\u5426\u4f7f\u7528\u6743\u91cd":74,"\u662f\u5426\u4f7f\u7528arm\u6a21\u5f0f":116,"\u662f\u5426\u4f7f\u7528eigen\u5e93\u8fdb\u884c\u77e9\u9635\u8ba1\u7b97":[116,117],"\u662f\u5426\u4f7f\u7528mkl\u6570\u5b66\u5e93":0,"\u662f\u5426\u4f7f\u7528neon\u6307\u4ee4":[116,118],"\u662f\u5426\u4f7f\u80fd":117,"\u662f\u5426\u5185\u5d4cpython\u89e3\u91ca\u5668":0,"\u662f\u5426\u5219\u5171\u4eab\u540c\u4e00\u4e2a":75,"\u662f\u5426\u542f\u7528gpu\u8bad\u7ec3":91,"\u662f\u5426\u5c06\u5168\u5c40\u79cd\u5b50\u5e94\u7528\u4e8e\u672c\u5730\u7ebf\u7a0b\u7684\u968f\u673a\u6570":103,"\u662f\u5426\u5f00\u542f\u5355\u5143\u6d4b\u8bd5":0,"\u662f\u5426\u6253\u5370\u7248\u672c\u4fe1\u606f":103,"\u662f\u5426\u6253\u5f00":41,"\u662f\u5426\u652f\u6301gpu":0,"\u662f\u5426\u663e\u793a":103,"\u662f\u5426\u7a00\u758f":74,"\u662f\u5426\u7f16\u8bd1\u4e2d\u82f1\u6587\u6587\u6863":0,"\u662f\u5426\u7f16\u8bd1\u542b\u6709avx\u6307\u4ee4\u96c6\u7684paddlepaddle\u4e8c\u8fdb\u5236\u6587\u4ef6":0,"\u662f\u5426\u7f16\u8bd1\u65f6\u8fdb\u884c\u4ee3\u7801\u98ce\u683c\u68c0\u67e5":0,"\u662f\u5426\u7f16\u8bd1c":117,"\u662f\u5426\u7f16\u8bd1go\u8bed\u8a00\u7684\u53ef\u5bb9\u9519paramet":0,"\u662f\u5426\u7f16\u8bd1python\u7684swig\u63a5\u53e3":0,"\u662f\u5426\u8fd0\u884c\u65f6\u52a8\u6001\u52a0\u8f7dcuda\u52a8\u6001\u5e93":0,"\u662f\u5426\u9700\u8981\u7b49\u5f85\u8be5\u8f6e\u6a21\u578b\u53c2\u6570":103,"\u662f\u56e0\u4e3a\u8fd9\u4e2a\u6d41\u7a0b\u6bd4\u5176\u4ed6\u65b9\u6cd5\u90fd\u66f4\u7b80\u4fbf":0,"\u662f\u56e0\u4e3ac99\u652f\u6301":45,"\u662f\u5728paddlepaddle\u4e2d\u6784\u9020\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u65f6\u6700\u91cd\u8981\u7684\u6982\u5ff5":114,"\u662f\u5b58\u6709\u4e00\u7cfb\u5217\u53d8\u6362\u77e9\u9635\u7684\u6743\u91cd":74,"\u662f\u5b58\u6709\u504f\u7f6e\u5411\u91cf\u7684\u6743\u91cd":74,"\u662f\u5bf9\u7528\u6237\u6587\u4ef6\u5b58\u50a8\u7a7a\u95f4\u7684\u62bd\u8c61":27,"\u662f\u5bfb\u627e\u74f6\u9888\u7684\u5173\u952e\u6307\u6807":107,"\u662f\u5f00\u542favx\u7f16\u8bd1\u7684":1,"\u662f\u5f85\u6269\u5c55\u7684\u6570\u636e":110,"\u662f\u6210\u719f\u7684\u9ad8\u6027\u80fd\u5e76\u884c\u8ba1\u7b97\u6846\u67b6":94,"\u662f\u6211\u4eec":72,"\u662f\u6211\u4eec\u8981\u5206\u6790\u7684\u7a0b\u5e8f":107,"\u662f\u6307":46,"\u662f\u6307\u4e00\u7cfb\u5217\u7684\u7279\u5f81\u6570\u636e":111,"\u662f\u6307recurrent_group\u7684\u591a\u4e2a\u8f93\u5165\u5e8f\u5217":111,"\u662f\u6570\u636e\u8f93\u5165":114,"\u662f\u6709\u610f\u4e49\u7684":111,"\u662f\u6784\u5efa\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u6700\u91cd\u8981\u7684\u5de5\u5177":114,"\u662f\u6ca1\u6709\u540d\u5b57\u7684":0,"\u662f\u7528\u6237\u4f7f\u7528c":46,"\u662f\u7684":0,"\u662f\u77e9\u9635":74,"\u662f\u795e\u7ecf\u7f51\u7edc\u5b9a\u4e49\u65f6":89,"\u662f\u7f51\u7edc\u5c42\u5b9e\u4f8b\u7684\u540d\u5b57\u6807\u8bc6\u7b26":74,"\u662f\u7f51\u7edc\u5c42\u7684\u6807\u8bc6\u7b26":74,"\u662f\u7f51\u7edc\u5c42\u7684\u7c7b\u578b":74,"\u662f\u7f51\u7edc\u5c42\u8f93\u51fa\u7684\u5927\u5c0f":74,"\u662f\u8be5\u5c42\u7684\u6807\u8bc6\u7b26":74,"\u662f\u8be5\u5c42\u7684\u7c7b\u540d":74,"\u662f\u8be5\u7f51\u7edc\u5c42\u7684":74,"\u662f\u8f93\u5165":114,"\u662f\u8fd9\u4e00\u7c7b\u7684":82,"\u662f\u8fdb\u884c\u8ba1\u7b97\u7684\u57fa\u672c\u5355\u4f4d":89,"\u662f\u9700\u8981\u4e86\u89e3\u54ea\u4e9b\u6b65\u9aa4\u62d6\u6162\u4e86\u6574\u4f53":108,"\u662fc":46,"\u662fdecoder\u7684\u6570\u636e\u8f93\u5165":113,"\u662fgoogle\u5f00\u6e90\u7684\u5bb9\u5668\u96c6\u7fa4\u7684\u8c03\u5ea6\u6846\u67b6":94,"\u662fnvidia\u6027\u80fd\u5206\u6790\u5de5\u5177":108,"\u662fpaddlepaddle\u4e2d\u5355\u5c42\u5e8f\u5217\u548c\u53cc\u5c42\u5e8f\u5217\u5b58\u50a8\u793a\u610f\u56fe":89,"\u662fpaddlepaddle\u652f\u6301\u7684\u4e00\u79cd\u4efb\u610f\u590d\u6742\u7684rnn\u5355\u5143":113,"\u662fpython\u5c01\u88c5\u7684\u7c7b\u540d":74,"\u662frnn\u72b6\u6001":114,"\u663e\u5f97\u76f8\u5bf9\u6765\u8bf4\u8f83\u4e3a\u8017\u65f6":41,"\u663e\u7136":107,"\u6682\u4e0d\u8003\u8651\u5728\u5185":81,"\u6682\u65e0":3,"\u6682\u65f6\u4e0d\u652f\u6301python3":3,"\u6682\u65f6\u4e0d\u8003\u8651\u591a\u4e2aparamet":10,"\u66b4\u9732\u8fd9\u4e2a\u6982\u5ff5\u5fc5\u8981\u51fd\u6570":46,"\u66f4\u522b\u63d0\u7b80\u5316\u95ee\u9898\u590d\u73b0\u5e26\u6765\u7684\u597d\u5904\u4e86":0,"\u66f4\u591a\u5173\u4e8edocker\u7684\u5b89\u88c5\u4e0e\u4f7f\u7528":78,"\u66f4\u591a\u7684\u8f6c\u6362\u65b9\u6cd5\u8bf7\u53c2\u8003eigen":76,"\u66f4\u597d\u5730\u5b8c\u6210\u4e00\u4e9b\u590d\u6742\u7684\u8bed\u8a00\u7406\u89e3\u4efb\u52a1":113,"\u66f4\u5feb":114,"\u66f4\u65b0":78,"\u66f4\u65b0\u53ef\u80fd\u5bfc\u81f4\u9700\u8981\u65b0\u7684\u5f00\u53d1\u5de5\u5177":0,"\u66f4\u65b0\u6a21\u5f0f":81,"\u66f4\u65b0\u7684\u6587\u6863\u4ee5pr\u7684\u5f62\u5f0f\u63d0\u4ea4\u5230github\u4e2d":77,"\u66f4\u65b0\u7f51\u7edc\u53c2\u6570\u65f6\u5e94\u7528":81,"\u66f4\u65b9\u4fbf\u7684\u8bbe\u7f6e\u65b9\u5f0f":83,"\u66f4\u8be6\u7ec6\u7684\u5b89\u88c5\u548c\u7f16\u8bd1\u65b9\u6cd5\u53c2\u8003":86,"\u66f4\u8fdb\u4e00\u6b65":113,"\u66f4\u9ad8":114,"\u66ff\u6211\u4eec\u5b8c\u6210\u4e86\u539f\u59cb\u8f93\u5165\u6570\u636e\u7684\u62c6\u5206":113,"\u6700\u4e3b\u8981\u7684\u5de5\u4f5c\u5c31\u662f\u89e3\u6790\u51fa":97,"\u6700\u540e":[1,72,74,91],"\u6700\u540e\u4e00\u4e2a":110,"\u6700\u540e\u4e00\u5c42cost\u4e2d\u8bb0\u5f55\u4e86\u795e\u7ecf\u7f51\u7edc\u7684\u6240\u6709\u62d3\u6251\u7ed3\u6784":84,"\u6700\u540e\u518d\u8c03\u7528mutabl":76,"\u6700\u540e\u5220\u9664":63,"\u6700\u540e\u6211\u4eec\u4f7f\u7528\u94fe\u5f0f\u6cd5\u5219\u8ba1\u7b97":74,"\u6700\u540e\u7684\u6267\u884c\u811a\u672c\u7684\u547d\u4ee4":0,"\u6700\u540e\u7ed9\u51fa\u7ec6\u8282\u63cf\u8ff0":104,"\u6700\u540e\u8ba1\u7b97softmax":82,"\u6700\u5c0f\u5316\u751f\u6210\u7684\u5e93\u7684\u5927\u5c0f":116,"\u6700\u5c0f\u7684ios\u90e8\u7f72\u7248\u672c":117,"\u6700\u5c11\u663e\u793a\u591a\u5c11\u4e2a\u8282\u70b9":103,"\u6700\u5e38\u89c1\u7684\u9519\u8bef\u5904\u7406\u65b9\u5f0f\u662fexcept":45,"\u6700\u65b0\u7684\u4ee3\u7801":72,"\u6700\u65b0\u7684paddlepaddl":[1,78],"\u6700\u7ec8":74,"\u6700\u7ec8\u5b9e\u73b0\u4e00\u4e2a\u5c42\u6b21\u5316\u7684\u590d\u6742rnn":113,"\u6700\u7ec8\u6211\u4eec\u53ef\u4ee5\u8c03\u7528trainer\u7684train\u65b9\u6cd5\u542f\u52a8\u8bad\u7ec3":84,"\u6700\u7ec8\u7684\u8f93\u51fa\u7ed3\u679c":113,"\u6709\u4e00\u4e9b\u5fc5\u987b\u914d\u7f6e\u7684\u53c2\u6570":[116,117,118],"\u6709\u4e24\u79cd\u65b9\u6cd5":0,"\u6709\u4e9b\u5c42\u53ef\u80fd\u9700\u8981\u9ad8\u7cbe\u5ea6\u6765\u4fdd\u8bc1\u68af\u5ea6\u68c0\u67e5\u5355\u6d4b\u6b63\u786e\u6267\u884c":74,"\u6709\u4e9b\u5c42\u6216\u8005\u6fc0\u6d3b\u9700\u8981\u505a\u5f52\u4e00\u5316\u4ee5\u4fdd\u8bc1\u5b83\u4eec\u7684\u8f93\u51fa\u7684\u548c\u662f\u4e00\u4e2a\u5e38\u6570":74,"\u6709\u4e9b\u7279\u5f81\u7684\u53d6\u503c\u8fbe\u5230\u6570\u767e\u4e07":81,"\u6709\u4eba\u7528\u865a\u62df\u673a\u6765\u7c7b\u6bd4":0,"\u6709\u4ee5\u4e0b\u5efa\u8bae":[116,117],"\u6709\u5173":111,"\u6709\u5173\u53c2\u6570\u914d\u7f6e\u7684\u8be6\u7ec6\u8bf4\u660e\u89c1":116,"\u6709\u5173\u7ebf\u6027\u56de\u5f52\u7684\u5b9e\u9645\u5e94\u7528":84,"\u6709\u52a9\u4e8e\u5728\u8bad\u7ec3\u65f6\u89c2\u5bdf\u5177\u4f53\u6570\u503c":81,"\u6709\u52a9\u4e8e\u8bca\u65ad\u5206\u5e03\u5f0f\u9519\u8bef":93,"\u6709\u591a\u96be":0,"\u6709\u6548\u63d0\u5347paddlepaddle\u5728\u82f1\u7279\u5c14\u67b6\u6784\u4e0a\u7684\u6027\u80fd":[41,42],"\u6709\u6807\u51c6\u7684":45,"\u6709\u7684\u65f6\u5019":45,"\u6709\u7684\u65f6\u5019\u7b80\u7b80\u5355\u5355\u7684\u6539\u53d8\u5c31\u80fd\u5728\u6027\u80fd\u4e0a\u4ea7\u751f\u660e\u663e\u7684\u4f18\u5316\u6548\u679c":108,"\u6709\u7684\u8bdd\u9700\u8981\u5148\u5378\u8f7d":78,"\u6709\u975e\u5e38\u5927\u7684\u5dee\u522b":107,"\u670d\u52a1\u5668\u4e4b\u95f4\u53ef\u4ee5\u901a\u8fc7\u5c40\u57df\u7f51":101,"\u672a\u6307\u5b9a\u6309\u7167double\u7cbe\u5ea6\u7f16\u8bd1":83,"\u672a\u8bbe\u7f6e":117,"\u672c\u4f8b\u4e2d\u7684\u539f\u59cb\u6570\u636e\u4e00\u5171\u670910\u4e2a\u6837\u672c":111,"\u672c\u5217\u8868\u8bf4\u660epaddlepaddle\u53d1\u7248\u4e4b\u524d\u9700\u8981\u6d4b\u8bd5\u7684\u529f\u80fd\u70b9":63,"\u672c\u5730":[3,78],"\u672c\u5730\u6d4b\u8bd5":102,"\u672c\u5730\u8bad\u7ec3":[89,102],"\u672c\u5730\u8bad\u7ec3\u4e0e\u9884\u6d4b":80,"\u672c\u5730\u8bad\u7ec3\u7684\u5b9e\u9a8c":105,"\u672c\u6559\u7a0b\u4e3b\u8981\u4ecb\u7ecd\u5e26kernel\u7684op\u5982\u4f55\u5199":75,"\u672c\u6559\u7a0b\u5c06\u6307\u5bfc\u4f60\u5982\u4f55\u5728":114,"\u672c\u6587\u4e2d\u6240\u6709\u7684\u4f8b\u5b50":111,"\u672c\u6587\u4e2d\u7684\u4f8b\u5b50\u91cc":0,"\u672c\u6587\u4e2d\u793a\u4f8b\u6240\u4f7f\u7528\u7684\u5355\u5143\u6d4b\u8bd5\u6587\u4ef6\u662f":111,"\u672c\u6587\u4ee5paddlepaddle\u7684\u53cc\u5c42rnn\u5355\u5143\u6d4b\u8bd5\u4e3a\u793a\u4f8b":111,"\u672c\u6587\u5c06\u4ecb\u7ecd\u5728kubernetes\u5bb9\u5668\u7ba1\u7406\u5e73\u53f0\u4e0a\u5feb\u901f\u6784\u5efapaddlepaddle\u5bb9\u5668\u96c6\u7fa4":97,"\u672c\u6587\u6863\u5bf9\u5173\u4e8epaddlepaddle\u7684\u4e00\u4e9b\u5e38\u89c1\u95ee\u9898\u63d0\u4f9b\u4e86\u89e3\u7b54":80,"\u672c\u6587\u6863\u5c06\u4ee5linux":116,"\u672c\u6587\u6863\u63cf\u8ff0paddl":46,"\u672c\u6587\u7684\u5c06\u4ecb\u7ecd\u5728macos\u4e0a":117,"\u672c\u6b21\u8bad\u7ec3\u6587\u4ef6\u6240\u5728\u76ee\u5f55":97,"\u672c\u6b21\u8bad\u7ec3\u7684yaml\u6587\u4ef6\u53ef\u4ee5\u5199\u6210":97,"\u672c\u6b21\u8bad\u7ec3\u8981\u6c42\u67093\u4e2apaddlepaddle\u8282\u70b9":97,"\u672c\u793a\u4f8b\u4e2d\u4f7f\u7528\u7684\u539f\u59cb\u6570\u636e\u5982\u4e0b":111,"\u672c\u793a\u4f8b\u610f\u56fe\u4f7f\u7528\u5355\u5c42rnn\u548c\u53cc\u5c42rnn\u5b9e\u73b0\u4e24\u4e2a\u5b8c\u5168\u7b49\u4ef7\u7684\u5168\u8fde\u63a5rnn":111,"\u672c\u8282\u5c06\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528paddlepaddle\u5728\u4e0d\u540c\u7684\u96c6\u7fa4\u6846\u67b6\u4e0b\u5b8c\u6210\u5206\u5e03\u5f0f\u8bad\u7ec3":92,"\u673a\u5668\u4e0a\u4ee5\u53ca":118,"\u673a\u5668\u7684\u8bbe\u5907":105,"\u673a\u5668\u7ffb\u8bd1":63,"\u6743\u91cd\u66f4\u65b0\u7684\u68af\u5ea6":103,"\u6765\u4e3a\u4e00\u4e2a":89,"\u6765\u4ee3\u66ff":72,"\u6765\u4f20\u8f93\u7f51\u7edc\u914d\u7f6e\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7f51\u7edc\u7ed3\u6784\u548c\u76f8\u5173\u53c2\u6570":90,"\u6765\u4f7f\u7528dropout":82,"\u6765\u4f7f\u7528dropout\u7684":82,"\u6765\u4fdd\u8bc1\u8bad\u7ec3\u8fc7\u7a0b\u53ef\u4ee5\u4ece\u4e2d\u95f4\u72b6\u6001\u91cd\u65b0\u542f\u52a8":10,"\u6765\u505a\u68af\u5ea6\u68c0\u67e5":74,"\u6765\u51b3\u5b9a\u662f\u5426\u5f00\u542fmkl":41,"\u6765\u5206\u6790\u6267\u884c\u6587\u4ef6":108,"\u6765\u521d\u59cb\u5316\u53c2\u6570":83,"\u6765\u542f\u52a8\u548c":0,"\u6765\u5b58\u50a8":89,"\u6765\u5b58\u50a8\u6570\u636e":[89,90],"\u6765\u5b8c\u6210\u524d\u5411\u548c\u53cd\u5411\u8ba1\u7b97":90,"\u6765\u5b8c\u6210\u7f51\u7edc\u7684\u8bad\u7ec3":84,"\u6765\u5b9a\u4e49\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":114,"\u6765\u5b9e\u73b0":42,"\u6765\u5b9e\u9645\u5b58\u50a8\u6570\u636e":[89,90],"\u6765\u5bf9\u6bd4\u5206\u6790\u4e24\u8005\u8bed\u4e49\u76f8\u540c\u7684\u539f\u56e0":111,"\u6765\u5f71\u54cdpaddlepaddle\u7684\u7f16\u8bd1\u8fc7\u7a0b":[116,117],"\u6765\u5f97\u5230\u67d0\u4e2a\u7279\u5b9a\u53c2\u6570\u7684\u68af\u5ea6\u77e9\u9635":74,"\u6765\u63cf\u8ff0\u7684":76,"\u6765\u63cf\u8ff0\u8be5op\u7684\u8f93\u5165":75,"\u6765\u63cf\u8ff0\u8f93\u5165":89,"\u6765\u642d\u5efa\u795e\u7ecf\u7f51\u7edc":84,"\u6765\u663e\u793a\u6027\u80fd\u5206\u6790\u7ed3\u679c":107,"\u6765\u67e5\u770b\u6027\u80fd\u5206\u6790\u7ed3\u679c":107,"\u6765\u6ce8\u518c\u8be5\u5c42":74,"\u6765\u6df7\u5408\u4f7f\u7528gpu\u548ccpu\u8ba1\u7b97\u7f51\u7edc\u5c42\u7684\u53c2\u6570":105,"\u6765\u6e05\u7406\u8fd9\u4e9b\u5185\u5bb9":0,"\u6765\u7279\u6307":89,"\u6765\u7279\u6307\u8c03\u7528paddlepaddl":90,"\u6765\u7279\u6307paddlepaddl":90,"\u6765\u7279\u6307paddlepaddle\u4e2d\u7684\u4e00\u7ef4\u6574\u578b\u6570\u7ec4":89,"\u6765\u7279\u6307paddlepaddle\u4e2d\u7684\u4e8c\u7ef4\u6d6e\u70b9\u578b\u77e9\u9635":89,"\u6765\u7279\u6307paddlepaddle\u4e2d\u795e\u7ecf\u7f51\u7edc\u8ba1\u7b97\u5c42\u4e00\u4e2a\u8f93\u5165":89,"\u6765\u786e\u4fdd\u628a":45,"\u6765\u786e\u5b9a\u7a00\u758f\u77e9\u9635\u7684\u5185\u5bb9":89,"\u6765\u83b7\u5f97\u8f93\u51fa\u7684\u68af\u5ea6":74,"\u6765\u8868\u793a":114,"\u6765\u8868\u793a\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":114,"\u6765\u8868\u793apaddle\u5185\u90e8\u7c7b":45,"\u6765\u89e3\u51b3\u4e0a\u9762\u7684\u95ee\u9898":81,"\u6765\u8ba1\u7b97\u68af\u5ea6":74,"\u6765\u8bb0\u5f55\u8f93\u5165":89,"\u6765\u8bb2\u89e3\u5982\u4f55\u4f7f\u7528\u53cc\u5c42rnn":111,"\u6765\u8bbe\u7f6e":83,"\u6765\u8bbf\u95ee\u7528\u6237\u81ea\u5df1\u7684\u6570\u636e":11,"\u6765\u8bfb\u53d6\u4e00\u4e2a":89,"\u6765\u8c03\u6574":72,"\u6765\u8c03\u7528":0,"\u6765\u8fd0\u884c\u6027\u80fd\u5206\u6790\u548c\u8c03\u4f18":108,"\u6765\u8fd0\u884c\u955c\u50cf":1,"\u6765\u8fdb\u884c\u8ba8\u8bba":46,"\u6765\u9884\u6d4b\u8fd9\u4e2a\u4e2d\u95f4\u7684\u8bcd":81,"\u6784\u5efa":116,"\u6784\u5efa\u597d\u5f00\u53d1\u955c\u50cf\u540e":116,"\u6784\u5efa\u7684\u955c\u50cf":0,"\u6784\u5efa\u76ee\u6807\u4e3a":117,"\u6784\u6210\u4e00\u4e2a\u5e8f\u5217":89,"\u6784\u6210\u4e86\u8f93\u51fa\u53cc\u5c42\u5e8f\u5217\u7684\u7b2ci\u4e2a":110,"\u6784\u9020":97,"\u6784\u9020\u51fd\u6570\u542b\u67092\u4e2a\u53c2\u6570":75,"\u6784\u9020\u51fd\u6570\u91cc\u901a\u8fc7":75,"\u67b6\u6784\u7684\u6a21\u62df\u5668\u5e73\u53f0":117,"\u67b6\u6784\u7684iphone\u6216\u8005ipad\u7b49\u7269\u7406\u8bbe\u5907":117,"\u67d0\u4e00\u4e2a\u795e\u7ecf\u5143\u7684\u4e00\u4e2a\u8f93\u5165\u4e3a\u4e0a\u4e00\u4e2a\u65f6\u95f4\u6b65\u7f51\u7edc\u4e2d\u67d0\u4e00\u4e2a\u795e\u7ecf\u5143\u7684\u8f93\u51fa":111,"\u67d0\u4e9b\u53c2\u6570\u53ea\u53ef\u7528\u4e8e\u7279\u5b9a\u7684\u5c42\u4e2d":102,"\u67e5\u627e\u7b54\u6848\u6216\u76f4\u63a5\u63d0":80,"\u67e5\u770b":72,"\u67e5\u770b\u5305\u7684\u5927\u5c0f":78,"\u67e5\u770b\u5f53\u524d\u72b6\u6001":72,"\u67e5\u770b\u5f53\u524d\u8fdc\u7a0b\u4ed3\u5e93\u7684\u540d\u5b57":72,"\u67e5\u770b\u6587\u4ef6\u5177\u4f53\u88ab\u4fee\u6539\u7684\u5185\u5bb9":72,"\u67e5\u770b\u662f\u5426\u662f\u5176\u4ed6\u9519\u8bef\u5f15\u53d1\u7684\u62a5\u9519":79,"\u67e5\u770bjob\u7684\u8be6\u7ec6\u60c5\u51b5":96,"\u67e5\u770blatest":63,"\u6807\u51c6":3,"\u6807\u51c6\u5dee\u4e3a":83,"\u6807\u51c6\u8868\u793apaddlepaddle\u7248\u672c\u53f7":63,"\u6807\u8bc6\u4e86\u4e00\u4e2a\u8f93\u51fa\u7684\u6587\u4ef6\u540d":107,"\u6807\u8bc6\u6027\u80fd\u5206\u6790\u7684\u7ed3\u679c\u6587\u4ef6":107,"\u6807\u8bc6\u662f\u5426\u4e3a\u8fde\u7eed\u7684batch\u8ba1\u7b97":103,"\u6807\u8bc6\u88ab\u6027\u80fd\u5206\u6790\u7684\u6e90\u6587\u4ef6":107,"\u6807\u8bc6http\u670d\u52a1\u7684\u7aef\u53e3":107,"\u6807\u8bc6http\u670d\u52a1\u7ed1\u5b9a\u7684ip":107,"\u6838\u4e00\u6837\u591a\u7684\u8fdb\u7a0b\u6765\u5e76\u884c\u7f16\u8bd1":0,"\u6838\u5fc3\u4ee3\u7801\u7f16\u8bd1\u6210\u94fe\u63a5\u5e93":87,"\u6839\u636e\u4e2a\u4eba\u7684\u9700\u6c42\u4fee\u6539\u5b9a\u5236docker\u5bb9\u5668\u6240\u6267\u884c\u7684\u811a\u672c":116,"\u6839\u636e\u4f60\u7684\u4efb\u52a1":105,"\u6839\u636e\u524d\u6587\u7684\u63cf\u8ff0":97,"\u6839\u636e\u7f51\u7edc\u914d\u7f6e\u4e2d\u7684":103,"\u6839\u636e\u8f93\u5165tensor\u7684\u5927\u5c0f\u6765\u8bbe\u7f6e\u8f93\u51fatensor\u7684\u5927\u5c0f":76,"\u6839\u636e\u8fd9\u4e9b\u53c2\u6570\u7684\u4f7f\u7528\u573a\u5408":102,"\u6839\u636e\u9ed8\u8ba4\u503c\u9012\u589e":103,"\u6839\u636e\u9ed8\u8ba4\u7aef\u53e3\u53f7\u9012\u589e":103,"\u6839\u636ejob\u5bf9\u5e94\u7684pod\u4fe1\u606f":96,"\u6839\u636eport":91,"\u683c\u5f0f":103,"\u683c\u5f0f\u4e0d\u5339\u914d\u65f6":42,"\u683c\u5f0f\u5b58\u50a8":89,"\u683c\u5f0f\u7684\u6587\u4ef6\u6765\u5b58\u653e":75,"\u6846\u67b6\u63d0\u4f9b\u7684blas\u51fd\u6570\u8fdb\u884c\u77e9\u9635\u8ba1\u7b97":117,"\u6846\u67b6\u8fdb\u884cblas\u77e9\u9635\u8ba1\u7b97":117,"\u68af\u5ea6\u4f1a\u5c31\u5730":74,"\u68af\u5ea6\u4f1a\u6709\u566a\u58f0":92,"\u68af\u5ea6\u53c2\u6570\u7684\u5206\u5757\u6570\u76ee":103,"\u68af\u5ea6\u5c31\u53ef\u4ee5\u901a\u8fc7\u8fd9\u4e2a\u65b9\u7a0b\u8ba1\u7b97\u5f97\u5230":74,"\u68af\u5ea6\u670d\u52a1\u5668\u7684\u6570\u91cf":103,"\u68af\u5ea6\u68c0\u67e5\u5355\u5143\u6d4b\u8bd5\u901a\u8fc7\u6709\u9650\u5dee\u5206\u6cd5\u6765\u9a8c\u8bc1\u4e00\u4e2a\u5c42\u7684\u68af\u5ea6":74,"\u68af\u5ea6\u68c0\u67e5\u7684\u8f93\u5165\u6570\u636e\u7684\u6279\u6b21\u5927\u5c0f":74,"\u68c0\u67e5\u70b9\u4fdd\u5b58\u7a0b\u5e8f\u6d41\u7a0b":10,"\u68c0\u67e5\u8f93\u5165\u6570\u636e\u7ef4\u5ea6":75,"\u6982\u5ff5\u4e0a":90,"\u6982\u5ff5\u4e0a\u53ef\u4ee5\u5c06":89,"\u6a21\u5757\u4e0b\u7684\u76f8\u5173":76,"\u6a21\u578b\u4e00\u76f4\u4e0d\u6536\u655b":81,"\u6a21\u578b\u4e2d\u6240\u6709\u53ef\u5b66\u4e60\u53c2\u6570\u4f1a\u88ab\u5b58\u4e3a\u4e00\u4e2a\u538b\u7f29\u6587\u4ef6":90,"\u6a21\u578b\u53c2\u6570\u68c0\u67e5\u70b9\u901a\u8fc7\u5b9a\u671f\u5411\u78c1\u76d8\u4e0a\u4fdd\u5b58\u4e00\u4efd\u5b58\u50a8\u5728paramet":10,"\u6a21\u578b\u6570\u636e\u68c0\u67e5\u70b9\u7684\u5b9e\u73b0":10,"\u6a21\u578b\u6587\u4ef6\u5c06\u88ab\u5199\u5165\u8282\u70b9":93,"\u6a21\u578b\u6765\u6307\u5bfc\u4f60\u5b8c\u6210\u8fd9\u4e9b\u6b65\u9aa4":114,"\u6a21\u578b\u6f14\u793a\u5982\u4f55\u914d\u7f6e\u590d\u6742\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u6a21\u578b":114,"\u6a21\u578b\u7684\u4ee3\u7801\u53ef\u4ee5\u5728":114,"\u6a21\u578b\u7684\u7f16\u7801\u5668\u90e8\u5206\u5982\u4e0b\u6240\u793a":114,"\u6a21\u578b\u7ed3\u6784":104,"\u6a21\u578b\u8bad\u7ec3\u7b49\u4efb\u52a1":84,"\u6a21\u578b\u914d\u7f6e":80,"\u6a21\u578b\u914d\u7f6e\u89e3\u6790":45,"\u6a21\u578b\u9884\u6d4bsdk\u9700\u8981\u5355\u72ec\u8bbe\u8ba1":88,"\u6a21\u5f0f\u4e0b\u7684\u6027\u80fd\u6d4b\u8bd5\u662f\u6ca1\u6709\u610f\u4e49\u7684":107,"\u6a2a\u5411\u62fc\u63a5":81,"\u6b21\u8fed\u4ee3\u6267\u884c\u7684\u8f6c\u6362\u6b21\u6570\u4e3a":41,"\u6b22\u8fce\u5411paddlepaddle\u793e\u533a\u53cd\u9988\u95ee\u9898":2,"\u6b22\u8fce\u901a\u8fc7":72,"\u6b63\u5728\u7b49\u5f85\u672a\u5b8c\u6210\u7684\u4efb\u52a1":78,"\u6b63\u5e38\u60c5\u51b5\u4e0b\u662f75m":78,"\u6b63\u786e\u7684\u89e3\u51b3\u65b9\u6cd5\u662f":78,"\u6b63\u8d1f\u5bf9\u9a8c\u8bc1":102,"\u6b64\u547d\u4ee4\u5c06\u5728":116,"\u6b64\u5904\u90fd\u4e3a2":111,"\u6b64\u5916":[0,72,82,116],"\u6b64\u6559\u7a0b\u4f1a\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528python\u7684cprofile\u5305":107,"\u6b64\u6559\u7a0b\u5c06\u5411\u60a8\u5206\u6b65\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528\u5185\u7f6e\u7684\u5b9a\u65f6\u5de5\u5177":108,"\u6b64\u65b9\u6cd5\u4e0d\u80fd\u83b7\u53d6":81,"\u6b64\u65f6\u53ef\u4ee5\u5728\u8c03\u7528infer\u63a5\u53e3\u65f6\u901a\u8fc7\u8bbe\u7f6e":81,"\u6b64\u65f6\u53ef\u4ee5\u8df3\u8fc7paddlepaddle\u6a21\u578b\u53c2\u6570\u6587\u4ef6\u7684\u5934\u4fe1\u606f":83,"\u6b64\u65f6\u6bcf\u4e2a\u5c0f\u5206\u652f\u7684":42,"\u6b64\u65f6master\u5c06\u8d1f\u8d23\u542f\u52a8\u4e00\u4e2a\u65b0\u7684train":10,"\u6b64\u76ee\u5f55":90,"\u6b64\u793a\u4f8b":90,"\u6b64\u7c7b\u62a5\u9519\u901a\u5e38\u662f\u7531\u4e8e\u67d0\u4e00\u4e2a\u8282\u70b9\u7684\u9519\u8bef\u5bfc\u81f4\u8fd9\u4e2a\u8282\u70b9\u7684\u8bad\u7ec3\u8fdb\u7a0b\u9000\u51fa":79,"\u6b65\u9aa4":81,"\u6bb5\u843d\u53ef\u4ee5\u770b\u4f5c\u662f\u4e00\u4e2a\u5d4c\u5957\u7684\u53cc\u5c42\u7684\u5e8f\u5217":113,"\u6bb5\u843d\u662f\u7531\u53e5\u5b50\u6784\u6210\u7684\u5e8f\u5217":89,"\u6bcf\u4e00\u4e2a":[63,90],"\u6bcf\u4e00\u4e2a\u5916\u5c42\u5e8f\u5217\u53c8\u542b\u6709\u82e5\u5e72\u4e2a\u5185\u5c42\u5e8f\u5217":89,"\u6bcf\u4e00\u4e2a\u5e8f\u5217\u5728\u6574\u4e2a":89,"\u6bcf\u4e00\u4e2a\u6587\u4ef6\u662f\u6570\u636e\u96c6\u7684\u4e00\u4e2ashard":11,"\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65":111,"\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65\u4e4b\u95f4\u7684\u795e\u7ecf\u7f51\u7edc\u5177\u6709\u4e00\u5b9a\u7684\u76f8\u5173\u6027":111,"\u6bcf\u4e00\u4e2a\u8282\u70b9\u90fd\u6709\u76f8\u540c\u7684\u65e5\u5fd7\u7ed3\u6784":93,"\u6bcf\u4e00\u4e2a\u8f93\u5165":[89,90],"\u6bcf\u4e00\u4e2alayer\u8f93\u51fa\u77e9\u9635\u7684\u9ad8\u5ea6":81,"\u6bcf\u4e00\u5217\u7684\u542b\u4e49\u662f":107,"\u6bcf\u4e00\u7ec4\u5185\u7684\u6240\u6709\u53e5\u5b50\u548clabel":111,"\u6bcf\u4e00\u884c\u5143\u7d20\u5728":89,"\u6bcf\u4e2a":42,"\u6bcf\u4e2a\u503c\u7684\u7c7b\u578b\u53ef\u4ee5\u662f\u6574\u5f62":11,"\u6bcf\u4e2a\u5143\u7d20\u662f\u4e00\u4e2a0\u5c42\u5e8f\u5217":110,"\u6bcf\u4e2a\u5143\u7d20\u662f\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":110,"\u6bcf\u4e2a\u5355\u5c42rnn":113,"\u6bcf\u4e2a\u53c2\u6570\u670d\u52a1\u5668\u53ea\u4fdd\u5b58\u6574\u4e2a\u795e\u7ecf\u7f51\u7edc\u6240\u6709\u53c2\u6570\u7684\u4e00\u90e8\u5206":92,"\u6bcf\u4e2a\u53e5\u5b50\u53c8\u662f\u5355\u8bcd\u7684\u6570\u7ec4":111,"\u6bcf\u4e2a\u53e5\u5b50\u90fd\u4ee5\u5f00\u59cb\u6807\u8bb0\u5f00\u5934":114,"\u6bcf\u4e2a\u53e5\u5b50\u90fd\u4ee5\u7ed3\u675f\u6807\u8bb0\u7ed3\u5c3e":114,"\u6bcf\u4e2a\u5b50\u5e8f\u5217\u957f\u5ea6\u53ef\u4ee5\u4e0d\u4e00\u81f4":111,"\u6bcf\u4e2a\u5c42\u5728\u5176":74,"\u6bcf\u4e2a\u6279\u6b21\u6570\u636e":103,"\u6bcf\u4e2a\u65f6\u95f4\u6b65\u4e4b\u5185\u7684\u8fd0\u7b97\u662f\u72ec\u7acb\u7684":113,"\u6bcf\u4e2a\u65f6\u95f4\u6b65\u90fd\u7528\u4e86\u4e0a\u4e00\u4e2a\u65f6\u95f4\u6b65\u7684\u8f93\u51fa\u7ed3\u679c":111,"\u6bcf\u4e2a\u6743\u91cd\u5bf9\u5e94\u4e00\u4e2a\u8f93\u5165":74,"\u6bcf\u4e2a\u6837\u672c\u7531\u4e24\u90e8\u5206\u7ec4\u6210":111,"\u6bcf\u4e2a\u6837\u672c\u95f4\u7528\u7a7a\u884c\u5206\u5f00":111,"\u6bcf\u4e2a\u6d4b\u8bd5\u4f1a\u5bf9\u6bd4paddlepaddle\u4e2dcpu\u7b97\u51fa\u7684\u7ed3\u679c\u4e0emkl":42,"\u6bcf\u4e2a\u72b6\u6001":113,"\u6bcf\u4e2a\u7ebf\u7a0b":103,"\u6bcf\u4e2a\u7ebf\u7a0b\u5206\u914d\u5230128\u4e2a\u6837\u672c\u7528\u4e8e\u8bad\u7ec3":103,"\u6bcf\u4e2a\u8bad\u7ec3\u8282\u70b9\u5fc5\u987b\u6307\u5b9a\u4e00\u4e2a\u552f\u4e00\u7684id\u53f7":103,"\u6bcf\u4e2a\u8f93\u5165\u90fd\u662f\u4e00\u4e2a":74,"\u6bcf\u4e2a\u8f93\u51fa\u8282\u70b9\u90fd\u8fde\u63a5\u5230\u6240\u6709\u7684\u8f93\u5165\u8282\u70b9\u4e0a":74,"\u6bcf\u4e2a\u90e8\u5206\u5206\u522b\u7ed9\u6bcf\u4e2atrainer\u4f7f\u7528":92,"\u6bcf\u4e2acommit\u53ea\u505a\u4e86\u5c11\u91cf\u7684\u4fee\u6539":72,"\u6bcf\u4e2adata":11,"\u6bcf\u4e2amkldnnlayer\u90fd\u5305\u542b\u7528\u4e8e\u5185\u90e8\u5b58\u50a8\u548c\u5916\u90e8\u5b58\u50a8\u7684\u4e00\u7cfb\u5217mkldnnmatrix":42,"\u6bcf\u4e2aparamet":10,"\u6bcf\u4e2apod\u5305\u542b\u4e00\u4e2apaddlepaddle\u5bb9\u5668":97,"\u6bcf\u4e2ashard\u5206\u522b\u5b58\u50a8\u5728\u5176\u4e2d\u4e00\u53f0paramet":10,"\u6bcf\u4e2atrainer\u542f\u52a8\u540e\u8bfb\u53d6\u5207\u5206\u597d\u7684\u4e00\u90e8\u5206\u6570\u636e":92,"\u6bcf\u4e2atrainer\u7684\u552f\u4e00id":91,"\u6bcf\u4e2atrainer\u8fdb\u7a0b\u9700\u8981\u80fd\u591f\u8bfb\u53d6\u5c5e\u4e8e\u81ea\u5df1\u7684\u4e00\u4efd\u6570\u636e":91,"\u6bcf\u53f0\u670d\u52a1\u5668\u5177\u6709\u96c6\u7fa4\u4e2d\u552f\u4e00\u7684ip\u5730\u5740":101,"\u6bcf\u5c42\u4e0a\u53ea\u80fd\u4fdd\u5b58\u56fa\u5b9a\u6570\u76ee\u4e2a\u6700\u597d\u7684\u72b6\u6001":103,"\u6bcf\u5c42\u4f7f\u7528\u7684gpu\u53f7\u4f9d\u8d56\u4e8e\u53c2\u6570train":105,"\u6bcf\u6279\u6b21":103,"\u6bcf\u6b21\u63d0\u4ea4\u4ee3\u7801":72,"\u6bcf\u6b21\u63d0\u4ea4\u65f6":72,"\u6bcf\u6b21\u8c03\u7528\u65f6\u5bf9\u539f\u6570\u636e\u7684\u91cd\u590dpacking\u4fbf\u6210\u4e3a\u4e86\u5197\u4f59":41,"\u6bcf\u6b21\u8c03\u7528\u7684\u8017\u65f6\u4e5f\u5f88\u957f":107,"\u6bcf\u6b21\u8f93\u51fa\u4e00\u4e2adata":11,"\u6bcf\u884c\u8868\u793a\u4e00\u4e2a\u6279\u6b21\u4e2d\u7684\u5355\u4e2a\u8f93\u5165":74,"\u6bcf\u8f6e\u4f1a\u5c06\u6570\u636e\u96c6\u4e2d\u7684\u6240\u6709\u8bad\u7ec3\u6837\u672c\u4f7f\u7528\u4e00\u6b21":103,"\u6bcf\u8f6e\u7ed3\u675f\u65f6\u5bf9\u6240\u6709\u6d4b\u8bd5\u6570\u636e\u8fdb\u884c\u6d4b\u8bd5":103,"\u6bcf\u8f6e\u90fd\u4f1a\u4fdd\u5b58\u9884\u6d4b\u7ed3\u679c":103,"\u6bcf\u8fd0\u884c\u591a\u5c11\u4e2a\u6279\u6b21\u6267\u884c\u4e00\u6b21\u7a00\u758f\u53c2\u6570\u5206\u5e03\u7684\u68c0\u67e5":103,"\u6bcf\u969410\u5206\u949f":10,"\u6bcfdot":103,"\u6bcflog":103,"\u6bcfsave":103,"\u6bcftest":103,"\u6bd4\u5982":[0,1,11,42,72,79,81],"\u6bd4\u5982\u4e00\u53e5\u8bdd\u4e2d\u7684\u6bcf\u4e00\u4e2a\u5355\u8bcd":111,"\u6bd4\u5982\u53ef\u80fd\u4f1a\u7528openmp\u6539\u8fdbsgd\u7684\u66f4\u65b0\u6027\u80fd":42,"\u6bd4\u5982\u5728":1,"\u6bd4\u5982\u5982\u679c\u8981build\u4e00\u4e2a\u4e0d\u4f9d\u8d56gpu":72,"\u6bd4\u5982\u5c06":63,"\u6bd4\u5982\u5e0c\u671b\u6700\u5c0f\u5316\u751f\u6210\u5e93\u7684\u5927\u5c0f":117,"\u6bd4\u5982\u5e0c\u671b\u6700\u5c0f\u5316\u751f\u6210\u7684\u5e93\u7684\u5927\u5c0f":118,"\u6bd4\u5982\u6bcf\u969410\u5206\u949f\u6700\u65b0\u7684\u5feb\u7167":10,"\u6bd4\u5982\u6d41\u5f0f\u6570\u636e\u5904\u7406":11,"\u6bd4\u5982\u8bbe\u7f6e\u4e00\u4e2a\u5168\u8fde\u63a5\u5c42\u7684\u53c2\u6570\u521d\u59cb\u5316\u65b9\u5f0f\u548cbias\u521d\u59cb\u5316\u65b9\u5f0f":83,"\u6bd4\u5982cento":3,"\u6bd4\u5982fpe":79,"\u6bd4\u5982ide\u914d\u7f6e\u91cc":72,"\u6bd4\u5982imagenet\u8fd9\u4e2a\u6570\u636e\u96c6\u53ef\u80fd\u88ab\u5206\u62101000\u4e2ashard":11,"\u6bd4\u5982pil\u5e93\u7b49":91,"\u6bd5\u7adf\u5355\u7ebf\u7a0b\u8c03\u8bd5\u66f4\u5bb9\u6613":107,"\u6ca1\u6709\u5fc5\u8981\u5728\u6bcf\u6b21\u524d\u5411\u4e2d\u6bcf\u4e2a\u65f6\u95f4\u6b65\u7684\u8ba1\u7b97\u65f6\u5bf9\u6743\u91cd\u8fdb\u884c\u91cd\u590d\u7684packing\u64cd\u4f5c":41,"\u6ca1\u6709\u627e\u5230\u548c\u5f53\u524d\u7cfb\u7edf\u5339\u914d\u7684paddlepaddle\u5b89\u88c5\u5305":[3,78],"\u6ca1\u6709\u8bbe\u7f6e":[116,118],"\u6ce8":[0,1,10,63,89],"\u6ce8\u518c":75,"\u6ce8\u518ccpu":75,"\u6ce8\u518clayer\u7684\u65f6\u5019\u4fdd\u8bc1":[41,42],"\u6ce8\u518cop":75,"\u6ce8\u518cop\u65f6\u7684\u7c7b\u578b\u540d":75,"\u6ce8\u610f":[0,42,74,77,81,84,90,91,97,107,114,116,117,118],"\u6ce8\u610f\u4e0a\u8ff0\u547d\u4ee4\u4e2d":97,"\u6ce8\u610f\u4e8b\u9879":89,"\u6ce8\u610f\u5230\u6211\u4eec\u5df2\u7ecf\u5047\u8bbe\u673a\u5668\u4e0a\u67094\u4e2agpu":105,"\u6ce8\u610fnode":97,"\u6ce8\u91ca":75,"\u6d41\u7a0b\u6765\u63d0\u4ea4\u4ee3\u7801":72,"\u6d4b\u8bd5":72,"\u6d4b\u8bd5\u5206\u4e3a\u6bcf\u4e2alayer":42,"\u6d4b\u8bd5\u65f6\u6307\u5b9a\u7684\u5b58\u50a8\u6a21\u578b\u5217\u8868\u7684\u6587\u4ef6":103,"\u6d4b\u8bd5\u662f":72,"\u6d4b\u8bd5\u672c\u6b21release\u7684\u6b63\u786e\u6027":63,"\u6d4b\u8bd5\u7684\u6027\u80fd\u5bf9\u6bd4\u7ed3\u679c\u4f1a\u5728":42,"\u6d4b\u8bd5\u7684\u6a21\u578b\u5305\u62ec\u4ece\u7b2cm\u8f6e\u5230\u7b2cn":105,"\u6d4b\u8bd5model_list":102,"\u6d4b\u8bd5oper":75,"\u6d4b\u8bd5save_dir":102,"\u6d6e\u70b9\u578b\u6570\u636e":11,"\u6d6e\u70b9\u578b\u7a00\u758f\u77e9\u9635":89,"\u6d6e\u70b9\u578b\u7a20\u5bc6\u77e9\u9635":89,"\u6d6e\u70b9\u5f02\u5e38\u901a\u5e38\u7684\u539f\u56e0\u662f\u6d6e\u70b9\u6570\u6ea2\u51fa":81,"\u6d6e\u70b9\u6570":89,"\u6d6e\u70b9\u6570\u5411\u91cf\u7b49":89,"\u6d6e\u70b9\u7a00\u758f\u6570\u636e":74,"\u6df1\u5165paddlepaddl":42,"\u6df1\u5ea6\u5b66\u4e60\u7b97\u6cd5\u7684\u5b9e\u73b0\u6709\u7740\u591a\u6837\u5316\u7684\u7279\u70b9":104,"\u6df7\u5408\u4ee3\u7801\u7684\u6027\u80fd\u5206\u6790\u6765\u8fdb\u884c\u8c03\u4f18":107,"\u6df7\u5408\u4ee3\u7801\u7684\u6027\u80fd\u74f6\u9888\u4e5f\u662f\u8981\u770b":107,"\u6df7\u5408\u5f53\u524d\u8bcd\u5411\u91cf\u548cattention\u52a0\u6743\u7f16\u7801\u5411\u91cf":114,"\u6dfb\u52a0":41,"\u6dfb\u52a0\u4e86\u4e00\u4e2a\u8f93\u51fa":75,"\u6dfb\u52a0\u542f\u52a8\u811a\u672c":97,"\u6dfb\u52a0\u5e8f\u5217\u4fe1\u606f":89,"\u6dfb\u52a0\u7684\u76f8\u5173\u6587\u4ef6\u548c\u76ee\u5f55\u7ed3\u6784\u5982\u4e0b":[41,42],"\u6dfb\u52a0\u8f93\u5165\u53c2\u6570":75,"\u6dfb\u52a0\u8f93\u51fa\u53c2\u6570":75,"\u6dfb\u52a0op\u7684\u6ce8\u91ca":75,"\u6e05\u7406\u548c\u7ed3\u675f":90,"\u6e05\u7406\u6389\u8001\u65e7\u7684paddlepaddle\u5b89\u88c5\u5305":78,"\u6e90\u4ee3\u7801\u683c\u5f0f":72,"\u6e90\u5e8f\u5217":114,"\u6e90\u7801\u4e2d\u6784\u5efa\u7528\u4e8e\u7f16\u8bd1paddlepaddle\u7684docker\u955c\u50cf":0,"\u6e90\u7801\u6811\u6839\u76ee\u5f55":0,"\u6f5c\u5728\u4f1a\u5f15\u8d77\u672a\u5b9a\u4e49\u884c\u4e3a":89,"\u6fc0\u6d3b":74,"\u6fc0\u6d3b\u51fd\u6570\u662f\u72ec\u7acb\u4e8e":42,"\u6fc0\u6d3b\u65b9\u7a0b":74,"\u6fc0\u6d3b\u7684\u7c7b\u578b":74,"\u70b9\u51fb":[3,63],"\u70b9\u51fb\u8fd9\u91cc":77,"\u7136\u540e":[93,108],"\u7136\u540e\u4e0b\u8f7d\u4f18\u5316\u66f4\u65b0\u540e\u7684\u795e\u7ecf\u7f51\u7edc\u53c2\u6570":92,"\u7136\u540e\u4ea4\u7ed9step\u51fd\u6570":113,"\u7136\u540e\u4f7f\u7528":117,"\u7136\u540e\u4f7f\u7528resize\u63a5\u53e3\u8bbe\u7f6etensor\u7684\u5927\u5c0f":76,"\u7136\u540e\u5355\u51fb":72,"\u7136\u540e\u53ef\u4ee5\u4ecehead\u8282\u70b9ssh\u65e0\u5bc6\u7801\u767b\u5f55\u5230openmpi\u7684\u6bcf\u4e2a\u8282\u70b9\u4e0a":98,"\u7136\u540e\u53ef\u4ee5\u4f7f\u7528\u547d\u4ee4\u884c\u5de5\u5177\u521b\u5efajob":97,"\u7136\u540e\u5728\u4e0b\u4e00\u4e2a\u65f6\u95f4\u6b65\u8f93\u5165\u7ed9\u53e6\u4e00\u4e2a\u795e\u7ecf\u5143":111,"\u7136\u540e\u5728\u524d\u5411":41,"\u7136\u540e\u5728\u6d4f\u89c8\u5668\u4e2d\u8f93\u5165\u4ee5\u4e0b\u7f51\u5740":1,"\u7136\u540e\u5728dataprovider\u91cc\u9762\u6839\u636e\u8be5\u5730\u5740\u52a0\u8f7d\u5b57\u5178":83,"\u7136\u540e\u5728etcd\u7684":10,"\u7136\u540e\u5b89\u88c5paddle\u7684python\u73af\u5883":78,"\u7136\u540e\u5b9a\u4e49":114,"\u7136\u540e\u5c06\u6784\u5efa\u6210\u529f\u7684\u955c\u50cf\u4e0a\u4f20\u5230\u955c\u50cf\u4ed3\u5e93":97,"\u7136\u540e\u5c06\u8fd9\u4e9blayer\u7684\u53c2\u6570":82,"\u7136\u540e\u5c31\u53ef\u4ee5\u5e76\u53d1\u5199\u5165\u591a\u4e2achunk":27,"\u7136\u540e\u6240\u6709\u7528":72,"\u7136\u540e\u624d\u80fd\u4f7f\u7528pfsclient":27,"\u7136\u540e\u6253\u5370\u8f93\u51fa":84,"\u7136\u540e\u6309\u7167\u4e0a\u8ff0\u7684\u65b9\u6cd5":63,"\u7136\u540e\u63d0\u4ea4\u65b0\u6dfb\u52a0\u7684":72,"\u7136\u540e\u70b9\u51fb":[63,72],"\u7136\u540e\u7533\u660e\u4e00\u4e2a\u5b58\u50a8\u5377":97,"\u7136\u540e\u89c2\u5bdf\u5230\u8f93\u51fa\u7684\u53d8\u5316\u4e3a":74,"\u7136\u540e\u901a\u8fc7\u51fd\u6570":97,"\u7136\u540e\u901a\u8fc7\u81ea\u8eab\u7684ip\u5730\u5740\u5728":97,"\u7136\u540e\u91cd\u65b0cmake\u5373\u53ef":78,"\u7136\u800c":[103,114],"\u7248\u672c":[0,3,117],"\u7248\u672c\u4e3acpu_avx_mkl":1,"\u7248\u672c\u4e3acpu_avx_openbla":[3,86],"\u7248\u672c\u5206\u652f":63,"\u7248\u672c\u53f7":63,"\u7248\u672c\u53f7\u5bf9\u5e94\u7684tag\u5373\u53ef":63,"\u7248\u672c\u53f7rc":63,"\u7248\u672c\u5728":72,"\u7248\u672c\u8bf4\u660e":3,"\u7248\u672cfork\u51fa\u81ea\u5df1\u7684\u529f\u80fd\u5206\u652f":63,"\u7279\u522b\u662f\u5728lstm\u7b49rnn\u4e2d":81,"\u7279\u6307":90,"\u7279\u6709\u7684\u8bbe\u5907id":42,"\u72ec\u7acb\u5de5\u5177\u94fe":116,"\u72ec\u7acb\u5de5\u5177\u94fe\u6240\u5728\u7684\u7edd\u5bf9\u8def\u5f84":116,"\u73af\u5883\u51c6\u5907":92,"\u73af\u5883\u53d8\u91cf":91,"\u73af\u5883\u53d8\u91cf\u4e2d":87,"\u73af\u5883\u53d8\u91cf\u6765\u6307\u5b9a\u7279\u5b9a\u7684gpu":81,"\u73b0\u9636\u6bb5\u7684\u4f18\u5316\u4e3b\u8981\u9488\u5bf9":41,"\u73b0\u9636\u6bb5paddle\u6709\u4e00\u4e2a\u95ee\u9898\u662f":45,"\u7406\u89e3":0,"\u7406\u89e3\u4e3a\u4e00\u4e2a\u4e00\u7ef4\u7684\u6574\u578b\u6570\u7ec4":89,"\u751a\u81f3\u80fd\u89e3\u91ca\u4e3a\u4ec0\u4e48\u67d0\u4e2a\u64cd\u4f5c\u82b1\u4e86\u5f88\u957f\u65f6\u95f4":108,"\u751f\u4ea7\u73af\u5883\u4e2d\u7684\u8bad\u7ec3\u6570\u636e\u96c6\u901a\u5e38\u4f53\u79ef\u5f88\u5927":11,"\u751f\u4ea7\u73af\u5883\u7684\u65e5\u5fd7\u6570\u636e\u4f1a\u901a\u8fc7\u5b9e\u65f6\u6d41\u7684\u65b9\u5f0f":11,"\u751f\u4ea7\u955c\u50cf":72,"\u751f\u6210":97,"\u751f\u6210\u5404\u79cd\u8bed\u8a00\u7684\u7ed1\u5b9a\u4ee3\u7801":45,"\u751f\u6210\u540e\u7684\u6587\u6863\u5206\u522b\u5b58\u50a8\u5728\u7f16\u8bd1\u76ee\u5f55\u7684":77,"\u751f\u6210\u5e8f\u5217\u7684\u6700\u5927\u957f\u5ea6":114,"\u751f\u6210\u6587\u6863":45,"\u751f\u6210\u7684":11,"\u751f\u6210\u7684\u6027\u80fd\u5206\u6790\u6587\u4ef6\u4e3a":107,"\u751f\u6210\u7684\u6570\u636e\u5c06\u4f1a\u5b58\u50a8\u5728\u8fd9\u4e2avolume\u4e0b":97,"\u751f\u6210\u7684\u6570\u636e\u7f13\u5b58\u5728\u5185\u5b58\u91cc":81,"\u751f\u6210\u7ed9\u5b9a":11,"\u751f\u6210\u7f51\u7edc\u5c42\u914d\u7f6e":74,"\u751f\u6210\u81ea\u5df1\u76ee\u5f55\u4e0b\u7684\u4ed3\u5e93":72,"\u751f\u6210\u8c03\u8bd5\u4fe1\u606f":107,"\u751f\u6210\u968f\u673a\u7684\u8f93\u5165\u6570\u636e":75,"\u751f\u6210api\u6587\u6863":45,"\u751f\u6210pfsclient\u548cpfsserver\u7684\u6846\u67b6\u90e8\u5206":27,"\u751f\u6210python\u6027\u80fd\u5206\u6790\u7684\u547d\u4ee4\u5982\u4e0b":107,"\u7528":27,"\u7528\u4e8e\u521d\u59cb\u5316\u53c2\u6570\u548c\u8bbe\u7f6e":74,"\u7528\u4e8e\u5c06\u53c2\u6570\u4f20\u9012\u7ed9\u7f51\u7edc\u914d\u7f6e":105,"\u7528\u4e8e\u6307\u5b9a\u5176\u8981\u5173\u8054\u7684layer":82,"\u7528\u4e8e\u6307\u5b9a\u7f51\u7edc\u914d\u7f6e\u6587\u4ef6":103,"\u7528\u4e8e\u6ce8\u518c\u6ca1\u6709\u53cd\u5411\u7684op":75,"\u7528\u4e8e\u6d4b\u8bd5\u548c\u5bf9\u6bd4\u5728\u4f7f\u7528mkl":42,"\u7528\u4e8e\u7a00\u758f\u7c7b\u578b\u53c2\u6570\u901a\u4fe1\u7684\u7aef\u53e3\u4e2a\u6570":91,"\u7528\u4e8e\u7a00\u758f\u8bad\u7ec3\u4e2d":103,"\u7528\u4e8e\u7ba1\u7406mkl":42,"\u7528\u4e8e\u83b7\u53d6\u7279\u5b9alayer\u4e0a\u4e00\u65f6\u95f4\u6b65\u7684\u8f93\u51fa":82,"\u7528\u4e8e\u89e3\u51b3\u4e0a\u8ff0\u95ee\u9898":88,"\u7528\u4e8e\u8ba1\u7b97\u7f16\u7801\u5411\u91cf\u7684\u52a0\u6743\u548c":114,"\u7528\u4e8e\u8bad\u7ec3\u795e\u7ecf\u7f51\u7edc\u7684\u6570\u636e":92,"\u7528\u4e8e\u9009\u62e9\u662f\u5426\u4f7f\u7528\u76f8\u5173\u529f\u80fd":41,"\u7528\u4e8e\u9009\u62e9\u662f\u5426\u4f7f\u7528mkl":42,"\u7528\u4e8emkl":[41,42],"\u7528\u53cc\u5411\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7f16\u7801":114,"\u7528\u591a\u5bf9\u6548\u679c\u5b8c\u5168\u76f8\u540c\u7684":111,"\u7528\u6237\u4e00\u822c\u901a\u8fc7\u8c03\u7528":107,"\u7528\u6237\u4e0a\u4f20\u6570\u636e\u540e":11,"\u7528\u6237\u4e5f\u53ef\u4ee5\u4e0a\u4f20label":11,"\u7528\u6237\u4e5f\u53ef\u4ee5\u4f7f\u7528paddlepaddle\u63d0\u4f9b\u7684\u5b98\u65b9\u5f00\u53d1\u955c\u50cf":116,"\u7528\u6237\u4ea6\u53ef\u4ee5\u901a\u8fc7\u624b\u52a8\u8bbe\u7f6e":116,"\u7528\u6237\u4eceapp":117,"\u7528\u6237\u53ea\u9700\u5b9a\u4e49rnn\u5728\u4e00\u4e2a\u65f6\u95f4\u6b65\u5185\u5b8c\u6210\u7684\u8ba1\u7b97":113,"\u7528\u6237\u53ef\u4ee5\u5206\u522b\u67e5\u770b\u6700\u65b0\u7684":77,"\u7528\u6237\u53ef\u4ee5\u53c2\u8003\u4e0b\u6587":116,"\u7528\u6237\u53ef\u4ee5\u53c2\u8003sphinx\u6559\u7a0b\u8fdb\u884c\u4e66\u5199":77,"\u7528\u6237\u53ef\u4ee5\u5b89\u5168\u7684\u91ca\u653e\u67d0\u4e2ac":46,"\u7528\u6237\u53ef\u4ee5\u628a\u81ea\u5df1\u7684\u6570\u636e\u5206\u4eab\u7ed9\u522b\u4eba":11,"\u7528\u6237\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528\u8fd9\u4e2a\u52a8\u6001\u5e93\u6765\u5f15\u5165paddl":46,"\u7528\u6237\u53ef\u4ee5\u81ea\u5b9a\u4e49beam":103,"\u7528\u6237\u53ef\u4ee5\u8bbe\u7f6e":105,"\u7528\u6237\u53ef\u5728\u81ea\u5df1\u719f\u6089\u7684\u5f00\u53d1\u5e73\u53f0\u4e0a\u7f16\u8bd1android\u5e73\u53f0\u4e0a\u9002\u7528\u7684paddlepaddle\u5e93":116,"\u7528\u6237\u53ef\u5728\u8c03\u7528cmake\u7684\u65f6\u5019\u8bbe\u7f6e\u5b83\u4eec":0,"\u7528\u6237\u53ef\u5c06":116,"\u7528\u6237\u53ef\u5c06\u5408\u6210\u7684fat\u5e93\u7528\u4e8e\u6df1\u5ea6\u5b66\u4e60\u76f8\u5173\u7684io":117,"\u7528\u6237\u53ef\u6839\u636e\u81ea\u5df1\u7684\u7f16\u8bd1\u76ee\u6807\u67b6\u6784":116,"\u7528\u6237\u53ef\u81ea\u884c\u524d\u5f80\u4e0b\u8f7d\u9884\u7f16\u8bd1\u597d\u7684\u7248\u672c":116,"\u7528\u6237\u53ef\u901a\u8fc7\u5982\u4e0b\u4e24\u79cd\u65b9\u5f0f":116,"\u7528\u6237\u5728\u4f7f\u7528\u8fd9\u4e00\u7c7brecurr":82,"\u7528\u6237\u5728\u4f7f\u7528paddlepaddl":78,"\u7528\u6237\u5728\u672c\u5730\u8f6c\u6362\u597d\u518d\u4e0a\u4f20":11,"\u7528\u6237\u5c06\u53c2\u6570\u8f7d\u5165":83,"\u7528\u6237\u5c06\u914d\u7f6e\u4e0e\u8bad\u7ec3\u6570\u636e\u5207\u5206\u597d\u653e\u5728\u5206\u5e03\u5f0f\u6587\u4ef6\u7cfb\u7edf\u9884\u5148\u5206\u914d\u597d\u7684\u76ee\u5f55\u4e2d":97,"\u7528\u6237\u5f3a\u5236\u6307\u5b9a\u7279\u5b9a\u7684python\u7248\u672c":78,"\u7528\u6237\u6587\u4ef6\u53ef\u80fd\u662f\u6bd4\u8f83\u5927\u7684":27,"\u7528\u6237\u7684\u96c6\u7fa4\u73af\u5883\u4e0d\u5c3d\u76f8\u540c":94,"\u7528\u6237\u8fd8\u53ef\u6839\u636e\u81ea\u5df1\u7684\u9700\u6c42\u8bbe\u7f6e\u5176\u4ed6\u7f16\u8bd1\u53c2\u6570":[116,117,118],"\u7528\u6237\u901a\u8fc7\u53c2\u6570":[82,83],"\u7528\u6237\u901a\u8fc7c":46,"\u7528\u6237\u9700\u8981\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d\u6307\u5b9a":105,"\u7528\u6237\u9700\u8981\u5728cmake\u65f6\u624b\u52a8\u8bbe\u7f6e\u8fd9\u4e9b\u503c":[116,118],"\u7528\u6237\u9700\u8981\u6307\u5b9a\u672c\u673a\u4e0apython\u7684\u8def\u5f84":78,"\u7528\u6237\u9700\u8981\u63d0\u524d\u51c6\u5907\u597d\u4ea4\u53c9\u7f16\u8bd1\u73af\u5883":116,"\u7528\u6765\u4ece\u53c2\u6570\u670d\u52a1\u5668\u9884\u53d6\u53c2\u6570\u77e9\u9635\u76f8\u5e94\u7684\u884c":74,"\u7528\u6765\u5b58\u50a8\u672c\u6b21\u6027\u80fd\u5206\u6790\u7684\u7ed3\u679c":107,"\u7528\u8fd9\u4e2a\u955c\u50cf\u521b\u5efa\u7684\u5bb9\u5668\u9700\u8981\u6709\u4ee5\u4e0b\u4e24\u4e2a\u529f\u80fd":97,"\u7528web\u6d4f\u89c8\u5668\u8bbf\u95ee\u5bf9\u5e94\u7f51\u5740":107,"\u7531":[82,89,113],"\u7531\u4e8e":87,"\u7531\u4e8e\u5728\u73b0\u6709\u7684\u67d0\u4e9b\u60c5\u51b5\u4e0b":41,"\u7531\u4e8e\u5b83\u5185\u90e8\u5305\u542b\u4e86\u6bcf\u7ec4\u6570\u636e\u4e2d\u7684\u6240\u6709\u53e5\u5b50":111,"\u7531\u4e8e\u5bf9parameters\u7684\u66f4\u65b0\u9700\u8981\u83b7\u53d6parameters\u5185\u5b58\u7684":10,"\u7531\u4e8e\u6211\u4eec\u60f3\u8981\u7684\u53d8\u6362\u662f\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217":111,"\u7531\u4e8e\u6211\u4eec\u652f\u6301\u8bad\u7ec3\u6570\u636e\u6709\u4e0d\u540c\u7684\u6279\u6b21\u5927\u5c0f":74,"\u7531\u4e8e\u96c6\u7fa4\u4e2d\u540c\u65f6\u5b58\u5728\u4e24\u53f0\u673a\u5668\u6545\u969c\u7684\u6982\u7387\u6781\u4f4e":10,"\u7531\u4e8earm64\u67b6\u6784\u8981\u6c42android":116,"\u7531\u4e8ec":45,"\u7531\u4e8echunk\u6bd4\u8f83\u5c0f":27,"\u7531\u4e8eeigen":76,"\u7531\u4e8emkl":42,"\u7531\u4e8epypi":63,"\u7531\u4e8estep":113,"\u7531\u4e8etensor\u7684rank\u662f\u6a21\u677f\u53c2\u6570":76,"\u7531\u5206\u652f\u5904\u7684layer\u8d1f\u8d23\u6c42\u548c":42,"\u7531\u8bcd\u8bed\u6784\u6210\u7684\u53e5\u5b50":110,"\u7531\u94fe\u63a5\u65b9\u5f0f\u51b3\u5b9a":87,"\u7533\u8bf7\u7528\u6237\u7a7a\u95f4":27,"\u767b\u5f55\u5230head\u8282\u70b9":98,"\u7684":[3,72,76,89,90,91,93,97,117],"\u7684\u4e00\u4e2a\u5b50\u96c6":42,"\u7684\u4e00\u4e2a\u7b80\u5355\u8c03\u7528\u5982\u4e0b":113,"\u7684\u4e3a0":103,"\u7684\u4efb\u4e00\u4e00\u79cd":81,"\u7684\u4f5c\u7528\u662f\u5ef6\u8fdf\u5206\u914d\u5185\u5b58":76,"\u7684\u4f7f\u7528\u793a\u4f8b\u5982\u4e0b":110,"\u7684\u4fe1\u606f":42,"\u7684\u503c":[116,117,118],"\u7684\u503c\u81ea\u52a8\u63a8\u5bfc\u5f97\u5230":116,"\u7684\u504f\u7f6e\u5411\u91cf":74,"\u7684\u5171\u4eab\u5df2\u7ecf\u52a0\u8f7d\u7684\u9884\u6d4b\u6a21\u578b":90,"\u7684\u5177\u4f53\u8ba1\u7b97\u903b\u8f91":75,"\u7684\u5185\u5b58":81,"\u7684\u5185\u5bb9\u6765\u5b9a\u5236imag":97,"\u7684\u5185\u6838block\u4f7f\u7528\u60c5\u51b5":108,"\u7684\u5355\u5143\u6d4b\u8bd5":75,"\u7684\u5355\u5143\u6d4b\u8bd5\u548c\u7b80\u5355\u7f51\u7edc\u7684\u6574\u4f53\u6d4b\u8bd5":42,"\u7684\u53c2\u6570\u4f7f\u4e4b\u652f\u6301\u5f02\u6b65sgd\u66f4\u65b0":91,"\u7684\u53cd\u5411\u4f20\u64ad\u5c06\u4f1a\u6253\u5370\u65e5\u5fd7\u4fe1\u606f":103,"\u7684\u53d8\u6362\u77e9\u9635":74,"\u7684\u540d\u79f0\u76f8\u540c":114,"\u7684\u5411\u91cf":74,"\u7684\u542f\u52a8\u53c2\u6570":97,"\u7684\u542f\u52a8\u53c2\u6570\u5e76\u6267\u884c\u8fdb\u7a0b":97,"\u7684\u547d\u4ee4\u548c\u4e00\u822c\u7684":107,"\u7684\u547d\u540d\u98ce\u683c\u5e76\u4e0d\u80fd\u9002\u5e94\u5176\u4ed6\u7b2c\u4e09\u65b9\u8bed\u8a00":45,"\u7684\u5730\u65b9":72,"\u7684\u5747\u5300\u5206\u5e03":83,"\u7684\u57fa\u672c\u903b\u8f91":42,"\u7684\u591a\u79cd\u5b89\u88c5\u65b9\u5f0f":101,"\u7684\u5934\u6587\u4ef6":45,"\u7684\u5b50\u7c7b\u53ea\u9700\u8981\u4f7f\u7528\u5185\u90e8\u5b58\u50a8\u5c31\u53ef\u4ee5\u4e86":42,"\u7684\u5b9e\u73b0":75,"\u7684\u5de5\u4f5c\u6d41\u7a0b\u5982\u56fe1\u6240\u793a":90,"\u7684\u5e73\u5747\u503c":110,"\u7684\u5e8f\u5217":89,"\u7684\u5e8f\u5217\u5f62\u72b6\u4e00\u81f4":111,"\u7684\u5f00\u53d1\u5de5\u4f5c\u90fd\u5e94\u8be5\u5728\u4e00\u4e2a\u65b0\u7684\u5206\u652f\u4e0a\u5b8c\u6210":72,"\u7684\u5f00\u53d1\u6d41\u7a0b":0,"\u7684\u5f00\u59cb\u8bf7\u52a0\u4e0a\u5b8f\u5b9a\u4e49":75,"\u7684\u6027\u80fd\u5206\u6790\u4e0e\u8c03\u4f18\u5206\u4e3a\u4e24\u4e2a\u90e8\u5206":107,"\u7684\u6027\u80fd\u5206\u6790\u5de5\u5177\u975e\u5e38\u591a":107,"\u7684\u6027\u80fd\u6709\u95ee\u9898":107,"\u7684\u60c5\u51b5\u4e0b":41,"\u7684\u63a5\u53e3\u6837\u5f0f":45,"\u7684\u63a5\u53e3\u8bf7\u67e5\u770b":89,"\u7684\u63cf\u8ff0\u8bf4\u660e\u4e2d":72,"\u7684\u64cd\u4f5c":76,"\u7684\u6570\u636e\u6d41\u56fe":11,"\u7684\u6570\u76ee\u4e00\u81f4":110,"\u7684\u6587\u4ef6\u4e5f\u5e26\u5230\u65b0\u5206\u652f\u4e0a":72,"\u7684\u65b9\u7a0b":74,"\u7684\u65f6\u5019":42,"\u7684\u65f6\u95f4\u6b65\u4fe1\u606f\u6210\u6b63\u6bd4":81,"\u7684\u66f4\u8be6\u7ec6\u51c6\u786e\u7684\u5b9a\u4e49":111,"\u7684\u6700\u5c0f\u503c":103,"\u7684\u6700\u65b0\u4ee3\u7801\u5e76\u66f4\u65b0\u5f53\u524d\u5206\u652f":72,"\u7684\u6784\u9020\u51fd\u6570":75,"\u7684\u67b6\u6784\u7684\u793a\u4f8b":114,"\u7684\u6837\u5f0f":72,"\u7684\u6838\u5fc3\u662f\u8bbe\u8ba1step\u51fd\u6570\u7684\u8ba1\u7b97\u903b\u8f91":113,"\u7684\u6839\u76ee\u5f55":117,"\u7684\u683c\u5f0f\u59cb\u7ec8\u662f":42,"\u7684\u683c\u5f0f\u5b58\u50a8":42,"\u7684\u6982\u5ff5":42,"\u7684\u6bb5\u843d\u5b9a\u4e49\u4e3a\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":113,"\u7684\u6bcf\u4e2a\u8fdb\u7a0b\u90fd\u53ef\u4ee5\u4ececeph\u8bfb\u53d6\u6570\u636e":96,"\u7684\u6e90\u7801\u4ee5\u53ca\u751f\u6210\u6587\u6863\u9700\u8981\u591a\u79cd\u5f00\u53d1\u5de5\u5177":72,"\u7684\u6e90\u7801\u91cc\u4f7f\u7528\u4e86":45,"\u7684\u7248\u672c":[63,118],"\u7684\u72b6\u6001":113,"\u7684\u72ec\u7acb\u5de5\u5177\u94fe":116,"\u7684\u77e9\u9635":[74,81],"\u7684\u7a20\u5bc6\u5411\u91cf\u4f5c\u4e3a\u8f93\u5165":74,"\u7684\u7a20\u5bc6\u77e9\u9635":89,"\u7684\u7a20\u5bc6\u77e9\u9635\u662f\u4e00\u4e2a\u7531":89,"\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570":90,"\u7684\u7b2ci\u4e2a\u503c":74,"\u7684\u7b2cj\u4e2a\u503c":74,"\u7684\u7cfb\u7edf":0,"\u7684\u7ed3\u679c":41,"\u7684\u7f16\u5199":91,"\u7684\u7f16\u8bd1\u5de5\u5177\u94fe":116,"\u7684\u7f29\u5199":27,"\u7684\u7f51\u7edc\u6a21\u578b":41,"\u7684\u89c4\u8303":45,"\u7684\u89d2\u5ea6":11,"\u7684\u8ba1\u7b97\u4ee3\u7801":76,"\u7684\u8ba1\u7b97\u8fc7\u7a0b\u4e66\u5199\u66f4\u52a0\u7b80\u5355":75,"\u7684\u8bdd":81,"\u7684\u8be6\u7ec6\u4fe1\u606f":107,"\u7684\u8f93\u5165":113,"\u7684\u8f93\u51fa":[81,108],"\u7684\u8f93\u51fa\u4fe1\u606f\u5165\u624b\u662f\u4e2a\u4e0d\u9519\u7684\u9009\u62e9":108,"\u7684\u8f93\u51fa\u51fd\u6570\u8fd4\u56de\u7684\u662f\u4e0b\u4e00\u4e2a\u65f6\u523b\u8f93\u51fa\u8bcd\u7684":114,"\u7684\u8f93\u51fa\u683c\u5f0f":111,"\u7684\u8f93\u51fa\u88ab\u7528\u4f5c":114,"\u7684\u8f93\u51fab\u662f\u4e00\u4e2a":81,"\u7684\u8fd0\u884c\u73af\u5883":0,"\u7684\u8fdc\u7a0b\u4ed3\u5e93\u7684\u540d\u5b57":72,"\u7684\u914d\u7f6e\u5199\u5230\u914d\u7f6e\u6587\u4ef6\u4e2d":11,"\u7684\u96c6\u88c5\u7bb1\u6280\u672f":0,"\u7684\u9875\u9762\u5220\u9664\u8fdc\u7a0b\u4ed3\u5e93\u7684\u5206\u652f":72,"\u7684cpu":75,"\u7684docker\u955c\u50cf":1,"\u7684flag":[41,42],"\u7684linux\u670d\u52a1\u5668\u7ec4\u6210":101,"\u7684paddlepaddle\u5e93":116,"\u7684vanilla":41,"\u76d1\u542c\u7684\u7aef\u53e3\u4e2a\u6570":91,"\u76ee\u524d":113,"\u76ee\u524d\u4f7f\u7528":72,"\u76ee\u524d\u53ea\u8003\u8651":42,"\u76ee\u524d\u53ea\u8003\u8651\u52a8\u6001\u6269\u5bb9trainer\u6570\u91cf":10,"\u76ee\u524d\u5728paddlepaddle\u4e2d":42,"\u76ee\u524d\u5728paddlepaddle\u4e2d\u6570\u636e\u90fd\u662f\u4ee5":42,"\u76ee\u524d\u5d4c\u5165python\u89e3\u91ca\u5668":45,"\u76ee\u524d\u5fc5\u987b\u8bbe\u7f6e\u6210":118,"\u76ee\u524d\u6211\u4eec\u7528cephfs\u6765\u642d\u5efa":27,"\u76ee\u524d\u63d0\u4f9b\u4e09\u79cd\u94fe\u63a5\u65b9\u5f0f":87,"\u76ee\u524d\u652f\u6301":116,"\u76ee\u524d\u652f\u6301\u4e24\u79cd":110,"\u76ee\u524d\u652f\u6301cento":86,"\u76ee\u524d\u652f\u6301fail":103,"\u76ee\u524d\u7684\u4f18\u5316":42,"\u76ee\u524d\u8be5\u53c2\u6570\u4ec5\u7528\u4e8eaucvalidationlayer\u548cpnpairvalidationlayer\u5c42":103,"\u76ee\u524d\u8fd8\u672a\u652f\u6301":113,"\u76ee\u524dpaddle\u7684\u8fdb\u7a0b\u6a21\u578b\u662fc":45,"\u76ee\u524dpaddlepaddle\u7684develop\u5206\u652f\u7684\u6587\u6863\u662f\u81ea\u52a8\u89e6\u53d1\u66f4\u65b0\u7684":77,"\u76ee\u524dpaddlepaddle\u91c7\u7528\u4e86":41,"\u76ee\u5f55":[0,1,93,96,97,116,117,118],"\u76ee\u5f55\u4e0b":[46,74,93],"\u76ee\u5f55\u4e0b\u5bf9\u5e94\u7684\u5730\u65b9":42,"\u76ee\u5f55\u4e0b\u65b0\u589e\u7684":75,"\u76ee\u5f55\u4e0b\u6700\u65b0\u7684":117,"\u76ee\u5f55\u4e0b\u7684\u4ee3\u7801\u793a\u4f8b":90,"\u76ee\u5f55\u4e0b\u7684\u751f\u6210\u6587\u4ef6\u7528\u4e8e\u6df1\u5ea6\u5b66\u4e60\u76f8\u5173android":116,"\u76ee\u5f55\u4e0b\u7684python\u5305":78,"\u76ee\u5f55\u4e2d":[87,90,93],"\u76ee\u5f55\u4e2d\u4f1a\u5305\u542b":[116,118],"\u76ee\u5f55\u4e2d\u4f1a\u5305\u542b\u4ee5\u4e0b\u5185\u5bb9":117,"\u76ee\u5f55\u4e2d\u7684":108,"\u76ee\u5f55\u4e2dpaddl":97,"\u76ee\u5f55\u548c":[116,117,118],"\u76ee\u5f55\u5c31\u6210\u4e3a\u4e86\u5171\u4eab\u5b58\u50a8":97,"\u76ee\u5f55\u751f\u6210\u4e00\u5957\u72ec\u7acb\u7f16\u8bd1\u5de5\u5177\u94fe":116,"\u76ee\u5f55\u91cc\u627e\u5230\u4ea4\u53c9\u7f16\u8bd1\u5668":118,"\u76ee\u6807\u5411\u91cf":114,"\u76ee\u6807\u5de5\u5177\u94fe":116,"\u76ee\u6807\u673a\u7248protobuf\u5e93":118,"\u76ee\u6807\u67b6\u6784":117,"\u76ee\u6807\u67b6\u6784abi":116,"\u76f4\u5230\u8bad\u7ec3\u6536\u655b\u4e3a\u6b62":83,"\u76f4\u63a5\u4f7f\u7528c\u8bed\u8a00\u7684":45,"\u76f4\u63a5\u5220\u9664\u8fd9\u4e2a\u53c2\u6570\u5373\u53ef":46,"\u76f4\u63a5\u5347\u7ea7\u5230\u66f4\u65b0\u7684\u7248\u672c":0,"\u76f4\u63a5\u5bfc\u51fa\u5230c\u7684\u63a5\u53e3\u6bd4\u8f83\u56f0\u96be":45,"\u76f4\u63a5\u8c03\u7528\u76f8\u5e94\u63a5\u53e3\u5373\u53ef":75,"\u76f4\u63a5\u8fd0\u884c":1,"\u76f8\u5173\u5c42":41,"\u76f8\u540c\u540d\u5b57\u7684\u53c2\u6570":83,"\u76f8\u6bd4":75,"\u76f8\u6bd4\u4e8e\u6a21\u578b\u8bad\u7ec3":88,"\u770b\u5f53\u524dmpi\u96c6\u7fa4\u662f\u5426\u652f\u6301resourc":79,"\u77a7":86,"\u77e9\u9635":102,"\u77e9\u9635\u4e2d\u6bcf\u4e2a\u5143\u7d20\u7684\u503c\u968f\u673a\u751f\u6210":89,"\u77e9\u9635\u4e58\u6cd5\u7684\u516c\u5f0f":75,"\u77e9\u9635\u5927\u5c0f\u662f":41,"\u77e9\u9635\u662f\u5426\u662f\u4e00\u4e2a\u5e8f\u5217":89,"\u77e9\u9635\u7684\u9ad8\u5ea6":89,"\u77e9\u9635\u91cc\u7684\u5143\u7d20\u662f\u6d6e\u70b9\u6570":89,"\u786e\u4fdd\u7f16\u8bd1\u5668\u9009\u9879":72,"\u78c1\u76d8\u4e0d\u591f":0,"\u78c1\u76d8\u7a7a\u95f4\u4e0d\u8db3\u7b49":79,"\u793a\u4f8b":[81,83,90],"\u793a\u4f8b3\u5bf9\u4e8e\u5355\u5c42rnn\u548c\u53cc\u5c42rnn\u6570\u636e\u5b8c\u5168\u76f8\u540c":111,"\u793a\u4f8b3\u7684\u914d\u7f6e\u4f7f\u7528\u4e86\u5355\u5c42rnn\u548c\u53cc\u5c42rnn":111,"\u793a\u4f8b3\u7684\u914d\u7f6e\u5206\u522b\u4e3a":111,"\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b":[81,90],"\u793a\u4f8b\u5982\u4e0b":83,"\u793a\u4f8b\u7a0b\u5e8f":91,"\u793e\u533a\u53c2\u4e0e\u56f0\u96be":45,"\u793e\u533a\u8d21\u732e\u4ee3\u7801\u5b66\u4e60\u6210\u672c\u9ad8":45,"\u795e\u7ecf\u7f51\u7edc\u4e2d\u4e00\u4e2a\u8ba1\u7b97\u5c42\u7684\u8f93\u5165":89,"\u795e\u7ecf\u7f51\u7edc\u4e2d\u4e00\u4e2a\u8ba1\u7b97\u5c42\u7684\u8f93\u5165\u8f93\u51fa\u88ab\u7ec4\u7ec7\u4e3a\u4e00\u4e2a":90,"\u795e\u7ecf\u7f51\u7edc\u4e2d\u7684\u53c2\u6570":10,"\u795e\u7ecf\u7f51\u7edc\u4e5f\u9700\u8981\u4e00\u4e9b\u7279\u5b9a\u7684layer\u4f5c\u4e3a\u8f93\u5165\u63a5\u53e3":84,"\u795e\u7ecf\u7f51\u7edc\u53c2\u6570\u4ee5\u53ca\u8fed\u4ee3\u65b9\u7a0b":84,"\u795e\u7ecf\u7f51\u7edc\u5728\u8bad\u7ec3\u7684\u65f6\u5019":81,"\u795e\u7ecf\u7f51\u7edc\u672c\u8d28\u4e0a\u662f\u4e00\u4e2a\u8ba1\u7b97\u56fe":76,"\u795e\u7ecf\u7f51\u7edc\u6a21\u578b\u7ed3\u6784\u548c\u8bad\u7ec3\u597d\u7684\u6a21\u578b\u5c06\u88ab\u5e8f\u5217\u5316\u5408\u5e76\u5165\u4e00\u4e2a\u6587\u4ef6":90,"\u795e\u7ecf\u7f51\u7edc\u7684\u7f51\u7edc\u7ed3\u6784\u4e2d\u5177\u6709\u6709\u5411\u73af\u7ed3\u6784":111,"\u795e\u7ecf\u7f51\u7edc\u7684\u8bad\u7ec3\u672c\u8eab\u662f\u4e00\u4e2a\u975e\u5e38\u6d88\u8017\u5185\u5b58\u548c\u663e\u5b58\u7684\u5de5\u4f5c":81,"\u79bb\u7ebf\u6279\u5904\u7406":11,"\u79f0\u4e3a":[72,114],"\u79f0\u4e3a\u5f00\u53d1\u955c\u50cf":116,"\u79f0\u4e4b\u4e3a":89,"\u79f0\u4e4b\u4e3a\u53cc\u5c42\u5e8f\u5217\u7684\u4e00\u4e2a\u5b50\u5e8f\u5217":110,"\u79f0\u4e4b\u4e3a\u96c6\u675f\u5927\u5c0f":103,"\u79f0\u4f5c\u6709kernel":75,"\u79f0\u4f5ckernel":75,"\u79fb\u52a8\u7aef\u9884\u6d4b":89,"\u7a00\u758f\u6570\u636e\u7684\u683c\u5f0f":74,"\u7a00\u758f\u66f4\u65b0\u7684\u7aef\u53e3\u6570\u91cf":97,"\u7a00\u758f\u768401\u5411\u91cf":84,"\u7a00\u758f\u7684\u5411\u91cf":84,"\u7a00\u758f\u77e9\u9635":89,"\u7a00\u758f\u77e9\u9635\u4f7f\u7528":89,"\u7a00\u758f\u77e9\u9635\u53ca\u76f8\u5173\u7684\u63a5\u53e3":89,"\u7a00\u758f\u77e9\u9635\u5b58\u50a8\u793a\u610f\u56fe":89,"\u7a00\u758f\u77e9\u9635\u7684\u4e58\u79ef\u5e94\u7528\u4e8e\u524d\u5411\u4f20\u64ad\u8fc7\u7a0b":105,"\u7a0b\u5e8f\u4ece\u6b64\u76ee\u5f55\u62f7\u8d1d\u6587\u4ef6\u5230\u5bb9\u5668\u5185\u8fdb\u884c\u8bad\u7ec3":97,"\u7a0b\u5e8f\u4f9d\u8d56":91,"\u7a0b\u5e8f\u505c\u6b62":103,"\u7a0b\u5e8f\u662f\u4e00\u6837\u7684":107,"\u7a0b\u5e8f\u76f4\u63a5\u9000\u51fa":103,"\u7a20\u5bc6\u5411\u91cf":74,"\u7a20\u5bc6\u66f4\u65b0\u7684\u7aef\u53e3\u6570\u91cf":97,"\u7a20\u5bc6\u7684\u6d6e\u70b9\u6570\u5411\u91cf":84,"\u7a20\u5bc6\u77e9\u9635":89,"\u7acb\u523b\u9000\u51fa":81,"\u7acb\u5373\u6267\u884c\u5355\u5143\u6d4b\u8bd5":0,"\u7ae0\u8282":116,"\u7aef\u53e3":79,"\u7aef\u6570\u636e\u7c7b\u578b":89,"\u7aef\u7684":107,"\u7aef\u8bfb\u53d6\u6570\u636e":81,"\u7b2c\u4e00\u4e2a":72,"\u7b2c\u4e00\u4e2a\u53c2\u6570":75,"\u7b2c\u4e00\u4e2a\u6837\u672c\u540c\u65f6encode\u4e24\u6761\u6570\u636e\u6210\u4e24\u4e2a\u5411\u91cf":111,"\u7b2c\u4e00\u4e2atag\u4e3a":63,"\u7b2c\u4e00\u6b65\u9700\u8c03\u7528":90,"\u7b2c\u4e00\u7ae0\u8282":84,"\u7b2c\u4e09\u4e2a\u53c2\u6570":75,"\u7b2c\u4e09\u65b9\u4f9d\u8d56\u5e93\u9700\u8981\u6309\u7167\u4e0e\u65b9\u5f0f2\u540c\u6837\u65b9\u6cd5\u663e\u793a\u5730\u8fdb\u884c\u94fe\u63a5":87,"\u7b2c\u4e09\u65b9\u94fe\u63a5\u5e93\u548c\u5934\u6587\u4ef6":87,"\u7b2c\u4e09\u6b65\u5b8c\u6210\u540e":63,"\u7b2c\u4e8c\u4e2a":81,"\u7b2c\u4e8c\u4e2a\u4e3a":63,"\u7b2c\u4e8c\u4e2a\u53c2\u6570":75,"\u7b2c\u4e8c\u7c7b":82,"\u7b2ci\u884c\u7b2cj\u5217\u7684\u6570\u503c":74,"\u7b49":[42,46,75,79,90],"\u7b49\u4e8e\u6837\u672c\u6570":81,"\u7b49\u5168\u90e8\u9759\u6001\u5e93\u4e2d\u7684\u76ee\u6807\u6587\u4ef6\u5168\u90e8\u6253\u5305\u540e\u4ea7\u751f\u7684\u6587\u4ef6":46,"\u7b49\u53c2\u6570":97,"\u7b49\u5f85\u7f16\u8bd1\u5b8c\u6210\u540e":63,"\u7b49\u6587\u4ef6":46,"\u7b49\u7b2c\u4e09\u65b9\u5e93":87,"\u7b80\u5199":75,"\u7b80\u5355\u4ecb\u7ecd\u9700\u8981\u7528\u5230\u57fa\u7c7b":75,"\u7b80\u5355\u603b\u7ed3op\u9700\u8981\u5305\u542b\u7684\u5185\u5bb9\u5982\u4e0b":75,"\u7b80\u5355\u6765\u8bf4":108,"\u7b80\u5355\u7684\u5168\u8fde\u63a5\u7f51\u7edc":83,"\u7b80\u5355\u7684\u6027\u80fd\u5206\u6790":108,"\u7b80\u5355\u7684yaml\u6587\u4ef6\u5982\u4e0b":96,"\u7b97\u6cd5":[81,114],"\u7b97\u6cd5\u4e2d\u7684beam\u5927\u5c0f":114,"\u7ba1\u7406\u4e86\u6bcf\u4e2a\u8ba1\u7b97\u5c42\u8f93\u51fa\u7684\u5b58\u50a8\u7a7a\u95f4":90,"\u7ba1\u7406\u7684\u65b9\u6cd5":94,"\u7c7b\u4f3c":[46,110],"\u7c7b\u4f5c\u4e3a\u53c2\u6570\u7684\u62bd\u8c61":74,"\u7c7b\u522b\u4e2d\u7684\u53c2\u6570\u53ef\u7528\u4e8e\u6240\u6709\u573a\u5408":102,"\u7c7b\u522b\u6807\u7b7e\u4e4b\u4e00":90,"\u7c7b\u522b\u6807\u7b7e\u5c42":90,"\u7c7b\u540d\u548cc":45,"\u7c7b\u578b":[45,75,89,103],"\u7c7b\u578b\u4e3a":75,"\u7c7b\u578b\u4ecd\u7136\u4e3aeigenvector":76,"\u7c7b\u578b\u53ef\u4ee5\u662fpaddlepaddle\u652f\u6301\u7684\u4efb\u610f\u8f93\u5165\u6570\u636e\u7c7b\u578b":110,"\u7c7b\u578b\u540d\u4e3a":75,"\u7c7b\u578b\u662fnumpy\u7684ndarrai":81,"\u7c7b\u578b\u662fsparse_binary_vector":84,"\u7c7b\u578b\u662fsparse_float_vector":84,"\u7c7b\u578b\u7684":111,"\u7c7b\u578b\u7b49\u662f\u5426\u5408\u6cd5":75,"\u7c7b\u578b\u8fd8\u662f":89,"\u7c7b\u7684\u5b9a\u4e49\u5199\u5728":75,"\u7c7b\u7684\u5bf9\u8c61":90,"\u7c7b\u7684\u6784\u9020\u51fd\u6570\u548c\u6790\u6784\u51fd\u6570":74,"\u7c7b\u91cd\u5199":75,"\u7c7b\u9700\u8981\u5b9e\u73b0\u521d\u59cb\u5316":74,"\u7cfb\u6570":75,"\u7cfb\u7edf\u4e2d\u7684\u74f6\u9888\u53ef\u80fd\u548c\u7a0b\u5e8f\u5458\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u60f3\u8c61\u7684\u74f6\u9888\u76f8\u53bb\u751a\u8fdc":107,"\u7cfb\u7edf\u4f1a\u5bf9\u65b0\u589e\u7684op\u81ea\u52a8\u7ed1\u5b9apython":75,"\u7cfb\u7edf\u4f1a\u63d0\u4f9b\u4e00\u4e2a\u5206\u5e03\u5f0f\u5b58\u50a8\u670d\u52a1":91,"\u7cfb\u7edf\u4f1a\u6839\u636e\u6587\u4ef6\u540d\u81ea\u52a8\u6784\u5efaop\u548c\u5176\u5bf9\u5e94\u7684python\u6269\u5c55":75,"\u7ebf\u7a0bid\u53f7":105,"\u7ec6\u8282\u63cf\u8ff0":104,"\u7ecf\u5e38\u4f1a\u6d88\u8017\u657010gb\u7684\u5185\u5b58\u548c\u6570gb\u7684\u663e\u5b58":81,"\u7ecf\u8fc7\u6a21\u578b\u5904\u7406\u4e4b\u540e":88,"\u7ed3\u5c3e":75,"\u7ed3\u675f\u6807\u8bb0":114,"\u7ed3\u675f\u9884\u6d4b\u4e4b\u540e":90,"\u7ed3\u6784\u4f53":[89,90],"\u7ed3\u679c\u4f1a\u5199\u5165\u5f53\u524d\u8fd0\u884c\u76ee\u5f55\u4e0b\u7684":90,"\u7ed3\u679c\u5982\u4e0b\u56fe\u6240\u793a":107,"\u7ed3\u8bba":45,"\u7ed9\u4e2a\u7b80\u5355\u7684":72,"\u7ed9\u5b9aencoder\u8f93\u51fa\u548c\u5f53\u524d\u8bcd":113,"\u7edf\u4e00\u7528":11,"\u7ee7\u627f\u81ea":75,"\u7ee7\u627f\u81eaoperatorbas":75,"\u7ef4\u57fa\u767e\u79d1\u4e2d\u6587\u9875\u9762":111,"\u7ef4\u57fa\u767e\u79d1\u9875\u9762":111,"\u7ef4\u7a7a\u95f4":114,"\u7ef4\u7a7a\u95f4\u5b8c\u6210":114,"\u7f13\u5b58\u6c60\u7684\u51cf\u5c0f":81,"\u7f16\u5199":1,"\u7f16\u5199\u4e86\u4e00\u4e2apaddlepaddle\u7684\u7a0b\u5e8f":1,"\u7f16\u5199\u5b8cyaml\u6587\u4ef6\u540e":97,"\u7f16\u5199\u672c\u6b21\u8bad\u7ec3\u7684yaml\u6587\u4ef6":97,"\u7f16\u5199\u6df1\u5ea6\u5b66\u4e60\u7a0b\u5e8f":107,"\u7f16\u5199\u7684\u90e8\u5206":3,"\u7f16\u53f7\u4ece0\u5f00\u59cb":81,"\u7f16\u7801\u5411\u91cf":114,"\u7f16\u7801\u5668\u8f93\u51fa":114,"\u7f16\u7801\u6e90\u5e8f\u5217":114,"\u7f16\u8bd1":[1,72,116],"\u7f16\u8bd1\u51fa\u7684paddlepaddle\u9884\u6d4b\u5e93\u548c\u5934\u6587\u4ef6":87,"\u7f16\u8bd1\u53ca\u5b89\u88c5":2,"\u7f16\u8bd1\u540e\u7684\u6587\u4ef6\u5c06\u88ab\u5b58\u50a8\u5728\u5de5\u4f5c\u76ee\u5f55":77,"\u7f16\u8bd1\u548c\u5b89\u88c5paddlepaddl":118,"\u7f16\u8bd1\u548c\u5b89\u88c5paddlepaddle\u9884\u6d4b\u5e93":[116,117],"\u7f16\u8bd1\u5668":[116,117,118],"\u7f16\u8bd1\u5668\u6ca1\u6709":45,"\u7f16\u8bd1\u5668\u8981\u6c42\u7cfb\u7edf\u652f\u6301":116,"\u7f16\u8bd1\u578b\u8bed\u8a00":45,"\u7f16\u8bd1\u5b89\u88c5\u4e0e\u5355\u5143\u6d4b\u8bd5":80,"\u7f16\u8bd1\u5b89\u88c5\u7ed3\u675f\u4e4b\u540e":116,"\u7f16\u8bd1\u5b8c\u6210\u4e4b\u540e":77,"\u7f16\u8bd1\u5b8c\u6210\u540e\u4f1a\u5728build":0,"\u7f16\u8bd1\u5de5\u5177\u94fe":116,"\u7f16\u8bd1\u5de5\u5177\u94fe\u6240\u5728\u7684\u7edd\u5bf9\u8def\u5f84":118,"\u7f16\u8bd1\u6027\u80fd\u4f1a\u548c":107,"\u7f16\u8bd1\u6210\u529f\u540e":75,"\u7f16\u8bd1\u6210\u529f\u540e\u5728":87,"\u7f16\u8bd1\u6210\u52a8\u6001\u5e93":103,"\u7f16\u8bd1\u65f6\u4e00\u5b9a\u8981\u5f00\u542f\u4f18\u5316":107,"\u7f16\u8bd1\u65f6\u4f1a\u628a\u5bf9\u5e94\u7684\u5934\u6587\u4ef6\u548c\u5e93\u653e\u5728":42,"\u7f16\u8bd1\u65f6\u53ef\u80fd\u4f1a\u53bb\u6389\u8c03\u8bd5\u4fe1\u606f":107,"\u7f16\u8bd1\u65f6\u6307\u5b9a":107,"\u7f16\u8bd1\u751f\u6210":77,"\u7f16\u8bd1\u8fd9\u4e2a\u7248\u672c\u7684docker\u53d1\u884c\u955c\u50cf":63,"\u7f16\u8bd1\u8fd9\u4e2a\u7248\u672c\u7684python":63,"\u7f16\u8bd1c":46,"\u7f16\u8bd1paddlepaddl":0,"\u7f51\u7edc\u5c42\u53ef\u4ee5\u6709\u591a\u4e2a\u8f93\u5165":74,"\u7f51\u7edc\u5c42\u7684\u6807\u8bc6\u7b26\u4e3a":74,"\u7f51\u7edc\u5c42\u7684\u7c7b\u578b":74,"\u7f51\u7edc\u5c42\u7684\u7ec6\u8282\u53ef\u4ee5\u901a\u8fc7\u4e0b\u9762\u8fd9\u4e9b\u4ee3\u7801\u7247\u6bb5\u6765\u6307\u5b9a":74,"\u7f51\u7edc\u5c42\u7684\u8f93\u51fa\u662f\u7ecf\u8fc7\u6fc0\u6d3b\u51fd\u6570\u4e4b\u540e\u7684\u503c":103,"\u7f51\u7edc\u5c42\u914d\u7f6e\u5305\u542b\u4ee5\u4e0b\u51e0\u9879":74,"\u7f51\u7edc\u63a5\u53d7\u4e00\u5e45\u56fe\u7247\u4f5c\u4e3a\u8f93\u5165":90,"\u7f51\u7edc\u7ed3\u6784\u7684\u5e8f\u5217\u5316\u7ed3\u679c\u548c\u6a21\u578b\u53c2\u6570\u5b58\u50a8\u76ee\u5f55":90,"\u7f51\u7edc\u901a\u4fe1":74,"\u7f51\u901f\u6216ssl\u94fe\u63a5\u539f\u56e0":78,"\u800c":[82,107,114],"\u800c\u4e0d\u4f1a\u6539\u53d8\u539f\u6709tensor\u7684shape\u4fe1\u606f":76,"\u800c\u4e0d\u5fc5\u5728\u610fpaddl":46,"\u800c\u4e0d\u652f\u6301pypy\u89e3\u91ca\u5668":45,"\u800c\u4e0d\u662f\u5728layer\u91cc\u5b9e\u73b0":82,"\u800c\u4e0d\u662f\u6e90\u7801\u76ee\u5f55\u91cc":78,"\u800c\u4e0d\u662f\u7279\u5f81\u7684\u96c6\u5408":111,"\u800c\u4e0d\u662f\u76f8\u5bf9":89,"\u800c\u4e0d\u662fc":89,"\u800c\u4e0d\u66b4\u9732\u6982\u5ff5\u7684\u5b9e\u73b0":46,"\u800c\u4e14\u4e2a\u6570\u5e76\u4e0d\u786e\u5b9a":91,"\u800c\u4e14\u5305\u542b\u4e86c":3,"\u800c\u4e14\u5728\u4f20\u8f93\u7684\u8fc7\u7a0b\u4e2d\u4e5f\u53ef\u80fd\u51fa\u73b0\u7f51\u7edc\u4e0d\u7a33\u5b9a\u7684\u60c5\u51b5":27,"\u800c\u4e14cento":3,"\u800c\u4e4b\u524d\u7684\u53c2\u6570\u5c06\u4f1a\u88ab\u5220\u9664":103,"\u800c\u4ece\u5e94\u7528\u7684\u89d2\u5ea6":108,"\u800c\u4f18\u5316\u6027\u80fd\u7684\u9996\u8981\u4efb\u52a1":108,"\u800c\u5176\u4ed6\u5c42\u4f7f\u7528cpu\u8ba1\u7b97":105,"\u800c\u51fa\u73b0\u9636\u6bb5\u6027\u7684\u8fd0\u884c\u505c\u6ede":10,"\u800c\u53cc\u5c42rnn\u662f\u53ef\u4ee5\u5904\u7406\u8fd9\u79cd\u8f93\u5165\u6570\u636e\u7684\u7f51\u7edc\u7ed3\u6784":111,"\u800c\u53cd\u5411\u6d4b\u8bd5\u4e2d":75,"\u800c\u53ea\u9700\u8981\u83b7\u5f97recurr":82,"\u800c\u5728\u8ba1\u7b97\u7ed3\u675f\u4e4b\u540e":76,"\u800c\u5728cpp\u91cc\u9762\u5b9e\u73b0\u8fd9\u4e2ac\u7684\u63a5\u53e3":45,"\u800c\u591a\u8bed\u8a00\u63a5\u53e3\u9700\u8981\u76f4\u63a5\u8bfb\u53d6\u751f\u6210\u7684\u4e8c\u8fdb\u5236":45,"\u800c\u5b89\u88c5\u5305":[3,78],"\u800c\u5b89\u88c5\u5305\u662f":[3,78],"\u800c\u5bf9\u4e8e\u53cc\u5c42\u5e8f\u5217":111,"\u800c\u5bf9\u4e8e\u6bcf\u4e00\u4e2a\u5185\u5c42\u7279\u5f81\u6570\u636e\u800c\u8a00":111,"\u800c\u5bf9\u4e8egolang":45,"\u800c\u5bf9\u4e8egolang\u9519\u8bef\u5904\u7406\u5e94\u8be5\u4f7f\u7528\u8fd4\u56de\u503c":45,"\u800c\u5c06\u8fd9\u4e2a\u6bb5\u843d\u7684\u6bcf\u4e00\u53e5\u8bdd\u7528lstm\u7f16\u7801\u6210\u4e00\u4e2a\u5411\u91cf":111,"\u800c\u5f53\u524d\u5df2\u7ecf\u67095":108,"\u800c\u662f\u5c06\u8f93\u5165":[89,90],"\u800c\u662f\u76f4\u63a5\u4ece\u5185\u5b58\u7684\u7f13\u5b58\u91cc\u8bfb\u53d6\u6570\u636e":81,"\u800c\u662f\u76f4\u63a5\u4fee\u6539paddl":46,"\u800c\u662f\u76f4\u63a5\u7528api\u7684\u63a5\u53e3\u8fdc\u7a0b\u8bbf\u95ee":11,"\u800c\u66f4\u6df1\u5165\u7684\u5206\u6790":108,"\u800c\u6709\u4e9b\u53c2\u6570\u9700\u8981\u5728\u96c6\u7fa4\u591a\u673a\u8bad\u7ec3\u4e2d\u4f7f\u7528\u7b49":102,"\u800c\u6e90\u5e8f\u5217\u7684\u7f16\u7801\u5411\u91cf\u53ef\u4ee5\u88ab\u65e0\u8fb9\u754c\u7684memory\u8bbf\u95ee":114,"\u800c\u795e\u7ecf\u7f51\u7edc\u662f\u6211\u4eec\u8981\u642d\u5efa\u7684\u5b9d\u5854":84,"\u800c\u7a00\u758f\u66f4\u65b0\u5728\u53cd\u5411\u4f20\u64ad\u4e4b\u540e\u7684\u6743\u91cd\u66f4\u65b0\u65f6\u8fdb\u884c":105,"\u800c\u8ba1\u7b97\u8fc7\u7a0b\u662f\u7531":76,"\u800c\u8fd9\u4e00\u53e5\u8bdd\u5c31\u53ef\u4ee5\u8868\u793a\u6210\u8fd9\u4e9b\u4f4d\u7f6e\u7684\u6570\u7ec4":111,"\u800c\u8fd9\u6bcf\u4e00\u4e2a\u6570\u7ec4\u5143\u7d20":111,"\u800c\u975e\u76f4\u63a5\u56de\u590d\u7684\u65b9\u5f0f":72,"\u800c\u975e\u9759\u6001\u52a0\u8f7dcuda\u52a8\u6001\u5e93":0,"\u800ceigenvector":76,"\u800crnn\u662f\u6700\u6d41\u884c\u7684\u9009\u62e9":113,"\u800cswig\u53ea\u80fd\u7b80\u5355\u7684\u66b4\u9732c":45,"\u800ctrainer\u9700\u8981\u8bfb\u53d6\u8bad\u7ec3\u6570\u636e\u8fdb\u884c\u8bad\u7ec3":84,"\u800cy_predict\u662f\u63a5\u6536x\u4f5c\u4e3a\u8f93\u5165":84,"\u8054\u901a":101,"\u80fd\u591f\u5904\u7406\u53cc\u5c42\u5e8f\u5217":113,"\u80fd\u591f\u5bf9\u53cc\u5411\u5e8f\u5217\u8fdb\u884c\u5904\u7406\u7684\u6709":113,"\u80fd\u591f\u8bb0\u5f55\u4e0a\u4e00\u4e2asubseq":113,"\u80fd\u591f\u9488\u5bf9cpu\u548cgpu\u7684\u8ba1\u7b97\u505a\u66f4\u591a\u4f18\u5316":82,"\u80fd\u83b7\u53d6":93,"\u811a\u672c":[0,90,116],"\u811a\u672c\u5f00\u59cb\u65f6":97,"\u811a\u672c\u96c6\u6210\u4e86\u5e8f\u5217\u5316\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u7684\u8fc7\u7a0b":90,"\u81ea\u52a8\u5173\u95ed\u5bf9\u5e94\u7684":72,"\u81ea\u52a8\u5730\u5c06\u8fd9\u4e9b\u9009\u9879\u5e94\u7528\u5230":93,"\u81ea\u52a8\u5b8c\u6210\u8fd9\u4e00\u8fc7\u7a0b":113,"\u81ea\u52a8\u6302\u8f7d\u5206\u5e03\u5f0f\u5b58\u50a8\u76ee\u5f55":10,"\u81ea\u52a8\u6784\u5efa\u72ec\u7acb\u5de5\u5177\u94fe":116,"\u81ea\u52a8\u751f\u6210":77,"\u81ea\u52a8\u83b7\u53d6\u4e0a\u4e00\u4e2a\u751f\u6210\u7684\u8bcd":114,"\u81ea\u52a8\u9009\u62e9":117,"\u81ea\u6b64":[116,117],"\u81ea\u7136\u4e5f\u5c31\u6709\u7ba1\u7406\u5458\u6743\u9650":0,"\u81ea\u7136\u8bed\u8a00\u4e2d\u7684\u53e5\u5b50\u662f\u4e00\u4e2a\u5e8f\u5217":89,"\u81ea\u7136\u8bed\u8a00\u4e2d\u7684\u6bb5\u843d\u662f\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":89,"\u81ea\u7136\u8bed\u8a00\u5904\u7406\u7b49":105,"\u81f3\u4e8e\u4e3a\u4ec0\u4e48\u9700\u8981c":46,"\u81f3\u5c11\u5305\u542bgcc_3":3,"\u81f3\u5c11\u5305\u542bglibcxx_3":3,"\u81f3\u6b64":[72,111],"\u826f\u597d\u7684\u6587\u6863":45,"\u8282\u70b9":[98,101],"\u8282\u7701\u4e86\u4e0d\u5fc5\u8981\u7684\u64cd\u4f5c":42,"\u82e5":74,"\u82e5\u5728paddlepaddle\u7f16\u8bd1\u65f6":83,"\u82e5\u5e0c\u671b\u5f97\u5230\u6700\u5feb\u7684\u6267\u884c\u901f\u5ea6":117,"\u82e5\u5e0c\u671b\u6700\u5feb\u7684\u6267\u884c\u901f\u5ea6":118,"\u82e5\u5e72\u4e2a\u53e5\u5b50\u6784\u6210\u4e00\u4e2a\u6bb5\u843d":110,"\u82e5\u6709\u4e0d\u4e00\u81f4\u4e4b\u5904":108,"\u82e5\u6709\u5fc5\u8981":74,"\u82e5\u672a\u663e\u5f0f\u6307\u5b9a":117,"\u82e5\u6ca1\u6709\u663e\u5f0f\u8bbe\u7f6e":116,"\u82e5\u73af\u5883\u53d8\u91cf":[116,117,118],"\u82e5\u8981\u5bf9\u8fd9\u51e0\u4e2alayer\u4f7f\u7528dropout":82,"\u82e5\u8f93\u51fa\u662f\u5355\u5c42\u5e8f\u5217":110,"\u82e5\u8f93\u51fa\u662f\u53cc\u5c42\u5e8f\u5217":110,"\u82f1\u6587\u6587\u6863":77,"\u82f1\u6587\u6587\u6863\u76ee\u5f55":77,"\u8303\u56f4":105,"\u83b7\u53d6":72,"\u83b7\u53d6\u53ef\u9009\u7684tag":1,"\u83b7\u53d6\u5f53\u524d\u7cfb\u7edf\u652f\u6301\u7684\u5b89\u88c5\u5305\u683c\u5f0f":3,"\u83b7\u53d6\u5f53\u524d\u7cfb\u7edf\u652f\u6301\u7684python\u5305\u7684\u540e\u7f00":78,"\u83b7\u53d6\u6700\u65b0\u7684\u68c0\u67e5\u70b9\u7684\u6587\u4ef6uuid":10,"\u83b7\u53d6\u6e90\u7801":0,"\u83b7\u53d6\u8f93\u51fa\u65f6":90,"\u83b7\u53d6trainer":97,"\u83b7\u5f97\u53c2\u6570\u5c3a\u5bf8":74,"\u83b7\u5f97\u5728\u6a21\u578b\u914d\u7f6e\u4e2d\u67d0\u4e00\u5c42\u7684name":81,"\u83b7\u5f97\u57fa\u672c\u7684docker\u5b89\u88c5\u548c\u4f7f\u7528\u65b9\u6cd5":1,"\u83b7\u5f97\u5f53\u524dmini":81,"\u83b7\u5f97\u6700\u5feb\u7684\u6267\u884c\u901f\u5ea6":116,"\u83b7\u5f97\u7684\u503c\u7c7b\u578b\u5747\u4e3a":81,"\u83b7\u5f97\u8ba1\u7b97\u7ed3\u679c":90,"\u83b7\u5f97\u8fd9\u4e9b\u8282\u70b9\u7684ip\u5730\u5740":93,"\u83b7\u5f97head\u548cnode\u8282\u70b9\u7684ip\u5730\u5740":98,"\u865a\u62df\u673a\u4e0a":0,"\u867d\u7136\u4e0d\u9f13\u52b1\u8fd9\u6837":46,"\u867d\u7136\u5f02\u6b65sgd\u65b9\u5f0f\u4f1a\u63d0\u9ad8\u53c2\u6570\u66f4\u65b0\u5e76\u884c\u5ea6":92,"\u867d\u7136paddle\u770b\u8d77\u6765\u5305\u542b\u4e86\u4f17\u591a\u53c2\u6570":102,"\u884c":89,"\u884c\u504f\u79fb":89,"\u884c\u53f7":107,"\u8865\u5145\u4e0a\u6b21\u7684commit":72,"\u8868\u660e\u4e86\u8fd9\u4e9b\u884c\u7684\u6807\u53f7":74,"\u8868\u660e\u8fd9\u4e2a\u5c42\u7684\u4e00\u4e2a\u5b9e\u4f8b\u662f\u5426\u9700\u8981\u504f\u7f6e":74,"\u8868\u793a":75,"\u8868\u793a\u4e3adeviceid":105,"\u8868\u793a\u5bf9\u8f93\u5165\u6570\u636e":42,"\u8868\u793a\u5c06\u5916\u5c42\u7684outer_mem\u4f5c\u4e3a\u5185\u5c42memory\u7684\u521d\u59cb\u72b6\u6001":111,"\u8868\u793a\u5f53\u524d\u96c6\u7fa4\u4f5c\u4e1a\u7684\u8282\u70b9":93,"\u8868\u793a\u6570\u636e\u7c7b\u578b":75,"\u8868\u793a\u7684\u504f\u79fb\u662f\u4ee5":89,"\u8868\u793a\u8bbe\u5907\u7c7b\u578b":75,"\u8868\u793a\u8bcd\u8bed\u5728\u8bcd\u5178\u4e2d\u7684\u5e8f\u53f7":89,"\u8868\u793a\u8bfb\u8005\u6240\u4f7f\u7528\u7684docker\u955c\u50cf\u4ed3\u5e93\u5730\u5740":97,"\u8868\u793a\u8fd9\u4e2ajob\u7684\u540d\u5b57":97,"\u8868\u793a\u9700\u8981\u6784\u5efa\u63a8\u7406\u5e93":118,"\u88ab":72,"\u88ab\u5207\u5206\u6210\u591a\u4e2a\u90e8\u5206":92,"\u88ab\u6269\u5c55\u4e3a\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":110,"\u88ab\u653e\u5728":74,"\u88ab\u79f0\u4e3a":114,"\u8981\u4f7f\u7528\u547d\u4ee4\u884c\u5206\u6790\u5de5\u5177":108,"\u8981\u5728\u5df2\u6709\u7684kubernetes\u96c6\u7fa4\u4e0a\u8fdb\u884cpaddlepaddle\u7684\u5206\u5e03\u5f0f\u8bad\u7ec3":97,"\u8981\u6c42\u5355\u5c42\u5e8f\u5217\u542b\u6709\u5143\u7d20\u7684\u6570\u76ee":110,"\u8981\u751f\u6210\u7684\u76ee\u6807\u5e8f\u5217":113,"\u8981\u8c03\u7528":74,"\u89c6\u9891\u7b49":89,"\u89e3\u51b3\u529e\u6cd5\u662f":78,"\u89e3\u51b3\u65b9\u6848\u662f":83,"\u89e3\u6790\u73af\u5883\u53d8\u91cf\u5f97\u5230":97,"\u89e3\u7801\u5668\u4f7f\u7528":114,"\u89e3\u7801\u5668\u57fa\u4e8e\u7f16\u7801\u6e90\u5e8f\u5217\u548c\u6700\u540e\u751f\u6210\u7684\u76ee\u6807\u8bcd\u9884\u6d4b\u4e0b\u4e00\u76ee\u6807\u8bcd":114,"\u89e3\u7801\u5668\u662f\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":114,"\u89e3\u91ca\u578b\u8bed\u8a00\u53ea\u80fd\u8c03\u7528\u52a8\u6001\u5e93":45,"\u89e3\u91ca\u6027\u8bed\u8a00\u5b9e\u9645\u8fd0\u884c\u7684\u4e8c\u8fdb\u5236\u662f\u89e3\u91ca\u5668\u672c\u8eab":45,"\u8ba1\u5212\u5728":[41,42],"\u8ba1\u7b97":[92,114],"\u8ba1\u7b97\u504f\u7f6e\u7684\u68af\u5ea6":74,"\u8ba1\u7b97\u53cd\u5411rnn\u7684\u7b2c\u4e00\u4e2a\u5b9e\u4f8b":114,"\u8ba1\u7b97\u53d8\u6362\u77e9\u9635\u7684\u5927\u5c0f\u548c\u683c\u5f0f":74,"\u8ba1\u7b97\u5f53\u524d\u5c42\u6743\u91cd\u7684\u68af\u5ea6":74,"\u8ba1\u7b97\u6548\u7387\u66f4\u9ad8":82,"\u8ba1\u7b97\u6bcf\u4e2a\u8bcd\u7684\u8bcd\u5411\u91cf":114,"\u8ba1\u7b97\u6fc0\u6d3b\u51fd\u6570\u7684\u68af\u5ea6":74,"\u8ba1\u7b97\u7684\u7ec6\u8282\u5c06\u5728\u4e0b\u9762\u7684\u5c0f\u8282\u7ed9\u51fa":74,"\u8ba1\u7b97\u8282\u70b9":92,"\u8ba1\u7b97\u8282\u70b9\u4e4b\u95f4\u4e5f\u4e0d\u4f1a\u76f8\u4e92\u4f9d\u8d56":92,"\u8ba1\u7b97\u8f6c\u6362\u77e9\u9635\u548c\u8f93\u5165\u7684\u68af\u5ea6":74,"\u8ba1\u7b97\u8f93\u5165\u548c\u53c2\u6570\u7684\u68af\u5ea6":74,"\u8ba1\u7b97\u8f93\u5165\u5c42\u7684\u504f\u5dee":74,"\u8ba1\u7b97\u8f93\u51fa":74,"\u8ba1\u7b97\u8fd9\u4e2a\u6587\u4ef6\u7684md5":10,"\u8ba1\u7b97\u96c6\u7fa4\u901a\u5e38\u7531\u4e00\u7ec4":101,"\u8ba1\u7b97\u9700\u8981\u7684\u6570\u636e\u5b58\u653e\u5728":76,"\u8ba9paddle\u6838\u5fc3\u4e2d":46,"\u8bad\u7ec3":102,"\u8bad\u7ec3\u4efb\u52a1\u7684\u8fd0\u884c\u53ef\u80fd\u4f1a\u5360\u6ee1trainer\u548cparamet":10,"\u8bad\u7ec3\u548c\u7eaf\u4f7f\u7528":63,"\u8bad\u7ec3\u5931\u8d25\u65f6\u53ef\u4ee5\u68c0\u67e5\u9519\u8bef\u65e5\u5fd7":93,"\u8bad\u7ec3\u597d\u4e00\u4e2a\u6df1\u5c42\u795e\u7ecf\u7f51\u7edc\u901a\u5e38\u8981\u8017\u8d39\u975e\u5e38\u957f\u7684\u65f6\u95f4":108,"\u8bad\u7ec3\u597d\u7684\u6a21\u578b\u9ed8\u8ba4\u4fdd\u5b58\u5728\u5f53\u524d\u8fd0\u884c\u76ee\u5f55\u4e0b\u7684":90,"\u8bad\u7ec3\u6570\u636e\u6709\u95ee\u9898":81,"\u8bad\u7ec3\u6570\u636e\u683c\u5f0f\u548c\u8bad\u7ec3\u7a0b\u5e8f\u7684":91,"\u8bad\u7ec3\u65f6":97,"\u8bad\u7ec3\u6a21\u578b\u540e":114,"\u8bad\u7ec3\u6a21\u578b\u6b63\u786e\u6027":63,"\u8bad\u7ec3\u7a0b\u5e8f":91,"\u8bad\u7ec3\u7b56\u7565\u7b49\u7b49\u8fd9\u4e9b\u90fd\u662f\u5e38\u89c1\u7684\u53d8\u5316\u56e0\u7d20":104,"\u8bad\u7ec3\u7ed3\u675f\u540e\u67e5\u770b\u8f93\u51fa\u7ed3\u679c":97,"\u8bad\u7ec3\u8282\u70b9\u6570\u91cf":97,"\u8bad\u7ec3\u8bed\u8a00\u6a21\u578b\u8ddd\u79bb":81,"\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u53c2\u6570\u6216\u8005\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u7684\u68af\u5ea6\u5c3a\u5ea6\u8fc7\u5927":81,"\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u6d4b\u8bd5test_period":102,"\u8bad\u7ec3\u8fc7\u7a0b\u662f\u5426\u4e3a\u672c\u5730\u6a21\u5f0f":103,"\u8bad\u7ec3\u8fc7\u7a0b\u662f\u5426\u4f7f\u7528gpu":103,"\u8bad\u7ec3\u914d\u7f6e\u4e2d\u7684\u8bbe\u5907\u5c5e\u6027\u5c06\u4f1a\u65e0\u6548":103,"\u8bad\u7ec3dot_period":102,"\u8bb0\u5f55\u4e0b\u6240\u6709\u5931\u8d25\u7684\u4f8b\u5b50":63,"\u8bb0\u5fc6\u6a21\u5757":114,"\u8bbe\u4e3a\u5df2\u90e8\u7f72\u7684\u5de5\u4f5c\u7a7a\u95f4\u76ee\u5f55":93,"\u8bbe\u4e3a\u672c\u5730":93,"\u8bbe\u5b9a":82,"\u8bbe\u7f6e":[0,46,81,82,91,116,117],"\u8bbe\u7f6e\u4e3a":74,"\u8bbe\u7f6e\u4e3a\u4e0d\u540c\u7684\u503c":82,"\u8bbe\u7f6e\u4e3atrue\u4f7f\u7528\u672c\u5730\u8bad\u7ec3\u6216\u8005\u4f7f\u7528\u96c6\u7fa4\u4e0a\u7684\u4e00\u4e2a\u8282\u70b9":103,"\u8bbe\u7f6e\u4e3atrue\u4f7f\u7528gpu\u6a21\u5f0f":103,"\u8bbe\u7f6e\u4e86\u76f8\u540c\u7684\u53d6\u503c":82,"\u8bbe\u7f6e\u5176\u53c2\u6570\u5c5e\u6027":83,"\u8bbe\u7f6e\u53c2\u6570\u7684\u540d\u5b57":83,"\u8bbe\u7f6e\u547d\u4ee4\u884c\u53c2\u6570":81,"\u8bbe\u7f6e\u5b66\u4e60\u7387\u8870\u51cf\u56e0\u5b50\u5206\u6bb5\u51fd\u6570":83,"\u8bbe\u7f6e\u5e8f\u5217\u4fe1\u606f\u7684\u63a5\u53e3":89,"\u8bbe\u7f6e\u6210":83,"\u8bbe\u7f6e\u6210\u4e00\u4e2a\u5c0f\u4e00\u4e9b\u7684\u503c":81,"\u8bbe\u7f6e\u8f93\u51fa\u7684\u5c3a\u5bf8":74,"\u8bbe\u7f6e\u8f93\u51fatensor\u7684\u5f62\u72b6":75,"\u8bbe\u7f6e\u9ed8\u8ba4\u8bbe\u5907\u53f7\u4e3a0":105,"\u8bbe\u7f6egpu":103,"\u8bbf\u95ee\u5bf9\u5e94\u7684\u7f51\u5740":107,"\u8bbf\u95eekubernetes\u7684\u63a5\u53e3\u6765\u67e5\u8be2\u6b64job\u5bf9\u5e94\u7684\u6240\u6709pod\u4fe1\u606f":97,"\u8bc4\u5ba1\u4eba\u4e00\u822c\u4e0d\u505a\u8bc4\u5ba1":72,"\u8bc4\u5ba1\u4eba\u7684\u6bcf\u4e2a\u610f\u89c1\u90fd\u5fc5\u987b\u56de\u590d":72,"\u8bc4\u5ba1\u4eba\u9700\u8981\u9010\u4e00\u67e5\u770b\u6bcf\u4e2acommit\u624d\u80fd\u77e5\u9053\u505a\u4e86\u54ea\u4e9b\u4fee\u6539":72,"\u8bc4\u8bba\u6846\u4e2d\u52a0\u4e0a":72,"\u8bc6\u522b\u6570\u5b57":63,"\u8bcd\u5411\u91cf":63,"\u8bd5\u7740\u8ba9\u8f93\u51fa\u7684\u5206\u6790\u6570\u636e\u548c\u7406\u8bba\u503c\u5bf9\u5e94":108,"\u8be5\u53c2\u6570\u5728\u7f51\u7edc\u914d\u7f6e\u7684output":103,"\u8be5\u53c2\u6570\u5728\u96c6\u7fa4\u63d0\u4ea4\u73af\u5883\u4e2d\u81ea\u52a8\u8bbe\u7f6e":103,"\u8be5\u53c2\u6570\u5df2\u7ecf\u5728\u96c6\u7fa4\u63d0\u4ea4\u73af\u5883\u4e2d\u5b8c\u6210\u8bbe\u7f6e":103,"\u8be5\u53c2\u6570\u5fc5\u987b\u80fd\u88abflag":103,"\u8be5\u53c2\u6570\u6307\u793a\u662f\u5426\u6253\u5370\u65e5\u5fd7\u622a\u65ad\u4fe1\u606f":103,"\u8be5\u53c2\u6570\u6307\u793a\u662f\u5426\u6253\u5370\u9519\u8bef\u622a\u65ad\u65e5\u5fd7":103,"\u8be5\u53c2\u6570\u7528\u4e8e\u6307\u5b9a\u52a8\u6001\u5e93\u8def\u5f84":103,"\u8be5\u53c2\u6570\u7684\u610f\u601d\u662f\u8bad\u7ec3num":103,"\u8be5\u53c2\u6570\u9ed8\u8ba4\u4e3anull":103,"\u8be5\u5c42\u4ec5\u9700\u8981\u8fd9\u4e9b\u975e\u96f6\u6837\u672c\u4f4d\u7f6e\u6240\u5bf9\u5e94\u7684\u53d8\u6362\u77e9\u9635\u7684\u90a3\u4e9b\u884c":74,"\u8be5\u622a\u65ad\u4f1a\u5f71\u54cd":103,"\u8be5\u6279\u6b21\u7684\u8f93\u5165\u4e2d\u4ec5\u6709\u4e00\u4e2a\u5b50\u96c6\u662f\u975e\u96f6\u7684":74,"\u8be5\u63a5\u53e3\u53ef\u7528\u4e8e\u9884\u6d4b\u548c\u5b9a\u5236\u5316\u8bad\u7ec3":0,"\u8be5\u63a5\u53e3\u63a5\u53d7\u4e24\u4e2a\u53c2\u6570":90,"\u8be5\u6570\u76ee\u662f\u63d0\u524d\u5b9a\u4e49\u597d\u7684":103,"\u8be5\u6587\u4ef6\u5bf9\u76f8\u5173gemm":41,"\u8be5\u65b9\u5f0f\u5177\u6709\u4ee5\u4e0b\u4f18\u52bf":2,"\u8be5\u65f6\u95f4\u53bb\u9664\u6389\u672c\u51fd\u6570\u8c03\u7528\u5176\u4ed6\u51fd\u6570\u7684\u65f6\u95f4":107,"\u8be5\u6a21\u578b\u7684\u8bf4\u660e\u5982\u4e0b\u56fe\u6240\u793a":114,"\u8be5\u7c7b\u7684":75,"\u8be5\u7c7b\u7684\u5b9e\u73b0\u7ec6\u8282\u5728":74,"\u8be5\u7c7b\u7ee7\u627f\u4e8epaddlepaddle\u7684\u57fa\u7c7b":42,"\u8be5\u811a\u672c\u4e2d\u8bb0\u5f55\u4e86\u4ea4\u53c9\u7f16\u8bd1android\u7248paddlepaddle\u5e93\u5e38\u7528\u7684cmake\u914d\u7f6e":116,"\u8be5\u8bed\u53e5\u4f1a\u4e3a\u6bcf\u4e2a\u5c42\u521d\u59cb\u5316\u5176\u6240\u9700\u8981\u7684\u53d8\u91cf\u548c\u8fde\u63a5":74,"\u8be5layer\u662f\u901a\u8fc7\u53c2\u6570":82,"\u8be6\u7ec6\u4ecb\u7ecd\u53ef\u4ee5\u53c2\u8003":111,"\u8be6\u7ec6\u4ecb\u7ecd\u8bf7\u53c2\u8003\u8bbe\u8ba1\u6587\u6863":75,"\u8be6\u7ec6\u4fe1\u606f\u8bf7\u68c0\u67e5":93,"\u8be6\u7ec6\u53c2\u8003":0,"\u8be6\u7ec6\u53ef\u53c2\u8003":72,"\u8be6\u7ec6\u6587\u6863\u53c2\u8003":81,"\u8be6\u7ec6\u7684cmake\u4f7f\u7528\u65b9\u6cd5\u53ef\u4ee5\u53c2\u8003":0,"\u8be6\u7ec6\u89c1":110,"\u8be6\u7ec6\u89e3\u91ca\u8fd9\u4e9b\u53c2\u6570\u7684\u5c5e\u6027\u548c\u610f\u4e49":104,"\u8be6\u7ec6\u8bbe\u8ba1":27,"\u8be6\u7ec6\u8bf7\u4e86\u89e3":94,"\u8bed\u610f\u89d2\u8272\u6807\u6ce8":63,"\u8bed\u8a00\u91cd\u6784\u540e\u7684":107,"\u8bf4\u660e":[0,3,10,89],"\u8bf4\u660e\u63d0\u4ea4\u7684\u4ee3\u7801\u5b58\u5728\u95ee\u9898":72,"\u8bf4\u660e\u8fd9\u4e2a\u5c42\u7684\u8f93\u5165":74,"\u8bf7\u4e0d\u8981\u521b\u5efa\u7a7a\u7684":75,"\u8bf7\u4e0d\u8981\u5fd8\u8bb0\u63d0\u524d\u5728\u7269\u7406\u673a\u4e0a\u5b89\u88c5gpu\u6700\u65b0\u9a71\u52a8":1,"\u8bf7\u4fdd\u8bc1travi":72,"\u8bf7\u5148\u4f7f\u7528":[116,117,118],"\u8bf7\u5148\u5c1d\u8bd5\u5728\u4e0b\u9762\u7684\u9875\u9762\u5bfb\u627e\u7b54\u6848":2,"\u8bf7\u53c2\u7167\u4ee5\u4e0b\u6559\u7a0b":2,"\u8bf7\u53c2\u7167\u7f51\u7edc\u914d\u7f6e\u7684\u6587\u6863\u4e86\u89e3\u66f4\u8be6\u7ec6\u7684\u4fe1\u606f":105,"\u8bf7\u53c2\u8003":[46,74,75,78,81,84,90,111],"\u8bf7\u53c2\u8003\u6b64":90,"\u8bf7\u53c2\u89c1":72,"\u8bf7\u53c2\u9605":114,"\u8bf7\u5728\u8be5pull":72,"\u8bf7\u5728\u8f93\u5165\u65f6\u8fdb\u884c\u5408\u6cd5\u6027\u68c0\u67e5":89,"\u8bf7\u60a8\u5230":80,"\u8bf7\u60a8\u6bcf\u6b21\u63d0\u4ea4\u4ee3\u7801\u65f6":72,"\u8bf7\u60a8\u9075\u5b88\u4ee5\u4e0b\u7ea6\u5b9a":72,"\u8bf7\u6307\u5b9a\u7684paddlepaddle\u5de5\u4f5c\u76ee\u5f55\u7ed9\u73af\u5883\u53d8\u91cf":77,"\u8bf7\u6307\u5b9a\u8be5\u76ee\u5f55":103,"\u8bf7\u663e\u793a\u5730\u8c03\u7528":75,"\u8bf7\u6839\u636e\u673a\u5668\u914d\u7f6e\u548c\u7cfb\u7edf\u9009\u62e9\u5bf9\u5e94\u7684\u5b89\u88c5\u5305":2,"\u8bf7\u68c0\u67e5python\u7248\u672c\u662f\u5426\u4e3a2":3,"\u8bf7\u6ce8\u610f":[75,96,114],"\u8bf7\u6ce8\u610f\u662f\u5426\u9700\u8981\u4fee\u6539\u7f51\u7edc\u7ed3\u6784":90,"\u8bf7\u6ce8\u610f\u6bcf\u4e2acommit\u7684\u540d\u79f0":72,"\u8bf7\u6ce8\u610fcommit\u7684\u6570\u91cf":72,"\u8bf7\u76f4\u63a5\u586b\u51450":83,"\u8bf7\u770b\u4e0b\u9762\u7684\u4f8b\u5b50":105,"\u8bf7\u786e\u4fdd":72,"\u8bf7\u7ed9\u51fa\u603b\u4f53\u7684\u4fee\u6539\u60c5\u51b5":72,"\u8bf7\u7ed9\u51fa\u60a8\u81ea\u5df1\u7684\u53cd\u9a73\u7406\u7531":72,"\u8bf7\u9009\u62e9\u5408\u9002\u7684\u8bcd\u6c47":72,"\u8bf7\u9009\u62e9\u6b63\u786e\u7684\u7248\u672c":78,"\u8bf7\u9075\u5b88":72,"\u8bf7\u91c7\u7528":72,"\u8bf7\u9605\u8bfb\u4ee5\u4e0b\u6307\u5357":94,"\u8bf8\u5982\u56fe\u50cf\u5206\u7c7b":105,"\u8bfb\u53d6\u9700\u8981\u7684\u7ed3\u679c\u5373\u53ef":89,"\u8bfb\u53d6volume\u4e2d\u7684\u6570\u636e\u8fdb\u884c\u8fd9\u6b21\u5206\u5e03\u5f0f\u8bad\u7ec3":97,"\u8bfb\u8005\u53ef\u4ee5\u67e5\u770b":97,"\u8bfb\u8005\u9700\u8981\u66ff\u6362\u6210\u81ea\u5df1\u4f7f\u7528\u7684\u4ed3\u5e93\u5730\u5740":97,"\u8c03\u7528":[74,90,117],"\u8c03\u7528\u5bf9\u5e94":76,"\u8c03\u7528\u65b9\u6cd5\u89c1c":[116,117],"\u8c03\u7528\u7528":107,"\u8c03\u7528\u7684\u4e00\u4e9b\u7528\u6237\u5b9a\u4e49\u7684\u5e93\u51fd\u6570":91,"\u8c03\u7528\u7684\u51fd\u6570\u662f\u5426\u652f\u6301\u4e0d\u540c\u8bbe\u5907":75,"\u8c03\u7528\u8be5\u51fd\u6570\u540e":74,"\u8c03\u7528c":[89,90],"\u8d21\u732e\u6587\u6863":77,"\u8d77\u59cb\u5b58\u50a8\u5730\u5740\u4ee5\u6570\u636e\u7684\u5b58\u50a8\u5927\u5c0f\u4e3a\u5355\u4f4d\u7684\u504f\u79fb":89,"\u8df3\u8f6c\u5230":72,"\u8df3\u8fc7":81,"\u8f6c\u5316\u65b9\u6cd5\u5728\u76f8\u5e94\u7684\u9886\u57df\u90fd\u6709\u901a\u7528\u89e3\u51b3\u65b9\u6848":89,"\u8f6c\u6362\u5185\u5b58\u7684\u5de5\u4f5c":42,"\u8f6c\u6362\u5197\u4f59":41,"\u8f6c\u6362\u51fd\u6570":42,"\u8f6c\u6362\u751f\u6210\u7684\u6587\u4ef6\u540d\u4f1a\u662f\u4ee5\u4e0b\u683c\u5f0f":11,"\u8f6c\u6362\u8017\u65f6":41,"\u8f93\u5165":[88,90,110,114],"\u8f93\u5165\u4e86\u6027\u80fd\u5206\u6790\u7ed3\u679c":107,"\u8f93\u5165\u548c\u8f93\u51fa\u90fd\u662f\u5355\u5c42\u5e8f\u5217":113,"\u8f93\u5165\u548c\u8f93\u51fa\u90fd\u662f\u53cc\u5c42\u5e8f\u5217":113,"\u8f93\u5165\u5e8f\u5217\u4e2d\u5143\u7d20\u7684\u603b\u6570":81,"\u8f93\u5165\u6570\u636e\u4e3a\u4e00\u4e2a\u5b8c\u6574\u7684\u65f6\u95f4\u5e8f\u5217":111,"\u8f93\u5165\u6570\u636e\u4e3a\u5728\u5355\u5c42rnn\u6570\u636e\u91cc\u9762":111,"\u8f93\u5165\u6570\u636e\u53ef\u5206\u4e3a":89,"\u8f93\u5165\u6570\u636e\u6574\u4f53\u4e0a\u662f\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217":111,"\u8f93\u5165\u6570\u636e\u7684\u5b57\u5178\u7ef4\u6570\u662f1\u767e\u4e07":105,"\u8f93\u5165\u6570\u636e\u7c7b\u578b":89,"\u8f93\u5165\u662f\u5426\u662f\u8f6c\u7f6e\u7684":74,"\u8f93\u5165\u662f\u7531\u4e00\u4e2alist\u4e2d\u7684\u7f51\u7edc\u5c42\u5b9e\u4f8b\u7684\u540d\u5b57\u7ec4\u6210\u7684":74,"\u8f93\u5165\u68af\u5ea6":42,"\u8f93\u5165\u7684\u540d\u5b57":74,"\u8f93\u5165\u7684\u5927\u5c0f":74,"\u8f93\u5165\u7684\u7c7b\u578b":74,"\u8f93\u5165\u9700\u8981\u9884\u6d4b\u7684\u5411\u91cf\u7ec4":84,"\u8f93\u51fa":[75,90,110,114],"\u8f93\u51fa\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":113,"\u8f93\u51fa\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":113,"\u8f93\u51fa\u4fe1\u606f\u6709\u673a\u5730\u7ec4\u7ec7\u5728\u4e00\u8d77":89,"\u8f93\u51fa\u51fd\u6570":114,"\u8f93\u51fa\u521b\u5efa":[89,90],"\u8f93\u51fa\u5e8f\u5217\u7684\u7c7b\u578b":110,"\u8f93\u51fa\u5e8f\u5217\u7684\u8bcd\u8bed\u6570\u548c\u8f93\u5165\u5e8f\u5217\u4e00\u81f4":113,"\u8f93\u51fa\u6240\u643a\u5e26\u7684\u5e8f\u5217\u4fe1\u606f":89,"\u8f93\u51fa\u6570\u636e\u548c\u8f93\u51fa\u68af\u5ea6":42,"\u8f93\u51fa\u6570\u636e\u548c\u8f93\u51fa\u68af\u5ea6\u7684\u8f6c\u6362":42,"\u8f93\u51fa\u6570\u636e\u662f\u5728\u4e0a\u6587\u4ecb\u7ecd\u7684":89,"\u8f93\u51fa\u6570\u636e\u6709\u673a\u5730\u7ec4\u7ec7\u5728\u4e00\u8d77":90,"\u8f93\u51fa\u6570\u636e\u7ec4\u7ec7":[88,90],"\u8f93\u51fa\u7531":89,"\u8f93\u51fa\u7684\u5e8f\u5217\u4fe1\u606f":89,"\u8f93\u51fa\u7684\u68af\u5ea6":103,"\u8f93\u51fa\u7ed3\u679c\u53ef\u80fd\u4f1a\u968f\u7740\u5bb9\u5668\u7684\u6d88\u8017\u800c\u88ab\u5220\u9664":96,"\u8f93\u51fa\u88ab\u7ec4\u7ec7\u4e3a":89,"\u8f93\u51fa\u88ab\u7ec4\u7ec7\u4e3a\u4e00\u4e2a":89,"\u8f93\u51fa\u90fd\u4f1a\u5bf9\u5e94\u6709\u81ea\u5df1\u7684":[89,90],"\u8fbe\u5230\u5bb9\u707e\u7684\u76ee\u7684":10,"\u8fc7\u4e86\u4e00\u4e2a\u5f88\u7b80\u5355\u7684recurrent_group":111,"\u8fc7\u5b8c\u6240\u6709\u8bad\u7ec3\u6570\u636e\u5373\u4e3a\u4e00\u4e2apass":81,"\u8fc7\u7a0b\u4e2d\u6240\u6709\u65f6\u95f4\u6b65":41,"\u8fd0\u884c":90,"\u8fd0\u884c\u4e00\u4e2a":0,"\u8fd0\u884c\u4e0b\u9762\u547d\u4ee4\u53ef\u4ee5\u8fdb\u884c\u7f16\u8bd1":75,"\u8fd0\u884c\u5355\u5143\u6d4b\u8bd5\u6d4b\u65f6\u9700\u8981\u7f16\u8bd1\u6574\u4e2a\u5de5\u7a0b":75,"\u8fd0\u884c\u5931\u8d25":105,"\u8fd0\u884c\u5b8c\u6210\u540e":93,"\u8fd0\u884c\u5b8c\u6bd5\u540e\u8f93\u51fa":107,"\u8fd0\u884c\u6027\u80fd\u5206\u6790\u7684\u65f6\u5019":107,"\u8fd0\u884c\u65e5\u5fd7":93,"\u8fd0\u884c\u65f6\u4e5f\u53ef\u80fd\u56e0\u4e3a\u591a\u7ebf\u7a0b\u4ea7\u751f\u6df7\u4e71\u4e0d\u53ef\u8bfb\u7684\u6027\u80fd\u5206\u6790\u7ed3\u679c":107,"\u8fd0\u884c\u65f6\u4f1a\u81ea\u52a8\u627e\u5230\u7cfb\u7edf\u4e2d\u5b89\u88c5\u7684cuda\u548ccudnn\u5e93\u8fdb\u884c\u7f16\u8bd1\u548c\u6267\u884c":0,"\u8fd0\u884c\u65f6c":90,"\u8fd0\u884c\u73af\u5883":104,"\u8fd0\u884c\u7684\u4e00\u4e9b\u53c2\u6570\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\u4f20\u9012\u5230\u5bb9\u5668\u5185":97,"\u8fd0\u884c\u8be5\u7f16\u8bd1\u5de5\u5177\u94fe\u9700\u8981\u4e00\u53f0":118,"\u8fd0\u884c\u9636\u6bb5":104,"\u8fd1\u671f\u76ee\u6807":42,"\u8fd4\u56de\u7684\u662f":84,"\u8fd4\u56de\u7b2c\u4e8c\u6b65":63,"\u8fd4\u56de\u7b2ci\u4e2a\u8f93\u5165\u77e9\u9635":74,"\u8fd4\u56depython\u7aef\u7684\u8ba1\u7b97\u7ed3\u679c":75,"\u8fd8\u4f1a\u4e0b\u8f7dmkl":0,"\u8fd8\u4f1a\u5f3a\u5236\u8bbe\u7f6e\u4e00\u4e9bpaddlepaddle\u53c2\u6570\u7684\u503c":116,"\u8fd8\u4f1a\u8f93\u51fa\u4e00\u4e2a":72,"\u8fd8\u53ef\u4ee5\u901a\u8fc7\u51cf\u5c0f\u5b66\u4e60\u7387\u6216\u8005\u5bf9\u6570\u636e\u8fdb\u884c\u5f52\u4e00\u5316\u5904\u7406\u6765\u89e3\u51b3\u8fd9\u7c7b\u95ee\u9898":81,"\u8fd8\u662f\u4ece":11,"\u8fd8\u662f\u865a\u62df\u673a":0,"\u8fd8\u9700\u8981\u5728\u8282\u70b9\u4e0a\u5b89\u88c5\u5bf9\u5e94\u7684gpu\u9a71\u52a8\u4ee5\u53cacuda":101,"\u8fd8\u9700\u8981\u91cd\u5199":75,"\u8fd9":81,"\u8fd98\u79cdlearning_rate_schedule\u53ca\u5176\u5bf9\u5e94\u5b66\u4e60\u7387\u8ba1\u7b97\u65b9\u5f0f\u5982\u4e0b":83,"\u8fd9\u4e00\u4e2a\u5e93":87,"\u8fd9\u4e00\u5757\u7684\u8017\u65f6\u6bd4\u4f8b\u771f\u7684\u592a\u9ad8":108,"\u8fd9\u4e00\u5c42\u8fdb\u884c\u5c01\u88c5":46,"\u8fd9\u4e00\u6570\u636e\u683c\u5f0f\u7684\u8f6c\u6362\u64cd\u4f5c":41,"\u8fd9\u4e00\u6982\u5ff5\u4e0d\u518d\u7410\u788e":46,"\u8fd9\u4e00\u8282\u5bf9\u56fe1\u4e2d\u9884\u6d4b\u4ee3\u7801\u7f16\u5199\u76845\u4e2a\u6b65\u9aa4\u8fdb\u884c\u4ecb\u7ecd\u548c\u8bf4\u660e":90,"\u8fd9\u4e00\u8ba1\u7b97\u5355\u5143":82,"\u8fd9\u4e00\u8fc7\u7a0b\u5bf9\u7528\u6237\u662f\u5b8c\u5168\u900f\u660e\u7684":113,"\u8fd9\u4e09\u4e2a\u5206\u652f":63,"\u8fd9\u4e24\u4e2a\u6307\u6807\u4ee3\u8868\u4e86\u67d0\u4e00\u4e2a\u51fd\u6570\u771f\u5b9e\u7684\u8fd0\u884c\u65f6\u95f4":107,"\u8fd9\u4e2a":3,"\u8fd9\u4e2a\u4efb\u52a1\u7684\u914d\u7f6e\u4e3a":81,"\u8fd9\u4e2a\u4efb\u52a1\u7684dataprovider\u4e3a":81,"\u8fd9\u4e2a\u4f8b\u5b50\u6709\u4e24\u5904\u4e0d\u540c":75,"\u8fd9\u4e2a\u51fd\u6570\u672c\u8eab\u4f1a\u5728\u8ba1\u7b97\u524d\u5c06\u539f\u6570\u636e\u8f6c\u6362\u4e3a\u66f4\u9002\u5408\u82f1\u7279\u5c14\u5e73\u53f0\u7684\u5185\u90e8\u683c\u5f0f":41,"\u8fd9\u4e2a\u51fd\u6570\u7684":114,"\u8fd9\u4e2a\u51fd\u6570\u8fdb\u884c\u53d8\u6362":111,"\u8fd9\u4e2a\u51fd\u6570\u9700\u8981\u8bbe\u7f6e":114,"\u8fd9\u4e2a\u52a8\u6001\u5e93\u7684\u8fde\u63a5\u53c2\u6570\u4e0epaddle\u7684\u5176\u4ed6\u4e8c\u8fdb\u5236":46,"\u8fd9\u4e2a\u53c2\u6570\u4e5f\u4e0d\u4f1a\u4e00\u5e76\u5220\u9664":46,"\u8fd9\u4e2a\u5730\u5740\u6765\u8868\u793a\u6b64\u6b65\u9aa4\u6240\u6784\u5efa\u51fa\u7684\u955c\u50cf":97,"\u8fd9\u4e2a\u57fa\u7c7b":74,"\u8fd9\u4e2a\u5934\u6587\u4ef6\u4e0d\u5047\u8bbe\u5176\u4ed6\u6587\u4ef6\u7684\u5f15\u7528\u987a\u5e8f":46,"\u8fd9\u4e2a\u5e8f\u5217\u7684\u6bcf\u4e2a\u5143\u7d20\u53c8\u662f\u4e00\u4e2a\u5e8f\u5217":113,"\u8fd9\u4e2a\u60c5\u51b5\u4e0b\u6240\u6709\u7684\u6587\u4ef6\u4f1a\u5b58\u5728\u6574\u7406\u8fc7\u7684\u7684\u6587\u4ef6\u76ee\u5f55":77,"\u8fd9\u4e2a\u63a5\u53e3\u9700\u8981\u505a\u5230":45,"\u8fd9\u4e2a\u6570\u636e\u4e5f\u88ab\u5355\u5c42rnn\u7f51\u7edc\u76f4\u63a5\u4f7f\u7528":111,"\u8fd9\u4e2a\u6587\u4ef6\u5177\u6709\u72ec\u7279\u7684\u8bed\u6cd5":45,"\u8fd9\u4e2a\u662f\u76ee\u524d\u63a8\u8350\u7684\u4f7f\u7528\u65b9\u6cd5":77,"\u8fd9\u4e2a\u73af\u5883\u53d8\u91cf\u5173\u95edopenmp\u4f18\u5316":107,"\u8fd9\u4e2a\u76ee\u5f55\u4e2d\u9664\u4e86":46,"\u8fd9\u4e2a\u793a\u4f8b":90,"\u8fd9\u4e2a\u795e\u7ecf\u7f51\u7edc\u5355\u5143\u5c31\u53ebmemori":111,"\u8fd9\u4e2a\u7c7b\u7684\u53c2\u6570\u5305\u62ec":74,"\u8fd9\u4e2a\u7c7b\u9700\u8981\u7ee7\u627f":74,"\u8fd9\u4e2a\u7ed3\u6784\u4f53\u4e2d\u7684\u53e6\u4e00\u4e2a\u9879\u76ee\u662f":46,"\u8fd9\u4e2a\u7ed3\u6784\u4f53\u5305\u542b\u4e24\u4e2a\u9879\u76ee":46,"\u8fd9\u4e2a\u811a\u672c\u8c03\u7528":0,"\u8fd9\u4e2a\u8f93\u5165\u4e0d\u53c2\u4e0e":75,"\u8fd9\u4e2a\u8fc7\u7a0b\u5bf9\u7528\u6237\u4e5f\u662f\u900f\u660e\u7684":113,"\u8fd9\u4e2a\u8fc7\u7a0b\u9664\u4e86\u7f16\u8bd1paddlepaddle\u4e3a":72,"\u8fd9\u4e2a\u9009\u62e9":[41,42],"\u8fd9\u4e2a\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u751f\u6210\u4e00\u7cfb\u5217\u6743\u91cd":114,"\u8fd9\u4e2a\u9759\u6001\u5e93\u5305\u542b\u4e86paddle\u7684\u5168\u90e8\u7b26\u53f7":46,"\u8fd9\u4e2ainstance\u53ef\u4ee5\u662f\u5355\u4e2a\u503c":11,"\u8fd9\u4e2aissu":0,"\u8fd9\u4e2ajob\u624d\u7b97\u6210\u529f\u7ed3\u675f":97,"\u8fd9\u4e2alayer\u7684\u8f93\u51fa\u4f1a\u4f5c\u4e3a\u6574\u4e2a":113,"\u8fd9\u4e5f\u4f1a\u6781\u5927\u51cf\u5c11\u6570\u636e\u8bfb\u5165\u7684\u8017\u65f6":81,"\u8fd9\u4e9b\u4f1a\u5728":[41,42],"\u8fd9\u4e9b\u51fd\u6570\u4f1a\u5c06\u5bf9\u5e94\u5185\u5bb9\u6dfb\u52a0\u5230":75,"\u8fd9\u4e9b\u51fd\u6570\u4f1a\u6839\u636e\u8f93\u5165\u53c2\u6570\u91cd\u65b0\u8bbe\u7f6e\u5185\u90e8\u548c\u5916\u90e8\u5b58\u50a8":42,"\u8fd9\u4e9b\u5206\u5e03\u5f0f\u5b58\u50a8\u670d\u52a1\u901a\u5e38\u4f1a\u628a\u6570\u636e\u5207\u5272\u6210\u591a\u4e2a\u5206\u7247\u5206\u5e03\u5f0f\u7684\u5b58\u50a8\u5728\u591a\u4e2a\u8282\u70b9\u4e4b\u4e0a":11,"\u8fd9\u4e9b\u53c2\u6570\u53ef\u4ee5\u901a\u8fc7":91,"\u8fd9\u4e9b\u53c2\u6570\u7684\u5177\u4f53\u63cf\u8ff0":97,"\u8fd9\u4e9b\u540d\u5b57\u5fc5\u987b\u8981\u5199\u5bf9":74,"\u8fd9\u4e9b\u6570\u636e\u4f1a\u88ab\u7528\u6765\u66f4\u65b0\u53c2\u6570":81,"\u8fd9\u4e9b\u6570\u636e\u4f7f\u7528\u7684\u5185\u5b58\u4e3b\u8981\u548c\u4e24\u4e2a\u53c2\u6570\u6709\u5173\u7cfb":81,"\u8fd9\u4e9b\u7279\u5f81\u6570\u636e\u4e4b\u95f4\u7684\u987a\u5e8f\u662f\u6709\u610f\u4e49\u7684":111,"\u8fd9\u4e9b\u955c\u50cf\u4e5f\u53ef\u4ee5\u4ece":63,"\u8fd9\u4efd\u6559\u7a0b\u5c55\u793a\u4e86\u5982\u4f55\u5728paddlepaddle\u4e2d\u5b9e\u73b0\u4e00\u4e2a\u81ea\u5b9a\u4e49\u7684\u7f51\u7edc\u5c42":74,"\u8fd9\u4f1a\u63d0\u793a\u5f53\u524d\u76ee\u5f55\u7684\u4e00\u4e9b\u53d8\u5316":72,"\u8fd9\u4f1a\u7ed9\u8bc4\u5ba1\u4eba\u5e26\u6765\u5f88\u5927\u56f0\u6270":72,"\u8fd9\u4f1a\u81ea\u52a8\u8fdb\u884c\u7f51\u7edc\u914d\u7f6e\u4e2d\u58f0\u660e\u7684\u6fc0\u6d3b\u64cd\u4f5c":74,"\u8fd9\u4fbf\u662f\u4e00\u79cd\u53cc\u5c42rnn\u7684\u8f93\u5165\u6570\u636e":111,"\u8fd9\u51e0\u4e2a\u7f16\u8bd1\u9009\u9879\u7684\u8bbe\u7f6e":0,"\u8fd9\u53e5\u8868\u793a\u4f7f\u7528\u57fa\u7c7b":75,"\u8fd9\u53ef\u4ee5\u5e2e\u60a8\u7701\u6389\u82b1\u4e00\u5c0f\u65f6\u5b89\u88c5\u548c\u914d\u7f6e\u5404\u79cd\u5f00\u53d1\u5de5\u5177":0,"\u8fd9\u53ef\u4ee5\u8ba9\u5176\u4ed6\u4eba\u77e5\u9053\u8fd9\u6b21\u63d0\u4ea4\u505a\u4e86\u54ea\u4e9b\u6539\u53d8":72,"\u8fd9\u53ef\u4ee5\u901a\u8fc7":72,"\u8fd9\u548c\u5355\u5c42rnn\u7684\u914d\u7f6e\u662f\u7b49\u4ef7\u7684":111,"\u8fd9\u56db\u4e2a\u5e8f\u5217\u53c8\u5206\u522b\u542b\u67093":89,"\u8fd9\u56db\u6761\u6570\u636e\u540c\u65f6\u5904\u7406\u7684\u53e5\u5b50\u6570\u91cf\u4e3a":111,"\u8fd9\u5728\u6784\u9020\u975e\u5e38\u590d\u6742\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u65f6\u662f\u6709\u7528\u7684":114,"\u8fd9\u5bf9\u4e8e\u901a\u5e38\u7684java\u7684\u5f00\u53d1\u8005\u6765\u8bf4":45,"\u8fd9\u5c06\u4f1a\u5bfc\u81f4\u5355\u5143\u6d4b\u8bd5\u51fa\u9519":75,"\u8fd9\u5c06\u4f1a\u5bfc\u81f4\u7f16\u8bd1\u51fa\u9519":75,"\u8fd9\u610f\u5473\u7740":114,"\u8fd9\u610f\u5473\u7740\u9664\u4e86\u6307\u5b9adevic":105,"\u8fd9\u65f6":[81,90],"\u8fd9\u65f6\u5728\u4f7f\u7528":83,"\u8fd9\u65f6\u7684":89,"\u8fd9\u65f6\u7684\u9700\u8981\u540c\u65f6\u63d0\u4f9b":89,"\u8fd9\u65f6\u884c\u504f\u79fb\u548c\u5217\u53f7\u6307\u5b9a\u7684\u5143\u7d20\u9ed8\u8ba4\u5176\u503c\u4e3a1":89,"\u8fd9\u65f6\u8fdb\u884c\u77e9\u9635\u4e58\u6cd5\u8fd0\u7b97\u5c31\u53ef\u80fd\u5bfc\u81f4\u6d6e\u70b9\u6570\u6ea2\u51fa":81,"\u8fd9\u65f6\u9700\u8981\u8c03\u7528\u521b\u5efa\u5e8f\u5217\u4fe1\u606f\u548c\u4e3a":89,"\u8fd9\u662f\u4e00\u79cd\u6309\u5df2\u8bad\u7ec3\u6837\u672c\u6570\u5206\u6bb5\u53d6\u503c\u7684\u5b66\u4e60\u7387\u9000\u706b\u65b9\u6cd5":83,"\u8fd9\u662f\u4e00\u79cd\u6309\u5df2\u8bad\u7ec3pass\u6570\u5206\u6bb5\u53d6\u503c\u7684\u5b66\u4e60\u7387\u9000\u706b\u65b9\u6cd5":83,"\u8fd9\u662f\u4e00\u79cd\u975e\u5e38\u7075\u6d3b\u7684\u6570\u636e\u7ec4\u7ec7\u65b9\u5f0f":110,"\u8fd9\u662f\u56e0\u4e3a":45,"\u8fd9\u662f\u5f00\u6e90\u793e\u533a\u7684\u57fa\u672c\u793c\u8c8c":72,"\u8fd9\u662f\u666e\u901a\u7684\u5355\u5c42\u65f6\u95f4\u5e8f\u5217\u7684dataprovider\u4ee3\u7801":111,"\u8fd9\u662f\u6700\u4fbf\u6377\u7684\u5b89\u88c5\u65b9\u5f0f":2,"\u8fd9\u662f\u76ee\u524dcmake\u5bfb\u627epython\u7684\u903b\u8f91\u5b58\u5728\u7f3a\u9677":78,"\u8fd9\u6837":[46,92],"\u8fd9\u6837\u4e0b\u4e00\u4e2acpu":42,"\u8fd9\u6837\u4fdd\u5b58\u5728\u5206\u5e03\u5f0f\u5b58\u50a8\u4e2d\u7684\u6570\u636e\u53ef\u4ee5\u88ab\u96c6\u7fa4\u4e2d\u7684\u6bcf\u4e2a\u8282\u70b9\u8bfb\u53d6\u5230":91,"\u8fd9\u6837\u4fdd\u8bc1":63,"\u8fd9\u6837\u4fdd\u8bc1\u8fd0\u884c\u7ed3\u675f\u4e4b\u540e\u7684":0,"\u8fd9\u6837\u505a\u53ef\u4ee5\u6781\u5927\u7684\u51cf\u5c11\u5185\u5b58\u5360\u7528":81,"\u8fd9\u6837\u53ef\u4ee5\u514d\u53bb\u5355\u72ec\u5b89\u88c5\u7f16\u8bd1\u4f9d\u8d56\u7684\u6b65\u9aa4":0,"\u8fd9\u6837\u53ef\u4ee5\u51cf\u5c0fgpu\u5185\u5b58":105,"\u8fd9\u6837\u5982\u679c\u9047\u5230\u95ee\u9898":0,"\u8fd9\u6837\u5bb9\u5668\u7684":97,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u5728\u4e91\u7aef\u6267\u884c\u591a\u79cd\u6570\u636e\u7c7b\u8ba1\u7b97\u4efb\u52a1":11,"\u8fd9\u6837\u5df2\u7ecf\u4f20\u8f93\u6210\u529f\u7684\u90e8\u5206\u5c31\u4e0d\u7528\u91cd\u65b0\u4f20\u8f93\u4e86":27,"\u8fd9\u6837\u5e26\u6765\u7684\u597d\u5904\u5c31\u662f\u4e0d\u9700\u8981\u4e00\u76f4\u6e05\u7a7amemori":42,"\u8fd9\u6837\u5f53\u8be5pull":72,"\u8fd9\u6837\u65e2\u4f7f\u5f97\u6700\u7ec8\u4fdd\u5b58\u7684\u53c2\u6570\u683c\u5f0f\u4e0epaddlepaddle\u4e00\u81f4":42,"\u8fd9\u6837\u6781\u5927\u5730\u63d0\u9ad8\u4e86\u8ba1\u7b97\u7684\u5e76\u884c\u6027":92,"\u8fd9\u6837\u7684\u88c5\u9970\u5668":74,"\u8fd9\u6837\u7684\u8bdd":96,"\u8fd9\u6837\u8bad\u7ec3\u6587\u4ef6\u7684\u4e2a\u6570\u4f1a\u6bd4\u8f83\u591a":91,"\u8fd9\u6b63\u662f\u5b83\u4eec\u901f\u5ea6\u5feb\u7684\u539f\u56e0":108,"\u8fd9\u7528\u4e8e\u5728\u591a\u7ebf\u7a0b\u548c\u591a\u673a\u4e0a\u66f4\u65b0\u53c2\u6570":74,"\u8fd9\u79cd\u521d\u59cb\u5316\u65b9\u5f0f\u5728\u4e00\u822c\u60c5\u51b5\u4e0b\u4e0d\u4f1a\u4ea7\u751f\u5f88\u5dee\u7684\u7ed3\u679c":83,"\u8fd9\u79cd\u5b89\u88c5\u65b9\u5f0f\u4f1a\u6d89\u53ca\u5230\u4e00\u4e9b\u7b2c\u4e09\u65b9\u5e93\u7684\u4e0b\u8f7d":2,"\u8fd9\u79cd\u60c5\u51b5\u4e0b\u4e0d\u9700\u8981\u91cd\u5199\u8be5\u51fd\u6570":74,"\u8fd9\u79cd\u60c5\u51b5\u591a\u51fa\u73b0\u5728\u4f7f\u7528\u591a\u7ebf\u7a0b\u9884\u6d4b\u65f6":90,"\u8fd9\u79cd\u60c5\u51b5\u5e38\u5e38\u53d1\u751f\u5728":81,"\u8fd9\u79cd\u65b9\u5f0f\u5bf9\u5185\u5b58\u6d88\u8017\u8f83\u5927":82,"\u8fd9\u79cd\u65b9\u5f0f\u5fc5\u987b\u4f7f\u7528paddle\u5b58\u50a8\u7684\u6a21\u578b\u8def\u5f84\u683c\u5f0f":105,"\u8fd9\u79cd\u65b9\u5f0f\u6700\u4e3a\u7b80\u4fbf":87,"\u8fd9\u79cd\u751f\u6210\u6280\u672f\u53ea\u7528\u4e8e\u7c7b\u4f3c\u89e3\u7801\u5668\u7684\u751f\u6210\u8fc7\u7a0b":114,"\u8fd9\u79cd\u7c7b\u578b\u7684\u8f93\u5165\u5fc5\u987b\u901a\u8fc7":113,"\u8fd9\u79cd\u94fe\u63a5\u65b9\u5f0f\u4e3b\u8981\u7528\u4e8e\u79fb\u52a8\u7aef\u9884\u6d4b":87,"\u8fd9\u79cd\u96c6\u7fa4\u8282\u70b9\u7ba1\u7406\u65b9\u5f0f\u4f1a\u5728\u5c06\u6765\u4f7f\u7528":97,"\u8fd9\u7bc7":1,"\u8fd9\u7bc7\u6587\u6863":72,"\u8fd9\u7bc7\u6587\u6863\u4e4b\u540e\u90e8\u5206\u4f1a\u4f7f\u7528":90,"\u8fd9\u7bc7\u6587\u6863\u4e4b\u540e\u90e8\u5206\u4f1a\u7edf\u4e00\u4f7f\u7528":89,"\u8fd9\u7bc7\u6587\u6863\u4e4b\u540e\u90e8\u5206\u5c06\u4f1a\u7edf\u4e00\u4f7f\u7528":89,"\u8fd9\u7bc7\u6587\u6863\u4ecb\u7ecd":90,"\u8fd9\u7bc7\u6587\u6863\u4ecb\u7ecd\u5728":118,"\u8fd9\u7bc7\u6587\u6863\u4ecb\u7ecd\u5728\u4f7f\u7528":89,"\u8fd9\u7bc7\u6587\u6863\u4ecb\u7ecd\u57fa\u4e8e":0,"\u8fd9\u7bc7\u6587\u6863\u7684\u4e4b\u540e\u90e8\u5206\u4f1a\u4f7f\u7528":90,"\u8fd9\u7bc7\u6587\u7ae0":0,"\u8fd9\u7ec4\u8bed\u4e49\u76f8\u540c\u7684\u793a\u4f8b\u914d\u7f6e\u5982\u4e0b":111,"\u8fd9\u884c\u547d\u4ee4\u4e2d":107,"\u8fd9\u901a\u8fc7\u83b7\u5f97\u53cd\u5411\u5faa\u73af\u7f51\u7edc\u7684\u7b2c\u4e00\u4e2a\u5b9e\u4f8b":114,"\u8fd9\u90fd\u9700\u8981\u8fd9\u4e2a\u63a5\u53e3\u6309\u7167\u7ea6\u5b9a\u4fd7\u6210\u7684\u89c4\u5219\u6765\u6ce8\u91ca\u5b8c\u5907":45,"\u8fd9\u91cc":[0,42,72,83,97,114],"\u8fd9\u91cc\u4e0d\u518d\u8d58\u8ff0":75,"\u8fd9\u91cc\u4ecb\u7ecdc":90,"\u8fd9\u91cc\u4f7f\u7528\u4e86\u7528":107,"\u8fd9\u91cc\u4f7f\u7528\u4e86paddlepaddle\u9884\u5b9a\u4e49\u597d\u7684rnn\u5904\u7406\u51fd\u6570":111,"\u8fd9\u91cc\u4f7f\u7528\u7b80\u5355\u7684":81,"\u8fd9\u91cc\u5c06\u4ecb\u7ecdpaddlepaddle\u7684\u57fa\u672c\u4f7f\u7528\u6982\u5ff5":84,"\u8fd9\u91cc\u6211\u4eec\u5c55\u793a\u4e00\u4efd\u7b80\u5316\u8fc7\u7684\u4ee3\u7801":74,"\u8fd9\u91cc\u6211\u4eec\u901a\u8fc7\u5728kubernetes\u96c6\u7fa4\u4e0a\u542f\u52a8\u4e00\u4e2ajob\u6765\u4e0b\u8f7d\u5e76\u5207\u5272\u6570\u636e":97,"\u8fd9\u91cc\u6709\u4e24\u79cd\u6709\u6548\u7684\u89e3\u51b3\u65b9\u6cd5":81,"\u8fd9\u91cc\u68c0\u9a8c\u8fd0\u884c\u65f6\u95f4\u6a21\u578b\u7684\u6536\u655b":93,"\u8fd9\u91cc\u7684dockerimage\u4f5c\u4e3a\u7f16\u8bd1\u73af\u5883\u4ee5\u652f\u6301\u66f4\u591a\u7684linux":63,"\u8fd9\u91cc\u7684eigentensor\u4e4b\u95f4\u7684\u8fd0\u7b97\u53ea\u662f\u6539\u53d8\u4e86\u539f\u6709tensor\u4e2d\u7684\u6570\u636e":76,"\u8fd9\u91cc\u9009\u62e90":63,"\u8fd9\u91cc\u9700\u8981\u7528\u6237\u989d\u5916\u6ce8\u610f":10,"\u8fd9\u9700\u8981\u8054\u5408\u6211\u4eec\u7b2c\u4e8c\u8282":107,"\u8fdb\u4e00\u6b65\u4f18\u5316":42,"\u8fdb\u4e3b\u4ed3\u5e93\u540e":72,"\u8fdb\u5165":63,"\u8fdb\u5165\u5bb9\u5668":96,"\u8fdb\u5165\u5bf9\u5e94\u7684\u76ee\u5f55":78,"\u8fdb\u7a0b\u542f\u52a8\u7684\u5fc5\u8981\u53c2\u6570":97,"\u8fdb\u7a0b\u7684":93,"\u8fdb\u7a0b\u7684\u542f\u52a8\u53c2\u6570":97,"\u8fdb\u7a0b\u7684\u8fd0\u884c\u73af\u5883":97,"\u8fdb\u7a0b\u9700\u8981\u7684":97,"\u8fdb\u800c\u591a\u673a":107,"\u8fdb\u800c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u5982\u4e0b\u547d\u4ee4\u5f00\u542f\u4e00\u4e2ahttp\u670d\u52a1":107,"\u8fdb\u800c\u6307\u5b9a\u4e86python\u53ef\u6267\u884c\u6587\u4ef6\u7684\u8def\u5f84":107,"\u8fdb\u800c\u8fdb\u884c\u4ee3\u7801\u8bc4\u5ba1":63,"\u8fdb\u884c\u4e86":111,"\u8fdb\u884c\u5206\u5e03\u5f0f\u8bad\u7ec3\u7684\u65b9\u6848":97,"\u8fdb\u884c\u5206\u5e03\u5f0f\u8bad\u7ec3\u7684\u65b9\u6cd5":97,"\u8fdb\u884c\u524d\u5411\u8ba1\u7b97":90,"\u8fdb\u884c\u56de\u590d":72,"\u8fdb\u884c\u5e8f\u5217\u5316":90,"\u8fdb\u884c\u5f00\u53d1":72,"\u8fdb\u884c\u62c6\u89e3":111,"\u8fdb\u884c\u6fc0\u6d3b\u64cd\u4f5c":74,"\u8fdb\u884c\u7f16\u8bd1\u548c\u5b89\u88c5":116,"\u8fdb\u884c\u8bad\u7ec3":90,"\u8fdb\u884c\u8bbe\u7f6e":75,"\u8fdb\u884c\u90e8\u7f72":94,"\u8fdb\u884c\u94fe\u63a5":87,"\u8fdb\u884c\u9884\u6d4b\u4f9d\u8d56\u4e8e\u5c06":87,"\u8fdb\u884c\u9884\u6d4b\u65f6":90,"\u8fdb\u884cpython\u4e0ec":107,"\u8fdb\u9636\u4f7f\u7528":115,"\u8fdb\u9636\u6307\u5357":84,"\u8fde\u63a5":113,"\u8fde\u63a5\u5230pserver\u7684\u7aef\u53e3":91,"\u8fde\u63a5\u5230pserver\u7684\u7aef\u53e3\u4e2a\u6570":91,"\u9000\u51fa\u5bb9\u5668":96,"\u9009\u62e9\u4e0b\u8f7d\u4f7f\u7528\u4e0d\u540c\u7684blas\u5e93\u7684docker\u955c\u50cf":1,"\u9009\u62e9\u662f\u5426\u7f16\u8bd1mkl":42,"\u9009\u62e9\u76ee\u6807\u5206\u652f":72,"\u9009\u62e9\u8def\u5f84\u6765\u52a8\u6001\u52a0\u8f7dnvidia":103,"\u9009\u62e9\u9700\u8981\u53d1\u5e03\u7684\u7248\u672c":63,"\u9009\u9879":0,"\u900f\u4f20\u7528\u6237\u8eab\u4efd\u7684\u529e\u6cd5":27,"\u9012\u5f52\u795e\u7ecf\u7f51\u7edc":102,"\u901a\u5e38":[46,75,107],"\u901a\u5e38\u4f1a\u4f7f\u7528\u73af\u5883\u53d8\u91cf\u914d\u7f6ejob\u7684\u914d\u7f6e\u4fe1\u606f":97,"\u901a\u5e38\u4f1a\u4f7f\u7528mapreduce\u4efb\u52a1\u7684\u8f93\u51fa\u7ed3\u679c\u4f5c\u4e3a\u8bad\u7ec3\u7ed3\u679c":91,"\u901a\u5e38\u4f7f\u7528\u7a00\u758f\u8bad\u7ec3\u6765\u52a0\u901f\u8ba1\u7b97\u8fc7\u7a0b":105,"\u901a\u5e38\u4f7f\u7528cento":3,"\u901a\u5e38\u505a\u6cd5\u662f\u4ece\u4e00\u4e2a\u6bd4\u8f83\u5927\u7684learning_rate\u5f00\u59cb\u8bd5":83,"\u901a\u5e38\u5305\u542b\u4e00\u4e2acpu\u7248\u672c\u548c\u4e00\u4e2agpu\u7248\u672c":63,"\u901a\u5e38\u540d\u5b57\u662f":72,"\u901a\u5e38\u60c5\u51b5\u4e0b":108,"\u901a\u5e38\u6211\u4eec\u4f1a\u5b89\u88c5ceph\u7b49\u5206\u5e03\u5f0f\u6587\u4ef6\u7cfb\u7edf\u6765\u5b58\u50a8\u8bad\u7ec3\u6570\u636e":96,"\u901a\u5e38\u6307\u5c06\u4e00\u4e2a\u6574\u4f53\u62c6\u5206\u6210\u591a\u4efd\u7684\u5176\u4e2d\u7684\u4e00\u4efd":10,"\u901a\u5e38\u6709\u4e24\u4e2a\u65b9\u6cd5\u6765\u6784\u5efa\u57fa\u4e8e":118,"\u901a\u5e38\u7528\u4e8e\u8868\u793a\u79bb\u6563\u7684\u7c7b\u522b\u6807\u7b7e":89,"\u901a\u5e38\u7684\u505a\u6cd5\u662f\u4f7f\u7528":114,"\u901a\u5e38\u7684\u505a\u6cd5\u662f\u5c06\u914d\u7f6e\u5b58\u4e8e":74,"\u901a\u5e38\u8981\u6c42\u65f6\u95f4\u6b65\u4e4b\u95f4\u5177\u6709\u4e00\u4e9b\u4f9d\u8d56\u6027":111,"\u901a\u5e38\u89c2\u5bdf\u70ed\u70b9\u51fd\u6570\u95f4\u7684\u8c03\u7528\u5173\u7cfb":107,"\u901a\u5e38\u90fd\u4f1a\u4f7f\u7528\u4e0b\u9762\u8fd9\u4e9b\u547d\u4ee4\u884c\u53c2\u6570":105,"\u901a\u5e38\u9700\u8981\u53bb\u6389\u7f51\u7edc\u4e2d\u7684":90,"\u901a\u7528":102,"\u901a\u8fc7":[72,74,75,81,89,111],"\u901a\u8fc7\u4e24\u4e2a\u5d4c\u5957\u7684":113,"\u901a\u8fc7\u4f7f\u7528":0,"\u901a\u8fc7\u4f7f\u7528\u8fd9\u4e9bapi":41,"\u901a\u8fc7\u51fd\u6570":97,"\u901a\u8fc7\u547d\u4ee4\u884c\u53c2\u6570":81,"\u901a\u8fc7\u591a\u4e2a\u7ebf\u7a0b\u5171\u4eab\u540c\u4e00\u4e2a\u6a21\u578b\u6765\u51cf\u5c11\u5185\u5b58\u5f00\u9500":90,"\u901a\u8fc7\u5f15\u7528memory\u5f97\u5230\u8fd9\u4e2alayer\u4e0a\u4e00\u4e2a\u65f6\u523b\u7684\u8f93\u51fa":113,"\u901a\u8fc7\u5f15\u7528memory\u5f97\u5230\u8fd9\u4e2alayer\u4e0a\u4e00\u4e2a\u65f6\u523b\u8f93\u51fa":113,"\u901a\u8fc7\u6240\u6709\u5355\u5143\u6d4b\u8bd5":72,"\u901a\u8fc7\u6a21\u578b\u63a8\u65adapi\u7684\u5b9e\u73b0\u4f5c\u4e3a\u4e00\u4e2a\u6837\u4f8b":46,"\u901a\u8fc7\u7075\u6d3b\u4f7f\u7528\u4ee5\u4e0a\u4e24\u4e2a\u63a5\u53e3":90,"\u901a\u8fc7\u7ec4\u5408\u4e0d\u540c\u7684layer":84,"\u901a\u8fc7\u7f51\u7edc\u5c42\u7684\u6807\u8bc6\u7b26\u6765\u6307\u5b9a":74,"\u901a\u8fc7\u8ba1\u7b97\u8282\u70b9\u548c\u53c2\u6570\u670d\u52a1\u5668\u7684\u5206\u5e03\u5f0f\u534f\u4f5c":92,"\u901a\u8fc7\u8be5\u53c2\u6570\u53ef\u83b7\u53d6\u5230\u8f93\u5165\u8f93\u51fa\u4ee5\u53ca\u5c5e\u6027":75,"\u901a\u8fc7\u8c03\u7528":[89,90],"\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u63a5\u53e3\u521b\u5efa\u7a00\u758f\u77e9\u9635":89,"\u901a\u8fc7data":113,"\u901a\u8fc7ssh\u7b49\u65b9\u5f0f\u767b\u5f55\u5230raspberri":118,"\u903b\u8f91\u4e0a\u9ad8\u4e8e\u4e8c\u7ef4\u7684\u6570\u636e":89,"\u903b\u8f91\u5212\u4e0a\u6587\u4ef6\u5206\u5757\u7684\u5355\u4f4d":27,"\u9047\u5230\u8be5\u9519\u8bef\u65f6":82,"\u9075\u5b88\u4ee5\u4e0b\u7ea6\u5b9a":72,"\u9075\u5faa\u4ee5\u4e0b\u6d41\u7a0b":63,"\u90a3\u4e48":[46,74,113],"\u90a3\u4e480\u5c42\u5e8f\u5217\u5373\u4e3a\u4e00\u4e2a\u8bcd\u8bed":113,"\u90a3\u4e48\u4f1a\u643a\u5e26\u6709":89,"\u90a3\u4e48\u53ef\u4ee5\u8ba4\u4e3a\u8bad\u7ec3\u4e0d\u6536\u655b":83,"\u90a3\u4e48\u5728":75,"\u90a3\u4e48\u5982\u4f55\u5224\u65ad\u8bad\u7ec3\u4e0d\u6536\u655b\u5462":83,"\u90a3\u4e48\u5bf9\u5e94\u7684\u5185\u90e8\u5b58\u50a8\u4e5f\u4f1a\u4e0e\u5b83\u4eec\u5171\u4eab\u5185\u5b58":42,"\u90a3\u4e48\u5c31\u4f1a\u4f7f":42,"\u90a3\u4e48\u5e38\u6570\u8f93\u51fa\u6240\u80fd\u8fbe\u5230\u7684\u6700\u5c0fcost\u662f":83,"\u90a3\u4e48\u6211\u4eec\u53ef\u4ee5\u5224\u65ad\u4e3a\u8bad\u7ec3\u4e0d\u6536\u655b":83,"\u90a3\u4e48\u63a8\u8350\u4f7f\u7528":114,"\u90a3\u4e48\u63a8\u8350\u4f7f\u7528\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u65b9\u6cd5":114,"\u90a3\u4e48\u6536\u655b\u53ef\u80fd\u5f88\u6162":83,"\u90a3\u4e48\u6700\u597d\u5c06\u6570\u636e\u6587\u4ef6\u5728\u6bcf\u6b21\u8bfb\u53d6\u4e4b\u524d\u505a\u4e00\u6b21shuffl":81,"\u90a3\u4e48\u7528\u6237\u9700\u8981\u62c9\u53d6\u6240\u6709\u7684\u8fdc\u7a0b\u5206\u652f\u5230\u672c\u673a":78,"\u90a3\u4e48\u8bad\u7ec3\u6709\u53ef\u80fd\u4e0d\u6536\u655b":83,"\u90a3\u4e48\u8be5\u4f18\u5316\u7b97\u6cd5\u81f3\u5c11\u9700\u8981":81,"\u90a3\u4e48fc1\u548cfc2\u5c42\u5c06\u4f1a\u4f7f\u7528\u7b2c1\u4e2agpu\u6765\u8ba1\u7b97":105,"\u90a3\u4e5f\u5c31\u4e0d\u9700\u8981\u6025\u7740\u4f18\u5316\u6027\u80fd\u5566":108,"\u90a3\u4f30\u8ba1\u8fd9\u91cc\u7684\u6f5c\u529b\u5c31\u6ca1\u5565\u597d\u6316\u7684\u4e86":108,"\u90a3\u51cf\u5c11\u5b66\u4e60\u738710\u500d\u7ee7\u7eed\u8bd5\u9a8c":83,"\u90a3\u6211\u4f1a\u671f\u671b\u5206\u6790\u5de5\u5177\u7edf\u8ba1\u5230\u901f\u5ea6\u662f100gb":108,"\u90a3\u7a0b\u5e8f\u5206\u6790\u5de5\u5177\u662f\u5fc5\u4e0d\u53ef\u5c11\u7684\u5229\u5668":108,"\u90fd\u4e0d\u4f1a\u60f3\u8981\u77e5\u9053next":42,"\u90fd\u4e0d\u9700\u8981":0,"\u90fd\u4f1a\u4ea7\u751f\u5f53\u524d\u5c42\u72b6\u6001\u7684\u6240\u6709\u7ee7\u627f\u7ed3\u679c":103,"\u90fd\u4f1a\u7ba1\u7406\u7ef4\u62a4\u4e00\u4efd\u8bad\u7ec3\u597d\u7684\u6a21\u578b":90,"\u90fd\u4f1a\u9020\u6210\u8bad\u7ec3\u4e2d\u7684\u6570\u636e\u4ecec":81,"\u90fd\u4f7f\u7528":89,"\u90fd\u53ea\u662f\u4ecb\u7ecd\u53cc\u5c42rnn\u7684api\u63a5\u53e3":111,"\u90fd\u53ef\u4ee5\u8fd0\u884c":0,"\u90fd\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4e0b\u9762\u7684\u63a5\u53e3\u4e3a\u539f\u6709\u7684\u6570\u636e\u8f93\u5165\u9644\u52a0\u4e0a\u5e8f\u5217\u4fe1\u606f":89,"\u90fd\u5e94\u4f7f\u7528c":89,"\u90fd\u662f\u4e94\u4f4d\u7684\u6570\u5b57":11,"\u90fd\u662f\u4ee5ext\u5f00\u5934":42,"\u90fd\u662f\u5bf9layer1\u5143\u7d20\u7684\u62f7\u8d1d":110,"\u90fd\u662f\u5c06\u6bcf\u4e00\u53e5\u5206\u597d\u8bcd\u540e\u7684\u53e5\u5b50":111,"\u90fd\u662fabi\u8c03\u7528\u6807\u51c6\u7684":45,"\u90fd\u7528":72,"\u90fd\u7ee7\u627f\u4e8epaddlepaddle\u7684\u57fa\u7c7b":41,"\u90fd\u9700\u8981\u5199\u63d0\u4ea4\u8bf4\u660e":72,"\u90fd\u9700\u8981\u8c03\u7528\u4e00\u6b21":74,"\u914d\u5236\u7f16\u8bd1\u9009\u9879":87,"\u914d\u7f6e\u6253\u5f00":108,"\u914d\u7f6e\u6587\u4ef6\u63a5\u53e3\u662ffc_layer":74,"\u914d\u7f6e\u6587\u4ef6\u91cc\u52a0\u4e24\u884c":0,"\u914d\u7f6e\u7684\u65b9\u6cd5\u53c2\u8003":27,"\u914d\u7f6e\u7b80\u5355\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u4f8b\u5b50":114,"\u914d\u7f6e\u7f51\u7edc\u5c42\u7684\u8f93\u5165":74,"\u914d\u7f6eapi":110,"\u91c7\u7528\u5747\u5300\u5206\u5e03\u6216\u8005\u9ad8\u65af\u5206\u5e03\u521d\u59cb\u5316":103,"\u91c7\u7528multi":83,"\u91ca\u653e\u5bf9paramters\u5185\u5b58\u7684\u9501\u5b9a":10,"\u91cc\u53ef\u4ee5\u6807\u51c6\u5316\u7f16\u8bd1\u73af\u5883":0,"\u91cc\u5b8c\u6210":75,"\u91cc\u6240\u6709\u7684\u7b26\u53f7\u90fd\u5199\u5165\u81ea\u5df1\u7684\u7a0b\u5e8f\u7684\u4e8c\u8fdb\u5236\u6587\u4ef6\u91cc":45,"\u91cc\u7684":0,"\u91cc\u7684\u65e5\u5fd7":93,"\u91cc\u8fd0\u884c\u7684\u7f16\u8bd1\u5de5\u5177\u5b9e\u9645\u4e0a\u90fd\u662f\u5728\u672c\u673a\u7684":0,"\u91cc\u9009\u62e9\u9700\u8981\u53d1\u5e03\u7684\u5206\u652f":63,"\u91cc\u9762":75,"\u91cc\u9762\u6db5\u76d6\u4e86\u4ea4\u53c9\u7f16\u8bd1android\u7248paddlepaddle\u5e93\u9700\u8981\u7684\u6240\u6709\u7f16\u8bd1\u5de5\u5177":116,"\u91cc\u9762\u6dfb\u52a0":42,"\u91ccstep\u7684\u5185\u5bb9":81,"\u91cd\u5199\u7236\u7c7blayer\u7684":42,"\u91cd\u547d\u540d\u6210":45,"\u91cd\u65b0\u7f16\u8bd1paddlepaddl":108,"\u9488\u5bf9\u4e0d\u540c\u7684":117,"\u9488\u5bf9\u4efb\u52a1\u8fd0\u884c\u5b8c\u6210\u540e\u5bb9\u5668\u81ea\u52a8\u9000\u51fa\u7684\u573a\u666f":96,"\u9488\u5bf9\u5185\u5b58\u548c\u663e\u5b58":81,"\u94fe\u63a5":87,"\u94fe\u63a5\u4e2d\u627e\u5230":3,"\u94fe\u63a5\u4f55\u79cdblas\u5e93\u7b49":0,"\u94fe\u63a5\u5230\u81ea\u5df1\u7684\u7a0b\u5e8f\u91cc":45,"\u94fe\u63a5\u76f8\u5bf9\u5bb9\u6613":87,"\u94fe\u63a5\u9009\u9879":87,"\u94fe\u63a5\u9759\u6001\u5e93":87,"\u9519\u8bef":78,"\u9519\u8bef\u5904\u7406":45,"\u9519\u8bef\u5904\u7406\u65b9\u5f0f\u662f\u8fd4\u56de\u503c":45,"\u9519\u8bef\u5904\u7406\u7684\u65b9\u5f0f\u4e5f\u4e0d\u5c3d\u76f8\u540c":45,"\u9519\u8bef\u7684define_py_data_sources2\u7c7b\u4f3c":83,"\u952e\u6765\u542f\u52a8\u7f16\u8bd1\u4e86":0,"\u955c\u50cf\u91cc":0,"\u955c\u50cf\u91cc\u6709paddlepaddle\u7684\u6e90\u7801\u4e0edemo":96,"\u957f\u5ea6":81,"\u95e8\u63a7\u5faa\u73af\u5355\u5143\u5355\u6b65\u51fd\u6570\u548c\u8f93\u51fa\u51fd\u6570":114,"\u95e8\u63a7\u5faa\u73af\u5355\u5143\u7684\u8f93\u51fa\u88ab\u7528\u4f5c\u8f93\u51famemori":114,"\u9644\u52a0\u4e0a\u5e8f\u5217\u4fe1\u606f":89,"\u9650\u5236\u5957\u63a5\u5b57\u53d1\u9001\u7f13\u51b2\u533a\u7684\u5927\u5c0f":103,"\u9650\u5236\u5957\u63a5\u5b57\u63a5\u6536\u7f13\u51b2\u533a\u7684\u5927\u5c0f":103,"\u9664\u4e86\u53ef\u4ee5\u81ea\u52a8\u7f16\u8bd1\u6587\u6863":77,"\u9664\u4e86boot_lay":111,"\u9664\u6784\u9020\u67d0\u79cd\u7c7b\u578b\u7684\u51fd\u6570":46,"\u9664\u6b64\u4e4b\u5916":81,"\u9664\u96f6\u7b49\u95ee\u9898":81,"\u968f\u540e\u53ef\u4ee5\u7528\u8fd9\u4e2a\u5f00\u53d1\u955c\u50cf\u5f00\u59cbbuild":72,"\u968f\u673a\u6570\u7684\u79cd\u5b50":103,"\u968f\u673a\u6570seed":102,"\u9694\u5f00":91,"\u96c6\u6210\u5230":41,"\u96c6\u6210\u5230paddlepaddl":42,"\u96c6\u675f\u641c\u7d22\u4f7f\u7528\u5e7f\u5ea6\u4f18\u5148\u641c\u7d22\u7684\u65b9\u5f0f\u6784\u5efa\u67e5\u627e\u6811":103,"\u96c6\u7fa4\u4e0a\u542f\u52a8\u4e00\u4e2a\u5355\u673a\u4f7f\u7528cpu\u7684paddlepaddle\u8bad\u7ec3\u4f5c\u4e1a":96,"\u96c6\u7fa4\u4e2d\u7684\u6bcf\u53f0\u8ba1\u7b97\u673a\u901a\u5e38\u88ab\u6210\u4e3a\u4e00\u4e2a":101,"\u96c6\u7fa4\u4efb\u52a1":93,"\u96c6\u7fa4\u4f5c\u4e1a\u5c06\u4f1a\u5728\u51e0\u79d2\u540e\u542f\u52a8":93,"\u96c6\u7fa4\u6d4b\u8bd5":102,"\u96c6\u7fa4\u8bad\u7ec3":102,"\u96c6\u7fa4\u8bad\u7ec3\u4e0e\u9884\u6d4b":80,"\u96c6\u7fa4\u8fdb\u7a0b":93,"\u9700\u52a0\u8be5\u6a21\u677f\u53c2\u6570":75,"\u9700\u5728nvvp\u754c\u9762\u4e2d\u9009\u4e0a\u624d\u80fd\u5f00\u542f":108,"\u9700\u6307\u5b9a":87,"\u9700\u63d0\u4f9b\u975e\u96f6\u5143\u7684\u503c":89,"\u9700\u6ce8\u610f":87,"\u9700\u8981":[0,11,75,90],"\u9700\u8981\u4e3a":75,"\u9700\u8981\u4f7f\u7528":81,"\u9700\u8981\u4f7f\u7528\u5176\u5236\u5b9a\u7684\u65b9\u5f0f\u6302\u8f7d\u540e\u5e76\u5bfc\u5165\u6570\u636e":97,"\u9700\u8981\u4f7f\u7528\u6700\u65b0\u7684pip":3,"\u9700\u8981\u4f7f\u7528\u8005\u81ea\u5df1\u4e86\u89e3\u5e76\u5b8c\u6210\u8f6c\u5316":89,"\u9700\u8981\u4fdd\u6301\u5f53\u524d\u5206\u652f\u76ee\u5f55":72,"\u9700\u8981\u4fee\u6539build":63,"\u9700\u8981\u521b\u5efa\u5e76\u586b\u5199":89,"\u9700\u8981\u5347\u7ea7pip\u7248\u672c\u5230\u6700\u65b0":[3,78],"\u9700\u8981\u5355\u72ec":1,"\u9700\u8981\u53ef\u4ee5\u8de8\u5e73\u53f0\u6267\u884c":27,"\u9700\u8981\u540c\u65f6\u63d0\u4f9b\u6bcf\u4e00\u4e2a\u5185\u5c42\u5e8f\u5217\u5728\u6574\u4e2a":89,"\u9700\u8981\u540c\u6b65\u539f\u4ed3\u5e93":72,"\u9700\u8981\u542f\u52a8\u7684\u8282\u70b9\u4e2a\u6570\u4ee5\u53ca":97,"\u9700\u8981\u548c\u8be5op\u7684\u540d\u5b57\u4e00\u6837":75,"\u9700\u8981\u54ea\u4e9b\u5c42\u7684\u8ba1\u7b97\u7ed3\u679c\u4f5c\u4e3a\u8f93\u51fa":90,"\u9700\u8981\u5728":75,"\u9700\u8981\u5728\u521b\u5efa\u5bb9\u5668\u524d\u6302\u8f7d\u5377\u4ee5\u4fbf\u6211\u4eec\u4fdd\u5b58\u8bad\u7ec3\u7ed3\u679c":96,"\u9700\u8981\u5728\u7cfb\u7edf\u91cc\u5148\u5b89\u88c5\u597ddocker\u5de5\u5177\u5305":77,"\u9700\u8981\u5728cmake\u7684\u65f6\u5019":46,"\u9700\u8981\u5728macos\u7cfb\u7edf\u4e0a\u8fdb\u884c":117,"\u9700\u8981\u5c06\u5176parameter\u8bbe\u7f6e\u6210":81,"\u9700\u8981\u5c06\u7f51\u7edc\u7ed3\u6784\u4f7f\u7528":90,"\u9700\u8981\u5c06bugfix\u7684\u5206\u652f\u540c\u65f6merge\u5230":63,"\u9700\u8981\u5c06cuda\u76f8\u5173\u7684\u5e93\u8bbe\u7f6e\u5230":87,"\u9700\u8981\u5c06paddl":87,"\u9700\u8981\u5f15\u7528":46,"\u9700\u8981\u5f3a\u8c03\u7684\u662f":0,"\u9700\u8981\u601d\u8003\u5b8c\u6210\u4ee5\u4e0b\u5de5\u4f5c":[89,90],"\u9700\u8981\u624b\u52a8\u8fdb\u884c\u89e3\u538b":90,"\u9700\u8981\u6267\u884c":[0,3,86],"\u9700\u8981\u6307\u5b9a":87,"\u9700\u8981\u6307\u5b9a\u4e0e\u67d0\u4e00\u4e2a\u8f93\u5165\u7684\u5e8f\u5217\u4fe1\u606f\u662f\u4e00\u81f4\u7684":111,"\u9700\u8981\u6307\u5b9alayer\u7684\u8f93\u5165\u6765\u6e90":84,"\u9700\u8981\u63d0\u9192\u7684\u662f":2,"\u9700\u8981\u660e\u786e\u6307\u5b9a":103,"\u9700\u8981\u663e\u5f0f\u5730\u94fe\u63a5":87,"\u9700\u8981\u663e\u793a\u5730\u94fe\u63a5":87,"\u9700\u8981\u663e\u793a\u5730\u94fe\u63a5mkl\u7684\u52a8\u6001\u5e93":87,"\u9700\u8981\u6709\u7a33\u5b9a\u7684\u5bfc\u51fa\u7b26\u53f7":45,"\u9700\u8981\u6839\u636e\u4e0d\u540c\u7684\u5206\u5e03\u5f0f\u5b58\u50a8\u6765\u7ed1\u5b9a\u4e00\u4e2a":97,"\u9700\u8981\u6ce8\u610f":75,"\u9700\u8981\u6ce8\u610f\u7684\u662f":[42,63,81,103],"\u9700\u8981\u6ce8\u610f\u7684\u662f\u68af\u5ea6\u68c0\u67e5\u4ec5\u4ec5\u9a8c\u8bc1\u4e86\u68af\u5ea6\u7684\u8ba1\u7b97":74,"\u9700\u8981\u6ce8\u610f\u7684\u662fpaddlepaddle\u76ee\u524d\u53ea\u652f\u6301\u5b50\u5e8f\u5217\u6570\u76ee\u4e00\u6837\u7684\u591a\u8f93\u5165\u53cc\u5c42rnn":111,"\u9700\u8981\u7528\u5230\u7684\u7f16\u8bd1\u5de5\u5177\u548c\u7cfb\u7edf\u5e93":116,"\u9700\u8981\u7528\u6237\u663e\u5f0f\u8bbe\u5b9a":82,"\u9700\u8981\u7d2f\u52a0\u4e0d\u540clayer\u4f20\u8fc7\u6765\u7684\u68af\u5ea6":42,"\u9700\u8981\u81ea\u5df1\u94fe\u63a5mkl\u94fe\u63a5\u5e93":87,"\u9700\u8981\u88ab\u66b4\u9732\u5230\u5176\u4ed6\u8bed\u8a00":46,"\u9700\u8981\u8bf7\u7ba1\u7406\u5458\u5b89\u88c5\u548c\u914d\u7f6e\u597d":0,"\u9700\u8981\u9075\u5faa\u4ee5\u4e0b\u7ea6\u5b9a":113,"\u9700\u8981\u91cd\u547d\u540dwheel\u5305\u4e2dplatform\u76f8\u5173\u7684\u540e\u7f00":63,"\u9700\u8981\u989d\u5916\u6ce8\u610f\u7684\u662f":76,"\u9700\u9644\u52a0\u53cc\u5c42\u5e8f\u5217\u4fe1\u606f":89,"\u9700\u9644\u52a0\u5e8f\u5217\u4fe1\u606f":89,"\u975e\u5e38\u6570":74,"\u975e\u5e8f\u5217\u8f93\u5165\u4e0d\u643a\u5e26":89,"\u975e\u5e8f\u5217\u8f93\u5165\u65e0\u9700\u6784\u9020":89,"\u975e\u96f6\u5143\u4e2a\u6570":89,"\u975e\u96f6\u5143\u7d20\u7684\u503c":89,"\u975e\u96f6\u5143\u7d20\u7684\u5217\u53f7":89,"\u975e\u96f6\u6570\u5b57\u7684\u4e2a\u6570":74,"\u9762\u5411\u67b6\u6784\u4e3a32\u4f4darm\u67b6\u6784":116,"\u9762\u5411\u67b6\u6784\u4e3a64\u4f4darm64\u67b6\u6784":116,"\u9879\u76ee\u5728\u52aa\u529b\u5f00\u59cb\u652f\u6301\u5176\u4ed6\u4e0d\u9700\u8981":0,"\u987a\u5e8f":111,"\u9884\u63d0\u4ea4\u94a9\u5b50":72,"\u9884\u6d4b\u4e0d\u9700\u8981\u6807\u7b7e":88,"\u9884\u6d4b\u4e0d\u9700\u8981\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u53cd\u5411\u4f20\u64ad\u548c\u53c2\u6570\u66f4\u65b0\u7684\u90e8\u5206":88,"\u9884\u6d4b\u4ee3\u7801\u66f4\u591a\u8be6\u7ec6\u793a\u4f8b\u4ee3\u7801\u8bf7\u53c2\u8003":90,"\u9884\u6d4b\u4f7f\u7528\u7684\u7f51\u7edc\u7ed3\u6784\u5f80\u5f80\u4e0d\u540c\u4e8e\u8bad\u7ec3":90,"\u9884\u6d4b\u5c31\u662f\u51c6\u5907\u8f93\u5165\u6570\u636e":88,"\u9884\u6d4b\u5f88\u591a\u65f6\u5019\u9700\u8981\u548c\u7528\u6237\u7cfb\u7edf\u6574\u5408\u5728\u4e00\u8d77":88,"\u9884\u6d4b\u65f6":90,"\u9884\u6d4b\u65f6\u53ea\u9700\u52a0\u8f7d\u4e00\u4e2a\u6587\u4ef6\u4fbf\u4e8e\u53d1\u5e03":90,"\u9884\u6d4b\u6709\u5982\u4e0b\u7279\u70b9":88,"\u9884\u6d4b\u7a0b\u5e8f\u5f00\u53d1\u4e24\u5927\u90e8\u5206":90,"\u9884\u6d4bsdk\u4e0d\u5305\u542b\u53cd\u5411\u4f20\u64ad\u548c\u53c2\u6570\u66f4\u65b0\u90e8\u5206":88,"\u9884\u6d4bsdk\u9700\u8981\u63d0\u4f9b\u4e00\u4e2a\u7b80\u6d01\u7684\u7528\u6237\u63a5\u53e3":88,"\u9996\u5148":[74,111,114],"\u9996\u5148\u4ee5\u51e0\u4e2a\u5b9e\u9645\u573a\u666f\u4e3a\u4f8b":104,"\u9996\u5148\u5728\u7cfb\u7edf\u8def\u5f84":0,"\u9996\u5148\u5b89\u88c5\u5e76\u5728\u5f53\u524d\u76ee\u5f55\u8fd0\u884c\u5b83":72,"\u9996\u5148\u5b9a\u4e49":75,"\u9996\u5148\u5bf9\u8f93\u5165\u505a\u4e00\u4e2a\u5c0f\u7684\u6270\u52a8":74,"\u9996\u5148\u6211\u4eec\u9700\u8981\u63a8\u5bfc\u8be5\u7f51\u7edc\u5c42\u7684":74,"\u9996\u5148\u6784\u9020\u5934\u4fe1\u606f":83,"\u9996\u5148\u901a\u8fc7":72,"\u9996\u5148\u9700\u8981\u52a0\u8f7d\u76f8\u5e94\u7684python\u5e93":84,"\u9a71\u52a8":77,"\u9ad8\u4eae\u90e8\u5206":111,"\u9ad8\u5ea6":89,"\u9ad8\u5ea6\u652f\u6301\u7075\u6d3b\u548c\u9ad8\u6548\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u914d\u7f6e":114,"\u9ad8\u65af\u5206\u5e03":83,"\u9ed8\u8ba4":103,"\u9ed8\u8ba40":91,"\u9ed8\u8ba41":91,"\u9ed8\u8ba4127":91,"\u9ed8\u8ba4256k":27,"\u9ed8\u8ba47164":91,"\u9ed8\u8ba4\u4e0d\u663e\u793a":103,"\u9ed8\u8ba4\u4e0d\u8bbe\u7f6e":113,"\u9ed8\u8ba4\u4e3a0":[103,105],"\u9ed8\u8ba4\u4e3a1":[89,105],"\u9ed8\u8ba4\u4e3a100":105,"\u9ed8\u8ba4\u4e3a4096mb":103,"\u9ed8\u8ba4\u4e3a\u7b2c\u4e00\u4e2a\u8f93\u5165":113,"\u9ed8\u8ba4\u4e3anull":103,"\u9ed8\u8ba4\u4f1a\u5c06a\u548cb":81,"\u9ed8\u8ba4\u4f7f\u7528concurrentremoteparameterupdat":103,"\u9ed8\u8ba4\u4f7f\u7528mkl":0,"\u9ed8\u8ba4\u503c":[0,105,110,117],"\u9ed8\u8ba4\u503c\u4e3a":[116,117,118],"\u9ed8\u8ba4\u503c\u4e3a\u73af\u5883\u53d8\u91cf":117,"\u9ed8\u8ba4\u521d\u59cb\u72b6\u4e3a0":113,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b":[83,93],"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u6309\u7167float\u7cbe\u5ea6\u8ba1\u7b97":83,"\u9ed8\u8ba4\u6307\u5b9a\u7b2c\u4e00\u4e2a\u8f93\u5165":111,"\u9ed8\u8ba4\u662f\u4f7f\u7528mkl\u7684\u955c\u50cf":1,"\u9ed8\u8ba4\u6ca1\u6709\u5b89\u88c5vim":1,"\u9ed8\u8ba4\u7684paddlepaddle\u751f\u4ea7\u73af\u5883\u955c\u50cf":96,"\u9ed8\u8ba4\u7f16\u8bd1\u6240\u6709\u67b6\u6784":117,"\u9ed8\u8ba4\u8bbe\u7f6e\u4e3a":41,"\u9ed8\u8ba4\u8bbe\u7f6e\u4e3a\u771f":105,"\u9ed8\u8ba4\u8bbe\u7f6e\u6210\u73af\u5883\u53d8\u91cf":[116,118],"\u9ed8\u8ba4\u8c03\u7528":0,"\u9ed8\u8ba4fals":91,"abi\u7684paddlepaddle\u5e93":116,"abstract":[18,19,26,30,53,62,64],"android\u5b98\u65b9\u63d0\u4f9b\u7684":116,"android\u5e73\u53f0\u4e0a\u4f7f\u7528\u7684c":116,"android\u5e73\u53f0\u53ef\u9009\u914d\u7f6e\u53c2\u6570":116,"android\u7684docker\u5f00\u53d1\u955c\u50cf\u5411\u7528\u6237\u63d0\u4f9b\u4e24\u4e2a\u53ef\u914d\u7f6e\u7684\u53c2\u6570":116,"api\u4e0d\u4f1a\u76f4\u63a5\u52a0\u8f7d":90,"api\u4e0d\u5c0f\u4e8e21":116,"api\u4e2d":89,"api\u4e2d\u4f7f\u7528":45,"api\u4e2d\u7684\u4e00\u7ef4\u6570\u7ec4":89,"api\u4e2d\u7684\u77e9\u9635\u6765\u8868\u793a":89,"api\u4e2d\u795e\u7ecf\u7f51\u7edc\u7684\u4e00\u4e2a\u8f93\u5165":90,"api\u4f7f\u7528\u4e2d\u7684\u4e00\u4e2a\u91cd\u8981\u6982\u5ff5":90,"api\u4f7f\u7528\u6d41\u7a0b":88,"api\u4f7f\u7528\u6d41\u7a0b\u793a\u610f\u56fe":90,"api\u4f7f\u7528\u793a\u4f8b":90,"api\u521b\u5efa\u7684gradientmachine\u7c7b\u7684\u5bf9\u8c61":90,"api\u53ef\u4ee5\u901a\u8fc7\u5206\u522b\u6307\u5b9a\u5e8f\u5217\u5316\u540e\u7684\u7f51\u7edc\u7ed3\u6784\u6587\u4ef6\u548c\u53c2\u6570\u76ee\u5f55\u6765\u52a0\u8f7d\u8bad\u7ec3\u597d\u7684\u6a21\u578b":90,"api\u53ef\u4ee5\u901a\u8fc7\u6307\u5b9a":90,"api\u5b8c\u6210\u5206\u5e03\u5f0f\u8bad\u7ec3":91,"api\u5bf9\u6bd4\u4ecb\u7ecd":112,"api\u5bfc\u51fa\u7684\u52a8\u6001\u5e93":46,"api\u5bfc\u51fa\u7684\u9759\u6001\u5e93":46,"api\u5e93\u5c06\u88ab\u5b89\u88c5\u5230":116,"api\u5f00\u53d1\u5305\u5e76\u5b89\u88c5":3,"api\u5f00\u53d1\u9884\u6d4b\u7a0b\u5e8f\u65f6":87,"api\u5f00\u53d1\u9884\u6d4b\u7a0b\u5e8f\u9700\u8981\u4e00\u4e2a\u8bad\u7ec3\u597d\u7684\u6a21\u578b":90,"api\u6240\u9700\u7684\u4f9d\u8d56":87,"api\u63a5\u53d7\u7684\u7c7b\u578b\u5168\u662f":46,"api\u63a5\u53e3":27,"api\u63a5\u53e3\u751f\u6210":75,"api\u63a5\u53e3\u7684\u53c2\u6570\u8f6c\u53d1\u7ed9":46,"api\u63a5\u53e3\u7684\u751f\u6210":75,"api\u63d0\u4f9b\u7684":90,"api\u652f\u6301\u7684\u6240\u6709\u8f93\u5165\u6570\u636e\u7c7b\u578b\u548c\u4ed6\u4eec\u7684\u7ec4\u7ec7\u65b9\u5f0f":90,"api\u6587\u6863":[116,117],"api\u65f6":46,"api\u65f6\u4e3a\u8f93\u51fa":90,"api\u65f6\u6240\u552f\u4e00\u9700\u8981\u5f15\u5165\u7684\u5934\u6587\u4ef6":46,"api\u662f\u591a\u8bed\u8a00api\u7684\u57fa\u7840\u90e8\u5206":46,"api\u66b4\u9732\u7684\u7c7b\u578b":46,"api\u6765\u9884\u6d4b":[116,117],"api\u751f\u6210\u7684\u4e8c\u8fdb\u5236\u6587\u4ef6\u4f1a\u88ab\u5b89\u88c5\u5230":46,"api\u7684\u4f7f\u7528":88,"api\u7684\u5934\u6587\u4ef6":[116,117,118],"api\u7684\u5b9e\u4f8b":46,"api\u7684\u5b9e\u73b0\u7ec6\u8282":46,"api\u7684\u63a5\u53e3":46,"api\u7684\u65f6\u5019\u63a8\u8350paddle\u4e0d\u5d4c\u5165python\u89e3\u91ca\u5668":46,"api\u7684\u7f16\u8bd1\u9009\u9879\u9ed8\u8ba4\u5173\u95ed":46,"api\u76ee\u5f55\u7ed3\u6784\u5982\u4e0a\u56fe\u8868\u6240\u793a":46,"api\u76f8\u5173\u63a5\u53e3":89,"api\u7ea7\u522b":116,"api\u7ea7\u522b\u4e3a21":116,"api\u83b7\u5f97\u4e86\u795e\u7ecf\u7f51\u7edc\u7684\u53c2\u6570\u5b9e\u4f8b":46,"api\u8bad\u7ec3":90,"api\u9700\u8981\u521b\u5efa\u7684\u6570\u636e\u7c7b\u578b":89,"api\u9759\u6001\u5e93":117,"api\u9884\u6d4b\u5e93":[106,117],"api\u9884\u6d4b\u65f6":90,"apis\u505a\u4e86\u5c01\u88c5":41,"app\u4e2d":[116,117],"apple\u5b98\u65b9\u4e3aios\u5f00\u53d1\u63d0\u4f9b\u4e86\u5b8c\u6574\u7684\u4ea4\u53c9\u7f16\u8bd1\u5de5\u5177\u548c\u96c6\u6210\u5f00\u53d1\u73af\u5883":117,"async_sgd\u8fdb\u884c\u8bad\u7ec3\u65f6":83,"avx\u662f\u4e00\u79cdcpu\u6307\u4ee4\u96c6":1,"avx\u7248\u672c":1,"avx\u7684\u955c\u50cf":1,"batch\u4e2d\u5305\u542b":81,"batch\u7684\u6743\u91cd":81,"batches\u4e2a\u6279\u6b21\u4fdd\u5b58\u4e00\u6b21\u53c2\u6570":103,"batches\u6b21":103,"block\u6784\u6210\u4e00\u4e2amodel":10,"book\u4e00\u5b9a\u662f\u60a8\u6700\u597d\u7684\u9009\u62e9":1,"book\u4e2d\u6240\u6709\u7ae0\u8282\u529f\u80fd\u7684\u6b63\u786e\u6027":63,"book\u662f\u4e3a\u7528\u6237\u548c\u5f00\u53d1\u8005\u5236\u4f5c\u7684\u4e00\u4e2a\u4ea4\u4e92\u5f0f\u7684jupyt":1,"book\u7684":84,"book\u7684docker\u955c\u50cf":1,"boolean":[26,28,36,45,69],"break":[8,67,69,70,71],"bugfix\u5206\u652f\u4e5f\u662f\u5728\u5f00\u53d1\u8005\u81ea\u5df1\u7684fork\u7248\u672c\u5e93\u7ef4\u62a4":63,"bugfix\u5206\u652f\u9700\u8981\u5206\u522b\u7ed9\u4e3b\u7248\u672c\u5e93\u7684":63,"byte":[27,44,83],"c99\u662f\u76ee\u524dc\u6700\u5e7f\u6cdb\u7684\u4f7f\u7528\u6807\u51c6":45,"c\u6709\u6807\u51c6\u7684abi":45,"c\u8bed\u8a00\u662f\u6709\u5bfc\u51fa\u7b26\u53f7\u7684\u6807\u51c6\u7684":45,"case":[12,18,20,21,26,30,40,46,53,57,59,60,69,95,108,119],"cc\u4e2d\u7684":76,"cells\u7b49":82,"char":14,"ci\u73af\u5883\u4f7f\u7528":63,"ci\u7f16\u8bd1wheel\u5b8c\u6210\u540e\u4f1a\u81ea\u52a8\u5c06docker\u955c\u50cfpush\u5230dockerhub":63,"class":[4,7,18,19,20,21,24,25,29,30,31,32,34,35,37,40,45,49,50,55,56,60,61,62,64,65,66,68,70,74,75,76,83,109],"cmake\u4e2d\u5c06":108,"cmake\u5b98\u65b9\u5bf9android\u5e73\u53f0\u7684\u4ea4\u53c9\u7f16\u8bd1\u63d0\u4f9b\u4e86\u901a\u7528\u7684\u652f\u6301":116,"cmake\u627e\u5230\u7684python\u5e93\u548cpython\u89e3\u91ca\u5668\u7248\u672c\u53ef\u80fd\u6709\u4e0d\u4e00\u81f4\u73b0\u8c61":78,"cmake\u7cfb\u7edf\u5bf9\u4ea4\u53c9\u7f16\u8bd1\u63d0\u4f9b\u4e86\u652f\u6301":116,"cmake\u7f16\u8bd1\u65f6":0,"cmake\u7f16\u8bd1\u7684\u76ee\u6807\u5e73\u53f0":[116,117,118],"cmake\u914d\u7f6e\u4e2d\u5c06":108,"cmake\u914d\u7f6e\u5b8c\u6210\u540e":[116,117,118],"compute\u51fd\u6570":41,"const":[7,12,14,19,29,31,37,38,39,54,55,57,61,64,66,68,70,74,75,76],"container\u4e2d":96,"core\u4e2d\u7684\u6a21\u578b\u8fd8\u5728\u4f7f\u7528\u8fd9\u4e2a\u53c2\u6570":46,"core\u4e2d\u8fd9\u4e00\u7c7b\u578b\u63a5\u53e3\u7684\u667a\u80fd\u6307\u9488":46,"core\u662f\u5426\u8fd8\u5728\u4f7f\u7528\u8fd9\u4e2a\u5b9e\u4f8b":46,"core\u6982\u5ff5":46,"cost\u63a5\u6536y_predict\u4e0ey\u4f5c\u4e3a\u8f93\u5165":84,"cost\u8fd8\u5927\u4e8e\u8fd9\u4e2a\u6570":83,"count\u4e2agpu\u4e0a\u4f7f\u7528\u6570\u636e\u5e76\u884c\u6765\u8ba1\u7b97\u67d0\u4e00\u5c42":105,"count\u548cgpu":105,"csr\u5b58\u50a8\u683c\u5f0f\u901a\u8fc7":89,"cuda\u5171\u4eabkernel\u5b9e\u73b0\u5728":75,"cuda\u5b9e\u73b0\u5171\u4eab\u540c\u4e00\u4e2a":75,"cuda\u5b9e\u73b0\u5728":75,"cuda\u5e93":103,"cuda\u7684\u4ee3\u7801\u53ef\u4ee5\u590d\u7528":75,"cuda\u76f8\u5173\u5e93\u4f1a\u5728\u9884\u6d4b\u7a0b\u5e8f\u8fd0\u884c\u65f6\u52a8\u6001\u88c5\u8f7d":87,"cudnn\u5e93":[0,103],"cumtime\u7684\u6bcf\u6b21\u8c03\u7528\u5e73\u5747\u65f6\u95f4":107,"data\u5230\u5206\u5e03\u5f0f\u5b58\u50a8\u8865\u5145\u8bad\u7ec3\u6570\u636e":11,"data\u63a5\u53e3\u5206\u914d\u5b9e\u9645\u7684\u5185\u5b58":76,"data\u76ee\u5f55\u4e2d\u5b58\u653e\u5207\u5206\u597d\u7684\u6570\u636e":97,"dataprovider\u5171\u8fd4\u56de\u4e24\u4e2a\u6570\u636e":111,"dataprovider\u5171\u8fd4\u56de\u4e24\u7ec4\u6570\u636e":111,"dataprovider\u7f13\u51b2\u6c60\u5185\u5b58":81,"decoder\u5faa\u73af\u5c55\u5f00\u7684\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65\u4f1a\u5f15\u7528\u5168\u90e8\u7ed3\u679c":113,"decoder\u63a5\u53d7\u4e24\u4e2a\u8f93\u5165":113,"decoder\u6bcf\u6b21\u9884\u6d4b\u4ea7\u751f\u4e0b\u4e00\u4e2a\u6700\u53ef\u80fd\u7684\u8bcd\u8bed":113,"decoer\u67b6\u6784":113,"default":[4,7,8,18,20,24,33,37,44,47,48,57,58,64,65,66,69,71,95,96,97,105,116,119],"device\u5c31\u80fd\u62ff\u5230\u6b63\u786e\u7684\u6570\u636e":42,"dist\u76ee\u5f55\u4e0b\u751f\u6210\u8f93\u51fa\u7684whl\u5305":0,"dnn\u4e09\u8005\u5173\u7cfb\u5982\u4e0b\u8868":42,"dnn\u4e2d\u7684":42,"dnn\u4e2d\u7684\u6392\u5217\u65b9\u5f0f\u4e0d\u6b62\u8fd9\u4e00\u79cd":42,"dnn\u4f1a\u4f5c\u4e3a\u7b2c\u4e09\u65b9\u5e93\u96c6\u6210\u8fdbpaddlepaddl":42,"dnn\u4f1a\u7528\u5230":42,"dnn\u5171\u540c\u4f7f\u7528":42,"dnn\u524d\u540e\u7684cnn\u7f51\u7edc\u6027\u80fd":42,"dnn\u5728\u53d1\u5e03":42,"dnn\u5b9e\u73b0":42,"dnn\u5e0c\u671b\u7684\u683c\u5f0f":42,"dnn\u6570\u5b66\u5e93":0,"dnn\u6570\u636e\u7684\u4e0d\u540c\u683c\u5f0f\u4ee5\u53ca\u76f8\u4e92\u4e4b\u95f4\u7684\u8f6c\u6362":42,"dnn\u7684":42,"dnn\u7684\u5e93\u76ee\u524d\u53ea\u6709\u52a8\u6001\u5e93":42,"dnn\u7684\u6027\u80fd":42,"dnn\u7684\u60c5\u51b5\u4e0b":42,"dnn\u7684\u64cd\u4f5c\u90fd\u662f\u76f4\u63a5\u8986\u76d6\u7684\u5f62\u5f0f":42,"dnn\u7684\u6d4b\u8bd5":42,"dnn\u7684\u73af\u5883\u4e0b":42,"dnn\u7684\u76f8\u5173\u529f\u80fd":42,"dnn\u7684\u7ed3\u679c":42,"dnn\u7684\u9ad8\u6027\u80fd\u683c\u5f0f\u4e0epaddlepaddle\u539f\u6709\u7684":42,"dnn\u7684layer":42,"dnn\u7684layers\u90fd\u4f1a\u7ee7\u627f\u4e8e":42,"docker\u5b89\u88c5\u65b9\u5f0f\u53ef\u4ee5\u8fdb\u5165docker\u5bb9\u5668\u6267\u884c":101,"docker\u5b89\u88c5\u8bf7\u53c2\u8003":77,"docker\u5b89\u88c5\u8bf7\u53c2\u8003docker\u7684\u5b98\u7f51":77,"docker\u5b98\u7f51":1,"docker\u5bb9\u5668\u4e2d\u5c06\u9ed8\u8ba4\u4f7f\u7528":116,"docker\u7684\u5b98\u7f51":77,"docker\u80fd\u5728\u6240\u6709\u4e3b\u8981\u64cd\u4f5c\u7cfb\u7edf":116,"docker\u955c\u50cf":1,"docker\u955c\u50cf\u4e3a\u4e86\u51cf\u5c0f\u4f53\u79ef":1,"docker\u955c\u50cf\u9ed8\u8ba4":1,"dockerhub\u7f51\u7ad9":1,"double\u7c7b\u578b\u65f6\u4e3a8":83,"dropout\u7684\u6bd4\u4f8b":74,"eigenscalar\u7684\u8f6c\u6362":76,"encode\u6210\u7684\u6700\u540e\u4e00\u4e2a\u5411\u91cf":111,"encoder\u548cdecoder\u53ef\u4ee5\u662f\u80fd\u591f\u5904\u7406\u5e8f\u5217\u7684\u4efb\u610f\u795e\u7ecf\u7f51\u7edc\u5355\u5143":113,"encoder\u8f93\u51fa":113,"entropy\u4f5c\u4e3acost":83,"enum":[12,14,20,47,55,56,65,66,71],"export":[1,30,35,77,78,91],"f\u4ee3\u8868\u4e00\u4e2a\u6d6e\u70b9\u6570":84,"fc1\u548cfc2\u5c42\u5728gpu\u4e0a\u8ba1\u7b97":105,"fc3\u5c42\u4f7f\u7528cpu\u8ba1\u7b97":105,"final":[5,6,21,35,48,49,67,70],"flatten\u65b9\u6cd5\u662f\u628apaddle\u4e2d\u7684\u4e00\u4e2atensor\u8fdb\u884creshape\u64cd\u4f5c":76,"float":[24,29,37,39,66,68,75,76,89,108],"float\u7b49":105,"forward\u7684output\u7684\u503c":81,"from\u65b9\u6cd5\u662f\u628apaddle\u4e2d\u7684\u4e00\u7ef4tensor\u8f6c\u4e3aeigen\u7684\u4e00\u7ef4tensor":76,"from\u662feigentensor\u6a21\u677f\u63d0\u4f9b\u7684\u4e00\u4e2a\u63a5\u53e3":76,"full\u53c2\u6570\u63d0\u4ea4":79,"function":[4,6,7,9,13,14,15,17,18,19,20,21,24,25,29,31,34,37,43,48,49,53,54,55,56,57,59,60,61,62,64,66,70,107,114,119],"function\u4f7f\u7528":82,"git\u6d41\u5206\u652f\u6a21\u578b":72,"github\u9996\u9875":72,"glibc\u81f3\u5c11\u5305\u542bglibc_2":3,"golang\u53ef\u4ee5\u4f7f\u7528":45,"golang\u7684":45,"gpu\u4e8c\u8fdb\u5236\u6587\u4ef6":0,"gpu\u5219\u8fd8\u9700\u8981\u9ad8\u5e76\u884c\u6027":108,"gpu\u6027\u80fd\u8c03\u4f18":106,"gpu\u6267\u884c":76,"gpu\u6838\u5728\u8bad\u7ec3\u914d\u7f6e\u4e2d\u6307\u5b9a":103,"gpu\u7684docker\u955c\u50cf\u7684\u65f6\u5019":78,"gpu\u7b49":63,"group\u6559\u7a0b":112,"group\u7684\u5b9e\u73b0\u65b9\u5f0f":82,"gru\u6216lstm":114,"h\u5e76\u4e0d\u56f0\u96be":45,"html\u5373\u53ef\u8bbf\u95ee\u672c\u5730\u6587\u6863":77,"i\u4ee3\u8868\u4e00\u4e2a\u6574\u6570":84,"id\u6307\u5b9a\u4f7f\u7528\u54ea\u4e2agpu\u6838":103,"id\u6307\u5b9a\u7684gpu":105,"id\u65e0\u6548":103,"image\u91cc":96,"images\u6570\u636e\u96c6\u4e0a\u4f20\u5230\u4e91\u7aef\u7684":11,"imikolov\u6570\u636e\u96c6":91,"import":[3,4,7,8,18,20,23,31,33,35,36,43,48,49,56,64,67,75,84,86,90,91,95],"infer\u63a5\u53e3\u7684\u8fd4\u56de\u503c\u662f\u4e00\u4e2apython":81,"ingress\u9700\u8981\u628apfsclient\u7684\u8eab\u4efd\u4fe1\u606f\u4f20\u7ed9pfsserv":27,"instance\u4e0e\u751f\u6210\u6570\u636e\u96c6\u65f6":11,"instance\u5305\u6db5\u4e24\u4e2a\u503c":11,"instance\u662f\u4e00\u6a21\u4e00\u6837\u7684":11,"int":[6,7,12,13,14,17,18,20,22,36,37,41,42,43,45,46,55,56,58,59,65,66,68,70,74,76,89,91,105],"interface\u6587\u4ef6\u7684\u5199\u6cd5\u975e\u5e38":45,"ios\u5e73\u53f0\u53ef\u9009\u914d\u7f6e\u53c2\u6570":117,"issue\u7f16\u53f7":72,"job\u662f\u672c\u6b21\u8bad\u7ec3\u5bf9\u5e94\u7684job":97,"job\u7684\u540d\u5b57":97,"kernel\u5b9e\u73b0":75,"kernel\u6ce8\u518ccpu\u5b9e\u73b0\u5728":75,"kernel\u7684\u5b9e\u73b0\u57fa\u4e8eeigen":75,"kubernetes\u4e3a\u8fd9\u6b21\u8bad\u7ec3\u521b\u5efa\u4e863\u4e2apod\u5e76\u4e14\u8c03\u5ea6\u5230\u4e863\u4e2anode\u4e0a\u8fd0\u884c":97,"kubernetes\u5206\u5e03\u5f0f\u8bad\u7ec3":94,"kubernetes\u5355\u673a\u8bad\u7ec3":94,"kubernetes\u53ef\u4ee5\u901a\u8fc7yaml\u6587\u4ef6\u6765\u521b\u5efa\u76f8\u5173\u5bf9\u8c61":97,"kubernetes\u5c31\u4f1a\u521b\u5efa3\u4e2apod\u4f5c\u4e3apaddlepaddle\u8282\u70b9\u7136\u540e\u62c9\u53d6\u955c\u50cf":97,"kubernetes\u6709job\u7c7b\u578b\u7684\u8d44\u6e90\u6765\u652f\u6301":96,"label\u662f\u539f\u59cb\u6570\u636e\u4e2d\u5bf9\u4e8e\u6bcf\u4e00\u53e5\u8bdd\u7684\u5206\u7c7b\u6807\u7b7e":111,"labels\u662f\u6bcf\u7ec4\u5185\u6bcf\u4e2a\u53e5\u5b50\u7684\u6807\u7b7e":111,"layer1\u5fc5\u987b\u662f\u4e00\u4e2a0\u5c42\u5e8f\u5217":110,"layer1\u5fc5\u987b\u662f\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":110,"layer\u4f5c\u4e3a\u4e00\u4e2a\u6574\u4f53\u6765\u5b9e\u73b0":82,"layer\u62ff\u5230\u7684\u7528\u6237\u8f93\u5165":113,"layer\u65f6":[42,82],"layer\u662f\u6211\u4eec\u7684\u79ef\u6728":84,"layer\u7684\u540e\u9762\u63a5\u6709cpu":42,"layer\u7c7b\u53ef\u4ee5\u81ea\u52a8\u8ba1\u7b97\u4e0a\u9762\u7684\u5bfc\u6570":74,"layer\u8ba1\u7b97\u7684\u8f93\u51fa":82,"linux\u4e2d":1,"list\u4e2d":90,"list\u4f5c\u4e3a\u68c0\u67e5\u5217\u8868":63,"list\u5982\u4e0b\u6240\u793a":105,"list\u6307\u5b9a\u6d4b\u8bd5\u7684\u6a21\u578b\u5217\u8868":105,"long":20,"memory\u4e0d\u80fd\u72ec\u7acb\u5b58\u5728":113,"memory\u4e5f\u53ef\u4ee5\u5177\u6709":114,"memory\u4e5f\u53ef\u4ee5\u662f\u5e8f\u5217":114,"memory\u53ea\u80fd\u5728":113,"memory\u53ef\u4ee5\u7f13\u5b58\u4e0a\u4e00\u4e2a\u65f6\u523b\u67d0\u4e00\u4e2a\u795e\u7ecf\u5143\u7684\u8f93\u51fa":111,"memory\u6307\u5411\u4e00\u4e2alay":113,"memory\u662f\u5728\u5355\u6b65\u51fd\u6570\u4e2d\u5faa\u73af\u4f7f\u7528\u7684\u72b6\u6001":114,"memory\u662fpaddlepaddle\u5b9e\u73b0rnn\u65f6\u5019\u4f7f\u7528\u7684\u4e00\u4e2a\u6982\u5ff5":111,"memory\u7684":114,"memory\u7684\u521d\u59cb\u72b6\u6001":113,"memory\u7684\u65f6\u95f4\u5e8f\u5217\u957f\u5ea6\u4e00\u81f4\u7684\u60c5\u51b5":111,"memory\u7684\u66f4\u591a\u8ba8\u8bba\u8bf7\u53c2\u8003\u8bba\u6587":113,"memory\u7684\u8f93\u51fa\u5b9a\u4e49\u5728":114,"memory\u7684i":113,"memory\u9ed8\u8ba4\u521d\u59cb\u5316\u4e3a0":113,"mkl\u5e93\u7684":41,"mklml\u4ee5\u53camkl":42,"mklml\u53ef\u4ee5\u4e0emkl":42,"mklml\u7684\u5e93\u76ee\u524d\u90fd\u662f\u52a8\u6001\u5e93":42,"mnist\u624b\u5199\u6570\u5b57\u8bc6\u522b\u76ee\u5f55":90,"mode\u4e0b\u7684\u7ed3\u679c":41,"model\u505a\u5206\u652f\u7ba1\u7406":63,"name\u7ec4\u5408\u53ef\u4ee5\u627e\u5230\u672c\u6b21\u8bad\u7ec3\u9700\u8981\u7684\u6587\u4ef6\u8def\u5f84":97,"ndarray\u7c7b\u578b\u7684\u503c\u548c\u6574\u578b\u7684\u503c":11,"ndk\u4e2d\u5305\u542b\u4e86\u6240\u6709android":116,"new":[5,6,7,8,9,12,13,14,15,16,19,20,21,24,29,30,40,41,43,47,49,53,58,59,60,62,66,67,70,72,74,95,119],"note\u7684\u4e66\u5199":63,"null":[35,74,89,103],"num\u51b3\u5b9a\u603b\u7aef\u53e3\u4e2a\u6570":91,"num_gradient_servers\u53c2\u6570":97,"num_samples_processed\u4e3a\u5df2\u8bad\u7ec3\u6837\u672c\u6570":83,"only\u7684\u4e8c\u8fdb\u5236":0,"op\u4e0d\u9700\u8981\u5b9a\u4e49opprotomak":75,"op\u5355\u5143\u6d4b\u8bd5\u7ee7\u627f\u81ea":75,"op\u5b9a\u4e49":75,"op\u6709\u8ba1\u7b97\u51fd\u6570":75,"op\u6ce8\u518c\u5b9e\u73b0\u5728":75,"op\u7684\u4fe1\u606f":42,"op\u8ba1\u7b97\u51fd\u6570\u7684\u57fa\u7c7b":75,"openmp\u7528\u4e8e\u63d0\u9ad8mklml\u7684\u6027\u80fd":42,"opprotomake\u5b9a\u4e49":75,"org\u5de5\u5177\u7684\u8be6\u7ec6\u4fe1\u606f":77,"org\u76ee\u524d\u9075\u5faa":63,"outer_mem\u662f\u4e00\u4e2a\u5b50\u53e5\u7684\u6700\u540e\u4e00\u4e2a\u5411\u91cf":111,"output\u53ef\u4ee5\u662f\u4efb\u610f\u7ef4\u5ea6\u7684tensor":76,"output\u6587\u4ef6\u5939\u5b58\u653e\u8bad\u7ec3\u7ed3\u679c\u4e0e\u65e5\u5fd7":97,"output\u7684\u539f\u6709shape\u4fe1\u606f\u4e0d\u53d8":76,"packages\u91cc\u9762":78,"packages\u91cc\u9762\u7684python\u5305":78,"packed\u4f18\u5316\u540elayer\u7684\u6d4b\u8bd5":41,"packed\u76f8\u5173\u529f\u80fd":41,"paddepaddle\u901a\u8fc7\u7f16\u8bd1\u65f6\u6307\u5b9a\u8def\u5f84\u6765\u5b9e\u73b0\u5f15\u7528\u5404\u79cdbla":0,"paddle\u4e00\u4e2a\u52a8\u6001\u5e93\u53ef\u4ee5\u5728\u4efb\u4f55linux\u7cfb\u7edf\u4e0a\u8fd0\u884c":45,"paddle\u4e2d\u7ecf\u5e38\u4f1a\u5c06\u65f6\u95f4\u5e8f\u5217\u6210\u4e3a":111,"paddle\u4e8c\u8fdb\u5236\u5728\u8fd0\u884c\u65f6\u6355\u83b7\u4e86\u6d6e\u70b9\u6570\u5f02\u5e38":81,"paddle\u5185\u5d4c\u7684python\u89e3\u91ca\u5668\u548c\u5916\u90e8\u4f7f\u7528\u7684python\u5982\u679c\u7248\u672c\u4e0d\u540c":45,"paddle\u5185\u90e8\u7684\u7c7b\u4e3ac":45,"paddle\u7684\u591a\u8bed\u8a00\u63a5\u53e3\u5b9e\u73b0\u5305\u62ec\u4e00\u4e0b\u51e0\u4e2a\u65b9\u9762":45,"paddle\u7684\u7c7b\u578b\u5168\u90e8\u9000\u5316\u6210":46,"paddle\u7684\u94fe\u63a5\u65b9\u5f0f\u6bd4\u8f83\u590d\u6742":45,"paddle\u7684c":46,"paddle\u8bad\u7ec3\u4efb\u52a1":11,"paddle\u8def\u5f84\u4e0b":46,"paddle\u9700\u8981\u4e00\u4e2a\u591a\u8bed\u8a00\u63a5\u53e3":45,"paddle\u9700\u8981\u66b4\u9732\u7684api\u5f88\u591a":46,"paddle\u9759\u6001\u5e93\u94fe\u63a5\u590d\u6742":45,"paddle_\u7c7b\u578b\u540d":46,"paddle_\u7c7b\u578b\u540d_\u51fd\u6570\u540d":46,"paddlepaddle\u4e2d":[110,113],"paddlepaddle\u4e2d\u4e00\u4e2a\u8ba1\u7b97\u5c42\u7684\u8f93\u51fa\u6570\u636e\u7ec4\u7ec7\u65b9\u5f0f\u548c\u8f93\u5165\u6570\u636e\u7ec4\u7ec7\u65b9\u5f0f\u5b8c\u5168\u76f8\u540c":89,"paddlepaddle\u4e2d\u7684\u8bb8\u591alayer\u5e76\u4e0d\u5728\u610f\u8f93\u5165\u662f\u5426\u662f\u65f6\u95f4\u5e8f\u5217":111,"paddlepaddle\u4e2d\u7684cudnn\u90e8\u5206\u4f7f\u7528\u7684\u4e5f\u662f":42,"paddlepaddle\u4e2d\u795e\u7ecf\u7f51\u7edc\u8ba1\u7b97\u5c42\u8f93\u5165":89,"paddlepaddle\u4e2d\u8fd8\u5305\u542b":82,"paddlepaddle\u4e2d\u901a\u8fc7reader\u6765\u52a0\u8f7d\u6570\u636e":84,"paddlepaddle\u4e3a\u4ea4\u53c9\u7f16\u8bd1\u63d0\u4f9b\u4e86\u5de5\u5177\u94fe\u914d\u7f6e\u6587\u6863":[116,117],"paddlepaddle\u4e3a\u6df1\u5ea6\u5b66\u4e60\u7814\u7a76\u4eba\u5458\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684api":84,"paddlepaddle\u4e3ano":1,"paddlepaddle\u4f1a\u81ea\u52a8\u8bbe\u5b9a":82,"paddlepaddle\u4f7f\u7528\u540c\u6b65\u5c4f\u969c":92,"paddlepaddle\u4f7f\u7528\u5747\u503c0":83,"paddlepaddle\u4f7f\u7528avx":78,"paddlepaddle\u4f7f\u7528git":63,"paddlepaddle\u4fdd\u5b58\u7684\u6a21\u578b\u53c2\u6570\u6587\u4ef6\u5185\u5bb9\u753116\u5b57\u8282\u5934\u4fe1\u606f\u548c\u7f51\u7edc\u53c2\u6570\u4e24\u90e8\u5206\u7ec4\u6210":83,"paddlepaddle\u4fdd\u5b58\u7684\u6a21\u578b\u53c2\u6570\u6587\u4ef6\u524d16\u5b57\u8282\u4e3a\u5934\u4fe1\u606f":83,"paddlepaddle\u53d1\u5e03\u7684\u5b89\u88c5\u5305\u4f1a\u5c3d\u91cf\u5bf9\u9f50":3,"paddlepaddle\u53ef\u4ee5\u4f7f\u7528\u5e38\u7528\u7684python\u5305\u7ba1\u7406\u5de5\u5177":3,"paddlepaddle\u53ef\u4ee5\u4f7f\u7528cudnn":0,"paddlepaddle\u53ef\u4ee5\u540c\u65f6\u652f\u6301\u540c\u6b65\u968f\u673a\u68af\u5ea6\u4e0b\u964d":92,"paddlepaddle\u53ef\u4ee5\u6bd4\u8f83\u7b80\u5355\u7684\u5224\u65ad\u54ea\u4e9b\u8f93\u51fa\u662f\u5e94\u8be5\u8de8\u8d8a\u65f6\u95f4\u6b65\u7684":111,"paddlepaddle\u53ef\u4ee5\u901a\u8fc7\u8be5\u673a\u5236\u5224\u65ad\u662f\u5426\u5df2\u7ecf\u6536\u96c6\u9f50\u6240\u6709\u7684\u68af\u5ea6":74,"paddlepaddle\u5728\u5b9e\u73b0rnn\u7684\u65f6\u5019":111,"paddlepaddle\u5728\u6fc0\u6d3b\u51fd\u6570\u91cc\u5b9e\u73b0dropout":82,"paddlepaddle\u5728\u7f16\u8bd1\u65f6":0,"paddlepaddle\u5b58\u7684\u662f\u6709\u503c\u4f4d\u7f6e\u7684\u7d22\u5f15":84,"paddlepaddle\u5b89\u88c5\u5305\u7531\u4e8e\u4e0d\u4ec5\u4ec5\u5305\u542b":3,"paddlepaddle\u5c06\u4f1a\u6839\u636e":117,"paddlepaddle\u5c06\u4f1a\u81ea\u52a8\u9009\u62e9":117,"paddlepaddle\u5c06\u6839\u636e":116,"paddlepaddle\u5c06\u81ea\u52a8\u4e0b\u8f7d\u548c\u7f16\u8bd1\u6240\u6709\u7b2c\u4e09\u65b9\u4f9d\u8d56\u5e93":[116,117,118],"paddlepaddle\u5e93\u5df2\u7ecf\u5b89\u88c5\u5b8c\u6210":117,"paddlepaddle\u5f00\u53d1\u8fc7\u7a0b\u4f7f\u7528":63,"paddlepaddle\u63d0\u4f9b\u4e13\u7528\u7684":11,"paddlepaddle\u63d0\u4f9b\u4e86\u57fa\u4e8edocker\u7684\u5b89\u88c5\u65b9\u5f0f":2,"paddlepaddle\u63d0\u4f9b\u4e86\u591a\u79cdpython":2,"paddlepaddle\u63d0\u4f9b\u4e86c":88,"paddlepaddle\u63d0\u4f9b\u7684":82,"paddlepaddle\u652f\u6301":0,"paddlepaddle\u652f\u6301\u4e0d\u540c\u7c7b\u578b\u7684\u8f93\u5165\u6570\u636e":84,"paddlepaddle\u652f\u6301\u4f7f\u7528pip\u5feb\u901f\u5b89\u88c5":86,"paddlepaddle\u652f\u6301\u7528\u6237\u7075\u6d3b\u5730\u8bbe\u7f6e\u5404\u79cd\u547d\u4ee4\u884c\u53c2\u6570":104,"paddlepaddle\u652f\u6301\u975e\u5e38\u591a\u7684\u4f18\u5316\u7b97\u6cd5":81,"paddlepaddle\u652f\u6301sparse\u7684\u8bad\u7ec3":81,"paddlepaddle\u6587\u6863\u4f7f\u7528":77,"paddlepaddle\u662f\u6e90\u4e8e\u767e\u5ea6\u7684\u4e00\u4e2a\u6df1\u5ea6\u5b66\u4e60\u5e73\u53f0":84,"paddlepaddle\u6bcf\u6b21\u53d1\u65b0\u7684\u7248\u672c":63,"paddlepaddle\u6bcf\u6b21\u53d1\u7248\u672c\u9996\u5148\u8981\u4fdd\u8bc1paddlepaddl":63,"paddlepaddle\u7684":96,"paddlepaddle\u7684\u4e3b\u7248\u672c\u5e93\u9075\u5faa":63,"paddlepaddle\u7684\u5185\u5b58\u5360\u7528\u4e3b\u8981\u5206\u4e3a\u5982\u4e0b\u51e0\u4e2a\u65b9\u9762":81,"paddlepaddle\u7684\u53c2\u6570\u4f7f\u7528\u540d\u5b57":83,"paddlepaddle\u7684\u5404\u7248\u672c\u955c\u50cf\u53ef\u4ee5\u53c2\u8003":96,"paddlepaddle\u7684\u5b89\u88c5\u53ef\u4ee5\u53c2\u8003":101,"paddlepaddle\u7684\u5df2\u7ecf\u5b89\u88c5\u5b8c\u6210":116,"paddlepaddle\u7684\u6240\u6709layer\u90fd\u6709\u552f\u4e00\u7684nam":82,"paddlepaddle\u7684\u6587\u6863\u5305\u62ec\u82f1\u6587\u6587\u6863":77,"paddlepaddle\u7684\u6587\u6863\u6784\u5efa\u6709\u4e09\u79cd\u65b9\u5f0f":77,"paddlepaddle\u7684\u6e90\u7801":72,"paddlepaddle\u7684\u7f16\u8bd1\u9009\u9879":0,"paddlepaddle\u7684activation\u4f1a\u76f4\u63a5\u4f7f\u7528":42,"paddlepaddle\u7684bas":74,"paddlepaddle\u7684c":116,"paddlepaddle\u7684cmake\u7cfb\u7edf\u4f1a\u81ea\u52a8\u7f16\u8bd1\u6240\u6709\u7684\u7b2c\u4e09\u65b9\u4f9d\u8d56\u5e93":117,"paddlepaddle\u7684cmake\u7cfb\u7edf\u5c06\u6839\u636e\u8be5\u503c\u81ea\u52a8\u63a8\u5bfc\u548c\u8bbe\u7f6e\u9700\u8981\u4f7f\u7528\u7684\u4ea4\u53c9\u7f16\u8bd1\u5668":116,"paddlepaddle\u7684cmake\u7cfb\u7edf\u5c06\u6839\u636e\u8be5\u503c\u81ea\u52a8\u8bbe\u7f6e\u9700\u8981\u4f7f\u7528\u7684\u4ea4\u53c9\u7f16\u8bd1\u5668":118,"paddlepaddle\u7684cmake\u7cfb\u7edf\u624d\u8ba4\u4e3a\u5728\u662f\u5728\u4ea4\u53c9\u7f16\u8bd1raspberri":118,"paddlepaddle\u7684cmake\u7cfb\u7edf\u624d\u8ba4\u4e3a\u662f\u5728\u4ea4\u53c9\u7f16\u8bd1android\u7cfb\u7edf\u7684\u7248\u672c":116,"paddlepaddle\u7684dock":96,"paddlepaddle\u7684softmax\u4e0d\u80fd\u6307\u5b9a\u8ba1\u7b97\u7ef4\u5ea6":82,"paddlepaddle\u76ee\u524d\u53ea\u652f\u6301\u5728\u6bcf\u4e2a\u65f6\u95f4\u6b65\u4e2d":111,"paddlepaddle\u76ee\u524d\u63d0\u4f9b\u4e24\u79cd\u53c2\u6570\u521d\u59cb\u5316\u7684\u65b9\u5f0f":83,"paddlepaddle\u76ee\u524d\u652f\u63018\u79cdlearning_rate_schedul":83,"paddlepaddle\u793e\u533a":80,"paddlepaddle\u7f16\u8bd1\u9700\u8981\u4f7f\u7528\u5230\u4e0b\u9762\u7684\u4f9d\u8d56":0,"paddlepaddle\u82e5\u68c0\u6d4b\u5230\u7528\u6237\u4f7f\u7528\u7684cmake\u7248\u672c\u4e0d\u4f4e\u4e8e3":116,"paddlepaddle\u8d1f\u8d23\u5b8c\u6210\u4fe1\u606f\u548c\u68af\u5ea6\u5728\u65f6\u95f4\u5e8f\u5217\u4e0a\u7684\u4f20\u64ad":113,"paddlepaddle\u8d1f\u8d23\u5b8c\u6210\u4fe1\u606f\u548c\u8bef\u5dee\u5728\u65f6\u95f4\u5e8f\u5217\u4e0a\u7684\u4f20\u64ad":113,"paddlepaddle\u9488\u5bf9\u4e0d\u540c\u7684\u7528\u6237\u7fa4\u4f53\u63d0\u4f9b\u4e86\u591a\u79cd\u5b89\u88c5\u65b9\u5f0f":2,"paddlepaddle\u955c\u50cf\u9700\u8981\u63d0\u4f9b":97,"paddlepaddle\u9700\u8981\u4f7f\u7528docker\u73af\u5883\u5b8c\u6210\u7f16\u8bd1":0,"pass\u4e2a\u6a21\u578b\u5230\u7b2c":103,"pass\u5c06\u4e0d\u8d77\u4f5c\u7528":103,"pass\u8f6e\u5f00\u59cb\u8bad\u7ec3":103,"pass\u8f6e\u7684\u6a21\u578b\u7528\u4e8e\u6d4b\u8bd5":103,"passes\u8f6e":103,"patch\u53f7":63,"patch\u53f7\u52a0\u4e00":63,"path\u6307\u5b9a\u6d4b\u8bd5\u7684\u6a21\u578b":105,"perftools\u6765\u8fdb\u884c\u6027\u80fd\u5206\u6790":107,"period\u4e2a\u6279\u6b21\u5bf9\u6240\u6709\u6d4b\u8bd5\u6570\u636e\u8fdb\u884c\u6d4b\u8bd5":103,"period\u4e2a\u6279\u6b21\u6253\u5370\u65e5\u5fd7\u8fdb\u5ea6":103,"period\u4e2a\u6279\u6b21\u8f93\u51fa\u53c2\u6570\u7edf\u8ba1":103,"period\u4e2a\u6279\u6b21\u8f93\u51fa\u7b26\u53f7":103,"period\u6574\u9664":103,"period\u8f6e\u4fdd\u5b58\u8bad\u7ec3\u53c2\u6570":103,"pfsclient\u9700\u8981\u548cingress\u4e4b\u95f4\u505a\u53cc\u5411\u9a8c\u8bc1":27,"pfsclient\u9700\u8981\u5728\u4f20\u8f93\u5b8c\u6bd5\u6700\u540e\u4e00\u4e2achunk\u7684\u65f6\u5019\u68c0\u67e5destination\u6587\u4ef6\u7684md5\u503c\u662f\u5426\u548csource\u6587\u4ef6\u4e00\u81f4":27,"pfsserver\u63d0\u4f9brest":27,"pi\u5e73\u53f0\u4e0a\u9002\u7528\u7684paddlepaddle\u7684\u65b9\u6cd5\u548c\u6b65\u9aa4":118,"pi\u7248\u672c\u7684\u5e93":118,"pi\u7248\u672cpaddlepaddle\u5e93\u65f6":118,"pi\u7684\u914d\u7f6e\u4fe1\u606f\u5728":118,"pi\u7cfb\u7edf\u4e0a\u6765\u6784\u5efa":118,"pi\u7cfb\u7edf\u7684\u7248\u672c":118,"pserver\u5730\u5740\u7b49\u53c2\u6570\u4f7ftrainer\u53ef\u4ee5\u6b63\u786e\u8fde\u63a5\u5230pserv":91,"pserver\u76d1\u542c\u7684\u8d77\u59cb\u7aef\u53e3":91,"public":[7,19,29,32,37,55,61,64,66,67,68,70,74,75,76,95,96],"pwd\u53d8\u91cf\u4f1a\u5c55\u5f00\u4e3a\u5f53\u524d\u8def\u5f84\u7684\u7edd\u5bf9\u8def\u5f84":1,"py\u4e2d":63,"py\u7a0b\u5e8f":3,"pydataprovider\u4f7f\u7528\u7684\u662f\u5f02\u6b65\u52a0\u8f7d":81,"pypi\u4e0a\u7684package\u540d\u79f0\u4e3apaddlepaddle\u548cpaddlepaddl":63,"pypi\u4e0d\u652f\u6301\u8986\u76d6\u4e0a\u4f20":63,"pypi\u5b89\u88c5\u5305\u53ef\u4ee5\u5728":3,"python\u5b89\u88c5\u5305\u652f\u6301linux":78,"python\u5c01\u88c5\u7684\u5b9e\u73b0\u4f7f\u5f97\u6211\u4eec\u53ef\u4ee5\u5728\u914d\u7f6e\u6587\u4ef6\u4e2d\u4f7f\u7528\u65b0\u5b9e\u73b0\u7684\u7f51\u7edc\u5c42":74,"python\u5e93yep":107,"python\u6807\u51c6\u5e93\u4e2d\u63d0\u4f9b\u4e86\u6027\u80fd\u5206\u6790\u7684\u5de5\u5177\u5305":107,"reader\u7684\u4f7f\u7528\u65b9\u5f0f\u90fd\u662f\u4e00\u81f4\u7684":11,"reader\u8f93\u51fa\u7684data":11,"recommendation\u6587\u4ef6\u5939\u5185\u5b58\u653e\u8bad\u7ec3\u6587\u4ef6":97,"request\u524d":72,"request\u7684":72,"request\u88ab\u5408\u5e76\u540e":72,"resnet\u7684mkl":42,"return":[4,5,6,7,11,12,14,17,18,19,20,25,29,31,32,33,35,37,38,40,43,48,49,50,55,56,57,61,64,66,68,70,74,76,81,83,84,95,97,114],"rnn\u5373\u65f6\u95f4\u9012\u5f52\u795e\u7ecf\u7f51\u7edc":111,"rnn\u5bf9\u4e8e\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65\u901a\u8fc7\u4e86\u4e00\u4e2alstm\u7f51\u7edc":111,"rnn\u603b\u662f\u5f15\u7528\u4e0a\u4e00\u65f6\u523b\u9884\u6d4b\u51fa\u7684\u8bcd\u7684\u8bcd\u5411\u91cf":113,"rnn\u6a21\u578b":106,"rnn\u90e8\u5206\u4e2d":41,"rnn\u914d\u7f6e":112,"root\u66ff\u6362\u4e3apaddlepaddle\u9884\u6d4b\u5e93\u7684\u5b89\u88c5\u8def\u5f84":87,"s3\u4e4b\u7c7b\u7684\u5206\u5e03\u5f0f\u5b58\u50a8\u4e4b\u4e0a":11,"sdk\u7684\u63a5\u53e3\u9700\u8981\u662f\u6ee1\u8db3c\u6807\u51c6\u7684\u63a5\u53e3":88,"search\u7684\u65b9\u6cd5":103,"sentences\u662f\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217\u7684\u6570\u636e":111,"seq\u53c2\u6570\u5fc5\u987b\u4e3afals":113,"server\u4e2a\u6279\u6b21\u6253\u5370\u65e5\u5fd7\u8fdb\u5ea6":103,"server\u4e4b\u4e0a":10,"server\u4e4b\u95f4\u7684\u7f51\u7edc\u5e26\u5bbd":10,"server\u4f1a\u6682\u505c\u53c2\u6570\u66f4\u65b0\u5e76\u7b49\u5f85":10,"server\u4f1a\u83b7\u53d6parameters\u5185\u5b58\u7684":10,"server\u5185\u5b58\u4e2d\u7684\u6a21\u578b\u6570\u636e\u7684\u5b8c\u6574\u955c\u50cf":10,"server\u540c\u6b65\u7684\u4fdd\u5b58\u4e00\u4e2a\u7279\u5b9a\u65f6\u95f4\u70b9\u7684\u5168\u5c40\u68c0\u67e5\u70b9":10,"server\u5728\u96c6\u7fa4\u4e2d\u542f\u52a8\u540e":10,"server\u6545\u969c\u540e\u88abkubernetes\u91cd\u65b0\u542f\u52a8":10,"server\u6b64\u65f6\u8fd8\u9700\u8981\u901a\u8fc7\u7f51\u7edc\u8bbf\u95ee\u5206\u5e03\u5f0f\u5b58\u50a8\u4ee5\u4fdd\u5b58\u5feb\u7167":10,"server\u751f\u6210\u4e00\u4e2auuid":10,"server\u7684\u5355\u70b9\u6216\u591a\u70b9\u540c\u65f6\u6545\u969c":10,"server\u7684\u6570\u636e\u5feb\u7167":10,"server\u7684\u68c0\u67e5\u70b9\u5404\u81ea\u72ec\u7acb\u4fdd\u5b58":10,"server\u7b2c\u4e00\u6b21\u542f\u52a8\u6216\u4efb\u610f\u65f6\u95f4paramet":10,"short":[29,33,58,64,67,70],"simd\u6307\u4ee4\u63d0\u9ad8cpu\u6267\u884c\u6548\u7387":78,"size\u4e3a512":103,"size\u53ef\u80fd\u4f1a\u5bf9\u8bad\u7ec3\u7ed3\u679c\u4ea7\u751f\u5f71\u54cd":81,"size\u672c\u8eab\u662f\u795e\u7ecf\u7f51\u7edc\u7684\u8d85\u53c2\u6570":81,"softmax\u6fc0\u6d3b\u7684\u8f93\u51fa\u7684\u548c\u603b\u662f1":74,"sparse\u8bad\u7ec3\u9700\u8981\u8bad\u7ec3\u7279\u5f81\u662f":81,"static":[14,46,64,66,95,119],"step\u51fd\u6570\u4e2d\u7684memori":113,"step\u51fd\u6570\u5185\u90e8\u53ef\u4ee5\u81ea\u7531\u7ec4\u5408paddlepaddle\u652f\u6301\u7684\u5404\u79cdlay":113,"store\u4e0b\u8f7d\u5b89\u88c5xcode\u5373\u53ef":117,"subseq\u7684\u6bcf\u4e2a\u5143\u7d20\u662f\u4e00\u4e2a0\u5c42\u5e8f\u5217":110,"super":[58,74],"swig\u652f\u6301\u7684\u8bed\u8a00\u6216\u8005\u89e3\u91ca\u5668\u6709\u5c40\u9650":45,"swig\u66b4\u9732\u7684\u63a5\u53e3\u4fdd\u7559\u4e86c":45,"swig\u751f\u6210\u7684\u4ee3\u7801\u4e0d\u80fd\u4fdd\u8bc1\u591a\u8bed\u8a00\u4ee3\u7801\u98ce\u683c\u7684\u4e00\u81f4\u6027":45,"swig\u76f4\u63a5\u8bfb\u53d6c":45,"swig\u9700\u8981\u5199\u4e00\u4e2ainterface\u6587\u4ef6":45,"switch":[7,46,95],"tag\u4e3a":63,"tag\u53ef\u4ee5\u662flatest\u6216latest":63,"tag\u7684\u66f4\u65b0\u65f6\u95f4\u662f\u5426\u5728\u4e0a\u8ff0\u7f16\u8bd1wheel\u5305\u5b8c\u6210\u540e\u662f\u5426\u6700\u65b0":63,"tensor\u5230\u5bf9eigentensor\u7684\u8f6c\u6362":76,"tensor\u5230eigentensor":76,"tensor\u5b9a\u4e49\u5728framework\u76ee\u5f55\u4e0b":76,"tensor\u662f\u4e00\u4e2a\u6b63\u5728\u5f00\u53d1\u4e2d\u7684\u6a21\u5757":76,"tensor\u6a21\u5757\u5bf9el":76,"tensor\u6a21\u5757\u6765\u5b9e\u73b0":75,"tensor\u6a21\u5757\u7684\u6587\u6863\u8f83\u5c11":76,"tensor\u6a21\u5757\u7684\u8be6\u7ec6\u4ecb\u7ecd\u8bf7\u53c2\u8003":76,"tests\u7684paddlepaddl":72,"tflops\u4e86":108,"throw":95,"tottime\u7684\u6bcf\u6b21\u8c03\u7528\u5e73\u5747\u65f6\u95f4":107,"trainer\u542f\u52a8\u9700\u8981\u4f20\u5165\u7aef\u53e3":91,"trainer\u63a5\u6536\u4e09\u4e2a\u53c2\u6570":84,"trainer\u8282\u70b9\u4e2a\u6570":91,"trainer\u9700\u8981\u548cpserver\u4fdd\u6301\u7f51\u7edc\u8054\u901a\u4ee5\u5b8c\u6210\u8bad\u7ec3":91,"true":[4,6,7,12,30,36,41,50,52,56,57,58,59,63,66,70,74,81,83,89,90,91,95,97,105,114],"true\u8868\u793a\u53cd\u5411\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":114,"try":[8,9,12,13,14,30,35,40,43,59,64,67,78],"type\u5b57\u6bb5\u5747\u4e0d\u5c3d\u76f8\u540c":46,"type\u6307\u5b9a\u4e3a":107,"ubuntu\u4e0b\u5b89\u88c5\u547d\u4ee4\u4e3a":107,"unit\u5728\u4e00\u4e2a\u65f6\u95f4\u6b65\u5185\u8ba1\u7b97\u5f97\u5230\u7684\u4e2d\u95f4\u503c":82,"unsupported\u6a21\u5757":75,"update\u53c2\u6570\u65f6\u624d\u6709\u6548":103,"v1\u7248\u672c":78,"var":[6,7,18,19,20,24,31,32,34,36,39,50,52,56,57,58,60,64,69,70,77],"vector\u662frank\u4e3a1\u7684tensor":76,"void":[7,12,14,19,26,29,31,32,37,39,43,44,45,46,56,57,65,66,68,74,75,76],"wheel\u5305":[2,63],"while":[7,16,19,20,30,35,38,40,49,53,54,59,62,64,68,97],"wise\u8ba1\u7b97\u63d0\u4f9b\u4e86\u5f3a\u5927\u7684\u652f\u6301":76,"wmt14\u6570\u636e\u7684\u63d0\u4f9b\u6587\u4ef6\u5728":114,"words\u5373\u4e3a\u8fd9\u4e2a\u6570\u636e\u4e2d\u7684\u5355\u5c42\u65f6\u95f4\u5e8f\u5217":111,"words\u662f\u539f\u59cb\u6570\u636e\u4e2d\u7684\u6bcf\u4e00\u53e5\u8bdd":111,"x86_64\u548cmaco":78,"x\u4e0ey\u4e3a\u4e4b\u524d\u63cf\u8ff0\u7684\u8f93\u5165\u5c42":84,"x\u548cwindow":116,"y\u8868\u793a\u8f93\u5165\u6570\u636e\u662f\u4e00\u4e2a\u7ef4\u5ea6\u4e3a1\u7684\u7a20\u5bc6\u5411\u91cf":84,"yaml\u6587\u4ef6\u4e2d\u5404\u4e2a\u5b57\u6bb5\u7684\u5177\u4f53\u542b\u4e49":97,"yaml\u6587\u4ef6\u63cf\u8ff0\u4e86\u8fd9\u6b21\u8bad\u7ec3\u4f7f\u7528\u7684docker\u955c\u50cf":97,"zero\u4e09\u79cd\u64cd\u4f5c":103,AGE:[95,96],AWS:[11,94,99,100],Added:67,And:[12,16,17,26,33,35,47,51,52,55,59,64,68,95],But:[5,32,38,47,55,64,78,119],For:[4,6,7,13,14,15,17,18,19,21,24,25,30,31,32,34,37,39,40,44,47,48,49,53,54,55,56,57,58,59,60,61,62,65,66,67,68,71,108,119],IDE:0,IDs:[16,20,49],IRs:21,Into:95,Its:[31,65,95],K8s:119,NOT:58,Not:[4,9,40,67,119],OPs:[21,23],One:[5,16,39,44,47,52,64,67],Ops:[60,62,66],PFS:27,QoS:96,Such:[37,58,67,70],TLS:[4,27,95],That:[19,51],The:[4,5,6,8,9,13,15,16,17,19,20,21,23,24,25,28,29,31,35,38,39,40,43,44,46,48,49,51,52,53,55,56,57,58,59,62,64,65,66,67,68,70,71,74,75,76,89,95,97,109],Their:9,Then:[18,21,32,37,40,51,55,57,95],There:[4,7,8,9,14,16,17,20,21,28,29,30,35,40,47,48,49,52,53,54,55,58,62,64,65,68,95],These:[6,7,19,24,29,34,50,62,65,66,67,71],Use:[4,22,28,59,60,67,95],Used:[60,68],Uses:40,Using:[9,30,53,59,60,62,64],VPS:95,Will:84,With:[18,19,24,30,51,56,67,70],YES:17,Yes:[1,42],___embedding_0__:97,___embedding_1__:97,___fc_layer_0__:95,__align__:29,__cuda_align__:29,__device__:29,__doc__:66,__file__:17,__forceinline__:29,__fp16:29,__global__:29,__hadd:29,__half:29,__half_raw:29,__impl__:66,__init__:[24,25,33,40,50,58,70,74,107],__main__:33,__name__:33,__rnn_step__:114,__square_error_cost_0__:97,__va_args__:61,__x:29,_addup_repetitive_outputs_:6,_append_backward_ops_:[6,24],_append_backward_vars_:6,_binari:8,_create_global_var:58,_def:40,_dtype:35,_filer:43,_filter:43,_fwd:43,_fwd_pd:43,_input:43,_librari:8,_live_in:40,_live_out:40,_loss:33,_op:[35,75],_output:43,_presucessor:40,_program:40,_recurrent_group:114,_remove_no_grad_branch_:6,_reorder_input:43,_source_language_embed:114,_src_input:43,_sucessor:40,_target_language_embed:114,_test:8,_update_op:25,_use:40,_value_index:35,a75:29,a_op:75,a_prev:67,aaaaa:11,aaaaaaaaaaaaa:95,abil:33,abl:[4,6,19,20,21,37,50,55,58,119],about:[5,7,8,17,23,28,31,40,48,59,64,66,67,68,95],abov:[4,5,6,7,8,9,13,18,20,21,29,30,31,32,34,39,43,48,49,50,51,53,55,56,58,66,67,69,70,95,108,119],abs:[5,33,81],abs_numerical_grad:5,absolut:[5,81],acc:21,acceler:[10,42,51,53],accept:[4,60],access:[4,8,13,16,17,18,20,21,58],accessmod:95,accessor:58,accord:[5,6,14,21,23,34,49,60,70],account:[60,119],accoust:67,accrodingli:12,accumul:[9,14,25,51,52,53,67],accur:[5,16,55],accuraci:[25,67],achiev:[19,23,51,52,53,67,68],acquir:30,across:[6,21,48,67],act1:35,act2:35,act:[7,19,21,35,49,58,70,81,84,86,109,114],act_output:66,act_typ:35,action:[20,95],activ:[8,35,40,49,52,55,58,62,66,81,84,86,114],actual:[12,24,30,33,35,39,43,47,53,66,68],actual_layout:43,adadelta:81,adagrad:[53,65,91],adagradoptim:50,adam:[4,14,21,33,83],adapt:[39,55],add:[5,6,7,8,12,16,19,20,21,23,25,29,32,36,38,50,52,53,57,58,60,62,64,68,69,72,76,78,109],add_activ:58,add_bia:58,add_depend:8,add_execut:8,add_input:[48,74],add_memori:48,add_output:48,add_scalar:[7,49,56],add_sum:58,add_test:[8,74],add_to:82,add_two:[7,48],add_unittest_without_exec:74,addattr:[52,66,75],addbia:74,addcom:[66,75],added:[7,23,24,29,47,51,53,62,72],adding:62,addinput:[52,66,75],addit:[6,20,51,55,60,62,70,71],addition:48,addmemori:43,addop:32,addoutput:[52,75],addprimit:43,addprimitivedesc:43,addr:9,address:[9,14,18,21,89,119],addrow:74,addtyp:66,adjust:[6,24],admin:119,administr:[16,119],adopt:[29,33],advanc:5,advantag:[5,29,30,53,59],adversari:[33,59],affect:7,affili:49,afford:13,aforement:8,after:[6,7,8,13,14,16,21,22,23,24,26,28,29,40,43,51,54,55,58,67,72,95],aftern:55,again:[4,5,9,53],against:95,age:97,agg_level:[110,111],aggreg:[25,51,95],aggregatelevel:[110,111],ago:8,agre:[81,84],ahead:67,alexnet_pass1:105,alexnet_pass2:105,algo:43,algo_hrnn_demo:111,algorithm:[6,13,24,39,40,43,49,53,62,67],all:[4,6,7,8,9,12,14,16,17,18,19,20,21,22,24,26,28,30,33,34,35,38,40,43,44,46,47,48,49,50,51,52,53,55,56,58,60,66,67,68,78,81,84,95,97,109,113,119],all_output_nam:6,alloc:[14,17,40,43,52,68,76,109],allow:[4,14,18,19,21,24,30,52,53,62,95],allow_only_one_model_on_one_gpu:[102,103,105],allreduc:[51,52],alpha:[8,62],alreadi:[8,9,30,43,58,64,78,95],also:[4,6,7,8,12,15,19,20,21,29,30,32,33,34,35,38,40,47,48,49,52,53,54,55,56,57,58,59,62,64,66,67,68,70,71,108,119],although:[6,51],altogeth:119,alwai:[8,20,44,65,95,97],amazon:[95,96],amazonaw:95,amazonec2fullaccess:95,amazonelasticfilesystemfullaccess:95,amazonroute53domainsfullaccess:95,amazonroute53fullaccess:95,amazons3fullaccess:95,amazonvpcfullaccess:95,ambigu:[59,67],amd64:95,amd:47,amend:72,amodei:67,among:95,amort:51,analys:55,analysi:55,analyz:40,ancestor:[56,58],andd:95,andrew:40,android:116,android_abi:116,android_api:116,android_arm_neon:116,android_native_api_level:116,android_standalone_toolchain:116,android_toolchain:116,androideabi:116,ani:[4,8,9,14,16,17,18,20,21,26,29,30,37,39,40,44,49,51,52,53,58,59,61,62,67,81,84,95],announc:29,anoth:[4,6,7,17,19,20,30,31,39,43,49,58,64,66,68,95],anroid_arm_mod:116,ans:95,answer:[18,30,95],anymor:51,anyth:[49,59,95],anytim:33,apach:[42,81,84],apart:71,api:[3,4,6,8,14,15,17,18,19,25,27,32,33,35,48,54,55,60,63,70,71,87,88,89,90,91,95,97,107,108,116,119],api_pydataprovider2:81,api_shar:8,api_test:8,api_trainer_config_helpers_lay:114,api_v2:110,apiserv:95,apivers:[95,96,97],appar:6,appear:[18,30,34,68],appel:40,append:[6,24,25,49,58,59,67,91,97,114],append_backward:[6,50,52,107],append_clip_op:24,append_op:[24,38,58],append_oper:58,append_optim:52,appleyard:108,appli:[33,34,51,52,55,64],applic:[18,20,29,30,31,34,58,60,81,84,95,96,108,119],applyl1:12,appreci:67,approach:[21,22,23,51,53,54,62,67,119],approxim:53,apt:[1,107],arbitrari:[21,44],arch:116,archetectur:67,architectur:[29,67],archiv:[45,46,87],area:33,arg:[6,35,50,66,75,83,97],argpars:97,args_ext:97,argu:57,argument:[6,7,12,13,21,50,54,57,58,87,89,90,97,116],argumentpars:97,arithmet:29,arm64:[116,117],arm64_standalone_toolchain:116,arm:[29,116,117,118],arm_standalone_toolchain:116,armeabi:116,armv7:[29,117],armv8:29,arn:95,around:[16,40,58,95,119],arrai:[14,18,20,34,49,56,58,59,60,70,75,81,83,84,89],arrang:70,arrari:89,array_to_lod_tensor:40,arrow:33,articl:[31,34,72],artifact:[63,95],artifici:40,arxiv:[33,67],as_step_input:7,asduplic:52,asgd:53,ask:[6,9,16],asr:67,assgin:40,assign:[6,13,18,22,24,29,31,51,67,89,95,119],assigne:67,assignmemt:40,associ:[54,61],assum:[7,21,43],assumpt:21,ast:18,astyp:[59,75],asyc:9,async:[9,23,52,102],async_count:[102,103],async_lagged_grad_discard_ratio:[91,103],async_lagged_ratio_default:[102,103],async_lagged_ratio_min:[102,103],asynchron:[9,20,51,55],atom:22,attr:[7,18,35,38,43,56,57,58,66,75,81,82,83,114],attr_map:66,attrdesc:56,attribu:43,attribut:[6,7,23,24,38,56,58,60,64,66,70],attributemap:75,attrproto:66,attrtyp:[56,66,75],attrvalu:66,auc:[25,102],audio:67,augment:67,authent:95,author:[27,67,81,84,95],auto:[0,7,12,22,31,39,43,45,57,60,64,70,74,75,76,108],autom:95,automat:[4,6,14,21,23,24,32,50,60,66,67,95],avail:[9,14,23,29,30,40,95,119],averag:[13,81],average_test_period:[102,103],avg:[108,110],avg_cost:[21,109],avoid:[5,7,9,20,21,38,43,51,52,53,54,108],avx:1,awai:30,await:96,awar:[4,18,20,25,31,48,58,95],awk:98,awni:67,aws:27,aws_account_id:95,awsaccountid:95,awskeymanagementservicepowerus:95,axi:81,axiom:20,b363:96,b8561f5c79193550d64fa47418a9e67ebdd71546186e840f88de5026b8097465:96,ba5f:95,back:[6,9,21,29,33,53],background:[52,62,67],backpropag:[5,6],backward:[5,7,12,14,24,33,41,42,50,52,53,54,57,61,62,69,74,75,109],backward_first:114,backward_op:5,backwardactiv:74,bacth:19,baidu:[30,67,96],bake:21,balanc:[23,51,95],bandwidth:[29,51],bare:[96,119],barrier:92,barrierstatset:108,basci:35,base:[4,13,19,24,25,29,30,37,43,47,50,51,53,55,60,61,62,68,70,95,109],baseerrorclipattr:24,baselin:67,basematrix:74,bash:[0,1,72,95,96,97,101],basi:[81,84],basic:[21,35,43,55,56,60,61,67,70],batch:[4,7,9,11,12,19,20,21,25,26,30,33,36,47,48,49,51,53,67,70,81,84,89,95,96,97],batch_id:[33,81,84],batch_im:33,batch_label:33,batch_norm:[33,67],batch_read:[11,19,59],batch_siz:[21,33,41,49,81,84],batch_szi:33,batch_z:33,batchnorm:[33,67],batchread:19,batchsiz:74,bazel:8,bbbbb:11,bcm2708:118,bdist_wheel:63,beacus:35,beam:114,beam_gen:114,beam_search:[49,113,114],beam_siz:[49,102,103,105,114],becaus:[4,5,7,8,9,14,29,39,49,54,58,59,62,64,65,69,70,71,95],becom:[22,23,64,68],been:[6,8,13,20,30],befor:[6,9,16,20,24,28,31,34,47,53,54,55,59,62,75,78,81,95,119],begin:[6,12,14,19,25,28,34,49,51],beginiter:4,beginn:114,beginpass:4,begintrain:4,behavior:20,behind:[30,70],being:[6,16,24,30,57,59],belong:[19,21,64],below:[7,9,14,21,23,29,30,44,54,59,62,70,71,95],benchmark:[44,67],benefit:[16,17,49],besid:[21,40,47,51],best:[8,43],besteffort:96,beta:33,better:[8,30,39,40,43,49,95,119],between:[6,8,9,14,21,23,29,30,43,46,51,54,61,64,95],bia:[49,58,74],bias_attr:[58,81,83,114],biases_:74,biasparameter_:74,biassiz:74,bidi:96,bidirect:67,bidirectional_lstm:82,big:[18,23,40,119],bigger:9,bilinearfwdbwd:108,bin:[0,1,90,91,95,96,97,101],binari:[8,17,21,29,31,33,44,90,95],bind:[18,20,29,32,64,68],bit:29,bitcod:117,black:33,blank:95,blob:0,block0:[40,52],block1:[40,52],block2:[40,52],block3:52,block:[6,10,12,14,18,20,21,22,23,24,25,26,30,37,40,47,48,50,68,71,76],block_expand:67,block_id:[18,26],blockdesc:[7,34,52,58,60],blockdescbind:37,blockingcount:22,blueprint:49,book:[1,60,67,77,109,114],bool:[7,19,29,36,38,41,42,43,57,58,65,66,70,71,74,89,103,105],boost:[47,67,68],boot:[113,114,119],boot_lay:114,boot_stat:70,bootstrapp:119,borrow:[33,70],bos_id:114,both:[4,7,8,9,16,19,20,21,23,29,30,33,37,40,47,49,51,55,57,65,67,68,95],bottl:51,bottleneck:55,bottom:67,bound:40,boundari:21,box:33,brace:[7,34],brain:16,branch:[4,7,8,21,30,36,56,63,69,72],break_if:70,brief:[8,14,29,68,76],bring:[30,40],broadcast:[9,51,60,119],broken:72,browser:95,bsd:[20,51],bsp:20,bucket_nam:95,buf:12,buf_siz:21,buffer:[12,20,43,44,53,59,64,109],buffer_s:20,buffered_read:59,bug:[72,95],build:[0,8,17,21,34,35,40,42,53,62,63,66,67,72,77,78,87,95,97,99,100,101,107,116,117,118],build_doc:77,build_model:33,buildtool:63,built:[8,18,21,29,31,40,47,51,66,67,70,107,108,119],bulk:20,bunch:44,button:95,c11:45,c703c041:72,c99:46,c99e:95,cach:[29,81],cache_pass_in_mem:81,cachetyp:81,cacul:25,caff:[7,30],caffe2:[7,18,20,30],caffe_poli:83,calcul:[5,6,9,14,22,25,29,40],calcut:40,calendar:55,call:[4,5,6,7,12,13,14,15,17,18,20,21,24,31,33,34,40,48,49,50,52,55,58,60,61,64,66,68,70,95,97,107,108],callback:[24,74],caller:[5,95],can:[4,5,6,7,8,9,12,13,16,17,18,19,20,21,23,24,26,29,30,31,32,33,34,35,37,38,39,40,43,47,48,49,50,51,52,53,55,56,57,58,59,60,61,62,66,68,70,71,95,108,119],cancel:16,candid:[49,67],cannot:[19,39,60,64,70,78],cantain:35,capabl:[29,54,60],capac:[62,95],capi:[45,87],capi_priv:87,capi_prvi:46,caption:49,card:51,care:[17,40,59,67,68,119],carefulli:67,carpedm20:33,cast:[29,39],cast_to_op_attr:66,cat:[1,97,98],categori:9,categoryfil:96,caus:[9,28],caution:95,cbla:[41,87],cc_:8,cc_binari:8,cc_test:8,cclient:15,cduadevicecontext:[47,68],cento:[3,119],central:62,ceph:11,cephf:[11,17,27],cer:67,certain:[19,38,47,50,55,64,68],certif:[4,27,78,95],cffi:45,cfg:[40,96],cgo:45,ch1:20,ch2:20,chain:[6,34],challeng:[5,9,30,36,68],chan:20,chanc:[4,29],chang:[8,13,17,21,30,43,54,56,59,61,63,64,67,72,95],changes:43,channel:[18,71,108],chapter:[48,49,67],chapter_data:48,chapter_out:48,charact:[20,67],check:[6,7,8,24,43,57,60,69,72,74,78,83,89,95,103],check_attr:66,check_eq:74,check_grad:[5,75],check_l:74,check_output:75,check_sparse_distribution_batch:[102,103],check_sparse_distribution_in_pserv:[102,103],check_sparse_distribution_ratio:[102,103],check_sparse_distribution_unbalance_degre:[102,103],checker:[5,60],checkgrad:103,checkgrad_ep:103,checkmark:119,checkout:72,checkpoint:[23,57],checksum:27,child:7,chip:30,chmod:95,choic:[8,30],choos:[20,38],chosen:[33,47],chunk:[13,27],circl:34,circular:20,circumst:68,claim:95,claimnam:[95,97],clang:[29,45,72,116],clariti:49,classic:[40,67],classif:34,classifi:33,classification_cost:81,claster:95,clean:[7,8,26,54,60,72,78],clear:[8,39,49,54,64],clearer:[54,58],clearli:64,cli:95,click:95,client:[12,15,60],clip:103,clip_op:24,clip_op_desc:24,clipe:52,clone:[0,77,87,107,116,118],close:[20,59,72],close_channel:20,cloud:[8,9,17,27,28,60,119],cludform:95,cluster:[4,7,9,14,21,67,91,93,97],cluster_test_fil:91,cluster_train:[81,93],cluster_train_fil:91,cluster_train_v2:[93,94,98],cm469:95,cmake:[0,46,72,75,77,78,87,108,116,117,118],cmake_build_typ:[116,117,118],cmake_c:[116,117],cmake_system_nam:[116,117,118],cmakefil:78,cmakelist:[8,41,42,74],cmatrix:[45,46],cname:95,cnn:96,coars:32,code:[4,6,8,16,19,20,21,23,26,29,32,33,34,38,44,47,50,52,53,54,55,57,59,60,61,62,66,70,74,95,96],codebas:60,coded_stream:83,codedinputstream:83,colindic:89,collabor:9,collect:55,collectbia:74,colum:89,column:[34,59,89],com:[0,1,8,33,63,72,77,78,87,95,96,107,109,116,118,119],combin:[40,50,60,64],come:[21,25,40,56,67,70,71],comma:14,command:[0,8,12,17,28,74,95,96,97,99,100,105],commandlin:[97,108],comment:[8,35,66,67,97],commit:[8,96],common:[11,62,68],commonli:[28,62],commun:[9,14,15,20,21,23,51,95],compani:30,compar:[5,8,18,60],comparison:[8,30],compat:[29,32,51],compil:[0,8,21,30,35,37,40,47,51,61,65,66,71,101,116,117,118],complaint:8,complet:[6,7,9,13,14,24,27,34,44,47,60,95,96,97,119],complex:[16,20,40,49,60],complianc:[81,84],complic:[21,32,39,59,70],compon:[20,21,35,67,70,71],compos:[4,20,32,35,48,58,60],composit:32,compress:[13,89],compris:6,comput:[4,5,9,20,21,23,26,29,30,31,35,39,40,44,47,50,51,52,53,55,61,64,67,68,71,75,76,95,109],computationgraph:35,con:51,concat:[33,114],concaten:[33,48,70,81],concentr:60,concept:[4,18,19,20,30,32,33,35,43,48,49,53,54,56,64,70,71],conceptu:[20,26,30,33,35],concern:[4,20,25],concis:[33,70],concret:[60,68],concurr:[9,16,23,55],cond:[7,30,36,56],condit:[13,21,30,36,43,67,69,81,84,96],condtion:33,conf:[83,93,97,111],conf_paddle_gradient_num:[95,97],conf_paddle_n:[95,97],conf_paddle_port:[95,97],conf_paddle_ports_num:[95,97],conf_paddle_ports_num_spars:[95,97],config:[11,28,49,74,84,87,95,96,97,102,103,105,119],config_:[12,103],config_arg:[102,103,105],config_lay:74,config_len:14,config_pars:[41,42,74],config_proto:14,configmap:21,configprotostr:83,configur:[6,12,14,16,17,21,23,30,35,38,39,58,67,68,74,86,119],confirm:28,conflict:[64,72],confus:[33,38],connect:[17,18,21,23,67,79,95,96,119],consid:[6,57,68,119],consider:[47,67],consist:[13,19,20,31,44,56,59,60,61,66,67,71],consol:95,consolid:7,constant:[35,37,38,47,83],constraint:64,construct:[4,26,35,40,48,58,60,64,66],constructbackwardgraph:34,constructoptimizationgraph:34,constructor:[24,29,55,58,60,64,66],consum:9,consumpt:40,contact:16,contain:[0,4,6,7,13,26,33,35,43,44,47,54,55,58,60,61,64,65,66,67,70,71,95,96,97],containerport:95,content:[14,28,44,49,77],content_dir:77,content_len:14,context:[24,43,64,65,68,75,76,81,109,114],contin:95,continu:[6,9,44,67],contrib:62,contribut:[62,67],contributor:60,control:[7,18,20,69,95,96,119],controlflowgraph:40,conv2d:33,conv:[33,39,43],conv_fwd:43,conv_pool_2:21,conveni:[4,6,35,50,66,67],convent:[6,14],convers:[29,30],convert:[11,21,22,23,29,30,31,43,59,61,67],convlut:67,convolut:[33,47,58,68],convolution_algorithm_opt:43,cool:72,cooper:67,coordin:[9,14],copi:[4,13,16,28,34,48,49,51,53,70,81,84,95],copy_from:24,copyright:[81,84],copyvariablewithtensor:39,core:[6,35,38,46,53,54,70,109],coreo:[95,119],corner:60,corpu:67,correct:[5,6,29,51,95],correctli:[6,29,33],corresond:29,correspoind:4,correspond:[4,6,7,8,24,29,35,36,43,47,48,49,58,60,61,62,66,68,69,83],corss_entropi:4,cortex:29,cos:66,cosin:66,cosineop:66,cosineopproto:66,cosineopprotomak:66,cost:[4,6,21,34,39,50,51,56,57,81,84,109],cost_np:57,could:[4,5,13,18,20,21,22,23,29,30,31,48,50,53,54,56,58,59,61,69,95],count:[9,17,25,57,59,67,91,96,103,105,108],counter:[9,13,22,34],cours:[17,47],cover:[30,67],cp27:3,cp27m:[3,63],cp27mu:[3,63],cpp:[5,12,32,41,42,45,46,54,60,71,74,83,97,108,111],cprofil:107,cprofilev:107,cpu:[0,5,17,29,38,39,47,52,53,54,55,60,62,63,68,75,76,96,105,108,109],cpu_avx_mkl:3,cpu_avx_openbla:3,cpu_kernel:38,cpu_noavx_openbla:3,cpu_ns_:55,cpu_per_pserv:21,cpu_per_train:21,cpudevicecontext:[47,68,75],cpuelapsedu:55,cpuengin:42,cpuinfo:1,cpuplac:[21,38,39,43,47,52,68,75,76,109],cpusparsematrix:46,crash:[9,108],creat:[4,5,7,9,14,18,19,22,24,25,26,27,28,29,30,32,33,34,43,47,48,50,51,53,54,58,61,62,67,72,74,77,81,83,84,89,96,97,98,119],create_backward_pass:50,create_bias_paramet:74,create_block:58,create_doc_str:66,create_input_paramet:74,create_local_scop:26,create_oper:32,create_optimization_pass:50,create_paramet:58,create_python_ops_creatation_funct:66,create_rnn:7,create_rnn_op:48,create_tmp_var:58,create_tmp_vari:58,create_var:58,create_whileloop:70,creategradientoper:61,creatememori:43,createop:66,createoper:7,createprimitivedesc:43,createstack:95,createvari:7,creation:[32,95],creationd:95,creator:[11,60,61],creator_:61,credenti:28,crf:[39,68],critic:33,crlf:72,crop:68,crop_grad:68,cropgradkernel:68,cropkernel:68,cross:[58,83,116,117,118],cross_entropi:[4,21,33,39,40,52],crt:27,csc:74,csr:[74,89],csv:83,ctc_error_evalu:67,ctest:[0,72,75],ctor:58,ctrl:[0,93],ctx:[39,43,75,76],cubla:47,cublas_handle_:68,cublashandle_t:68,cuda7:[3,86],cuda8:[0,1,3],cuda:[8,31,47,55,60,68,75,103,108],cuda_context:31,cuda_dir:[102,103],cuda_fp16:29,cuda_so:[1,78],cuda_visible_devic:81,cudaconfigurecal:108,cudadevicecontext:[31,47,68,75],cudadevicegetattribut:108,cudaelapsedu:55,cudaevent_t:55,cudaeventcr:108,cudaeventcreatewithflag:108,cudafre:108,cudagetdevic:108,cudagetdevicecount:108,cudagetdeviceproperti:108,cudagetlasterror:108,cudahostalloc:108,cudalaunch:108,cudamalloc:108,cudamemcpi:108,cudaplac:[39,47,68],cudaprofilerstart:108,cudaprofilerstop:108,cudaprofilestop:108,cudaruntimegetvers:108,cudasetdevic:108,cudasetupargu:108,cudastream_t:68,cudastreamcr:108,cudastreamcreatewithflag:108,cudastreamsynchron:108,cudeviceget:108,cudevicegetattribut:108,cudevicegetcount:108,cudevicegetnam:108,cudevicetotalmem:108,cudnn:[8,38,39,43,47,68],cudnn_conv_workspace_limit_in_mb:[102,103],cudnn_dir:[102,103],cudnn_kernel:38,cudnnv5:0,cudrivergetvers:108,cuinit:108,cumtim:107,cur_mem:49,curl:95,curli:[7,34],current:[6,7,8,9,12,14,18,23,25,30,38,39,47,48,49,53,54,55,58,64,70,77,95],current_block:[56,58],current_oper:56,current_word:[81,114],curv:4,custom:[4,17,29,33,49,53,60,67,95],custom_batch_read:59,cut:70,cxx:[116,117],cxx_compil:[116,117,118],cxx_flag:[116,117],cxxabi_1:3,cycl:9,cython:45,d3e0:95,d_b0:33,d_b1:33,d_b2:33,d_block:33,d_f:33,d_g:33,d_h0:33,d_h0_bn:33,d_h0_relu:33,d_h1:33,d_h1_bn:33,d_h1_relu:33,d_h2:33,d_loss:33,d_loss_fak:33,d_loss_real:33,d_optim:33,d_step:33,d_t:33,d_w0:33,d_w1:33,d_w2:33,dandroid_abi:116,dandroid_arm_mod:116,dandroid_arm_neon:116,dandroid_standalone_toolchain:116,dario:67,darwin:95,dash:33,dat:11,data:[4,5,7,11,12,13,20,23,25,27,29,30,33,34,35,37,38,40,43,44,47,48,49,50,51,52,53,54,56,58,60,62,64,65,66,67,68,70,71,76,81,84,86,89,92,96,97,99,102,109,114],data_batch:81,data_grad:52,data_i:33,data_lay:[12,81],data_layout_:39,data_read:59,data_reader_creator_random_imag:59,data_shar:70,data_typ:[39,44,65,67,71,82,84,86,89,114],data_type_:[38,39,47],data_x:33,datacent:[11,28],datacenter1:11,datacenter2:11,datacenter_1:11,datacenter_2:11,datacenter_nam:11,datafeed:109,dataflow:35,dataflow_analysi:40,datalayout:39,dataparallel:21,dataprovid:[81,83,97],dataprovider_convert:67,dataset:[11,17,21,53,59,67,84,86,91,107,114],datatransform:39,datatyp:[38,39,43,65,67],dcgan:33,dcmake_build_typ:[77,87],dcmake_install_prefix:[87,116,117,118],dcmake_system_nam:[116,117,118],dcuda_arch_nam:0,dcudnn_root:0,ddim:[19,47,68,76],dead:9,deal:[6,119],deb:72,debug:[5,6,21,28,30,58,77,107],debug_str:35,decai:52,decayr:12,decent:13,decid:[4,16,33,44,53,61,62,65],declar:[7,33,48,71],decod:[67,113,114],decoder_boot:114,decoder_dim:49,decoder_group_nam:114,decoder_input:[49,81,114],decoder_mem:[49,114],decoder_s:[81,114],decoder_st:114,deconv:33,decor:19,decrement:22,decrementcount:22,decrypt:95,deduc:60,deep:[6,16,20,26,33,34,40,42,55,60,62,67,68,108],deeper:31,deepspeech2:41,def:[4,5,6,11,17,24,25,32,33,35,38,40,48,49,50,58,59,66,70,74,75,81,83,84,97,114],def_block:33,default_block:33,default_decor:97,default_devic:105,default_main_program:109,default_param_attr:58,default_st:70,default_start_up_program:52,default_startup_program:109,default_valu:105,defaultdict:40,defaultinfervartyp:37,defect:54,defer:16,defin:[4,6,7,8,9,16,18,19,22,23,24,29,30,31,32,33,35,38,40,47,48,51,56,58,59,60,64,66,68,70,71,75,81,84,109],define_py_data_sources2:83,definit:[6,7,9,13,21,26,31,38,52,56,61,66,70,109],definiton:32,delai:[53,68],delet:[17,27,72],deletestack:95,delimit:83,deliv:119,delta:5,demand:[9,68],demo:[60,96,99],dens:[14,15,65,67,95],dense_arrai:82,dense_vector:[84,86,89],dense_vector_sequ:89,dense_vector_sub_sequ:89,densescann:67,dep:8,depart:67,depend:[7,8,9,17,19,20,21,23,35,51,57,65,119],dependent_var:57,deploi:119,deploy:[35,44,60,95,119],deprec:67,depth:[7,30,67],dequeu:23,deriv:[4,19,21,24,36,50],desc:[7,24,43,44,58,66,70],desc_:7,descend:70,descent:[9,53],descproto:44,describ:[4,6,7,8,13,18,21,26,31,38,39,43,44,48,49,54,56,58,60,65,66,71,95,96],describestack:95,describestackev:95,describestackresourc:95,descripotor:43,descript:[7,8,37,39,42,44,47,61,65,67,71,95,97],descriptor:[20,39,43],deseri:[44,54],deserializ:60,desgin:34,design:[6,12,19,38,40,45,53,55,62,119],desir:[9,21,53,95,96],destin:[14,28],destroi:[7,26],destruct:64,destructor:55,detail:[5,6,13,17,21,23,28,30,33,35,39,40,43,44,47,48,55,58,62,64,68,70,71,95,119],detect:[37,72],determin:[7,21,40,47,60],dev:[0,1,60,72,78,107,116,119],dev_ctx:[7,43,55],devel:63,develop:[0,6,8,30,37,54,55,58,61,63,67,72,109,117],devic:[1,5,18,21,25,29,35,39,42,43,47,51,54,55,60,76,78,105,109],device_:55,device_context:[43,75],devicecontext:[7,47,55,75],deviceid:[42,105],deviceid_:42,deviceplac:68,devot:67,dhcp:119,diagram:48,diamond:33,dict:[6,58,83,97],dict_dim:81,dict_siz:[12,49],dictionari:[4,5,58,81],did:54,diff:[72,81],diff_mat:5,differ:[5,6,7,8,9,14,16,19,21,22,23,24,25,26,29,30,33,35,36,39,40,43,47,49,51,53,55,57,61,64,67,69,70,71,95],differenti:32,difficult:[5,30],dig:95,digraph:35,dilat:43,dim0:75,dim1:75,dim:[12,43,44,48,60,65,68,71,74,75,76],dim_:[68,76],dimens:[33,60,65,67,68,70,76,81],dimension:89,dios_arch:117,dios_enable_bitcod:117,dios_platform:117,dios_use_veclib_for_bla:117,dir:[78,97,116],direcit:67,direct:[30,40,53,67],directli:[8,15,17,19,21,29,38,39,54,66,70],directori:[8,11,16,27,28,68,72,77,96,108],disabl:[55,83],disadvantag:[53,58],discard:[9,13,49,72,103],discexp:83,discov:9,discoveri:95,discrim:33,discuss:[4,7,13,14,15,21,43,67],disk:44,dispatch:[21,54],displai:[17,28],dist:[0,63,78],dist_train:[4,17],distinguish:8,distribut:[7,13,14,15,16,18,20,25,31,51,60,67,71,81,84,99,100,103,119],distribute_test:[102,103],distributedli:21,disucss:4,divid:[6,25,66,71],diy_beam_search_prob_so:[102,103],dnn:[43,67,78],dns:95,do_forward_backward:59,doc:[35,48,70,75,77,91,93,97],doc_cn:77,docker:[0,1,63,72,77,78,95,96,97,99,100,101,116,119],docker_build:4,docker_clust:[93,98],docker_push:4,dockerfil:[0,72,97,116,118],document:[5,19,21,27,34,48,49,55,60,67],doe:[9,13,14,16,17,18,19,21,23,26,29,35,40,48,54,58,60,61,62,109],doesn:[4,7,18,20,59],doing:[12,16,21,34,52],domain:95,don:[4,8,32,34,40,59,67,95],done:[6,8,9,13,14,21,22,37,40,44,53,61,62,67,72,95,97,108],dot:75,dot_period:[97,103,105],doubl:[21,29,34,39,55,75,103],down:[67,108],download:[8,9,12,16,27,78,96,119],doxygen:72,dozen:8,dpython_execut:78,dpython_include_dir:78,dpython_librari:78,draw:49,drive:64,drop:[19,49],drop_fc:82,drop_rat:82,dropout:82,dropout_r:82,drpi_arm_neon:118,drpi_toolchain:118,drwxr:96,ds2:67,dst:[14,43],dst_primitive_desc:43,dtoh:108,dtype:[20,21,35,58,83,109],due:[13,16,33,40,49,58,107],dummi:13,dump:[44,90],dump_config:90,dump_v2_config:90,duplic:[23,52],durat:13,dure:[6,7,9,13,16,17,25,30,40,51,53,55,58,60,67,71,95,119],duse_eigen_for_bla:116,dwith_c_api:[46,87,116,117,118],dwith_doc:77,dwith_golang:87,dwith_gpu:[0,77,87,118],dwith_mkl:[77,87],dwith_profil:108,dwith_python:[46,87,118],dwith_swig_pi:[46,87,116,117,118],dwith_test:[0,75,117],dwith_tim:108,dynam:[14,46,48,58,59],dynamic_cast:74,dynamic_recurrent_op:70,e2e:119,each:[5,6,8,9,12,13,14,16,17,18,19,20,21,24,25,26,31,34,37,39,40,43,47,48,49,51,52,54,55,57,58,59,60,61,64,65,66,67,68,69,70,71,95,119],eager:30,earli:[29,31],eas:37,easi:[5,6,49,53,59,60,62],easier:[4,23,29,30,59,69,70],easili:[4,33,51,55,59,61,64,68],echo:[1,78],edg:40,edit:[20,95],editor:58,edu:[95,96],eeoi3ezpr86c:95,effect:95,effici:[21,44,59,67,68],effort:[21,67],efs:95,efs_dns_nam:95,efsvol:95,egd:40,eigen:[29,47,53,60,62,68,75],eigen_device_:68,eigen_use_gpu:75,eigenmatrix:76,eigentensor:76,eigenvector:76,either:[4,21,33,36,37,48,53,62,81,84],elabor:67,elb:95,elbapis:95,electr:40,electron:96,element:[5,13,20,23,35,49,60,75],element_typ:14,elementari:60,elif:[4,66,69],els:[1,4,12,17,20,21,23,24,30,33,36,37,38,40,64,66,69,74],elsewher:55,emac:0,emailweixu:8,emb1:12,emb2:[12,111],emb:[81,83,96],emb_para:83,emb_param_fil:83,emb_sum:81,embed:[4,7,12,23,37,49,65,70,83,114],embedding_lay:[12,81,111],embedding_nam:114,embedding_s:114,emplace_back:74,emploi:[6,24,66],empti:[6,9,19,20,49],emul:29,enabl:[7,8,13,18,23,24,35,55,95,108],enable_grad_shar:[102,103],enable_parallel_vector:103,enc_proj:114,enc_vec:114,encapsul:14,encod:[13,49],encoded_proj:114,encoded_sequ:114,encoded_vector:114,encoder_ctx:49,encoder_ctx_expand:49,encoder_ctx_proj:49,encoder_dim:49,encoder_out_seq:49,encoder_s:114,encount:12,encourag:[21,26],encrypt:95,encrypt_decrypt:95,end2end:119,end:[6,7,21,24,31,35,40,49,54,55,59,64,67,69,72,114],end_pass:4,endforwardbackward:81,endian:44,endif:[47,55],enditer:[4,81,84],endpass:[4,84],endpoint:[11,95],endtrain:4,enforc:71,engin:[17,42,43,67],english:67,enough:[6,7,38,40,47],enqueu:23,ensur:[9,43,51,64],enter:[7,26],enterpris:60,entir:[14,16],entiti:[7,64],entranc:26,entri:[13,17,37,95],entropi:58,entry_point:17,enumer:[47,83],env:[77,81,95,97,107],environ:[4,19,21,78,95,96,108],environmenterror:91,eol:72,eos_id:114,epoch:33,epol:20,equal:[9,70,75],equat:[40,75],equival:[4,7,18,20,24,30,36,66,119],eras:19,erlang:20,error:[4,5,13,28,29,30,43,64,67,78,83,87,95,103],error_clip:24,error_clip_callback:24,error_clipping_threshold:81,errorclipbyvalu:24,especi:42,essenc:[4,6],essenti:[4,26,29],establish:18,estim:[4,23,53],eta:96,etc:[7,20,21,25,43,51,53,59,64,67,95,119],etcd:[9,13,14,16],etcd_addr:14,eth0:[95,97],etyp:20,eval:[7,25,33,60],eval_program:25,eval_result:25,evalu:[16,35,57,67,90,108,109],even:[4,29,51,58,59],evenli:[14,95],event:[81,84,96],event_:55,event_block:55,event_handl:[4,81,84],eventkind:55,eventlist:55,eventu:[21,70],everi:[4,9,13,14,16,24,25,34,35,37,39,40,43,47,48,51,58,64,66,84,109],everyth:[21,23,33],evid:54,evolv:30,exactli:[19,81,95],exampl:[7,17,19,21,23,25,28,30,31,32,33,34,35,37,39,40,43,47,48,49,54,55,56,58,59,60,61,62,65,68,69,70,95,109],exc_path:78,except:[16,18,30,34,55,67,70,84],excess:40,exchang:54,exe:[21,109],execut:[8,9,13,17,18,19,20,21,25,26,31,33,35,40,43,51,52,55,61,71,95],executioncontext:[39,43,75,76],executor:[18,21,25,29,30,31,33,39,50,52,56,58,71,107,109],exist:[4,7,9,19,28,30,49,58,59,61,66,68,70,76,95],exit:[14,28,96],exp:83,expand:49,expand_a:110,expand_level:110,expandlevel:110,expect:39,expected_desc:43,expected_kernel_kei:39,experi:[44,67],expert:8,expir:9,explain:[9,18,30,32,34],explan:[17,18,21,39,64],explicit:[19,55,70,74],explicitli:[4,21,26],explod:24,explor:[49,62],expos:[6,15,20,43,44,68,70,95],express:[4,23,25,35,40,81,84,95],extend:[53,70],extens:[16,23,49],extent:46,extern:[8,42,45,46,60,67],extern_mklml:78,external_librari:8,extingrad_:42,extinval_:42,extoutgrad_:42,extoutval_:42,extra:[21,62,68,119],extraattr:105,extract:[30,54,67,95],extralayerattribut:[81,82],extrem:[18,30],f1205:83,f120da72:96,f7e3:95,fa0wx:96,fabric:[93,94],face:[8,62],fact:[18,30,51,56,58],factori:45,fail:[9,13,49,78,83,96,103],failur:[9,14],fake:33,fake_imag:59,faked_imag:33,fall:[29,57],falloc:27,fals:[5,6,7,30,36,38,41,48,56,57,59,65,71,74,75,81,84,86,89,91,96,105,114],false_block:[7,36,56],false_label:59,false_neg:25,false_posit:25,false_read:59,familiar:20,faq:115,far:[24,70],fashion:21,fast:[13,30,108],faster:[9,30,52],fastest:30,father:6,fault:[13,60],fbd1f2bb71f4:96,fc1:[35,74,105],fc1_bia:35,fc1_weight:35,fc2:[35,105],fc3:[35,105],fc4:105,fc8a365:95,fc8a:95,fc_grad:52,fc_layer:[58,66,81,83,105],fc_op:66,fc_out:7,fc_output:66,fc_without_b:7,fclayer:74,fcop:32,feasibl:53,featur:[6,21,29,35,51,52,55,67,72],feed:[4,21,34,48,62,84,109],feed_dict:33,feed_list:109,feed_minibatch:71,feeder:[21,109],fetch:[9,12,19,21,57,72,78,109],fetch_list:[21,58,71,109],fetch_op:57,few:[8,9,20,21,40,53,59,65,67],fewer:[20,58],fft:67,field:[7,35,37,44,57,58,61,65,66,81,95],fifth:34,figur:[4,8,21,23,33,42,48,55,58,67],file:[4,6,8,9,11,13,14,16,17,19,20,27,28,30,31,35,44,46,59,60,67,68,71,72,75,81,84,109,119],file_nam:83,filelist:67,filenam:[11,58,81,107],fileoffset:27,filesystem:[16,17,21,27,95],fill:[9,13,47,58,89,95],fill_zero_grad:60,fill_zeros_like_op:6,filter:[24,43],find:[7,9,16,20,29,35,39,43,49,64],find_var:5,findmemori:43,findop:7,findprimit:43,findprimitivedesc:43,findvar:[7,64],fine:[13,32],fingerprint:95,finish:[9,13,16,17,26,40,51,66,95,96],first:[4,6,7,9,13,16,17,18,21,26,28,30,33,34,35,43,48,49,52,56,57,58,60,65,66,67,68,69,70,75,76,89,95,119],first_seq:114,firstseen:96,fit:[29,38,40,44,49,60],five:56,fix:[21,40,45,58,67,72,89],flag:[41,42,55],flatten0:35,flatten:[35,56,58,76],flatten_result:81,flexibl:[4,14,21,30,34,38,48,49,53,59,68,70],flist:91,fliud:18,float16:20,float16_t:29,float32:[21,29,32,33,58,59,75,83,109],float_to_half_rn:29,floor:83,flow:[7,18,20,48,55,63,69],fluid:[6,19,21,23,26,39,47,52,55,58,68,69,107],fluid_cuda_create_tensor:31,fluid_cuda_mult:31,fluid_cuda_read:31,fly:6,fmt:[20,83],fname:83,fnt03:95,focu:[20,35],folder:[8,11,17,28,95],follow:[4,5,6,7,8,9,13,17,18,19,20,21,23,26,29,30,31,32,33,34,35,36,37,39,40,43,47,48,49,51,52,53,55,56,57,58,59,60,61,62,64,65,66,67,68,69,70,71,95,99,100,109,119],footprint:31,forbid:4,forc:[39,51,58],force_cpu:38,force_cudnn:38,force_load:45,forest:7,forev:20,forget:4,form:[19,20,25],formal:39,format:[5,13,19,21,29,30,47,49,67,70,72,74,86,89,95],former:[4,8,30,40,53],formula:[5,40],forth:33,forward:[5,6,7,12,14,24,30,33,41,42,43,44,50,54,56,59,60,61,62,65,74],forward_infer:43,forward_list:55,forward_op:5,forward_train:43,forwardactiv:74,found:[29,56,62,64],four:[20,25,30,34,43,47],foward:57,fp16:[29,60,71],fp32:[39,47,60,71],fp64:[47,71],fparam:83,fpga:[47,109],fpgadevicecontext:68,fpgaengin:42,fpgaplac:[47,68],frame:[26,60,67,70],framework:[4,6,7,20,24,25,29,30,35,47,51,52,53,55,56,60,62,64,66,68,75,107,109],free:[31,68,119],freememoryop:31,frequenc:67,frequent:[13,59,60,62,68],fresh:16,friend:64,friendli:33,from:[5,6,7,8,9,11,12,13,14,18,19,20,21,23,24,25,28,29,30,32,33,34,35,36,38,39,40,43,48,49,50,51,52,54,56,58,59,60,61,64,67,68,69,70,71,75,76,78,90,95,96,107,108,113,119],from_no_sequ:110,from_sequ:110,from_tar:84,fromfil:[59,83],fromstr:83,front:[35,40],fulfil:108,full:[9,16,20,48,51,53,119],full_matrix_project:114,fulli:[21,23,67,119],fullsiz:12,fullyconnect:[35,58],fullyconnectedlay:74,func:[13,18,31,61],functor:[32,35],fundament:[19,20,23,29,60],further:[19,66,119],futur:[16,21,29,40,48,60],fvs:66,fwd_desc:43,fwd_op:61,fwd_primit:43,fwd_primitive_desc:43,fwd_var:24,g_b0:33,g_b1:33,g_b2:33,g_block:33,g_command_config_arg:[41,42],g_h0:33,g_h0_bn:33,g_h0_relu:33,g_h1:33,g_h1_bn:33,g_h1_relu:33,g_h2:33,g_im:33,g_loss:33,g_optim:33,g_program:58,g_state:55,g_step:33,g_w0:33,g_w1:33,g_w2:33,gan:4,gangliao:8,gatedrecurrentlay:41,gather:[6,40,51,54,75],gaussian_normal_random:33,gcc:[0,29,31,45,60,116,118],gcc_3:3,gcreators_:66,gemm:41,gen_proto_pi:77,gen_rand_param:83,gender:97,gendrated_id:49,gener:[4,5,6,7,8,9,11,13,14,16,18,21,30,32,37,40,43,47,51,53,56,57,58,59,60,61,65,66,67,68,69,70,84,89,95,97,105,108],generated_id:49,generated_scor:49,generatedinput:[113,114],genr:97,get:[1,5,6,7,8,9,13,14,16,17,19,27,30,33,35,38,39,40,41,42,43,47,48,49,55,58,60,61,64,66,70,74,81,89,93,95,96,98,107],get_all_op_proto:66,get_block:58,get_config_arg:105,get_data:96,get_data_from_prefetch_queu:52,get_dim:5,get_float_el:5,get_grad:81,get_grad_op_desc:6,get_input_lay:74,get_numeric_gradi:5,get_numerical_gradi:5,get_output:5,get_plac:52,get_program:40,get_sample_from_lin:81,get_support:[3,78],get_symbol:35,get_tensor:5,get_vari:7,get_worker_addr:18,getactualkerneltyp:38,getattr:24,getbatchs:74,geteigendevic:76,getengin:43,getenv:[4,17,91,97],getexpectedkerneltyp:[38,39,43],gethostbynam:97,gethostnam:97,getidmap:97,getinfervartyp:37,getinput:74,getinputgrad:74,getinputvalu:74,getkerneltyp:29,getkerneltypeforvar:39,getlayeroutput:81,getlibrari:43,getmat:12,getoptconfig:12,getoutputgrad:74,getoutputvalu:74,getparam:12,getparameterconfig:12,getparameterptr:74,getparameterspars:12,getparametersremot:12,getplac:[43,68,75,76],getpodlist:97,getsiz:74,gettask:13,gettempl:95,gettensor:39,gettranspos:74,getw:74,getweight:74,getwgrad:74,gflag:87,gflags_complet:87,gflags_declar:87,git:[0,63,72,77,78,87,116,118],github:[0,8,33,47,63,72,77,78,87,107,109,116,118],give:[9,39,48,58,60,95],given:[6,14,16,20,23,24,30,32,33,49,59,62,70],glibc:[116,118],glibc_2:3,glibcxx_3:3,glide:8,global:[0,4,7,8,9,31,35,38,39,54,55,60,64,66,68,95,108],global_block:58,globalstat:108,globalstatinfo:108,glog:87,gnueabihf:118,go_librari:8,go_test:8,goal:[19,20,23,29,34,51,60,67],gob:13,godep:8,godoc:45,goe:[9,30,36,64,109],going:[6,32,53,119],golang:8,good:[20,33,53,58,59,62,119],googl:[4,55,60,83,87,107,116],googleapi:95,googlenet:42,goroutin:[18,20],got:[38,64],govern:[81,84],gpg2:95,gpg:95,gprof:107,gprotos_:66,gpu:[1,3,5,17,20,25,29,39,40,47,51,52,53,54,55,60,62,63,68,78,86,89,91,105,108,109,119],gpu_id:[81,103,105],gpu_per_train:21,gpu_plac:52,gpudevic:68,gpugpu_id:102,gpukernel:60,grab:9,grad:[5,6,14,24,42,52,58,65,81,103],grad_info_map:6,grad_n:24,grad_nam:24,grad_op:24,grad_op_class:60,grad_op_desc:24,grad_op_maker_:61,grad_op_typ:[60,61],grad_op_type_:61,grad_s_block:6,grad_share_block_num:[102,103],grad_to_var:[6,24],grad_var_nam:5,gradient:[9,13,20,22,24,34,37,50,51,52,53,54,58,60,65,90,91,92,97,103],gradient_clipping_threshold:81,gradient_flat:5,gradient_machin:[46,87],gradientmachin:[46,54,97],gradientmachine_:12,gradopdescmak:[37,61],gradopdescmakerbas:61,gradopmak:61,grain:32,gram:67,grant:95,graph:[6,7,8,9,18,20,21,22,23,25,30,33,48,51,53,56],great:[23,67,119],greater:[24,53,89],greaterthan:66,greedi:67,green:[18,33],grep:[1,98],groudtruth:114,group:[13,35,43,68,119],group_input1:114,group_input2:114,group_input:114,grpc:119,gru:[49,67],gru_decod:114,gru_decoder_with_attent:114,gru_out:49,gru_step:[49,114],grumemori:[82,114],gserver:[41,42,74],gsizex:108,gtx:40,guarante:[43,58],guard:12,guest:3,guid:[27,40,60,95,96],gzip:[13,96],h0_bn:33,h1_grad:52,h2_grad:52,h_prev:7,hadoop:4,half:[29,95],half_to_float:29,hand:[40,60,67,68],handi:8,handl:[4,6,17,18,21,35,40,43,47,54,59,64,68,70,109],handler:7,hannun:67,happen:[13,66],hard:[21,30,49,67,70,95],hardwar:[30,31,68],has:[4,5,6,7,8,9,13,14,16,19,20,21,23,24,25,29,30,33,35,39,40,44,47,49,51,55,56,60,65,66,68,89,95,108,109,119],has_kei:[6,24],has_var_recurs:6,hasdependentvar:57,hash:[47,51],hasn:30,hasnext:19,have:[4,5,6,7,8,9,13,14,16,17,19,20,21,23,24,26,29,30,31,32,33,34,38,39,40,43,44,47,48,49,51,52,53,54,55,56,58,59,60,61,64,65,67,68,71,95,119],haven:30,hdf:11,head:[75,98],header:[14,44,46,60,68,83],headip:98,height:[7,45,59,74,75,83,89],height_:65,held:9,hello:4,help:[7,28,30,35,43,49,59,60,70,72],helper:[21,43,61,70],henc:[21,53,58,61,62,64],here:[4,8,9,15,20,23,24,26,28,30,34,35,43,47,48,59,62,66,71,89,95,119],heterogen:[21,23,55],heurist:[23,49],hidden:[50,58,82,83,95],hidden_a:83,hidden_b:83,hidden_out:7,hierach:113,hierarch:[56,58,60],hierarchi:60,high:[29,51,67,68,119],higher:[32,48,70],highest:7,highli:[67,70],him:4,hint:38,histor:32,hl_get_sync_flag:74,hold:[4,6,9,13,15,19,20,29,33,35,37,39,40,64,66,68,76,95],holder_:[68,76],home:[1,11,28,95,96,97,98,107],honor:13,host:[8,17,55,95,96],host_c:[116,117,118],hostfil:98,hostnam:95,hostnetwork:97,hostpath:[96,97],hostport:95,hous:86,how:[4,7,9,13,18,19,20,21,26,28,30,32,35,38,39,43,48,49,54,55,62,66,95],howev:[5,6,16,20,21,26,30,39,40,47,53,54,58,59,61,62,65,66,67,68,95],howto:[91,93,97],hpp:[29,45],htod:108,http:[0,1,8,17,33,63,72,77,78,81,84,87,95,96,107,109,116,118,119],hub:63,huge:53,human:[55,67],hyper:33,hyperparamet:62,i1116:97,i1117:108,i386:117,iOS:117,iamfullaccess:95,iamusersshkei:95,icc:31,icml:67,id_rsa:98,idea:[8,20,30,31,53,59,62],ideal:[21,39],ident:[61,95],identifi:[36,47],idmap:97,ids:[49,81,89],ids_arrai:89,idx:[13,19,33,40,74],ies:28,if_els:69,if_else_op:6,ifdef:[47,55],ifels:[7,56],ifelseop:56,iii:67,iil:83,illustr:[9,14,20,21,32,48],im_siz:33,imag:[0,4,21,30,33,34,49,50,56,59,67,72,95,96,97,99,100,119],image_a:59,image_b:59,image_conv_lay:67,image_fil:59,image_lay:59,image_nam:4,image_path:59,image_reader_cr:59,imagenet:11,imagepullpolici:[95,97],images_reader_cr:59,imagin:34,imgsiz:108,imgsizei:108,imgsizex:108,immedi:[40,43,53,62,95],immutable_paramet:4,imper:18,imperfect:60,implement:[7,13,14,15,16,17,18,20,21,23,30,32,35,36,37,39,40,43,45,46,47,49,52,54,57,64,66,67,68,69,70],implemet:12,impli:[8,81,84],implicitli:18,imposs:[19,49,119],impractic:39,improv:[22,23,40,60,67,95],in_arg:89,inarg:12,inbound:95,inc_path:78,includ:[4,7,8,14,17,19,20,29,30,33,35,40,45,46,48,49,55,56,58,60,66,72,75,87,95,108,116,117,118],inclus:49,incom:[18,38],increas:[9,13,29,83],increment:[20,25,34,40],incupd:74,inde:20,independ:[5,6,14,22,52,64,68,119],index:[5,6,7,9,13,18,56,58,70,95],indic:[6,7,14,26,33,48,56,61,65,68,70,89,95],indice_map:70,indices_map:70,individu:[9,51,95],industri:[9,44,119],ineffici:[39,54],infer:[4,6,7,9,25,30,36,37,38,39,40,41,45,47,57,58,60,65,67,84,86],infer_shap:58,infer_var_type_:37,inferer:67,inferfac:37,inferior:16,infershap:[7,58,60,75,76],infershapecontext:[75,76],infervartypefn:37,info:[29,48,74,81,84,93,97,119],inform:[7,17,28,35,38,40,43,44,47,48,51,58,62,64,65,95],infrastructur:[30,95],ingrad_:42,ingredi:[20,67],inherit:[7,19,50,60,68],ininst:4,init:[7,22,33,42,48,49,52,74,84,86,91,95,97],init_attr:58,init_model_path:[102,103,105],initi:[6,8,13,18,21,22,23,25,34,48,51,53,58,62,66,70,86,103,109],initial_max:83,initial_mean:83,initial_min:83,initial_std:83,initialize_op_attr:58,initrd:119,inlin:[68,76,95],inner:[81,89],inner_pos_arrai:89,inner_seq_pos_arrai:89,input0:76,input1:76,input:[5,6,7,12,16,18,19,21,22,23,24,25,29,30,31,32,33,34,35,37,38,39,40,42,43,47,48,49,53,54,57,58,59,60,61,64,66,67,68,70,74,75,76,81,82,83,84,86,89,97,105,109,110,113,114],input_data:74,input_data_target:74,input_hassub_sequence_data:74,input_index:74,input_label:74,input_lay:74,input_nam:4,input_seg:70,input_sequence_data:74,input_sequence_label:74,input_sparse_float_value_data:74,input_sparse_non_value_data:74,input_t:74,input_to_check:5,input_typ:81,input_valu:5,input_var:[5,58],inputbuff:12,inputdef:74,inputgradi:61,inputlayers_:74,inputs_to_check:5,inputsizechang:43,insert:[6,24,31,51,57,60,61,72],insid:[6,9,21,23,24,25,38,43,54,55,59,60,61,71,95],inspir:55,instal:[0,1,3,17,42,63,72,77,78,86,87,96,101,107,116,117,118],install_android:116,install_step:86,instanc:[5,7,9,11,15,18,19,21,22,24,26,31,36,43,48,49,53,58,60,61],instance_ip:95,instanti:[9,26,109],instead:[5,6,8,12,17,18,20,21,29,30,34,35,67],instrins:29,instruct:[7,34],int16:71,int32:[47,56,70,71,103],int64:[21,27,39,47,65,71],int64_t:55,int8:47,integ:[13,17,18,20,29,45,49,84],integer_sequ:81,integer_valu:[81,84,89],integer_value_sequ:[49,67,89,114],integer_value_sub_sequ:89,integr:119,intel:[30,47,68],intellig:40,inteloptimizedpaddl:42,intens:67,inter:21,interact:[21,95],interchang:[34,60],interconnect:51,interest:[18,29,51],interfac:[7,13,17,19,28,35,51,54,60,61,67,68,95,119],intermedi:[21,28,31,33,40,50,67],intern:[29,67,95,107],internel:42,internet:[8,9,119],interpret:[26,30,31,71],intrins:[18,26,29],introduc:[7,9,19,33,41,44,62,64,66],intuit:[16,60],inval_:42,invalid:[59,64],invent:30,invoc:[8,32,60],invok:[6,19,21,24,39,54,58,60,61,66,95,108],involv:49,ios:117,ios_arch:117,ios_deployment_target:117,ios_development_root:117,ios_enable_bitcod:117,ios_platform:117,ios_sdk_root:117,ios_use_veclib_for_bla:117,ip_str:97,ips:[95,97],ipt:[58,66,83,114],ipx:119,ipython:4,is_async:91,is_cpu_plac:43,is_inf:90,is_mkldnn_librari:43,is_seq:114,is_stat:83,is_target:57,is_tensor:66,is_test:43,is_traget:57,isbinari:89,isinst:[24,81,84],ismkldnnkernel:43,ispodallrun:97,isspars:74,issu:[0,8,33,67,80],issue_numb:72,istag:63,item:[16,29,59,86,97,119],iter:[4,9,21,30,31,40,43,53,55,59,67,70],iter_multiple_input_and_param:58,its:[4,6,7,9,13,18,19,20,23,24,25,30,31,33,34,35,37,39,40,44,48,49,51,53,54,57,58,60,61,64,65,66,68,95,108],itself:[6,9,16,19,31,43,53,64],ivector:[89,90],ivs:66,java:[7,45,56,60],jeremi:108,job:[6,16,18,21,24,60,97,102,103,105],job_desc:21,job_dispatch_packag:93,job_nam:[17,95,97],job_namespac:[95,97],job_path:[95,97],job_path_output:97,job_workspac:93,jobdesc:21,jobnam:[21,97],jobpath:[95,97],jobport0:95,jobport1:95,jobport2:95,jobport3:95,jobselector:97,jobserv:17,join:9,jpg:19,json:[35,67,95,96],juditski:53,jupyt:17,just:[8,13,14,18,21,30,31,33,37,43,53,54,58,59,60,61,62,64,65,95],jx4xr:95,jypyt:4,k8s:[18,97,119],k8s_data:[95,97],k8s_job:4,k8s_token:4,k8s_train:[95,97],k8s_user:4,kafka:11,kcpu:55,kcuda:55,kdisabl:55,kebilinearinterpbw:108,kebilinearinterpfw:108,keep:[9,20,30,31,34,49,53,58,64,66,119],kei:[0,5,6,7,9,11,13,27,29,38,43,60,61,66,67,70,72,81,97,108],kenlm:67,kept:[40,58],kera:62,kernel:[5,20,29,31,38,39,42,53,55,62,65,67,68,75,76],kernel_hint:38,kernel_type_for_var:39,kerneltyp:[38,43],key1:103,key2:103,key_pair_nam:95,keyid:95,keymetadata:95,keypair:95,keyserv:95,keystat:95,keyusag:95,keyword:[58,69,97],kforcecpu:38,kill:[9,95],kind:[4,5,9,15,19,21,24,31,34,38,39,43,50,51,55,68,71,81,84,95,96,97],kind_:55,kinput:52,kmark:55,kms:95,knchw8c:47,knchw:47,knhwc:47,know:[4,13,18,19,40,44,95],knowledg:67,known:[6,7,20,30,32,48],koutput:52,kparallelblock:52,kparallelscop:52,kparamet:52,kplace:52,kpoprang:55,kpushrang:55,kqueue:20,kselectedrow:65,kstate:55,kube_cluster_tl:4,kube_ctrl_start_job:4,kube_get_workers_addr:18,kube_list_containers_in_job_and_return_current_containers_rank:4,kubeconfig:95,kubectl:[93,96,97,98],kuberent:[9,95],kubernet:[4,9,18,21,60,94,97,99,100,119],kubernetes_service_host:4,kusecudnn:38,kusemkldnn:38,kwarg:[25,35,58,66],l1_regularization_op:62,l2_regularization_op:62,l2regular:[81,91],l93:12,label:[21,25,30,33,34,35,39,50,52,56,59,67,81,84,88,96,109],label_fil:59,label_lay:59,label_path:59,labelselector:97,lag:103,lambda:[18,24],lan:101,languag:[18,20,30,34,40,55,60,64,67,69,81,84],larg:[21,23,24,40,44,53,67,72],larger:[40,69],larger_than:[7,36,56],last:[6,24,40,48,55,56,110],last_seq:[49,111],lastseen:96,latenc:[29,67,95],later:[8,60,62,67,68,76,95],latest:[1,7,8,9,16,63,72,77,78,96,97,116],latter:[53,70],launch:[43,95],launcher:4,law:[81,84],layer1:[81,110],layer2:[81,110],layer:[6,7,12,18,20,21,23,30,33,34,36,50,52,53,56,59,60,62,66,67,68,70,74,81,83,84,86,89,90,109,110,113,114],layer_0:74,layer_att:82,layer_attr:[81,82,105,114],layer_expand:110,layer_first_seq:110,layer_help:38,layer_last_seq:110,layer_nam:81,layer_num:105,layer_pool:110,layer_s:89,layer_typ:[41,42],layerbas:74,layerconfig:74,layergradutil:74,layerhelp:[38,58],layermap:74,layers_test:78,layout:[39,43],layout_:[38,47],layouttyp:38,lazi:[53,62],ld_library_path:87,lead:[19,40,47],leaki:33,learing_r:50,learn:[1,4,6,14,16,20,21,23,26,33,34,40,42,49,51,53,55,59,60,62,68,108],learning_r:[14,21,81,83,91,109],learning_rate_arg:83,learning_rate_decay_a:83,learning_rate_decay_b:83,learning_rate_schedul:83,leas:9,least:9,leav:[7,95],lectur:40,left:7,left_scor:81,legal:66,len:[14,18,27,30,58,74,86,97],length:[14,29,41,44,48,49,60,67,70,96],leran:40,less:[4,24,119],less_equ:69,less_than:[4,40],let02:96,let:[4,7,16,18,20,31,32,34,38,39,43,47,48,49,50,61,68,95],level:[29,32,35,44,48,49,55,68,70,71,89,113],lgtest:8,lgtest_main:8,lib64:[1,78,103],lib:[0,46,87,107,116,117,118],lib_path:78,libapi:8,libari:46,libc:3,libcuda:[1,78],libgcc_:3,libgflag:87,libglog:87,libgoogl:107,libiomp5:42,libmkldnn:42,libmklml_intel:42,libnvidia:[1,78],libopenbla:87,libpaddl:[45,46,60,72,107],libpaddle_capi:46,libpaddle_capi_engin:87,libpaddle_capi_lay:87,libpaddle_capi_shar:87,libpaddle_capi_whol:87,libpaddle_gserv:46,libpaddle_math:46,libprotobuf:[83,87],librari:[8,15,20,21,39,42,43,46,51,67,103],library_:47,library_type_:39,librarydevicecontext:47,librarytyp:39,libstdc:3,libz:87,licens:[42,51,81,84],life:9,lifecycl:[55,119],lifetim:64,lightweight:32,like:[6,7,8,9,12,17,18,20,26,30,31,32,33,34,35,37,39,43,47,51,52,53,58,59,60,61,62,64,65,67,69,70,71,95,109,119],limit:[30,40,44,49,60,62,81,83,84,108],linaro:118,line:[8,12,17,20,28,34,53,56,58,60,62,72,81,83,95,105],line_count:83,linear:[49,81,83,84,86],lineno:107,link1:29,link2:29,link:[8,27,28,64,95,113,119],linux:[0,3,20,27,95,116,118],linux_x86_64:[3,63,78],lipo:117,list:[4,6,7,8,13,17,18,26,28,30,33,47,50,52,54,55,58,61,64,70,81,95,105,107],listdir:91,listen:[9,18,21],listen_and_do:18,listenanddo:18,lite:87,littl:[14,38,44],live:109,live_in:40,live_out:40,load:[4,9,21,33,51,58,84,95,97],load_missing_parameter_strategi:[102,103,105],load_mnist:33,load_paramet:83,loadsave_parameters_in_pserv:[12,102,103],local:[0,5,7,9,15,16,20,34,40,48,52,56,58,60,97,102,103],local_scop:5,local_w1_grad:52,local_w2_grad:52,localhost:[1,77],localip:97,localpath:28,locat:[8,30,47,55,68,70],lock:[8,9,13,14],lod:[20,44,48,65,70,71],lod_desc:65,lod_expand:49,lod_level:[58,65,71],lod_rank_t:71,lod_tensor:[48,65,71],lod_tensor_arrai:71,lodtenosr:19,lodtensor:[19,20,37,44,60,71],lodtensordesc:[44,65],log:[3,13,21,28,33,74,79,83,91,93,95,96,97,98,103],log_barrier_abstract:[102,103],log_barrier_lowest_nod:[102,103],log_barrier_show_log:[102,103],log_clip:[102,103],log_error_clip:[102,103],log_period:[96,97,103,105],log_period_serv:[102,103],logger:81,logic:[16,21,23,24,33,37,50,51,54,64,70],logit:[33,39],longer:[9,21,40],look:[7,17,18,20,30,31,34,52,53,58,61,62,67,71,95,109],lookahead:67,lookup:[37,49,109],lookup_t:40,loop:[5,7,19,30,40,55,59,64],loop_var:70,loss:[6,21,33,35,50,52,53,62,67],loss_gard:52,lot:[21,47,49,53,58,62,68,119],low:[50,51,67,68,70],low_rnn:48,lower:[29,48,49],lower_level_rnn:48,lpaddle_capi_engin:87,lpaddle_capi_lay:87,lpaddle_capi_shar:46,lpaddle_capi_whol:46,lrelu:33,lstm:[96,114],lstm_last:111,lstmemori:[82,114],lstmemory_group:82,lstmemory_unit:82,lstmlayer:41,luckili:40,mac:[46,116],machin:[21,23,30,33,40,42,51,53,62,81,90,95,98,113,119],machine_transl:114,maco:[0,3],macro:[32,47,61],made:[9,14,30],mai:[5,7,21,25,29,31,38,39,40,43,51,55,59,60,64,67,71,81,84,95],main:[18,20,24,30,31,35,51,56,60,87,95,107],main_program:[6,25,52],mainli:[15,40,47,68],maintain:[7,13,53,58,60,95],majel:8,major:[21,29,39],make:[0,4,6,7,8,9,13,14,16,20,21,22,29,30,34,48,49,52,53,54,58,59,60,62,67,70,72,74,75,77,78,87,95,108,116,117,118,119],make_chan:20,make_channel:20,make_ddim:76,make_function_oper:32,make_vari:66,maker:[60,61],malloc:68,man:27,manag:[9,14,15,18,20,21,28,55,64,68,77],mandarin:67,mani:[6,8,13,18,20,30,33,38,39,40,49,54,55,58,60,61,64,65,66,69,70],manili:35,manipul:[30,58,61],manner:[53,62,67,68],mantain:40,manual:[21,50,53,61,83,119],manufactur:30,manylinux1:3,manylinux1_x86_64:[3,63,78],manylinux:63,map:[4,7,13,24,43,47,58,61,64,66,68,70,84,87,119],map_fn:70,mapreduc:4,mark:[6,23,33,34,48,49,55,64,119],marker:55,market:29,master:[4,16,60,63,118],mastermind:8,mat:[45,46,89],mat_cache_row:12,mat_norm:12,mat_normal_shar:12,mat_sparse_row:12,mat_sparse_row_auto_grow:12,mat_sparse_row_id:12,mat_sparse_row_prefetch:12,mat_sparse_row_prefetch_full_s:12,mat_value_shar:12,match:[8,29,69,81],matchbox:119,math:[42,45,60,74,75,108],mathemat:62,matmul:[7,35,48,70,75],matrix:[12,45,46,74,75,87,89,90],matrixptr:74,matrixtyp:46,mattyp:12,max:[5,22,24,40,58,83,105,108,110],max_diff:5,max_length:[49,114],max_relative_error:[5,75],maxim:24,maximum:[7,14,52],maxoutfunctor:68,mayb:[7,43],md5:10,mean:[6,8,21,22,24,35,39,49,52,57,59,64,67,81,95,103,109,119],meant:70,measur:25,mechan:[6,15,19,25,43,58,61,95],mem:[7,17,49],mem_per_pserv:21,mem_per_train:21,member:[4,24,34,35,47,54,58,64],memcpi:[54,108],memori:[6,7,12,13,17,29,31,39,42,43,44,47,49,53,55,60,76,96,108,109,114],memory_nam:82,memory_optim:40,memory_threshold_on_load_data:[102,103],memoryalloc:68,memorydesc:43,mention:[6,8,13,21,23,30,48,51,53,55],merg:[14,16,22,25,42,48,51,52,54,72,90],merge_model:90,merge_v2_model:90,merge_v2_modelss:90,messag:[7,18,20,26,30,31,34,44,55,56,57,58,60,61,65,71,72,78,96],metadata:[27,95,96,97],metal:119,metaphor:34,metaplotlib:4,method:[5,7,16,18,19,21,22,24,29,33,34,35,38,39,50,51,58,59,60,64,65,70,107],methodolog:53,metric:[25,55],mfs:97,microarchitectur:29,might:[7,8,18,20,30,40,56,67,95],min:[22,24,58,95,105,108],min_block:7,min_count:23,min_desc:7,min_pool_s:81,mini:[7,9,20,25,26,30,36,48,81],mini_batch:59,minibatch:[7,25,34,36,56],minim:[7,21,23,24,30,33,50,60,109],minimum:67,minsizerel:[116,117,118],minu:61,minus_grad:61,minusgradop:61,minusop:61,minusopgradmak:61,minusopprotoandcheckermak:61,minut:[9,16,95],mip:116,mirror:8,mislead:14,miss:33,mistak:30,mit:95,mix:[52,55,70,114],mkdir:[28,77,87,95,98],mkl:[0,39,43,60,68,78,87],mkl_packed_:41,mkldnn:[39,42,47],mkldnn_:42,mkldnnactiv:42,mkldnnbase:42,mkldnnlayer:42,mkldnnmatrix:42,mkldnnstream:42,mkldnntester:42,mklml:[42,78],mklml_lnx_2018:78,mklpack:41,mklpackedgatedrecurrentlay:41,mklpackedgemm:41,mklpackedlstmlay:41,mklpackedrecurrentlay:41,mlp:35,mnist:[11,21,33,34,56,59,60,90,107],mnist_random_image_batch_read:59,mnist_train:59,mnist_train_batch_read:59,mnist_v2:90,mnt:97,mobil:[29,30,40,60,77],mode:[29,41,51,52,72,97],model:[6,7,9,10,18,21,23,24,25,34,39,40,41,50,51,53,60,62,67,70,77,84,86,90,95,105],model_list:[103,105],model_path:105,modelparallel:21,modern:40,modif:67,modifi:[21,29,35,62,72,95],modul:[21,32,33,49,67,70,75,83,107],modular:49,momentum:[64,81,84],momentumop:107,mon:96,monitor:[20,55],month:8,more:[4,5,6,8,9,13,16,17,19,20,21,23,28,29,30,31,32,34,38,40,43,47,48,49,50,55,58,59,60,62,67,68,69,70,83,108,109,119],most:[4,6,8,16,20,21,31,34,35,47,49,53,55,59,62,67,68,69,109,119],mostli:[29,119],motiv:60,mount:[17,95],mountpath:[95,96,97],move:[9,13,19,28,30,53,95,119],movidiu:30,movie_id:97,mpi:[20,51,98],mpirun:98,mse:[30,34,50,56],much:[9,30,43,50,59,62,70],mul:[32,40,58,74,75],mul_grad:75,mul_op:75,mul_result:58,mulgradkernel:75,mulkernel:75,mulop:[32,75],mulopgrad:75,mulopmak:75,mult:[18,31],multi:[25,39,51,54,119],multigradientmachin:54,multipl:[4,5,13,14,16,18,20,21,23,25,30,31,32,38,39,51,52,55,60,67,71,84,95],multiple_input:58,multiple_param_attr:58,multipli:18,multithread:52,must:[6,14,19,24,40,43,44,47,55,57,58,59,60,66,71,74,75,76,81,91,95],mutabl:[68,76],mutable_data:[43,68,75,76],mutex:20,mutuable_data:68,mxnet:[7,18,20,30],my_cluster_nam:95,my_cost:83,my_external_dns_nam:95,my_lib:91,my_net:52,myerrorclip:24,mypaddl:[96,97],naiv:18,name:[4,5,6,7,9,11,12,14,17,18,19,21,25,29,32,35,38,42,43,44,46,47,49,55,56,58,60,63,65,66,70,71,74,83,84,86,96,97,99,100,105,108,109,114,119],name_:55,name_prefix:11,namespac:[7,36,45,58,74,75,96,97],nativ:29,natur:[13,16,23,49,70],ncall:107,nccl1:51,nccl2:51,ncclinit:51,nchw8:39,nchw8c:39,nchw:[42,47],ndarrai:[11,81],ndk:116,nearest:29,nearli:[5,19],necess:70,necessari:[6,7,14,16,24,25,40,44,49,54,58,66,70],necessarili:18,neck:51,need:[4,5,6,8,12,13,14,16,17,19,20,21,23,24,25,28,30,31,32,33,38,40,43,47,49,50,51,52,53,54,55,57,58,60,61,62,64,65,66,67,68,70,71,78,95,97,108,119],need_tran:83,neighberhood:51,neon:29,nervana:30,nessesari:67,nest:[6,7,55,56,71,89],net:[0,7,33,48,64,90],netop:[7,60],network:[4,5,6,7,9,12,21,23,25,33,35,39,40,41,42,48,50,53,55,58,59,62,64,66,67,68,71,82,84,86,89,90,97,105,111,119],network_config:105,networkadministr:95,neural:[4,6,7,9,21,35,39,40,41,42,48,53,62,64,68,71,86,111,113],neuralnetwork:54,never:[40,59,64,95,96,97],new_block_idx:58,new_op_desc:24,new_scop:39,new_stat:48,newblock:58,newbuff:43,newest:14,newli:[29,119],newop:7,newopdesc:58,newprogram:58,newscop:39,newvardesc:58,next:[6,9,15,19,20,24,49,51,70,95],nextlay:42,nfs4:95,nfs:[95,97],nfsdir:97,nfsver:95,nic:[97,102,103],nil:[13,20],nmt_without_attent:81,nnz:[74,89],no_grad_dict:6,no_grad_set:[5,6,75],no_gradi:6,no_sequ:84,node0:97,node1ip:98,node2ip:98,node3ip:98,node:[8,16,18,21,23,35,40,49,51,60,95,96,97,98,119],node_0:[95,97],node_1:[95,97],node_2:[95,97],node_id:91,nodeattr:35,nodeentri:35,nodefil:93,nodesep:35,nohup:91,nois:[9,33],noisi:33,non:[9,20,29,30,65,95],none:[4,5,6,7,20,24,25,33,35,36,48,49,50,56,58,66,70,109,114],noneedtran:43,nor:18,norm:[33,47],normal:[52,53,67,96,97],notat:40,note:[4,6,7,12,13,17,39,40,44,47,51,59,60,68,76,95],notebook:[1,17],noteworthi:30,noth:[38,58,64,72],notic:[24,30,51,61],notimplementederror:24,notin:39,notingradi:75,notion:70,notori:5,now:[6,8,9,19,20,23,33,44,47,53,60,61,62,64,95,113],nproc:0,nullptr:[43,55,61,64,74],num:[91,97,103],num_class:35,num_gradient_serv:[91,102,103],num_hidden:35,num_parameter_serv:4,num_pass:[84,96,97,102,103,105],num_pserv:21,num_row:65,num_samples_process:83,num_shard:11,num_step:70,num_train:21,number:[7,9,11,23,25,40,53,55,59,60,66,70,95],numdevices_:105,numeric_grad:5,numerical_grad:5,numlogicaldevices_:105,numpi:[0,11,29,33,58,59,75,81,83,84],numreal:12,numsampl:108,numtimeout:13,nv_:8,nv_librari:8,nv_test:8,nvcc:[8,29,31],nvidia:[1,29,47,51,68,78],nvlink:51,nvprof:55,obj:83,object:[4,12,19,21,24,25,33,35,40,45,50,55,58,60,62,64,108],obtain:[16,19,53,68,81,84],obvious:[8,47],occup:[40,97],occupi:[29,55],occur:40,occurr:7,oct:96,off:[0,46,72,77,87,101,116,117,118,119],offer:[7,60,66],offici:[8,95],offlin:[9,11,119],offset:[12,89],often:[12,35,40,47],ograd:74,old:[5,14,16,49,60],older:30,omega:62,omit:81,omp_num_thread:107,ompi_comm_world_rank:91,onc:[9,13,18,21,23,25,30,34,53,69,95],one:[4,5,6,7,9,12,13,14,16,17,18,19,20,21,24,25,26,29,30,31,32,33,35,37,38,39,43,44,47,48,49,50,51,53,54,56,57,58,59,60,61,64,65,67,68,69,70,89,95,109,119],onehotcrossentropyopkernel:75,ones:[32,33,60],onli:[4,5,6,8,12,13,14,15,16,17,18,19,21,23,24,25,26,28,29,30,33,34,39,40,43,48,49,50,51,54,55,58,60,65,66,67,68,69,70,71,89,95,113,119],onlin:[9,11,40,59],only_cpu:5,onnx:30,onto:[21,23,95],op1:[39,40],op1_2_op2:39,op1_to_op2:39,op2:[39,40],op3:40,op_:75,op_check:75,op_class:[60,66],op_desc:[24,37,57],op_info:109,op_kei:43,op_maker_class:[60,66],op_proto:66,op_registri:109,op_siz:24,op_test:75,op_typ:[60,75],op_unique_kei:43,opattrcheck:75,opcreat:66,opdesc:[7,24,34,56,57,58,60,61,66,71],opdescbind:[37,61],opdescbuild:7,opeartor:52,open:[4,11,30,33,42,59,81,83,84,95],openbla:[0,1,87],openmpi:[94,98],opensourc:51,oper:[5,7,18,20,21,22,23,25,26,29,30,31,33,34,35,37,38,39,48,49,50,51,52,55,57,62,64,67,68,71,75,76,95,109],operand:29,operartor:76,operat:52,operator_grad:5,operator_list:55,operatorbas:[7,32,60,61,66,75],operatorwithkernel:[39,75],opinfo:[37,60,61],opinfomak:37,opinfomap:61,opkernel:[75,76],opkernelkei:60,opkerneltyp:[39,47],opmak:66,opproto:75,opprotoandcheckermak:[61,75],opprotomak:[66,75],opregist:66,opregistri:66,ops:[5,6,7,8,18,19,31,34,35,52,53,56,57,58,60,68,75,119],ops_:7,ops_test:8,opt:[0,4,50,57,66,97],opt_op_list:50,optest:75,optim:[5,6,21,22,23,31,33,51,53,54,56,60,62,65,67,81,83,84,91,109],optimis:50,optimize_op_attr:58,optimzi:81,option:[4,8,21,33,38,44,56,57,58,60,65,66,67,71,116,119],optmization_op_list:50,opts_np:57,optyp:[37,66],opwithkernel:65,order:[6,34,44,55,59,62,70,95,97,107,119],oregon:95,org:[11,27,33,81,84],orient:66,origin:[5,29,33,64,70,72],other:[7,9,14,18,28,29,30,31,37,39,40,43,47,48,53,57,62,64,66,67,68,71,95,109,119],otherwis:[4,6,9,14,16,33,37,43,59,67],our:[4,6,8,19,20,21,23,33,37,40,47,51,53,64,70,95],out:[4,7,8,13,16,19,21,24,30,35,39,40,43,48,49,58,75,76,81,95,107,113,114],out_dir:[95,97],out_mem:114,outer_mem:111,outgrad_:42,output:[4,5,6,7,11,16,18,19,23,24,28,31,32,33,34,35,36,37,39,40,43,44,48,49,52,53,56,57,58,59,60,61,64,65,66,68,70,75,76,81,84,90,93,96,97,105,114],output_:42,output_all_step:48,output_arg_nam:24,output_fil:90,output_lay:[81,84,86],output_mem:114,output_nam:5,output_num:48,output_path:11,output_seg:70,outputbuff:12,outputgradi:61,outsid:[21,64],outter:89,outter_pos_arrai:89,outter_seq_pos_arrai:89,outupt:70,outv:74,outval_:42,over:[4,30,40,51,52,53,70],overal:[33,53,55,119],overfit:62,overload:[29,38],overrid:[7,9,28,43,68,75,76],overview:[13,14,15,68],overwrit:28,own:[6,14,16,24,26,35,37,50,51,53,62,66,95],pack:[70,83],packag:[13,17,18,32,42,63,78,95,107],pad:[43,67],paddl:[0,1,3,4,7,8,9,11,17,19,21,28,31,32,33,36,41,42,43,44,45,46,48,49,54,56,60,62,63,66,67,68,70,72,74,75,77,81,83,84,86,87,89,90,91,93,95,96,97,98,101,105,107,108,109,114,116,119],paddle_arguments_get_sequence_start_po:89,paddle_arguments_set_id:89,paddle_arguments_set_sequence_start_po:89,paddle_arguments_set_valu:89,paddle_begin_init_param:14,paddle_capi:87,paddle_dir:75,paddle_doc:77,paddle_docs_cn:77,paddle_element_typ:14,paddle_element_type_float32:14,paddle_element_type_float64:14,paddle_element_type_int32:14,paddle_element_type_int64:14,paddle_element_type_uint32:14,paddle_element_type_uint64:14,paddle_enforc:[7,19,43],paddle_enforce_eq:[75,76],paddle_error:[45,46],paddle_exampl:17,paddle_finish_init_param:14,paddle_get_param:14,paddle_gradi:14,paddle_gradient_machine_create_shared_param:90,paddle_gradient_machine_forward:90,paddle_gradient_machine_load_parameter_from_disk:90,paddle_init:90,paddle_init_num_gradient_serv:91,paddle_init_param:14,paddle_init_port:91,paddle_init_ports_num:91,paddle_init_ports_num_for_spars:91,paddle_init_pserv:91,paddle_init_trainer_count:91,paddle_init_trainer_id:91,paddle_init_use_gpu:91,paddle_ivector:89,paddle_ivector_cr:89,paddle_job:17,paddle_manylinux_devel:0,paddle_matrix:[45,46,89,90],paddle_matrix_cr:[46,89],paddle_matrix_create_spars:89,paddle_matrix_get_row:89,paddle_matrix_get_shap:45,paddle_matrix_shap:45,paddle_matrix_sparse_copy_from:89,paddle_n:97,paddle_new_etcd_pserver_cli:14,paddle_new_pserver_cli:14,paddle_on_cloud:17,paddle_output:96,paddle_paramet:14,paddle_port:97,paddle_ports_num:97,paddle_ports_num_spars:97,paddle_process_by_paddl:97,paddle_pserver2:93,paddle_pserver_cli:14,paddle_pserver_client_releas:14,paddle_r:89,paddle_root:87,paddle_save_model:14,paddle_send_grad:14,paddle_server_num:97,paddle_train:[46,63,93,97],paddle_with_cuda:55,paddle_with_mkldnn:47,paddlepaddl:[0,1,3,8,9,11,14,15,16,17,18,21,27,28,32,33,34,36,38,44,48,49,50,54,55,58,59,60,64,70,71,72,81,84,86,87,89,90,93,96,97,99,100,101,107,108,114,116,118,119],paddlepaddle_gpu:3,paddlepaddlebook:1,paddlepaddlehub:[1,116],page:95,pair:[6,7,21,34,50,55,60],pakcag:8,panic:20,paper:[33,67],para:12,paradigm:[18,26,60],paragraph:48,paragraph_data:48,paragraph_out:48,parallel:[18,20,21,23,39,51,52,55,60,95,96,97,105,108],parallel_do_grad:52,parallel_do_op:52,parallel_for:18,parallel_nn:[102,103],paralleldo:[22,52],parallelfor:18,paralleliz:67,param:[5,7,14,52,54,58,68,76,81,83],param_attr:[12,58,81,83,114],param_config_proto:14,param_fil:[83,90],paramattr:[81,83,114],paramet:[5,6,7,8,10,12,16,18,21,22,24,26,28,30,31,33,34,35,37,44,48,50,51,56,59,64,66,67,70,81,83,84,86,89,92,93,97,103,109],parameter_block_s:[102,103],parameter_block_size_for_spars:[102,103],parameter_list:[6,50],parameter_nam:4,parameter_serv:4,parameter_valu:12,parameterattribut:12,parameterclient2:97,parameterclient_:12,parametermap:74,parametermutex_:12,parameters_:74,parameters_and_grad:50,parameterserver2:12,parameterset:4,parameterupdat:54,parameterupdater_:12,params_grad:50,params_pass_4:90,params_pass_90:84,params_pass_:84,paramt:95,paraspars:74,parent:[7,18,56,58,60],parent_:[7,64],parent_block:52,parent_idx:58,parenthes:60,pars:[0,8,21,35,95],parse_known_arg:97,parsefromstr:83,parser:97,part:[6,7,16,21,30,43,44,56,58,67,68,119],particular:[34,39,44,60,67],partit:[9,11,21,23,60,95],paserv:97,pass:[6,7,9,20,24,25,30,33,40,44,50,52,53,54,57,58,59,60,62,64,67,69,70,72,81,84,95,96,97,103,105,108],pass_id:[21,81,84],pass_idx:59,pass_manu:83,passtyp:74,past:[4,95],patch:27,path:[9,13,14,17,40,49,59,67,87,95,96,97,103,116,117,118],path_to_paddlepaddle_working_directori:77,pattern:[9,45,53,62,95],paus:[9,16],pcie:51,pd_api:89,peer:[51,79],pem:[4,11,95],pend:[9,13],pep425tag:[3,78],per:[9,14,51,53,59,62],percal:107,perf_test:107,perfectli:67,perform:[5,14,20,21,25,29,30,33,39,40,51,54,55,59,60,62,67,68,102,107,108],perftool:[55,107],period:[9,16,103],permiss:[81,84,95],persist:[26,65,67,71,95],persistentvolum:95,persistentvolumeclaim:[95,97],person:[4,38],perspect:60,perturb:5,pex:119,pfs:[11,28],pfsclient:11,pfspath:28,pgp:95,phase:[43,49,51,53,59,61,67,119],philosophi:[53,62],photo:33,physic:119,pick:95,pickl:[91,98],pictur:51,piec:[18,55],pillow:17,pip:[0,3,63,72,77,78,86,107],pipelin:[25,67],pivot:43,pixel:21,place:[6,7,9,16,21,23,26,38,39,43,51,52,60,76,109],place_:[38,39,47,68],place_list:71,placehold:[33,68,76],placement:23,plain:[17,44,46,47],plan:[9,18,43,60,67],platform:[3,7,31,39,43,47,55,68,75,76,95,109,116,117],pleas:[4,9,13,14,15,18,20,31,35,47,48,58,59,60,67,68,71,77,78,95,97],plot:4,plug:[51,53],pnpairvalid:102,pod:[11,17,18,71,95,96,97],pod_nam:95,podip:97,podlist:97,podtyp:71,point:[7,9,17,20,29,40,43,51,68,76,89,108,119],pointer:[7,14,35,40,47,58,60,64,68,76,89],poli:83,polici:95,poll:20,pollut:16,polyak:53,ponit:35,pool3:74,pool:[22,40,67],pooling_lay:81,pooling_typ:[81,110],pop:[7,26],popul:14,popular:[8,33,35,55],port:[8,18,91,95,96,97,102,103],port_num:102,portabl:35,portal:77,ports_num:[91,97,103],ports_num_for_spars:[12,91,97,102,103,105],pose:9,posit:89,possibl:[4,7,13,20,23,40,58,62,71],post:[0,17,27],postpon:62,potenti:[29,108],pow:83,power:[29,40,51,67,119],ppo_workspac:77,pprof:107,pre:[4,14,38,40,95],pre_activ:58,pre_bia:58,pre_stat:[48,70],preambl:58,precis:[25,29,53],precompil:26,pred:[35,40],predecessor:40,predict:[21,52,62,81,86,90],predict_fil:[102,103],predict_output_dir:[102,103],prefer:[30,38],prefetch:[12,52,74],prefix:[9,11,49,67,95],pregel:20,pregrad:74,prepand:58,prepar:[5,17,54,67,91,98,99],prepend:58,prepend_oper:58,preprocess:[67,70],present:[4,6,7,55,70,72],preserv:28,prev_batch_st:[102,103],prevent:[4,9,13,16,24,62],preview:60,previou:[6,9,23,28,48,49,95],previous_memori:7,price:[60,86],prim:43,primari:[30,34],primarili:[53,62],primit:[29,42,43,51,52,70],primitive_desc:43,primitivedesc:43,principl:[4,8,47],print:[3,4,20,21,30,35,58,69,78,84,86,98],print_graphviz:35,printallstatu:108,println:20,printstatu:108,prior:52,prioriti:60,privat:[7,46,55,58,64,65,66,68,70,72,76],privileg:95,pro:51,prob:86,probabl:[49,67],problem:[4,5,8,16,19,30,33,34,53,60,62],proc:1,proce:[9,59,95],procedur:[7,44],process:[4,6,7,11,12,13,16,18,19,20,21,25,26,30,31,35,39,40,42,44,51,52,62,66,81,83,95,97],processor:[29,108],prod:72,produc:[9,30,35,59],product:[17,30,84,95],productgraph:96,prof:107,profil:[28,55,67,107,108],profilerst:55,profl:107,proflier:[55,108],prog:97,program:[4,6,11,14,16,21,23,26,34,36,40,50,51,52,55,59,60,64,69,71,97,108],programdesc:[18,21,26,30,40,44,52,57,58,61,71],programm:[21,30,58],progress:[9,13],project:[17,46,67],promis:49,prompt:[28,30],prone:4,pronunc:67,prop_kind:43,propag:[6,30,53],proper:38,properli:38,properti:[35,62],propos:[7,22,23,49,50,51,53,70],proprietari:42,protect:[19,29,66,74,75],proto:[20,38,44,47,56,60,66,71,75],proto_:66,protobuf:[7,17,18,21,26,30,31,34,35,40,44,56,58,60,61,66,83,87,90],protocol:[109,119],protomak:75,provi:91,provid:[4,7,14,17,18,25,26,29,30,33,35,37,38,47,51,53,55,58,62,66,67,68,69,70,81,86,95,102,119],provis:[95,119],prune:7,ps_desir:9,pserver:[12,14,15,17,60,91,93,95,97,102,103],pserver_addr:14,pserver_cpu:17,pserver_id:10,pserver_mem:17,pserver_num_thread:[12,102,103],pseudo:[4,6,17,61,70],pseudocod:70,psize:74,ptr:[46,68],pub:98,pull:[1,8,60,63,116],purpos:[9,21,23,38,108],push:[7,26,30,55,63,97],push_back:74,put:[8,9,12,23,40,43,58,68],pvc:95,pwd:[0,1,72,77,116],pxe:119,py_paddl:78,pybind:[7,20,29],pydataprovid:81,pydataprovider2:97,python2:107,python:[0,3,4,7,15,19,20,25,26,30,32,33,34,35,38,45,49,52,54,55,60,63,68,70,72,74,75,77,78,81,86,90,91,98,107,109,114],pythonpath:78,pytorch:[30,55],qualcomm:29,queri:95,question:[4,18,23,66,95],queue:[20,23],quick:35,quick_start:[17,95,96,97,99],quick_start_data:96,quickli:[49,58,60],quickstart:96,quit:49,r14b:116,rais:[24,35,91],rajathkmp:33,ran:[23,108],rand:[33,83,89,103,105,108],rand_max:89,random:[11,20,33,47,54,58,59,75,83],random_imag:11,randomli:[16,89],rang:[11,18,21,29,33,40,55,59,66,97],rank0:51,rank1:51,rank:[4,70,95],rankdir:35,rapid:61,raspberrypi:118,raspbian:118,rasspberri:118,rate:[14,67,81,97],rather:[6,17,33,70,95],ratio:103,raw:44,rdma_tcp:[102,103],reach:[9,40,51],read:[4,6,9,11,18,19,20,21,23,30,31,59,60,67,70,83,95,119],read_from_arrai:40,read_from_realistic_imag:4,read_from_rng:4,read_lock:10,read_minibatch:30,read_mnist_imag:4,read_next_from_fil:81,read_paramet:83,read_ranking_model_data:4,readabl:[55,60],reader:[11,21,29,33,34,56,67,71,84,91,107],reader_cr:11,reader_creator_bool:59,reader_creator_random_imag:59,reader_creator_random_image_and_label:59,readi:[9,20,95,96,119],readlockguard:12,readm:[46,72],readnext:19,readwritebuffer_:12,readwritemani:95,real:[12,33,59],realist:4,realiti:67,realiz:[7,48],realli:[30,62],reason:[4,5,9,20,30,96],receiv:[9,17,20,21,23,48],recent:[40,53],recognit:67,recommend:[4,97],record:[13,43,55,66,95],recordev:55,recordio:[4,11,13,19],recov:[9,70],recover:60,recoveri:13,recurr:[41,48,64,67,111,112],recurrent_group:[67,81,82,111,113,114],recurrent_op:70,recurrentgradientmachin:[46,49,70],recurrentlay:41,recurs:[6,7,8,28,40,60],recv:[18,21,23,51,95],recvparametertyp:12,red:33,reduc:[23,29,51,60,107],reduce_by_kei:60,reduce_mean:33,refactor:[21,23,34,49,53,54,58,62,70],refer:[7,9,13,14,15,18,29,35,43,47,48,51,56,58,60,62,64,68,70,71],referenc:13,refine_unknown_arg:97,reflect:13,reg:66,regard:[19,119],region:64,regist:[20,39,40,47,61,68],register_gpu_profil:108,register_lay:74,register_op:[32,60,61,66,75],register_op_cpu_kernel:[68,75],register_op_cuda_kernel:[68,75],register_op_without_gradi:[60,75],register_oper:[37,61],register_tim:12,register_timer_info:108,registerop:66,registr:109,registri:[17,37,68,96,119],regular:[6,81,91,95],reinit:19,reiniti:[19,43],rel:[5,16,62],relat:[9,16,17,29,39,47,52,55,64,119],relationship:[61,68],releas:[63,67,78,87,95,116,117,118],reli:[5,18,49,50,53,62],reliabl:[9,62],relu1:35,relu2:35,relu:[33,35,40],relwithdebinfo:107,remain:70,remot:[8,12,21,60,72,95,103,105],remoteparameterupdat:[12,15],remov:[6,21,28,30,49,72],removing_docker_contain:0,renam:[6,28,29],reorder:43,reorder_primit:43,repeat:[7,34,56,57,65,66,71],repeatedli:[34,40],replac:[8,13,37,53,61,67],replic:21,replicaset:17,repo:[8,118],report:[13,29,30,55],reportdataset:13,repositori:[77,116],repres:[6,7,13,18,21,23,24,30,35,44,47,49,52,53,58,60,62,65,68,70,71,95],represent:[14,21,31,33,34,40,47,49,65],request:[8,9,12,16,18,60,63,95,96,119],requir:[4,6,9,14,16,17,19,21,23,24,28,29,35,40,42,48,52,53,55,56,57,60,62,65,66,67,71,77,81,84,95,119],requisit:40,research:[21,30],reserv:[28,81,84],reserveoutput:74,reset:[9,25,79],reset_program:25,resetingrad:42,resetinvalu:42,resetoutgrad:42,resetoutvalu:42,resetxxx:42,reshap:[5,59,83],residu:20,resiz:[12,68,75,76],resolv:[8,72,96],resourc:[21,26,51,55,68,95],respect:[5,19,24,29,33,48],respons:[12,20,21,25,33,51,53,54,62,95,96],rest:[7,17,27,31,39,119],restart:[9,14,95,96,119],restartpolici:[95,96,97],restor:[5,53],restrict:[62,64,107],result:[5,6,13,20,25,33,34,35,40,44,49,50,51,54,84,95,108,109],resum:16,retran:95,retriev:[7,49,64],reuqest:63,reus:[7,16,49,59,60],rev:0,revamp:21,reveal:4,revers:[6,113,114],review:[18,72,96],reviews_electronics_5:96,rewrit:[8,20],rid:[19,30],right:[5,6,7,8,17,25,40,60,62,81,84],right_scor:81,ring:51,risk:6,rkt:[0,17],rmsprop:[53,81],rmspropoptim:53,rnn:[7,30,33,49,58,60,64,67,102,113,114],rnn_bias_attr:114,rnn_layer_attr:114,rnn_out:114,rnn_output:70,rnn_use_batch:[41,102,103],rnnalgorithm:49,rnnstep:70,roadmap:[67,70],rocmplac:47,role:[4,13,14,21,51,95],rollback:58,root:[6,51,95,96,97],roughli:67,round:[29,51],routin:[29,42,51],row:[12,20,89],row_offset:89,rowoffset:89,rows_:65,rpc:13,rpcserver:13,rpi:118,rpi_arm_neon:118,rpi_toolchain:118,rsize:95,rstrip:97,rtk:119,rule:[6,21,24,30,34,95],run:[0,1,4,5,6,7,8,9,17,18,19,20,21,22,23,25,29,30,31,32,33,34,35,39,40,43,47,48,50,51,52,53,55,56,57,58,60,63,64,65,67,68,69,72,76,77,78,93,95,96,97,99,100,101,107,108,116,119],run_test:0,runinitfunct:[97,108],runnabl:23,running_on_cloud:17,runserv:77,runtim:[7,18,20,21,37,48,60,71,78],runtime_table_:7,s_block:6,safe:17,sai:[19,31,34,36,40,59],said:30,same:[4,5,13,14,16,18,19,20,21,32,33,35,38,39,40,48,49,51,58,60,61,64,67,70,76,95],sampl:[25,33,58,66,89],sampler:33,satifi:40,satisfi:[8,43,65,95],save:[9,11,13,14,17,18,21,34,35,40,44,53,65,71,95,96],save_dir:[96,97,103,105],save_only_on:[102,103],save_parameter_to_tar:84,savetxt:83,saving_period:[97,102,103],saving_period_by_batch:[102,103,105],scalabl:60,scalar:[6,7,36,69,70],scale:[21,23,53,61,66,67,75],scaleop:75,scaleopmak:[60,75],scan:[6,13,40,60],scatter:[6,51],scenario:49,schdule:95,schedul:[13,17,23,95],scheme:[12,62],scienc:40,scope:[5,18,22,26,31,39,52,109],score:[49,81],score_diff:81,scorer:67,scp:98,script:[0,51,77,93,95,98,116],sdk:117,search:[9,64,114],second:[4,18,28,30,33,35,48,49,56,57,59,64,66,75],secret:95,section:[6,23,30,58,95],see:[4,6,9,18,20,23,29,30,58,67,81,83,84,95],seed:[83,103,108],seem:[8,20,29,30,67],seen:62,segment:[48,70],sel:20,select:[49,95],selected_generation_scor:49,selected_id:49,selected_row:[65,71],selected_rows_desc:65,selected_scor:49,selectedrow:[37,71],selector:96,self:[5,24,25,33,35,40,41,42,44,50,58,70,74,75],self_addr:18,semant:[4,49,63],semaphor:20,semat:4,send:[9,14,18,21,23,38,51,60,66,95],send_back_parameter_typ:12,sendbackparameterspars:12,sendbackparametertyp:12,sendparameterrequest:12,sendparameterrespons:12,sens:[53,62],sent:[4,14,18,21,60,66,71,96],sentanc:81,sentenc:[30,48,49,70,114],sentence_input:70,separ:[14,21,32,53,61,62],seper:[52,70],seq_len:70,seq_po:89,seq_pool:110,seq_pos_arrai:89,sequenc:[6,7,18,26,30,34,41,50,56,67,70,81,84,89,111,113],sequence_layer_group:111,sequence_nest_layer_group:111,sequence_recurr:83,sequence_start_posit:89,sequencegen:111,sequencetyp:84,sequenti:[7,18,20],seri:[19,111],serial:[7,13,44,52,54,60,71],serializ:[60,71],serv:[21,29,60,70,95],server:[0,4,8,12,15,16,21,31,51,60,79,91,92,93,97,103,119],serverless:9,servic:119,sess:[33,35,50],session:[35,50,57],set:[0,4,6,9,17,19,33,37,40,43,47,48,49,55,57,58,60,61,64,67,68,70,75,76,77,81,83,84,89,95,96,108],set_active_typ:74,set_attr:24,set_drop_r:74,set_float_el:5,set_input:24,set_output:24,set_shap:19,set_siz:74,set_typ:[24,74],setdatatyp:65,setdefault:75,setp:95,setq:0,settotalbyteslimit:83,setup:[21,53,63,74,75,119],seven:67,sever:[5,12,21,23,33,48,49,51,54,55,58,65,68,70,95],sexstant:119,sgd:[4,9,17,23,52,53,54,65,84,92,102,109],sgd_optim:109,shall:[6,8],shape:[5,6,7,19,21,33,36,47,48,56,58,60,65,67,68,84,109],shapes_:19,shard:[9,10,11,12,13,14,16,21,23,92,95],share:[8,19,33,46,54,58,60,62,67,68,70],shared_librari:8,shared_ptr:[43,45,46,64,68,76],shell:95,shoul:5,should:[4,5,6,7,14,17,20,21,24,25,29,31,32,33,37,38,39,43,47,48,49,50,53,54,55,56,59,60,61,62,65,66,67,69,70,71,75,77,95,113],should_be_fals:4,should_be_tru:4,show:[0,6,7,9,19,20,28,30,36,40,44,48,51,53,56,69,70,95],show_check_sparse_distribution_log:[102,103],show_layer_stat:[102,103],show_parameter_stats_period:[96,102,103,105],shown:[4,21,25,51,52,55,67,95],shrunk:24,shuf:81,shuffl:[19,21,81],shuffleread:19,sid:95,side:[21,25,40,54],sig:95,sigint:93,sigmod:66,sigmod_op:66,sigmod_output:66,sigmoid:[7,66,70],sign:[27,44,95],signatur:95,signific:67,similar:[7,18,20,21,23,26,30,39,49,53,55,59,60,62,67,68,70,95,119],similarli:[30,40],simpl:[18,23,29,31,34,35,40,48,53,56,62,64,66,67,70,97],simple_attent:114,simple_gru:114,simple_lstm:82,simple_rnn:114,simpler:54,simplest:95,simpli:[4,14,21],simplifi:[4,49,58,66,67],simul:[30,117],simultan:95,sinc:[9,13,15,16,20,21,22,23,30,37,40,43,47,53,58,59,61,62,70,95,119],singl:[6,9,19,21,23,25,29,38,51,52,60,64,67],singleton:[18,22],sit:21,site:[8,95,107],situat:[6,39,57],size:[9,11,12,14,20,21,29,33,40,44,49,52,53,58,59,65,66,67,68,70,74,75,76,81,83,84,86,89,109,114],size_in_byt:43,size_t:[12,19,68,70,74],sizeof:[7,89],skip:[6,59,72,83,95],sleep:97,slice:18,slide:9,slight:30,slightli:33,small:[5,18,31,33,42,49],small_messag:[102,103],smaller:[5,9,29,49],smart:64,snap:96,snapdragon:29,snapshot:[10,16,95],snippet:[20,32,50,95],sock:17,sock_recv_buf_s:[102,103],sock_send_buf_s:[102,103],socket:97,softmax:[4,7,21,23,30,35,36,49,52,56,74,81,114],softmax_grad:52,softmax_param:83,softmaxoutput:35,softwar:[29,55,81,84,119],solid:33,solut:[51,119],solv:[4,6,19,40,60],some:[4,6,7,8,12,13,14,16,17,19,20,21,23,24,29,31,32,33,34,38,39,40,43,47,48,49,50,56,57,58,59,60,61,64,68,70,95,119],some_c_api_funct:46,some_inst:46,some_op:[37,48,70],some_python_class:45,somecppclass:45,somegotyp:45,someth:[6,12,58],sometim:[55,59],somewhat:14,somewher:64,soon:9,sort:[70,95,97],sort_by_length:70,sortagrad:67,sourc:[5,8,28,30,33,42,44,46,49,59,60,95],source_dict_dim:[49,114],source_dict_s:49,source_language_word:[49,114],space:[23,29,58,62,67],span:55,spars:[12,20,74,81,89,91,95,97,103,105],sparse_binary_vector:[81,84,89],sparse_binary_vector_sequ:89,sparse_binary_vector_sub_sequ:89,sparse_float_vector:84,sparse_remot:12,sparse_upd:[12,81],sparse_vector:[81,89],sparse_vector_sequ:89,sparse_vector_sub_sequ:89,sparseparam:74,sparseprefetchrowcpumatrix:74,spec:[95,96,97],special:[6,14,21,29,31,37,47,49,50],specialvartypeinfer:37,specif:[6,8,9,19,21,24,28,31,49,60,64,68,81,84],specifi:[4,5,12,13,14,17,18,20,21,22,24,25,26,28,33,44,55,58,64,66,70,77,95],spectrogram:67,speech:67,speed:[29,44,51,53,119],speedup:55,sphinx:[45,77],split:[16,18,19,22,30,36,49,60,70,91,95],split_count:[91,95,97],spread:6,squar:35,square_error_cost:[84,109],squash:72,srand:[89,103],src:[8,43,78,91,93,97],src_backward:114,src_dict:83,src_dict_path:83,src_embed:[49,114],src_forward:114,src_primitive_desc:43,src_word_id:[49,114],src_word_vec:49,ssh:[95,98],ssh_server:93,sstabl:4,stabil:[5,40],stabl:[63,95],stack:[26,60,70,95],stage:[8,15,22,33,40,43,67,71,72],stale:9,stamp:78,standalon:116,standard:[20,30,60,62,67],stanford:[5,96],star:8,start:[6,8,9,12,13,14,16,17,20,21,22,49,51,54,55,72,78,89,96,97,103],start_mpi_train:98,start_op_idx:6,start_paddl:97,start_pass:[102,103],start_program:52,start_pserv:[102,103],startpaddl:97,startup:[9,17,30,95],stat:[103,108],state:[7,9,25,26,48,49,55,64,67,70,82,96,113],statem:40,statement:[20,30,34,40,95],statfulset:97,static_cast:[43,76],staticinput:[113,114],statist:[25,55],statset:108,statu:[17,49,72,95,96,97,108],status:96,std:[8,12,19,35,37,38,43,45,46,55,57,60,61,64,66,68,74,75,76,103],stdbuf:91,stderr:93,stdout:93,step:[5,7,9,14,20,21,23,25,30,33,34,41,49,52,53,54,58,60,66,67,70,95,111,113,114,119],step_gradi:6,step_id:70,step_input:70,step_net:7,step_output:70,step_scop:[60,71],stepnet:[7,48,60,64],still:[6,13,16,21,30,40,61],stirng:58,stmt1482205552000:95,stmt1482205746000:95,stochast:[9,13,16,53],stop:58,stop_gradi:58,storag:[27,29,95],store:[5,7,8,12,26,35,37,44,47,49,54,56,58,60,61,62,64,70,95],str:[6,17,70,97,105],straight:[56,59,65],straightforward:43,strategi:[9,58,103],stream:[21,43,55,68],stream_:68,strict:59,stride:[43,47,67],string:[6,7,13,28,35,38,44,55,56,57,58,60,61,64,65,66,71,74,75,95,103],strip:83,struct:[13,14,27,29,37,38,39,46,47,55,61,66,83],structur:[6,7,13,30,33,44,49,56,58,60,65,95],sts:95,stuff:72,style:[60,66],sub:[4,6,16,18,23,33,40,48,51,54,58],sub_block:6,sub_sequ:84,subclass:58,subcommand:28,subgraph:[23,33],submiss:21,submit:[43,60,95],subnet0:95,subnet:[4,95],subobjectpath:96,subseq:[110,113],subsequ:51,subsequenceinput:111,subtract:5,succ:40,succeed:[13,96],success:[14,95,96],successfulcr:96,sucess:40,sucessor:40,sudo:[0,95],suffer:5,suffix:[17,91],suggest:8,suit:119,suitabl:[65,68],sum:[6,7,10,22,37,58],sum_op:6,summar:[33,55],summari:55,sumopgradmak:61,sumpool:81,supercomput:40,suppli:65,support:[3,5,7,9,16,17,18,20,21,23,30,32,33,39,40,43,44,47,49,53,54,55,57,59,60,61,62,65,67,71,95,119],support_inplac:40,suppos:[8,18,32,65,89],suppress:28,sure:95,svs:66,swagger:27,swig:[0,15,45,46],switch_ord:82,switchop:7,sychron:51,symbol:[7,35,46],symbols_ready_:7,symbolt:[7,60],symlink:72,sync:[9,53,62],sync_with_cpp:107,syncflag:74,synchron:[9,13,20,43,51,55,95],syntax:[18,26,30,49,59],sysroot:116,system:[7,8,9,14,16,20,21,23,27,32,33,40,42,67,81],tabl:[7,18,30,37,44,65,71],tablelookup:65,tablelookupgrad:65,tablelookupop:65,tag:[1,63,72,78,101],tail:49,tainer_id:97,take:[4,6,7,8,9,16,18,19,20,21,24,26,29,31,33,34,36,37,39,40,43,47,53,56,57,58,59,60,61,68,70,95],taken:[24,35,40,47,70],talk:[14,31],tanh:[33,49,74,114],tar:[78,84,90,95],tarbal:95,target:[6,7,8,24,26,33,35,50,57,60],target_block:[6,24],target_dict_dim:114,target_dict_s:49,target_language_word:114,target_link_librari:8,target_word:49,targetinlink:111,task13:67,task14:67,task:[21,44,49,55,66,90],task_queu:13,taskentri:13,taskqueu:13,tbd:[15,43,67,111],tcp:[95,103],tear:108,technic:[6,9],techniqu:40,technolog:30,tee:96,tell:[9,13,14,49,66],templat:[32,43,66,68,75,76,96,97,119],tempor:67,temporari:[6,17,26,40,53,58],tempori:40,tensor:[5,8,18,20,22,23,29,30,31,33,35,37,38,43,44,47,48,49,52,65,70,71,75,109],tensor_arrai:18,tensor_array_read:70,tensor_array_s:70,tensor_array_stack:70,tensor_array_unstack:70,tensor_array_writ:70,tensor_data:44,tensor_in:39,tensor_s:5,tensor_test:8,tensor_to_check:5,tensorarrai:22,tensorarraydesc:70,tensordesc:[44,65],tensorflow:[7,18,20,21,23,30,33,36,62,70],term:[9,61,62,67],termin:96,terminolog:40,tessorarrai:70,test1:11,test:[4,5,8,35,46,53,59,63,72,74,75,76,86,89,91,98,103,105,108,109],test_:75,test_all_data_in_one_period:96,test_check_grad_ingore_i:75,test_check_grad_ingore_x:75,test_check_grad_norm:75,test_check_output:75,test_compar:78,test_comparespars:78,test_comparetwonet:78,test_comparetwoopt:78,test_config_pars:78,test_data_dir:91,test_fcgrad:74,test_gpuprofil:108,test_layergrad:74,test_list:83,test_mkldnn:42,test_mklpack:41,test_mul_op:75,test_networkcompar:78,test_pass:[102,103,105],test_period:[102,103,105],test_predict:78,test_pydataprovid:78,test_pydataprovider2:78,test_pydataproviderwrapp:78,test_recurrent_machine_gener:78,test_recurrentgradientmachin:[78,111],test_sum_op:0,test_swig_api:78,test_train:78,test_traineronepass:78,test_wait:[102,103],testa:4,testb:4,testbilinearfwdbwd:108,testconfig:74,testfcgrad:74,testfclay:74,testlayergrad:74,testmulop:75,testq:4,testutil:74,text1:28,text:[4,44,48,55,67,95],tflop:108,tftp:119,tgz:[3,78],than:[6,9,17,18,19,24,30,31,32,33,58,60,62,69,70,83,89,95,119],the_step:30,theano:30,thei:[4,6,8,9,14,16,18,19,20,23,24,28,30,33,34,38,40,49,50,55,58,60,66,70,95,108],them:[4,5,6,8,9,12,17,19,20,23,24,30,31,32,37,38,39,40,49,58,59,60,61,64,65,66,70,71,95,108],themselv:[6,8],theori:30,therefor:[6,40,53],therein:7,theta:33,theta_d:33,theta_g:33,thi:[3,4,5,6,7,8,9,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,29,30,31,32,33,34,35,38,39,40,43,47,48,49,50,51,52,53,54,55,56,58,59,60,61,62,65,66,67,68,70,81,84,89,95,108,109,119],thin:37,thing:[21,33,60,68],think:[4,8],third:[9,35,89],third_parti:[42,78,87,116,117,118],those:[7,8,9,32,34,35,36,56],though:[70,119],thought:8,thread:[18,20,22,52,55,108],thread_count:22,thread_id:55,thread_id_:55,thread_local_rand_use_global_se:[102,103],thread_pool:22,threadid:105,threadloc:108,threadpool:18,three:[5,6,9,20,25,29,30,31,34,43,49,50,54,55,56,59,67,68],threshold:[9,13,24,103],through:[6,8,9,13,15,25,40,50,53,77,109],throughout:26,throughput:[52,108],thrust:60,thu:[16,25,35,40,67,95],tier:96,time:[4,5,8,9,13,16,19,20,21,23,24,30,32,37,40,41,47,48,49,51,55,58,59,60,61,65,66,67,70,71,89,96,97,103,107,108,111,119],timelin:[55,60],timeo:95,timeout:[9,13],timer:108,timestamp:10,timestep:64,titan:40,titl:97,tls:27,tmp:58,to_no_sequ:110,to_sequ:[110,111],to_your_paddle_clone_path:77,todo:[7,9,13,16,49,66,67],togeth:[6,70],token:[4,67,114],toler:5,too:[5,18,20,24,39,43,70],took:119,tool:[55,77,95,97,116,118],toolchain:116,toolkit:67,top:[48,49,67],top_k:49,top_level_rnn:48,topic:43,topk_generated_scor:49,topk_id:49,topk_scor:49,toplevel:0,topolog:[4,9,21,35,40,44,54],topoloi:35,torch:[7,30],tostr:83,total:[9,23,25,51,55,59,96,108,119],total_pass:59,tottim:107,touch:78,toward:30,trace:[7,31,33],track:[9,13,35,58,72],tradit:[7,29,67],traffic:21,train:[1,6,7,11,13,14,16,18,19,24,25,26,30,31,33,34,40,41,44,51,53,54,55,56,57,58,60,62,65,67,68,71,79,81,84,91,93,96,97,98,99,100,103,105,114],train_arg:97,train_args_dict:97,train_args_list:97,train_config_dir:[95,97],train_data:91,train_data_dir:91,train_i:84,train_id:95,train_list:[83,91],train_loop:30,train_read:[21,84],train_x:84,trainabl:[44,58],trainer:[4,10,11,12,13,15,21,23,31,41,42,53,54,60,74,84,91,92,97,103,105],trainer_config:[90,95,96,97],trainer_config_help:74,trainer_count:[81,86,91,95,96,97,102,103,105],trainer_cpu:17,trainer_cr:17,trainer_gpu:17,trainer_id:[91,95,97,103],trainer_intern:12,trainer_mem:17,trainer_packag:17,trainer_prog:21,trainerconfighelp:83,trainerid:[16,97],trainingjob:21,trainonebatch:12,tran:[43,74],trans_var:39,transact:[9,13],transcript:67,transfer:[40,55],transform:[60,67],translat:[40,81],translation_id:49,translation_scor:49,transpar:49,transpil:18,travers:[6,34,40],travi:72,treat:[7,14,40],treatment:[14,29],tree:[7,18,26,30,58,97,109,118],trg_dic_siz:49,trg_embed:[49,114],trick:49,tricki:45,trigger:[16,19,54],trivial:[49,70],true_block:[7,36,56],true_imag:59,true_label:59,true_neg:25,true_posit:25,true_read:59,tune:[67,102,107],tupl:[6,58,59],turn:[58,59,113],tutori:[95,97,98,99,100],twice:[23,33],twine:63,two:[4,6,14,15,16,17,18,19,20,21,25,28,29,30,31,33,34,37,39,40,44,47,49,53,55,56,59,60,61,62,64,65,66,67,70,71,75,76,95,108],txt:[8,17,28,41,42,74,77,91,95,98],type:[4,6,7,9,12,13,16,17,19,21,27,28,29,31,37,38,39,43,44,45,46,48,49,56,57,58,59,60,61,62,65,66,67,68,71,74,75,76,84,86,89,95,96,105,114],type_nam:66,typedef:[14,29,45,46,47,68],typeerror:24,typeid:66,typenam:[32,66,68,75,76],typic:21,ubuntu:[3,63,86],ubyt:59,uci_h:86,uid:96,uint16_t:29,uint32:[27,44],uint32_t:55,uint64:[44,45],uint64_t:[45,89],unawar:14,unbias:5,unblock:20,unbound:40,unbuff:20,unclear:16,uncreat:6,under:[8,13,23,39,51,81,84,95],underli:[19,49],understand:[30,58,67,119],understand_senti:114,undeterminist:108,uni:67,unidirect:67,unifi:[19,26,35,65],uniform:[11,33,58,59],uniform_random:58,uniniti:6,uninstal:[0,78],uniqu:[4,7,9,16,17,43,47,58,64,95],unique_nam:58,unique_name_gener:58,unique_ptr:[61,64,68,74],unit:[8,53,55,62,68],unittest:[46,75,78],unix:20,unk:[65,71],unless:[81,84],unlik:49,unnecessari:[6,67],unordered_map:64,unpack:70,unrol:48,unseen:62,unsign:[14,29],unstack:70,unstack_from:70,unsupervis:33,unsupport:75,until:[9,14,20,22,23,30,40,64,95,97],untrack:72,unzip:116,updat:[6,9,13,14,21,27,29,33,48,49,50,51,53,54,64,67,70,72,105,107],update_equ:84,update_memori:7,update_op:50,updatecallback:74,updatestack:95,upgrad:[3,51,78],upload:[9,17,20,27,63],upon:9,upstream:[72,78],uri:95,usag:[29,36,40,54,58,69,93,97],use:[4,5,7,8,9,15,19,20,21,22,23,26,29,33,35,37,38,39,40,43,47,49,50,51,52,54,55,58,64,65,66,67,70,72,75,81,84,89,91,95,97,108],use_cpu:38,use_cudnn:38,use_eigen_bla:116,use_eigen_for_bla:[116,117],use_gpu:[52,81,84,86,91,96,97,102,103,105],use_mkl_pack:41,use_mkldnn:[38,42],use_old_updat:[12,102,103],use_sparse_remote_updat:12,used:[4,5,7,8,9,15,16,19,20,21,24,26,29,30,33,35,39,40,48,49,52,53,54,55,58,59,60,62,64,66,68,70,95,108],useful:[5,29,39,40,58,64],usegpu:[74,89],user:[4,5,6,7,8,11,13,16,17,18,21,22,23,24,25,26,28,32,33,34,35,37,38,39,43,47,49,50,51,53,55,58,59,60,61,62,64,66,68,70,95,119],user_id:97,user_nam:11,usercert:11,userkei:11,usernam:[11,72,116],uses:[5,9,16,18,20,21,29,39,40,47,48,49,54,55,68,71,95],using:[4,5,6,7,8,9,13,14,16,17,20,21,26,28,29,30,32,33,35,37,40,48,50,53,56,58,59,61,62,64,66,67,68,75,86,95],usr:[0,1,78,91,95,97,103],usual:[6,17,40,47,55,56,62,68,95,108],util:[21,41,42,51,90,97,108,119],uuid:[10,16],v7a:116,v8a:116,val:6,valgrind:107,valid:[59,60,64,95],valu:[5,6,7,9,18,20,24,25,35,36,40,42,44,48,49,50,53,54,56,60,64,65,66,69,70,74,81,89,95,97,105,116],value1:103,value2:103,value_:65,valueerror:[35,81],values_:70,vanilla:[52,114],var_nam:[6,39],var_recurs:24,vardesc:[7,34,56,58,60,65,71],vardescbuild:7,vari:95,variabl:[4,5,7,18,19,20,21,23,24,25,26,31,33,34,35,36,37,39,47,48,49,50,52,53,56,57,61,62,65,66,67,70,95,96,109],variablenamemap:75,varialbl:33,variant:[37,47,68,70],varibal:6,varibl:35,varienc:70,varient:70,variou:[7,20,29,40,62],varproto:66,vars_:[7,64],vartyp:65,vartypeinfer:37,vec2seq:67,vec:83,veclib:117,vector:[4,7,12,14,19,35,36,43,48,49,55,58,60,61,65,67,69,70,87,89],vendor:8,verbos:28,veri:[8,13,18,23,26,30,32,33,40,43,49,54,59,62,64,67,68,70],verifi:7,version:[6,8,17,21,24,28,31,33,35,36,44,49,63,67,72,81,84,95,101,102,103,108,117],versu:4,via:[6,9,47,72,95,119],view:[44,47],vim:1,virtual:[19,24,37,38,61,68],virtualenv:0,visibl:[16,64],visit:6,visual:49,vlog:12,vocabulari:67,volum:[77,96,97],volumemount:[95,96,97],volumn:95,w1_grad:52,w2_grad:52,wai:[4,6,14,16,20,26,30,38,40,49,53,58,59,62,70],wait:[9,14,20,22,97],wangkuiyi:8,want:[4,17,18,20,25,33,38,39,47,53,55,57,59,62,64,68,69,70],warn:[28,78,83,97],warp_ctc:67,warranti:[81,84],wast:51,watch:9,wbia:95,weight:[41,44,62,74],weightlist:74,weights_:74,weights_primitive_desc:43,weights_t:74,welcom:[8,67],well:[6,17,20,21,23,30,32,33,62,65,67,95],wer:67,were:[8,20,30],west:95,wget:[78,116],wgt:43,what:[8,19,30,33,39,49,58,66,72,119],wheel:3,when:[6,7,8,9,12,13,14,17,18,21,23,24,25,26,28,29,30,31,35,49,51,53,54,55,56,58,60,68,70,95,108,119],whenev:[58,67],where:[4,6,7,9,16,18,21,30,31,34,47,48,49,53,56,60,62,68,70,109],wherea:[7,13,32,36,68,69,71],whether:[5,6,7,19,26,55,59,65,70,71,89],which:[4,5,6,7,8,9,11,13,14,16,17,18,19,20,21,22,24,26,29,30,31,32,33,35,37,39,40,43,44,47,48,49,50,51,54,56,57,58,59,60,61,64,65,66,69,70,71,84,95,107,119],while_grad:40,while_loop:[49,70],while_op:6,whileloop:70,whileop:7,white:67,whl:[0,3],who:[6,32,34,51,58],whoever:14,whole:[6,19,33,36,40,45,46,48,51,57,66,67,87,95,119],wholli:19,whose:[5,6,9,16,24,48,60,61,66,70],why:[5,46,108],wide:[8,24,33,93,98],width:[12,45,59,74,75,83,89],wiki:8,window:[0,53,67],wirt:35,wise:[23,60,67],with_avx:[0,72,101,116,117],with_bia:66,with_c_api:[0,87,116,117,118],with_doc:0,with_doubl:[0,74,101],with_dso:0,with_golang:[0,87,116],with_gpu:[0,72,87,101,116,117],with_mkl:[0,41,42,87,116],with_mkldnn:42,with_mklml:42,with_profil:108,with_python:[0,87,101,116,117],with_rdma:[101,116,117],with_style_check:[0,72],with_swig_pi:[0,87,116,117],with_test:[0,72,75],with_tim:[101,108],within:[13,21,30,67],without:[6,9,14,19,20,55,58,59,60,67,81,84],wloop:70,wmt14:114,word2vec:[17,81,91,93],word:[6,23,34,37,40,48,49,60,66,67,70,81,113],word_dict:[91,98],word_dim:83,word_id:81,word_vector_dim:[49,114],wordcount:67,work:[1,4,7,8,9,21,26,29,30,38,50,53,55,58,72,77,95,96,97,119],worker:[23,71,95],workercount:95,workflow:[60,95],workspac:[91,93],worri:5,worth:109,would:[7,8,9,16,20,21,22,23,30,32,33,34,43,50,53,54,58,59,65,67,70,95,119],wouldn:[30,34],wrap:[19,30,32,33,51,119],wrapper:[8,19,20,32,51,53,61,70,108],write:[4,9,16,18,19,20,21,23,29,30,31,32,35,37,43,50,52,53,58,59,60,61,68,70,81,83,84,95],write_lock:10,write_output:52,write_to_arrai:40,writer:[4,58],written:[6,7,18,23,26,33,44,53,60,61,65],wrong:59,wrote:35,wsize:95,www:[81,84],x64:118,x86:[116,117],x86_64:[116,117],x_neg:5,x_po:5,xarg:[1,74,78,98],xcode:117,xcodebuild:117,xgbe0:103,xgbe1:103,xpu:30,xrang:[5,30,33,55,59,74,84,86],xx_layer:38,xxx:[4,70],xxxx:10,xxxxxxxxx:95,xxxxxxxxxx:95,xxxxxxxxxxxxx:95,xxxxxxxxxxxxxxxxxxx:95,y_dim:33,y_neg:5,y_po:5,y_predict:[84,86,109],yaml:[8,93,95,96,97,98,119],yancey1989:17,yapf:72,year:30,yep:[55,107],yet:[30,67,119],yield:[4,11,19,59,81,84],you:[5,17,21,29,64,81,84,95,119],your:[4,8,12,17,28,60,78,95,116,117,118,119],your_access_key_id:95,your_param_nam:83,your_repo:97,your_secrete_access_kei:95,your_source_root:46,yuang:30,yuyang:107,z_dim:33,z_size:33,zaist:0,zero:[5,6,9,20,33,49,54,58,65,95,103],zhihu:0,zhuanlan:0,zip:[58,97,116],zlib:87,zone:95,zxf:78,zxvf:95},titles:["\u4ece\u6e90\u7801\u7f16\u8bd1","\u4f7f\u7528Docker\u5b89\u88c5\u8fd0\u884c","\u5b89\u88c5\u4e0e\u7f16\u8bd1","\u4f7f\u7528pip\u5b89\u88c5","PaddlePaddle Design Doc","Auto Gradient Check Design","Backward Building","Design Doc: Block and Scope","Required CMake Function","Design Doc: Distributed Training","\u6a21\u578b\u53c2\u6570\u68c0\u67e5\u70b9\uff08Checkpointing\uff09","\u8bad\u7ec3\u6570\u636e\u7684\u5b58\u50a8\u548c\u5206\u53d1","Alalysis of large model distributed training in Paddle","Design Doc: Master Server","Design Doc: The Client Library of Parameter Server","Design Doc: Remote Parameter Updater for Cluster Train","Design Doc: Save Model","Submit a Distributed Training Job","Design Doc: Concurrent Programming with Fluid","C++ Data Feeding","Design Doc: CSP in PaddlePaddle Fluid","Design Doc: Distributed Training Architecture","Design Doc: Execute the Program with Multi CPU","Design Doc: Parameter Server","Error Clip","Evaluator Design","Executor Design Doc","FileManager\u8bbe\u8ba1\u6587\u6863","PFSClient","Design Doc: float16","Design Doc: PaddlePaddle Fluid","PaddlePaddle Fluid: Towards a Compiled Programming Language","Design Doc: Functions, Operators, and Layers","Design for GAN","Design Doc: Computations as a Graph","Survey on Graph","The IfElse Operator","Design Doc: InferVarType","Problem","Background","Memory Optimization","Intel\u00ae MKL Packed on PaddlePaddle: Design Doc","Intel\u00ae MKL-DNN on PaddlePaddle: Design Doc","Design Doc: Add MKLDNN Kernel in Fluid Operator","Design Doc: Model Format","Paddle\u591a\u8bed\u8a00\u63a5\u53e3\u5b9e\u73b0","C-API \u6a21\u578b\u63a8\u65ad\u5b9e\u73b0\u6587\u6863","Design Doc: The Keys of Operator Kernel Type","RNNOp design","Design: Sequence Decoder Generating LoDTensors","Optimizer Design","Design Doc: NCCL support in Paddle Fluid","Design Doc: Parallel_Do in PaddlePaddle","Averaging Parameter in PaddlePaddle","Design Doc: The C++ Class Parameters","Introduction","Design Doc: PaddlePaddle Programs","Prune","Design Doc: Python API","Python Data Reader Design Doc","Design Doc: Refactorization Overview","Design Doc: Gradient Operators Registration","Regularization in PaddlePaddle","PaddlePaddle\u53d1\u884c\u89c4\u8303","Design of Scope in Paddle","Design Doc: Selected Rows","Interaction between C++ and Python","DeepSpeech2 on PaddlePaddle: Design Doc","Design Doc: Supporting new Device/Library","Design Doc: Switch","Design for TensorArray","Background","\u5982\u4f55\u8d21\u732e\u4ee3\u7801","\u5f00\u53d1\u6807\u51c6","\u5b9e\u73b0\u65b0\u7684\u7f51\u7edc\u5c42","\u5982\u4f55\u5199\u65b0\u7684Operator","\u5728Paddle\u4e2d\u5982\u4f55\u4f7f\u7528Eigen","\u5982\u4f55\u8d21\u732e\u6587\u6863","\u7f16\u8bd1\u5b89\u88c5\u4e0e\u5355\u5143\u6d4b\u8bd5","\u96c6\u7fa4\u8bad\u7ec3\u4e0e\u9884\u6d4b","FAQ","\u672c\u5730\u8bad\u7ec3\u4e0e\u9884\u6d4b","\u6a21\u578b\u914d\u7f6e","\u53c2\u6570\u8bbe\u7f6e","\u57fa\u672c\u4f7f\u7528\u6982\u5ff5","\u65b0\u624b\u5165\u95e8","\u5feb\u901f\u5f00\u59cb","\u5b89\u88c5\u4e0e\u7f16\u8bd1C-API\u9884\u6d4b\u5e93","C-API\u9884\u6d4b\u5e93","\u8f93\u5165/\u8f93\u51fa\u6570\u636e\u7ec4\u7ec7","C-API\u4f7f\u7528\u6d41\u7a0b","\u542f\u52a8\u53c2\u6570\u8bf4\u660e","\u5206\u5e03\u5f0f\u8bad\u7ec3","\u4f7f\u7528fabric\u542f\u52a8\u96c6\u7fa4\u8bad\u7ec3","\u5728\u4e0d\u540c\u96c6\u7fa4\u4e2d\u8fd0\u884c","Kubernetes on AWS","Kubernetes\u5355\u673a\u8bad\u7ec3","Kubernetes\u5206\u5e03\u5f0f\u8bad\u7ec3","\u5728OpenMPI\u96c6\u7fa4\u4e2d\u542f\u52a8\u8bad\u7ec3","<no title>","<no title>","\u73af\u5883\u51c6\u5907","\u53c2\u6570\u6982\u8ff0","\u7ec6\u8282\u63cf\u8ff0","\u547d\u4ee4\u884c\u53c2\u6570\u8bbe\u7f6e","\u4f7f\u7528\u6848\u4f8b","\u8fdb\u9636\u4f7f\u7528","Python\u4ee3\u7801\u7684\u6027\u80fd\u5206\u6790","GPU\u6027\u80fd\u8c03\u4f18","PaddlePaddle Fluid Source Code Overview","\u652f\u6301\u53cc\u5c42\u5e8f\u5217\u4f5c\u4e3a\u8f93\u5165\u7684Layer","\u5355\u53cc\u5c42RNN API\u5bf9\u6bd4\u4ecb\u7ecd","RNN\u6a21\u578b","Recurrent Group\u6559\u7a0b","RNN\u914d\u7f6e","PaddlePaddle \u6587\u6863","Android\u5e73\u53f0\u7f16\u8bd1\u6307\u5357","iOS\u5e73\u53f0\u7f16\u8bd1\u6307\u5357","Raspberry Pi\u5e73\u53f0\u7f16\u8bd1\u6307\u5357","Cluster bootstrapping tool survey"],titleterms:{"\u4e00\u4e9b\u7ec6\u8282\u7684\u8865\u5145":97,"\u4e0a\u4f20\u8bad\u7ec3\u6587\u4ef6":11,"\u4e0b\u8f7d\u6570\u636e":96,"\u4e0b\u8f7dmklml\u5e93\u5931\u8d25":78,"\u4e0d\u4f7f\u7528":45,"\u4e0d\u4f7f\u7528swig\u8fd9\u79cd\u4ee3\u7801\u751f\u6210\u5668":45,"\u4e0d\u540c\u7684":82,"\u4e0d\u5bfc\u51fapaddle\u5185\u90e8\u7684\u7ed3\u6784\u4f53":45,"\u4e0d\u5f15\u7528\u5176\u4ed6\u52a8\u6001\u5e93":45,"\u4e13\u6ce8\u6df1\u5ea6\u5b66\u4e60\u6a21\u578b\u5f00\u53d1":2,"\u4e24\u79cd\u4f7f\u7528":82,"\u4e3a\u4ec0\u4e48\u9700\u8981\u6027\u80fd\u5206\u6790":108,"\u4ec0\u4e48\u662f\u6027\u80fd\u5206\u6790":108,"\u4ec5\u4ec5\u4f7f\u7528void":45,"\u4ece\u5feb\u7167\u6062\u590d":10,"\u4ece\u6e90\u7801\u7f16\u8bd1":0,"\u4ee3\u7801\u8981\u6c42":72,"\u4f7f\u7528":[72,96],"\u4f7f\u7528\u52a8\u6001\u5e93\u6765\u5206\u53d1paddl":45,"\u4f7f\u7528\u6848\u4f8b":105,"\u4f7f\u7528\u6a21\u578b\u521d\u59cb\u5316\u7f51\u7edc":105,"\u4f7f\u7528\u6d41\u7a0b":90,"\u4f7f\u7528\u73af\u5883\u53d8\u91cf":97,"\u4f7f\u7528\u8f6c\u6362\u5e93":11,"\u4f7f\u7528docker\u542f\u52a8paddlepaddl":1,"\u4f7f\u7528docker\u5b89\u88c5\u8fd0\u884c":1,"\u4f7f\u7528docker\u6267\u884cgpu\u8bad\u7ec3":1,"\u4f7f\u7528docker\u6784\u5efa":77,"\u4f7f\u7528fabric\u542f\u52a8\u96c6\u7fa4\u8bad\u7ec3":93,"\u4f7f\u7528paddlepaddl":77,"\u4f7f\u7528pip\u5b89\u88c5":3,"\u4fdd\u6301\u672c\u5730\u4ed3\u5e93\u6700\u65b0":72,"\u4fee\u6539\u542f\u52a8\u811a\u672c":96,"\u514b\u9686":72,"\u5173\u6ce8\u5e95\u5c42\u6846\u67b6":2,"\u5177\u4f53\u67d0\u79cd\u7c7b\u578b\u7684\u5934\u6587\u4ef6":46,"\u5177\u4f53\u67d0\u79cd\u7c7b\u578b\u7684\u5b9e\u73b0\u6587\u4ef6":46,"\u5185\u7f6e\u5b9a\u65f6\u5668":108,"\u5199\u68af\u5ea6\u68c0\u67e5\u5355\u5143\u6d4b\u8bd5":74,"\u51c6\u5907\u4e00\u4e2alinux\u96c6\u7fa4":93,"\u51c6\u5907\u4ea4\u53c9\u7f16\u8bd1\u73af\u5883":[116,117],"\u51c6\u5907\u6570\u636e\u96c6":91,"\u51c6\u5907\u8bad\u7ec3\u6570\u636e":97,"\u51c6\u5907\u8bad\u7ec3\u7a0b\u5e8f":91,"\u51c6\u5907\u9884\u6d4b\u6a21\u578b":90,"\u51c6\u5907openmpi\u96c6\u7fa4":98,"\u51cf\u5c11\u6570\u636e\u8f7d\u5165\u7684\u8017\u65f6":81,"\u51cf\u5c11dataprovider\u7f13\u51b2\u6c60\u5185\u5b58":81,"\u51fa\u73b0":82,"\u5206\u5757\u6587\u4ef6\u4f20\u8f93":27,"\u5206\u5e03\u5f0f\u8bad\u7ec3":92,"\u5206\u652f\u89c4\u8303":63,"\u521b\u5efa\u672c\u5730\u5206\u652f":72,"\u521b\u5efa\u795e\u7ecf\u7f51\u7edc\u8f93\u5165":90,"\u521b\u5efajob":97,"\u521b\u5efapaddlepaddl":96,"\u521d\u59cb\u5316paddlepaddle\u8fd0\u884c\u73af\u5883":90,"\u5220\u9664\u672c\u5730\u5206\u652f":72,"\u5220\u9664\u8fdc\u7a0b\u5206\u652f":72,"\u5229\u7528\u66f4\u591a\u7684\u8ba1\u7b97\u8d44\u6e90":81,"\u5230\u8fdc\u7a0b\u4ed3\u5e93":72,"\u5236\u4f5c\u955c\u50cf":97,"\u5236\u4f5cdocker\u955c\u50cf":96,"\u524d\u5411\u8ba1\u7b97":90,"\u524d\u5411operator\u5355\u6d4b":75,"\u52a0\u8f7d\u6a21\u578b":90,"\u52a0\u8f7dpaddlepaddl":84,"\u52a0\u901f\u6267\u884c":10,"\u52a0\u901f\u8bad\u7ec3\u901f\u5ea6":81,"\u52a8\u6001\u5e93\u4e2d\u4e0d\u5d4c\u5165\u4efb\u4f55\u5176\u4ed6\u8bed\u8a00\u7684\u89e3\u91ca\u5668":45,"\u52a8\u6001\u6269\u5bb9":10,"\u5355\u5143\u6d4b\u8bd5":103,"\u5355\u53cc\u5c42rnn":111,"\u539f\u56e0":45,"\u539f\u56e0\u5217\u8868":45,"\u53c2\u6570\u5185\u5b58":81,"\u53c2\u6570\u670d\u52a1\u5668\u548c\u5206\u5e03\u5f0f\u901a\u4fe1":103,"\u53c2\u6570\u6982\u8ff0":102,"\u53c2\u6570\u8bbe\u7f6e":83,"\u53c2\u8003\u6587\u6863":27,"\u53c2\u8003\u8d44\u6599":108,"\u53cc\u5c42rnn":111,"\u53cc\u5c42rnn\u4ecb\u7ecd":113,"\u53cc\u5c42rnn\u7684\u4f7f\u7528":113,"\u53cd\u5411operator\u5355\u6d4b":75,"\u53d1\u5e03docker\u955c\u50cf":63,"\u53d1\u5e03wheel\u5305\u5230pypi":63,"\u5404\u4e2a\u7248\u672c\u6700\u65b0\u7684whl\u5305":3,"\u540d\u8bcd\u89e3\u91ca":27,"\u5411\u91cf":103,"\u542f\u52a8\u4efb\u52a1":97,"\u542f\u52a8\u53c2\u6570\u670d\u52a1\u5668":91,"\u542f\u52a8\u53c2\u6570\u8bf4\u660e":91,"\u542f\u52a8\u8ba1\u7b97\u8282\u70b9":91,"\u542f\u52a8\u96c6\u7fa4\u4f5c\u4e1a":[93,98],"\u547d\u4ee4\u884c\u53c2\u6570\u8bbe\u7f6e":104,"\u548c":110,"\u5728\u4e0d\u540c\u8bbe\u5907\u4e0a\u6307\u5b9a\u5c42":105,"\u5728\u4e0d\u540c\u96c6\u7fa4\u4e2d\u8fd0\u884c":94,"\u5728docker\u4e2d\u6267\u884cpaddlepaddle\u8bad\u7ec3\u7a0b\u5e8f":1,"\u5728openmpi\u96c6\u7fa4\u4e2d\u542f\u52a8\u8bad\u7ec3":98,"\u5728paddle\u4e2d\u5982\u4f55\u4f7f\u7528eigen":76,"\u57fa\u4e8edocker\u5bb9\u5668\u7684\u7f16\u8bd1\u65b9\u5f0f":116,"\u57fa\u4e8elinux\u4ea4\u53c9\u7f16\u8bd1\u73af\u5883\u7684\u7f16\u8bd1\u65b9\u5f0f":116,"\u57fa\u672c\u4f7f\u7528\u6982\u5ff5":[84,89],"\u57fa\u672c\u539f\u7406":113,"\u57fa\u672c\u8981\u6c42":45,"\u5982\u4f55\u4e66\u5199\u6587\u6863":77,"\u5982\u4f55\u4f7f\u7528":82,"\u5982\u4f55\u5171\u4eab\u53c2\u6570":83,"\u5982\u4f55\u5199\u65b0\u7684oper":75,"\u5982\u4f55\u51cf\u5c11\u5185\u5b58\u5360\u7528":81,"\u5982\u4f55\u521d\u59cb\u5316\u53c2\u6570":83,"\u5982\u4f55\u52a0\u8f7d\u9884\u8bad\u7ec3\u53c2\u6570":83,"\u5982\u4f55\u52a0\u901f\u8bad\u7ec3\u901f\u5ea6":81,"\u5982\u4f55\u548c\u660e\u6587\u8fdb\u884c\u76f8\u4e92\u8f6c\u5316":83,"\u5982\u4f55\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u83b7\u5f97\u53c2\u6570\u7684\u6743\u91cd\u548c\u68af\u5ea6":81,"\u5982\u4f55\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u83b7\u5f97\u67d0\u4e00\u4e2alayer\u7684output":81,"\u5982\u4f55\u6307\u5b9agpu\u8bbe\u5907":81,"\u5982\u4f55\u66f4\u65b0www":77,"\u5982\u4f55\u6784\u5efa\u6587\u6863":77,"\u5982\u4f55\u8bbe\u7f6e\u5b66\u4e60\u7387\u9000\u706b":83,"\u5982\u4f55\u8c03\u7528":81,"\u5982\u4f55\u8d21\u732e\u4ee3\u7801":72,"\u5982\u4f55\u8d21\u732e\u6587\u6863":77,"\u5982\u4f55\u8fdb\u884c\u6027\u80fd\u5206\u6790":108,"\u5982\u4f55\u9009\u62e9sgd\u7b97\u6cd5\u7684\u5b66\u4e60\u7387":83,"\u5b50\u5e8f\u5217\u95f4\u65e0memori":111,"\u5b50\u5e8f\u5217\u95f4\u6709memori":111,"\u5b58\u50a8\u7684\u53c2\u6570\u683c\u5f0f\u662f\u4ec0\u4e48":83,"\u5b89\u88c5":3,"\u5b89\u88c5\u4e0e\u7f16\u8bd1":2,"\u5b89\u88c5\u4e0e\u7f16\u8bd1c":87,"\u5b89\u88c5\u4ea4\u53c9\u7f16\u8bd1\u5668":118,"\u5b9a\u4e49operator\u7c7b":75,"\u5b9a\u4e49opkernel\u7c7b":75,"\u5b9a\u4e49protomaker\u7c7b":75,"\u5b9e\u73b0":45,"\u5b9e\u73b0\u5355\u5143\u6d4b\u8bd5":75,"\u5b9e\u73b0\u65b0\u7684\u7f51\u7edc\u5c42":74,"\u5b9e\u73b0\u65b9\u5f0f":46,"\u5b9e\u73b0\u8ba1\u7b97":76,"\u5b9e\u73b0c":[74,75],"\u5b9e\u73b0python\u5c01\u88c5":74,"\u5bfb\u627e\u6027\u80fd\u74f6\u9888":107,"\u5bfc\u51fac":45,"\u5c06\u547d\u4ee4\u53c2\u6570\u4f20\u7ed9\u7f51\u7edc\u914d\u7f6e":105,"\u5de5\u5177":108,"\u5e38\u89c1\u95ee\u9898":0,"\u5e38\u89c1\u95ee\u9898\u548c\u89e3\u51b3\u65b9\u6cd5":3,"\u5e38\u89c1\u95ee\u9898\u6c47\u603b":2,"\u5e76\u5b8c\u6210":72,"\u5efa\u7acb":72,"\u5f00\u53d1\u6807\u51c6":73,"\u5f00\u59cb\u5f00\u53d1":72,"\u5f02\u6b65":91,"\u5f02\u6b65\u968f\u673a\u68af\u5ea6\u4e0b\u964d":103,"\u5feb\u7167\u4fdd\u5b58\u7684\u8bbe\u8ba1\u5982\u4e0b":10,"\u5feb\u901f\u4f7f\u7528":86,"\u5feb\u901f\u5b89\u88c5":86,"\u5feb\u901f\u5f00\u59cb":86,"\u6027\u80fd\u5206\u6790\u5c0f\u6280\u5de7":108,"\u6027\u80fd\u5206\u6790\u5de5\u5177\u4ecb\u7ecd":108,"\u6027\u80fd\u8c03\u4f18":103,"\u603b\u7ed3":89,"\u6216\u8005\u662f":78,"\u6267\u884c\u5355\u5143\u6d4b\u8bd5":0,"\u627e\u5230\u7684pythonlibs\u548cpythoninterp\u7248\u672c\u4e0d\u4e00\u81f4":78,"\u62a5importerror":78,"\u6307\u9488\u4f5c\u4e3a\u7c7b\u578b\u7684\u53e5\u67c4":45,"\u63a5\u53e3\u8f93\u51fa\u591a\u4e2alayer\u7684\u9884\u6d4b\u7ed3\u679c":81,"\u63a8\u5bfc\u65b9\u7a0b":74,"\u63a8\u6d4b\u6267\u884c":10,"\u63d0\u4ea4":72,"\u63d0\u4ea4\u4ee3\u7801\u7684\u4e00\u4e9b\u7ea6\u5b9a":72,"\u63d0\u4ea4\u955c\u50cf":96,"\u642d\u5efa\u795e\u7ecf\u7f51\u7edc":84,"\u652f\u6301\u53cc\u5c42\u5e8f\u5217\u4f5c\u4e3a\u8f93\u5165\u7684layer":110,"\u652f\u6301\u7528\u6237\u81ea\u5b9a\u4e49\u7684\u6570\u636e\u9884\u5904\u7406job":11,"\u6570\u636e\u652f\u6301":103,"\u6574\u4f53\u65b9\u6848":97,"\u6587\u4ef6\u4f20\u8f93\u4f18\u5316":27,"\u6587\u4ef6\u8bbf\u95ee\u65b9\u5f0f":11,"\u6587\u4ef6\u8bbf\u95ee\u7684\u6743\u9650":11,"\u6587\u4ef6\u9884\u5904\u7406":11,"\u6587\u6863":115,"\u65b0\u624b\u5165\u95e8":85,"\u65e5\u5fd7\u4e2d\u4fdd\u5b58\u5747\u4e3a\u7f51\u7edc\u901a\u4fe1\u7c7b\u9519\u8bef":79,"\u65f6\u95f4\u5e8f\u5217":111,"\u65f6\u95f4\u6b65":111,"\u66b4\u9732\u63a5\u53e3\u539f\u5219":46,"\u66f4\u65b0":91,"\u672c\u5730\u6d4b\u8bd5":105,"\u672c\u5730\u8bad\u7ec3":105,"\u672c\u5730\u8bad\u7ec3\u4e0e\u9884\u6d4b":81,"\u672f\u8bed":10,"\u6784\u5efa\u548c\u6d4b\u8bd5":72,"\u6784\u5efapaddlepaddle\u7684android\u5f00\u53d1\u955c\u50cf":116,"\u67b6\u6784\u56fe":27,"\u67e5\u770b\u6027\u80fd\u5206\u6790\u6587\u4ef6":107,"\u67e5\u770b\u8bad\u7ec3\u7ed3\u679c":96,"\u67e5\u770b\u8f93\u51fa":97,"\u6846\u67b6\u751f\u6210":27,"\u6848\u4f8b\u4e00":105,"\u6848\u4f8b\u4e8c":105,"\u68c0\u67e5\u6a21\u578b\u8f93\u51fa":93,"\u68c0\u67e5\u96c6\u7fa4\u8bad\u7ec3\u7ed3\u679c":93,"\u6982\u5ff5\u7b80\u4ecb":75,"\u6982\u5ff5\u89e3\u91ca":11,"\u6982\u8ff0":[87,110,113],"\u6a21\u5757":27,"\u6a21\u578b\u53c2\u6570\u68c0\u67e5\u70b9":10,"\u6a21\u578b\u63a8\u65ad\u5b9e\u73b0\u6587\u6863":46,"\u6a21\u578b\u914d\u7f6e":[82,111],"\u6a21\u578b\u914d\u7f6e\u7684\u6a21\u578b\u914d\u7f6e":111,"\u6ce8\u518coper":75,"\u6ce8\u610f\u4e8b\u9879":[75,90],"\u6d41\u7a0b\u4ecb\u7ecd":11,"\u6d4b\u8bd5":103,"\u6df7\u5408\u4ee3\u7801\u7684\u6027\u80fd\u5206\u6790":107,"\u6e05\u7406":90,"\u73af\u5883\u51c6\u5907":101,"\u751f\u6210\u5e8f\u5217":114,"\u751f\u6210\u6027\u80fd\u5206\u6790\u6587\u4ef6":107,"\u751f\u6210\u6d41\u7a0b\u7684\u4f7f\u7528\u65b9\u6cd5":113,"\u751f\u6210sparse\u6587\u4ef6":27,"\u7528\u6237\u4f7f\u7528\u6d41\u7a0b":27,"\u7684\u533a\u522b":82,"\u7684\u53c2\u6570":82,"\u7684\u65b9\u6cd5\u6709\u4f55\u533a\u522b":82,"\u76ee\u5f55\u7ed3\u6784":46,"\u76ee\u6807":27,"\u76f4\u63a5\u6784\u5efa":77,"\u76f8\u5173\u6982\u5ff5":113,"\u77e9\u9635":103,"\u793a\u4f8b1":111,"\u793a\u4f8b2":111,"\u793a\u4f8b3":111,"\u793a\u4f8b4":111,"\u793a\u4f8b\u7a0b\u5e8f":11,"\u795e\u7ecf\u5143\u6fc0\u6d3b\u5185\u5b58":81,"\u7a00\u758f\u8bad\u7ec3":105,"\u7aef\u6570\u636e\u7c7b\u578b\u8bf4\u660e":89,"\u7b26\u53f7":45,"\u7b80\u5355\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":114,"\u7c7b":[45,74,75],"\u7ebf\u6027\u56de\u5f52\u5b8c\u6574\u793a\u4f8b":84,"\u7ec4\u7ec7\u5e8f\u5217\u4fe1\u606f":89,"\u7ec4\u7ec7\u8f93\u5165\u6570\u636e":[89,90],"\u7ec6\u8282\u63cf\u8ff0":103,"\u7ec8\u6b62\u96c6\u7fa4\u4f5c\u4e1a":93,"\u7ed1\u5b9apython":75,"\u7f16\u5199\u9884\u6d4b\u4ee3\u7801":90,"\u7f16\u5199yaml\u6587\u4ef6":96,"\u7f16\u8bd1":75,"\u7f16\u8bd1\u4f9d\u8d56":0,"\u7f16\u8bd1\u548c\u5b89\u88c5":[116,117,118],"\u7f16\u8bd1\u548c\u6267\u884c":75,"\u7f16\u8bd1\u5b89\u88c5\u4e0e\u5355\u5143\u6d4b\u8bd5":78,"\u7f16\u8bd1\u5b89\u88c5\u540e\u6267\u884c":78,"\u7f16\u8bd1\u65b9\u6cd5":0,"\u7f16\u8bd1\u9009\u9879":[0,46],"\u7f16\u8bd1\u9009\u9879\u7684\u8bbe\u7f6e":0,"\u7f16\u8bd1\u9009\u9879\u8bf4\u660e":0,"\u7f16\u8bd1paddlepaddl":116,"\u7f29\u5bb9":10,"\u800c\u662f\u624b\u5199\u591a\u8bed\u8a00\u7ed1\u5b9a":45,"\u80cc\u666f":45,"\u81ea\u7136\u8bed\u8a00\u5904\u7406":103,"\u83b7\u53d6paddlepaddle\u7684docker\u955c\u50cf":1,"\u8986\u76d6\u4e0d\u4e00\u81f4\u7684\u90e8\u5206":27,"\u8bad\u7ec3":103,"\u8bad\u7ec3\u56e0\u6b64\u9000\u51fa\u600e\u4e48\u529e":81,"\u8bad\u7ec3\u6570\u636e\u5b58\u50a8":11,"\u8bad\u7ec3\u6570\u636e\u7684\u5b58\u50a8\u548c\u5206\u53d1":11,"\u8bad\u7ec3\u6a21\u578b":84,"\u8bad\u7ec3\u6d41\u7a0b\u7684\u4f7f\u7528\u65b9\u6cd5":113,"\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u51fa\u73b0":81,"\u8bcd\u6c47\u8868":111,"\u8be6\u7ec6\u6559\u7a0b":108,"\u8bfb\u53d6\u53cc\u5c42\u5e8f\u5217\u6570\u636e":111,"\u8f6c\u6362\u5e93":11,"\u8f93\u5165":[89,113],"\u8f93\u5165\u4e0d\u7b49\u957f":111,"\u8f93\u5165\u793a\u4f8b":113,"\u8f93\u51fa":113,"\u8f93\u51fa\u6570\u636e":89,"\u8f93\u51fa\u6570\u636e\u7c7b\u578b":89,"\u8f93\u51fa\u6570\u636e\u7ec4\u7ec7":89,"\u8fd0\u884c\u5bb9\u5668":96,"\u8fd0\u884c\u73af\u5883\u4f9d\u8d56":3,"\u8fd0\u884cdocker":78,"\u8fd9\u4e2a\u52a8\u6001\u5e93\u4f7f\u7528c99\u6807\u51c6\u7684\u5934\u6587\u4ef6\u5bfc\u51fa\u4e00\u4e9b\u51fd\u6570":45,"\u8fdb\u884c\u8bad\u7ec3":[11,96],"\u8fdb\u9636\u4f7f\u7528":106,"\u901a\u7528":103,"\u9047\u5230":78,"\u914d\u7f6e\u4ea4\u53c9\u7f16\u8bd1\u53c2\u6570":[116,117,118],"\u914d\u7f6e\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u67b6\u6784":114,"\u914d\u7f6e\u7f51\u7edc":84,"\u94a9\u5b50":72,"\u94fe\u63a5\u8bf4\u660e":87,"\u9519\u8bef\u600e\u4e48\u529e":82,"\u9644\u5f55":0,"\u968f\u673a\u6570":103,"\u96c6\u7fa4\u591a\u8282\u70b9\u8bad\u7ec3":79,"\u96c6\u7fa4\u8bad\u7ec3":105,"\u96c6\u7fa4\u8bad\u7ec3\u4e0e\u9884\u6d4b":79,"\u9700\u8981\u7684\u8f6f\u786c\u4ef6":0,"\u975e\u6cd5\u6307\u4ee4":78,"abstract":[21,22,23,51,119],"android\u5e73\u53f0\u7f16\u8bd1\u6307\u5357":116,"api\u4f7f\u7528\u6d41\u7a0b":90,"api\u5bf9\u6bd4\u4ecb\u7ecd":111,"api\u5e93":116,"api\u9884\u6d4b\u5e93":[87,88],"beam_search\u7684\u751f\u6210":111,"book\u4e2d\u6240\u6709\u7ae0\u8282":63,"book\u6559\u7a0b":1,"case":6,"class":[33,54,58],"cmake\u6e90\u7801\u7f16\u8bd1":78,"filemanager\u8bbe\u8ba1\u6587\u6863":27,"final":38,"float":81,"function":[8,32,33,58],"gpu\u548ccpu\u6df7\u5408\u4f7f\u7528":105,"gpu\u6027\u80fd\u8c03\u4f18":108,"gpu\u955c\u50cf\u51fa\u73b0":78,"group\u6559\u7a0b":113,"import":78,"ios\u5e73\u53f0\u7f16\u8bd1\u6307\u5357":117,"kubernetes\u5206\u5e03\u5f0f\u8bad\u7ec3":97,"kubernetes\u5355\u673a\u8bad\u7ec3":96,"new":68,"org\u5de5\u5177":77,"paddle\u52a8\u6001\u5e93\u4e2d":45,"paddle\u591a\u8bed\u8a00\u63a5\u53e3\u5b9e\u73b0":45,"paddle\u7248\u672c\u53f7\u4e3a0":78,"paddlepaddle\u53d1\u884c\u89c4\u8303":63,"paddlepaddle\u56de\u5f52\u6d4b\u8bd5\u5217\u8868":63,"paddlepaddle\u662f\u5426\u652f\u6301\u7ef4\u6570\u53ef\u53d8\u7684\u6570\u636e\u8f93\u5165":82,"paddlepaddle\u73af\u5883\u4f9d\u8d56":3,"paddlepaddle\u7684softmax\u80fd\u5426\u6307\u5b9a\u8ba1\u7b97\u7684\u7ef4\u5ea6":82,"paddlepaddle\u7f16\u8bd1\u4f9d\u8d56":0,"pi\u5e73\u53f0\u7f16\u8bd1\u6307\u5357":118,"pod\u95f4\u901a\u4fe1":97,"python\u4e0ec":107,"python\u4ee3\u7801\u7684\u6027\u80fd\u5206\u6790":107,"python\u76f8\u5173\u7684\u5355\u5143\u6d4b\u8bd5\u90fd\u8fc7\u4e0d\u4e86":78,"return":[58,59],"rnn\u6a21\u578b":112,"rnn\u914d\u7f6e":114,"switch":[43,68,69],"tensor\u4f7f\u7528\u6837\u4f8b":76,"tensor\u5230eigentensor\u7684\u8f6c\u6362":76,"tensor\u6a21\u5757":76,AWS:95,DNS:95,EFS:95,For:8,KMS:95,The:[7,14,18,26,30,33,34,36,37,47,50,54,60,61,69],Use:[7,56],Using:[8,14],With:17,about:33,absolut:49,access:95,account:95,action:[41,42],activ:42,actor:20,add:[40,43,95],address:95,advanc:68,alalysi:12,algorithm:[5,9,21,48,57],all:[64,70],analog:18,analysi:[21,40],anneal:83,api:[21,41,42,46,50,53,58,62,66],appendix:119,arbitrari:30,architectur:[21,55],argument:[28,59],arrai:5,asset:95,associ:[64,95],assumpt:119,async:103,attent:114,attribut:[40,62],auto:5,averag:53,aws:95,background:[5,23,39,41,68,69,70,71],backward:[6,30,34,60],base:[17,49],basic:[40,68,119],batch:59,batch_siz:59,beam:[49,67],becaus:83,benchmark:[41,42],benefit:[23,60],between:[4,20,58,60,66,68],big:83,binari:7,bla:0,block:[7,31,33,34,56,58,60],blockdesc:56,bootstrap:119,bring:119,bucket:95,build:[6,33,60],can:64,capi:46,capi_priv:46,challeng:[6,23,57],chang:49,channel:20,check:5,checkpoint:[9,10,16],choic:38,choos:[8,95],client:14,clip:24,clone:72,close:5,cloudform:95,cluster:[15,95,119],cmake:[8,41,42],code:[17,31,58,109],commit:72,compar:119,comparis:58,compat:30,compil:[7,29,31,56,60,109],complet:30,compos:59,comput:[7,34,43,60,62],con:119,concept:[58,60,95],concern:42,conclus:[16,35,119],concurr:[18,20],condit:33,configur:95,construct:34,content:[41,42,46,67,78,79,81,82,83,95,108,110],control:[40,60],contruct:40,convert:16,convolut:67,copi:52,core:[5,58,95],corner:6,cpu:22,creat:[6,20,59,60,64,95],createreaderop:19,creation:[13,53,62],creator:59,credenti:95,csp:20,ctc:67,cuda:[0,29,78],cudnn:0,current:[29,61],custom:59,data:[9,19,21,39,59,95],dataflow:40,dataprovid:103,dataset:[9,13],datatyp:47,decod:49,decor:59,decoratedread:19,deep:[7,30],deepspeech2:67,defin:95,definit:71,delet:95,demo:[33,95],dens:16,depend:[33,67],deploi:17,describ:[30,50],descript:[28,60],design:[4,5,7,9,13,14,15,16,18,20,21,22,23,25,26,29,30,32,33,34,37,41,42,43,44,47,48,49,50,51,52,54,56,58,59,60,61,64,65,67,68,69,70],destroi:[64,95],detail:[12,67],develop:60,devic:[52,68],devicecontext:68,dictionari:59,differ:[52,60,68],directori:95,discrimin:33,discuss:[23,33],dispatch:[9,13],distribut:[4,9,12,17,21,23,95],dnn:42,doc:[4,7,9,13,14,15,16,18,20,21,22,23,26,29,30,32,34,37,41,42,43,44,47,51,52,54,56,58,59,60,61,65,67,68,69],docker:17,doe:59,down:95,download:95,driver:78,drop_out:82,duplic:82,dure:[49,59],dylib:46,dynam:[9,70],dynet:35,ec2:95,eigen:76,elast:95,elect:16,els:7,engin:33,enough:5,entri:59,environ:17,error:24,evalu:25,event:[4,55],evolut:30,exampl:[4,8,18,20,36,46],except:81,execut:[7,22,30,56,60],executor:26,expand:110,explan:5,extern:95,faq:80,fault:9,feed:19,file:[7,95],fileread:19,find:95,first_seq:110,float16:29,flow:40,fluid:[18,20,30,31,43,51,109],fork:72,format:[7,9,44],forward:[34,52],frame:7,framework:[5,76],from:[4,16,66],functor:68,futur:[30,67],gan:33,gate:114,gener:[31,33,49,119],give:59,global:[56,58],gpu:103,grad_op:6,gradient:[5,6,14,42,61],graph:[34,35,40,60,62],group:95,gru:103,handler:[4,45],happen:16,hardwar:29,helper:58,hierarchi:7,high:[50,53,62,66],how:[5,12,53,59,60,68],iam:95,ifels:36,ifelseop:7,illeg:78,imag:17,implement:[5,6,8,12,22,24,25,29,44,48,51,53,58,59,60,61,62],imporv:52,infer:81,infershap:[56,65],infervartyp:37,ingredi:4,ingress:27,initi:[14,33,95],input:52,insid:64,inspect:95,instal:[95,119],instanc:95,instead:59,instruct:78,insuffici:78,integr:[68,95],intel:[41,42],interact:66,interfac:[5,9,14,15,26,50,59,64],intermedi:60,introduc:[49,70],introduct:[55,62],isn:59,issu:[29,72],job:[9,17,95,96],kei:[41,47,95],kernel:[43,47,60],kube:95,kubectl:95,kubernet:[17,95,96],languag:[7,31],larg:12,last_seq:110,layer:[4,32,41,42,58,82],layout:47,learn:[7,30,83],leval:66,level:[50,53,62,66],libpaddle_capi_shar:46,libpaddle_capi_whol:46,librari:[14,29,47,60,68],limit:21,list:[10,59],live:40,load:20,local:[21,64,95],lod:49,lodtensor:[48,49,70],lodtensordesc:71,logic:13,low:[53,62,66],lstm:103,machin:49,macro:60,main:33,make:40,manag:8,map:[59,60],master:[9,13,17,18],math:68,mathemat:5,matrix:42,member:33,memori:[40,48,68,82,111,113],messag:[66,83],method:49,might:33,migrat:60,mileston:60,mini:59,minibatch:20,mkl:[41,42],mkldnn:43,mkldnn_helper:43,mkldnndevicecontext:43,model:[4,12,14,16,20,30,33,44,49,114],modul:[60,68,78],more:33,motiv:[6,20,26,44,51,57],multi:[22,31],multipl:59,mxnet:35,name:[64,78,82,95],nativ:31,nccl:51,necess:58,necessari:60,need:59,nest:48,network:[60,114],neural:114,nlp:103,norm:62,note:5,numer:5,numpi:5,nvprof:108,nvvp:108,object:9,offset:49,onli:[59,64],onto:52,op_mak:60,oper:[19,32,36,40,43,47,53,56,58,60,61,65,70],opinfomap:60,opkernel:[60,68],opproto:66,ops:62,optim:[9,14,34,40,50,58],option:28,opwithkernel:60,order:28,org:77,origin:60,orthogon:64,other:42,output:95,overview:[16,24,26,41,42,52,60,64,67,109],pack:[41,49],packag:8,paddl:[12,51,59,64,76,78,82],paddlejob:17,paddlepaddl:[4,7,20,30,31,41,42,52,53,56,62,63,67,77,78,95,109,115],pair:95,paradigm:30,parallel_do:52,parallel_nn:105,paramet:[4,9,14,15,17,20,23,42,52,53,54,58,62,95],parameteraverageoptim:53,parent:64,part:34,partit:14,path:[16,28],penalti:62,perform:[52,53,103],persist:13,pfsclient:[27,28],pfsserver:27,place:[40,47,68],placement:21,platform:78,point:[41,81,95],polici:40,pool:110,pose:[37,61],potenti:38,pre:72,prefetch:59,prepar:95,principl:43,privat:95,pro:119,problem:[25,37,38,39,40,47,50,61],procedur:119,process:[9,14,17,50,60],program:[7,18,20,22,30,31,56,58],programdesc:[31,56],project:8,propos:[37,61,62],protobuf:65,protocol:83,provid:59,prune:57,pserver:16,pull:72,push:72,python:[5,17,21,41,42,48,50,53,58,59,62,66,71,89],qualiti:60,queue:[9,13],raspberri:118,rate:83,reader:[4,19,59],readerbas:19,readerhold:19,readop:19,realiz:60,recoveri:9,recurr:[82,113,114],recv:20,refactor:60,refer:[5,21,23,40,41,42,67],region:95,regist:[37,60,66],registr:[60,61],registri:60,regular:[14,62],reject:83,rel:49,relat:[19,60,70],remot:15,remoteexecutor:21,render:95,represent:[7,60],request:72,requir:[8,33],retri:13,reus:58,rnn:[48,70,103,111],rnnop:[7,48,60],route53:95,row:[65,67],rpc:20,run:[26,109],runtim:17,save:16,scale:9,scope:[7,48,60,64],search:[49,67],secur:95,select:[14,20,65],selectedrow:65,semant:69,send:20,separ:60,sequenc:[49,114],server:[9,13,14,17,20,23,95],servic:95,setup:95,sextant:119,sgd:[91,103],shape:49,share:[4,6,40,64],should:64,shuffl:59,simpl:49,singl:59,solut:[37,38,39,40,41,47,57,61],sourc:109,spars:[14,15,16,65],split:52,stack:7,start:[4,95],statement:25,step2:90,step:[48,90],storag:62,store:9,strategi:40,subcommond:28,submit:17,suffici:59,suitabl:8,sulut:43,summar:[4,18],summari:44,support:[29,51,68,70,78],survei:[29,35,62,119],synopsi:28,syntax:20,system:[30,95],tabl:[46,67],task:[9,13,67],tear:95,tecton:119,templat:95,tensor:[60,68,76],tensorarrai:[49,70],tensordesc:71,tensorflow:35,test:[41,42,43],theori:5,thi:[64,78],think:33,three:70,time:109,timelin:16,todo:[10,11,22],togeth:64,toler:9,too:83,tool:[8,119],topic:68,toward:31,train:[4,9,12,15,17,21,50,59,95],trainer:[9,14,16,17,20,95],transform:39,translat:49,transpil:[21,22,23,31,40,51],tune:103,ture:30,two:5,type:[20,47],uniform:70,unit:[41,42,43],unpack:49,updat:[4,15,16,95],usag:[6,24,48,49,59],use:[12,59],user:9,valu:58,variabl:[6,40,58,60,64,71],vartyp:71,verifi:95,version:[18,29,78],volum:95,vpc:95,what:[12,16],wheel:78,when:[16,64],whl:78,why:[29,30,53,59,60,70],work:67,worker:18}}) \ No newline at end of file +Search.setIndex({docnames:["build_and_install/build_from_source_cn","build_and_install/docker_install_cn","build_and_install/index_cn","build_and_install/pip_install_cn","dev/contribute_to_paddle_cn","dev/index_cn","dev/new_layer_cn","dev/write_docs_cn","faq/build_and_install/index_cn","faq/cluster/index_cn","faq/index_cn","faq/local/index_cn","faq/model/index_cn","faq/parameter/index_cn","getstarted/concepts/use_concepts_cn","getstarted/index_cn","getstarted/quickstart_cn","howto/capi/compile_paddle_lib_cn","howto/capi/index_cn","howto/capi/organization_of_the_inputs_cn","howto/capi/workflow_of_capi_cn","howto/cluster/cmd_argument_cn","howto/cluster/index_cn","howto/cluster/multi_cluster/fabric_cn","howto/cluster/multi_cluster/index_cn","howto/cluster/multi_cluster/k8s_aws_cn","howto/cluster/multi_cluster/k8s_cn","howto/cluster/multi_cluster/k8s_distributed_cn","howto/cluster/multi_cluster/openmpi_cn","howto/cluster/multi_cluster/src/k8s_data/README","howto/cluster/multi_cluster/src/k8s_train/README","howto/cluster/preparations_cn","howto/cmd_parameter/arguments_cn","howto/cmd_parameter/detail_introduction_cn","howto/cmd_parameter/index_cn","howto/cmd_parameter/use_case_cn","howto/index_cn","howto/optimization/gpu_profiling_cn","howto/rnn/hierarchical_layer_cn","howto/rnn/hrnn_rnn_api_compare_cn","howto/rnn/index_cn","howto/rnn/recurrent_group_cn","howto/rnn/rnn_config_cn","index_cn"],envversion:50,filenames:["build_and_install/build_from_source_cn.rst","build_and_install/docker_install_cn.rst","build_and_install/index_cn.rst","build_and_install/pip_install_cn.rst","dev/contribute_to_paddle_cn.md","dev/index_cn.rst","dev/new_layer_cn.rst","dev/write_docs_cn.rst","faq/build_and_install/index_cn.rst","faq/cluster/index_cn.rst","faq/index_cn.rst","faq/local/index_cn.rst","faq/model/index_cn.rst","faq/parameter/index_cn.rst","getstarted/concepts/use_concepts_cn.rst","getstarted/index_cn.rst","getstarted/quickstart_cn.rst","howto/capi/compile_paddle_lib_cn.md","howto/capi/index_cn.rst","howto/capi/organization_of_the_inputs_cn.md","howto/capi/workflow_of_capi_cn.md","howto/cluster/cmd_argument_cn.md","howto/cluster/index_cn.rst","howto/cluster/multi_cluster/fabric_cn.md","howto/cluster/multi_cluster/index_cn.rst","howto/cluster/multi_cluster/k8s_aws_cn.md","howto/cluster/multi_cluster/k8s_cn.md","howto/cluster/multi_cluster/k8s_distributed_cn.md","howto/cluster/multi_cluster/openmpi_cn.md","howto/cluster/multi_cluster/src/k8s_data/README.md","howto/cluster/multi_cluster/src/k8s_train/README.md","howto/cluster/preparations_cn.md","howto/cmd_parameter/arguments_cn.md","howto/cmd_parameter/detail_introduction_cn.md","howto/cmd_parameter/index_cn.rst","howto/cmd_parameter/use_case_cn.md","howto/index_cn.rst","howto/optimization/gpu_profiling_cn.rst","howto/rnn/hierarchical_layer_cn.rst","howto/rnn/hrnn_rnn_api_compare_cn.rst","howto/rnn/index_cn.rst","howto/rnn/recurrent_group_cn.md","howto/rnn/rnn_config_cn.rst","index_cn.rst"],objects:{},objnames:{},objtypes:{},terms:{"00m":37,"01org":8,"03m":37,"0424m":37,"04\u4ee5\u4e0a":3,"04\u4ee5\u53camaco":16,"055ee37d":25,"0630u":37,"06u":37,"0810u":37,"0957m":37,"0\u53f7\u8bad\u7ec3\u8282\u70b9\u662f\u4e3b\u8bad\u7ec3\u8282\u70b9":33,"0\u5c42\u5e8f\u5217":38,"0_cudnn5":0,"0_cudnn5_avx_mkl":[1,3],"0_cudnn7_avx_mkl":3,"100gi":25,"100m":11,"1150u":37,"11e6":26,"124n":37,"12\u4ee5\u4e0a":3,"12\u64cd\u4f5c\u7cfb\u7edf":8,"13m":26,"1490u":37,"14\u8fd9\u79cd\u5199\u6cd5\u5c06\u4f1a\u6d4b\u8bd5\u6a21\u578b":35,"1550u":37,"15\u884c":39,"16\u5b57\u8282\u8868\u793a\u4fdd\u5b58\u7684\u53c2\u6570\u603b\u4e2a\u6570":13,"16u":37,"173n":37,"1770u":37,"18ad":25,"18e457ce3d362ff5f3febf8e7f85ffec852f70f3b629add10aed84f930a68750":26,"197u":37,"1\u4e4b\u540e\u7684\u4efb\u4f55\u4e00\u4e2a\u7248\u672c\u6765\u7f16\u8bd1\u8fd0\u884c":0,"1\u7684\u5c42\u4e4b\u5916":35,"1\u7a00\u758f\u6570\u636e":6,"1\u8f6e\u5b58\u50a8\u7684\u6240\u6709\u6a21\u578b":35,"210u":37,"215n":37,"228u":37,"2520u":37,"2680u":37,"26\u884c":39,"279n":37,"27m":37,"285m":37,"2863m":37,"28m":37,"2977m":37,"2\u4e09\u7c7b\u7684\u6bd4\u4f8b\u4e3a":13,"2\u4e2a\u5b50\u5e8f\u5217":19,"2\u5206\u522b\u4ee3\u88683\u4e2a\u8282\u70b9\u7684trainer":27,"2\u610f\u5473\u77400\u53f7\u548c1\u53f7gpu\u5c06\u4f1a\u4f7f\u7528\u6570\u636e\u5e76\u884c\u6765\u8ba1\u7b97fc1\u548cfc2\u5c42":35,"2\u8fd9\u51e0\u4e2a\u76ee\u5f55\u8868\u793apaddlepaddle\u8282\u70b9\u4e0etrain":27,"2cbf7385":25,"302n":37,"30u":37,"328n":37,"32u":37,"331n":37,"3320u":37,"365e":25,"36u":37,"3710m":37,"3768m":37,"387u":37,"38u":37,"3920u":37,"39u":37,"3\u4ee5\u4e0a\u7684\u7b26\u53f7":3,"3\u53f7gpu":11,"4035m":37,"4090u":37,"4096mb":33,"4279m":37,"43u":37,"448a5b355b84":26,"4560u":37,"4563m":37,"45u":37,"4650u":37,"4726m":37,"473m":26,"4\u4e2a\u5e8f\u5217\u7684\u957f\u5ea6\u5206\u522b\u4e3a":19,"4\u5b57\u8282\u8868\u793apaddlepaddle\u7248\u672c\u4fe1\u606f":13,"4gb":33,"500m":11,"50bd":25,"50gi":25,"514u":37,"525n":37,"526u":37,"536u":37,"5460u":37,"5470u":37,"54u":37,"5690m":37,"573u":37,"578n":37,"5798m":37,"586u":37,"58s":26,"5969m":37,"5\u4f5c\u4e3a\u7f16\u8bd1\u73af\u5883":3,"5\u5373\u5c06\u505c\u6b62\u7ef4\u62a4":3,"5_cudnn5_avx_mkl":3,"5_cudnn5_avx_openbla":[3,16],"6080u":37,"6140u":37,"6305m":37,"639u":37,"655u":37,"6780u":37,"6810u":37,"682u":37,"6970u":37,"6\u4e07\u4ebf\u6b21\u6d6e\u70b9\u8fd0\u7b97\u6bcf\u79d2":37,"6\u4ee5\u4e0a":[3,16],"6\u4f5c\u4e3a\u6807\u51c6\u7f16\u8bd1\u73af\u5883":3,"6ce9":25,"704u":37,"7090u":37,"72u":37,"73u":37,"75u":37,"760u":37,"767u":37,"783n":37,"784u":37,"78m":37,"7\u4ee5\u4e0a\u7684\u7b26\u53f7":3,"7\u548cpip":8,"7\u7cfb\u5217":3,"7kb":26,"8000\u5c31\u53ef\u4ee5\u5728\u7f51\u9875\u4e0a\u751f\u6210\u9700\u8981\u7684\u6587\u6863":7,"8250u":37,"8300u":37,"830n":37,"849m":37,"861u":37,"8661m":37,"892m":37,"8\u5b57\u8282\u8868\u793a\u6bcf\u4e2a\u53c2\u6570\u5360\u7528\u7684\u5b57\u8282\u6570":13,"901n":37,"90u":37,"918u":37,"9247m":37,"924n":37,"9261m":37,"9330m":37,"94u":37,"9530m":37,"983m":37,"988u":37,"997u":37,"99u":37,"9f18":26,"\u4e00":39,"\u4e00\u4e2a":19,"\u4e00\u4e2a0\u5c42\u5e8f\u5217":38,"\u4e00\u4e2a0\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u6269\u5c55\u6210\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":38,"\u4e00\u4e2a\u5206\u5e03\u5f0fpaddlepaddle\u8bad\u7ec3\u4efb\u52a1\u4e2d":26,"\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":38,"\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217\u6216\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":38,"\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u6269\u5c55\u6210\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":38,"\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217\u8fdb\u5165":41,"\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":38,"\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217\u6216\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":38,"\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u53d8\u6210\u4e00\u4e2a0\u5c42\u5e8f\u5217":38,"\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u53d8\u6210\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":38,"\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217\u8fdb\u5165":41,"\u4e00\u4e2a\u53cc\u5c42rnn\u7531\u591a\u4e2a\u5355\u5c42rnn\u7ec4\u6210":41,"\u4e00\u4e2a\u53ef\u8c03\u7528\u7684\u51fd\u6570":41,"\u4e00\u4e2a\u6570\u636e\u96c6\u5927\u90e8\u5206\u5e8f\u5217\u957f\u5ea6\u662f100":11,"\u4e00\u4e2a\u662f\u6d6e\u70b9\u8ba1\u7b97\u91cf":37,"\u4e00\u4e2a\u72ec\u7acb\u7684\u5143\u7d20":38,"\u4e00\u4e2a\u72ec\u7acb\u7684\u8bcd\u8bed":38,"\u4e00\u4e2a\u7f51\u7edc\u5c42\u7684\u524d\u5411\u4f20\u64ad\u90e8\u5206\u628a\u8f93\u5165\u8f6c\u5316\u4e3a\u76f8\u5e94\u7684\u8f93\u51fa":6,"\u4e00\u4e2a\u7f51\u7edc\u5c42\u7684\u53c2\u6570\u662f\u5728":6,"\u4e00\u4e2a\u7f51\u7edc\u5c42\u7684c":6,"\u4e00\u4e2a\u8f93\u51fa\u6570\u636e\u540c\u6837\u88ab\u7ec4\u7ec7\u4e3a\u4e00\u4e2a":19,"\u4e00\u4e2a\u91cd\u8981\u7684\u95ee\u9898\u662f\u9009\u62e9\u6b63\u786e\u7684learning_r":13,"\u4e00\u4e2agpu\u8bbe\u5907\u4e0a\u4e0d\u5141\u8bb8\u914d\u7f6e\u591a\u4e2a\u6a21\u578b":33,"\u4e00\u4e2agradientmachine\u7c7b\u7684\u5bf9\u8c61\u7ba1\u7406\u7740\u4e00\u7ec4\u8ba1\u7b97\u5c42":20,"\u4e00\u4e2alabel":39,"\u4e00\u4e2amemory\u5305\u542b":42,"\u4e00\u4e9b\u60c5\u51b5\u4e3a\u4e86\u4fbf\u4e8e\u53d1\u5e03":20,"\u4e00\u4eba":39,"\u4e00\u53e5\u8bdd\u662f\u7531\u8bcd\u8bed\u6784\u6210\u7684\u5e8f\u5217":41,"\u4e00\u53f0\u7535\u8111":0,"\u4e00\u65e9":39,"\u4e00\u662fbatch":11,"\u4e00\u6837\u7684\u65b9\u5f0f":0,"\u4e00\u6b21\u6027\u676f\u5b50":39,"\u4e00\u7ef4\u6570\u7ec4":[19,20],"\u4e00\u7ef4\u6574\u578b\u6570\u7ec4":19,"\u4e00\u81f4":[38,39],"\u4e00\u822c\u4ece":4,"\u4e00\u822c\u5728paddlepaddle\u4e2d":39,"\u4e00\u822c\u662f\u7531\u4e8e\u76f4\u63a5\u4f20\u9012\u5927\u5b57\u5178\u5bfc\u81f4\u7684":13,"\u4e00\u822c\u6765\u8bf4":42,"\u4e00\u822c\u8868\u793a":39,"\u4e00\u822c\u8bbe\u7f6e":13,"\u4e00\u8282":20,"\u4e09\u79cd\u5e8f\u5217\u6a21\u5f0f":14,"\u4e0a":4,"\u4e0a\u4f20\u8ba1\u7b97\u5f97\u51fa\u7684\u68af\u5ea6":22,"\u4e0a\u56fe\u4e2d\u7684":19,"\u4e0a\u56fe\u4e2d\u865a\u7ebf\u7684\u8fde\u63a5":39,"\u4e0a\u56fe\u63cf\u8ff0\u4e86\u4e00\u4e2a3\u8282\u70b9\u7684\u5206\u5e03\u5f0f\u8bad\u7ec3\u573a\u666f":27,"\u4e0a\u7f16\u8bd1\u5f88\u6162":0,"\u4e0a\u7f51":39,"\u4e0a\u8ff0\u4ee3\u7801\u5c06bias\u5168\u90e8\u521d\u59cb\u5316\u4e3a1":13,"\u4e0a\u8ff0\u547d\u4ee4\u4e2d":1,"\u4e0a\u8ff0\u547d\u4ee4\u628a\u5f53\u524d\u76ee\u5f55":0,"\u4e0a\u8ff0\u7684":12,"\u4e0a\u8ff0\u7684\u4ee3\u7801\u7247\u6bb5\u5305\u542b\u4e86\u4e24\u79cd\u65b9\u6cd5":37,"\u4e0a\u8ff0\u7b2c4\u6b65":0,"\u4e0b":7,"\u4e0b\u4e00\u6b65\u5c31\u662f\u7528\u6a21\u578b\u6765\u505a\u9884\u6d4b":18,"\u4e0b\u4f1a\u770b\u5230\u5982\u4e0b\u76ee\u5f55\u7ed3\u6784":17,"\u4e0b\u540c":13,"\u4e0b\u56fe\u4e2d\u5c31\u5c55\u793a\u4e86\u4e00\u4e9b\u5173\u4e8e\u5185\u5b58\u6570\u636e\u8fc1\u5f99\u548c\u8ba1\u7b97\u8d44\u6e90\u5229\u7528\u7387\u7684\u5efa\u8bae":37,"\u4e0b\u56fe\u662f\u4e00\u4e2a\u5168\u8fde\u63a5\u5c42\u7684\u793a\u610f\u56fe":6,"\u4e0b\u56fe\u662fcsr\u5b58\u50a8\u7a00\u758f\u77e9\u9635\u7684\u793a\u610f\u56fe":19,"\u4e0b\u627e\u5230":17,"\u4e0b\u6587\u4ee5nlp\u4efb\u52a1\u4e3a\u4f8b":41,"\u4e0b\u6587\u4f1a\u8be6\u7ec6\u8fdb\u884c\u4ecb\u7ecd":19,"\u4e0b\u6587\u4f7f\u7528":27,"\u4e0b\u6587\u5c31\u662f\u7528job\u7c7b\u578b\u7684\u8d44\u6e90\u6765\u8fdb\u884c\u8bad\u7ec3":26,"\u4e0b\u6587\u8be6\u7ec6\u89e3\u91ca":19,"\u4e0b\u6b21":39,"\u4e0b\u7684":[20,27],"\u4e0b\u8868\u5217\u51fa\u4e86python\u7aef\u8bad\u7ec3\u63a5\u53e3\u66b4\u9732\u7684\u6570\u636e\u7c7b\u578b":19,"\u4e0b\u8f7d\u5b8c\u6570\u636e\u540e":26,"\u4e0b\u8f7d\u6307\u5b9a\u7248\u672c\u7684docker\u955c\u50cf":1,"\u4e0b\u8f7dgpu\u7248\u672c":1,"\u4e0b\u9762":20,"\u4e0b\u9762\u4e3e\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50":37,"\u4e0b\u9762\u4ee5":21,"\u4e0b\u9762\u5217\u51fa\u4e86":42,"\u4e0b\u9762\u5217\u51fa\u4e86\u5168\u8fde\u63a5\u5c42\u7684\u68af\u5ea6\u68c0\u67e5\u5355\u5143\u6d4b\u8bd5":6,"\u4e0b\u9762\u5c31\u6839\u636e\u8fd9\u51e0\u4e2a\u6b65\u9aa4\u5206\u522b\u4ecb\u7ecd":27,"\u4e0b\u9762\u6211\u4eec\u4f7f\u7528\u8fd9\u4e2a\u955c\u50cf\u6765\u4e0b\u8f7d\u6570\u636e\u5230docker":26,"\u4e0b\u9762\u662fc":20,"\u4e0b\u9762\u7684\u4ee3\u7801\u5c06\u968f\u673a\u751f\u6210\u7684\u77e9\u9635\u8f6c\u5316\u4e3a\u53ef\u4ee5\u88abpaddlepaddle\u52a0\u8f7d\u7684\u6a21\u578b\u53c2\u6570":13,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u4ecegithub\u62c9\u53d6\u6700\u65b0\u4ee3\u7801":17,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u521b\u5efa\u4e86\u4e00\u4e2a\u9ad8\u5ea6\u4e3a1":19,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u521b\u5efa\u4e86\u4e00\u4e2acpu\u4e0a\u7684\u4e8c\u503c\u7a00\u758f\u77e9\u9635":19,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u521b\u5efa\u4e86\u542b\u6709\u4e09\u4e2a\u5143\u7d20":19,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u5728\u521b\u5efa\u4e86\u4e00\u4e2acpu\u4e0a\u7684\u5e26\u5143\u7d20\u503c\u7684\u7a00\u758f\u77e9\u9635":19,"\u4e0b\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u5b9e\u73b0\u4e86":6,"\u4e0b\u9762\u7ed9\u51fa\u4e86\u4e00\u4e2a\u4f8b\u5b50":6,"\u4e0b\u9762\u7ed9\u51fa\u5728\u4e09\u7ef4\u7a7a\u95f4\u4e2d\u4f7f\u7528\u7ebf\u6027\u56de\u5f52\u62df\u5408\u4e00\u6761\u76f4\u7ebf\u7684\u4f8b\u5b50":14,"\u4e0b\u9762\u8be6\u7ec6\u89e3\u91ca\u4ec0\u4e48\u662f":19,"\u4e0b\u9762\u8fd9\u4e9blayer\u80fd\u591f\u63a5\u53d7\u53cc\u5c42\u5e8f\u5217\u4f5c\u4e3a\u8f93\u5165":38,"\u4e0d":39,"\u4e0d\u4ec5\u8981\u63d0\u4f9b\u6bcf\u4e00\u4e2a\u5916\u5c42\u5e8f\u5217\u5728\u6574\u4e2a":19,"\u4e0d\u4f1a\u4fdd\u7559\u5728\u78c1\u76d8\u4e0a":0,"\u4e0d\u4f1a\u518d\u4ece":11,"\u4e0d\u4f1a\u865a\u62df\u4efb\u4f55\u786c\u4ef6":0,"\u4e0d\u4f7f\u7528\u989d\u5916\u7a7a\u95f4":6,"\u4e0d\u53ef\u518d\u8fdb\u884c\u62c6\u5206":19,"\u4e0d\u540c\u4e8e\u4e0a\u8ff0\u4ecb\u7ecd\u7684recurr":12,"\u4e0d\u540c\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u6570\u636e\u5927\u5c0f\u7684\u6700\u5927\u503c\u4e0e\u6700\u5c0f\u503c\u7684\u6bd4\u7387":33,"\u4e0d\u540c\u5e8f\u5217\u53ef\u80fd\u4f1a\u542b\u6709\u4e0d\u540c\u6570\u76ee\u4e2a\u5143\u7d20":19,"\u4e0d\u540c\u65f6\u95f4\u6b65\u7684\u8f93\u5165\u662f\u4e0d\u540c\u7684":42,"\u4e0d\u540c\u7684\u4f18\u5316\u7b97\u6cd5\u9700\u8981\u4f7f\u7528\u4e0d\u540c\u5927\u5c0f\u7684\u5185\u5b58":11,"\u4e0d\u540c\u7684\u5206\u5e03\u5f0f\u6587\u4ef6\u7cfb\u7edf":27,"\u4e0d\u540c\u7684\u6570\u636e\u7c7b\u578b\u548c\u5e8f\u5217\u6a21\u5f0f\u8fd4\u56de\u7684\u683c\u5f0f\u4e0d\u540c":14,"\u4e0d\u540c\u8ba1\u7b97\u5c42\u5bf9\u7a7a\u8f93\u5165\u7684\u5904\u7406\u7b56\u7565\u6709\u53ef\u80fd\u4e0d\u540c":19,"\u4e0d\u540c\u8f93\u5165\u542b\u6709\u7684\u5b50\u53e5":41,"\u4e0d\u540c\u8f93\u5165\u5e8f\u5217\u542b\u6709\u7684\u8bcd\u8bed\u6570\u5fc5\u987b\u4e25\u683c\u76f8\u7b49":41,"\u4e0d\u540cdataprovider\u5bf9\u6bd4\u5982\u4e0b":39,"\u4e0d\u5c11":39,"\u4e0d\u5e94\u8be5\u88ab\u62c6\u89e3":41,"\u4e0d\u6307\u5b9a\u65f6":41,"\u4e0d\u652f\u6301":19,"\u4e0d\u652f\u6301\u5e8f\u5217\u957f\u5ea6\u4e3a":19,"\u4e0d\u662f\u4e00\u6761\u5e8f\u5217":14,"\u4e0d\u662f\u771f\u6b63\u7684layer":12,"\u4e0d\u662f\u901a\u8fc7\u4e00\u822c\u7684\u65b9\u5f0f\u6765\u5b9e\u73b0\u5bf9\u8f93\u51fa\u7684\u6fc0\u6d3b":12,"\u4e0d\u6ee1\u8db3\u94a9\u5b50\u7684":4,"\u4e0d\u80fd\u592a\u968f\u610f":4,"\u4e0d\u80fd\u88ab\u63d0\u4ea4\u5230":4,"\u4e0d\u8981\u5728\u6ce8\u91cd\u6027\u80fd\u7684\u8bad\u7ec3\u573a\u666f\u4e0b\u4f7f\u7528":11,"\u4e0d\u8bba\u5e8f\u5217\u4e2d\u7684\u5143\u7d20\u5728\u5185\u5b58\u4e2d\u5360\u7528\u591a\u5c11\u5b9e\u9645\u5b58\u50a8\u7a7a\u95f4":19,"\u4e0d\u8bba\u6570\u636e\u57df\u662f":19,"\u4e0d\u8bba\u662f\u4e00\u7ef4\u6574\u578b\u6570\u7ec4\u8fd8\u662f\u4e8c\u7ef4\u6d6e\u70b9\u6570\u77e9\u9635":19,"\u4e0d\u8bba\u662f\u5355\u5c42\u5e8f\u5217\u8fd8\u662f\u53cc\u5c42\u5e8f\u5217\u7684\u5e8f\u5217\u4fe1\u606f":19,"\u4e0d\u8fc7":39,"\u4e0d\u8fc7\u5b9e\u9645\u4e0a\u662f\u8fd0\u884c\u5728\u4e00\u4e2a":0,"\u4e0d\u8fdc":39,"\u4e0d\u9519":39,"\u4e0d\u9700\u5728\u4f7f\u7528c":20,"\u4e0d\u9700\u8981\u4f9d\u8d56\u5176\u4ed6\u4efb\u4f55\u8f6f\u4ef6\u4e86":0,"\u4e0d\u9700\u8981\u63d0\u4f9b\u5143\u7d20\u503c":19,"\u4e0e":27,"\u4e0e\u5176\u5b83":20,"\u4e0e\u5355\u5c42rnn\u7684\u914d\u7f6e\u7c7b\u4f3c":39,"\u4e0e\u540c\u6b65sgd\u76f8\u6bd4":22,"\u4e0e\u5f53\u524d\u7684\u8870\u51cf\u56e0\u5b50\u7684\u4e58\u79ef":13,"\u4e0e\u672c\u5730\u8bad\u7ec3\u76f8\u540c":23,"\u4e0e\u6b64\u4e0d\u540c\u7684\u662f":27,"\u4e0e\u8f93\u5165\u4e0d\u540c\u7684\u662f":20,"\u4e0e\u8fd9\u4e2a\u8bad\u7ec3\u6570\u636e\u4ea4\u4e92\u7684layer":11,"\u4e0ejob":27,"\u4e14":39,"\u4e14\u4e0d\u6392\u9664commit\u4e4b\u95f4\u7684\u4fee\u6539\u5b58\u5728\u76f8\u4e92\u8986\u76d6\u7684\u60c5\u51b5":4,"\u4e14\u4f7f\u7528":17,"\u4e14\u5e8f\u5217\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20\u8fd8\u662f\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217":14,"\u4e14\u6bcf\u4e2a\u53e5\u5b50\u8868\u793a\u4e3a\u5bf9\u5e94\u7684\u8bcd\u8868\u7d22\u5f15\u6570\u7ec4":39,"\u4e24":39,"\u4e24\u4e2a\u5b50\u76ee\u5f55\u4e0b":7,"\u4e24\u4e2a\u5d4c\u5957\u7684":41,"\u4e24\u4e2a\u64cd\u4f5c":37,"\u4e24\u4e2a\u8f93\u5165\u7684\u5b50\u5e8f\u5217\u957f\u5ea6\u4e5f\u5e76\u4e0d\u76f8\u540c":39,"\u4e24\u4e2a\u90e8\u5206":7,"\u4e24\u4e2a\u9690\u5c42\u7684\u7b80\u5355\u5168\u8fde\u63a5\u7f51\u7edc":20,"\u4e24\u6b21":19,"\u4e24\u79cd\u5e38\u7528\u7684\u6a21\u578b\u52a0\u8f7d\u65b9\u5f0f":20,"\u4e24\u79cd\u65b9\u6cd5\u7684\u533a\u522b":11,"\u4e24\u79cdblas\u5e93":0,"\u4e24\u8005\u90fd\u662f\u5bf9\u68af\u5ea6\u7684\u622a\u65ad":11,"\u4e2a\u5185\u5b58\u6c60\u5b9e\u9645\u4e0a\u51b3\u5b9a\u4e86shuffle\u7684\u7c92\u5ea6":11,"\u4e2a\u6279\u6b21\u7684\u53c2\u6570\u5e73\u5747\u503c\u8fdb\u884c\u6d4b\u8bd5":33,"\u4e2a\u6a21\u578b\u6d4b\u8bd5\u6570\u636e":33,"\u4e2d":[6,11,19,27],"\u4e2d\u4e0d\u8981\u6dfb\u52a0\u5927\u6587\u4ef6\u7b49":4,"\u4e2d\u4f1a\u4f7f\u7528\u5230\u7684\u5b57\u5178\u6570\u636e\u6587\u4ef6":21,"\u4e2d\u4f20\u5165\u53c2\u6570":21,"\u4e2d\u4f20\u5165\u7684\u53c2\u6570":21,"\u4e2d\u5143\u7d20\u4e2a\u6570\u603b\u662f\u7b49\u4e8e\u884c\u6570":19,"\u4e2d\u5143\u7d20\u7684\u4e2a\u6570\u7b49\u4e8e\u7f51\u7edc\u4e2d\u8f93\u51fa\u5c42\u7684\u4e2a\u6570":11,"\u4e2d\u5173\u4e8e\u65f6\u95f4\u9012\u5f52\u795e\u7ecf\u7f51\u7edc\u7684\u4ecb\u7ecd":39,"\u4e2d\u5355\u5143\u6d4b\u8bd5\u7684\u4e00\u90e8\u5206":4,"\u4e2d\u5355\u5143\u6d4b\u8bd5\u80fd\u987a\u5229\u901a\u8fc7":4,"\u4e2d\u542b\u6709\u591a\u4e2a\u5e8f\u5217":19,"\u4e2d\u5b9a\u4e49":42,"\u4e2d\u5b9a\u4e49\u548c\u4f7f\u7528":41,"\u4e2d\u6253\u5370\u5176\u503c":11,"\u4e2d\u6307\u5b9a":33,"\u4e2d\u6307\u5b9a\u7684\u540d\u5b57":35,"\u4e2d\u641c\u7d22\u8fd9\u51e0\u4e2a\u5e93":0,"\u4e2d\u64cd\u4f5c":19,"\u4e2d\u6587\u6587\u6863":7,"\u4e2d\u6587\u6587\u6863\u76ee\u5f55":7,"\u4e2d\u6587\u7ef4\u57fa\u767e\u79d1\u9875\u9762":39,"\u4e2d\u6bcf\u4e2a\u5143\u7d20\u662f\u4e00\u4e2alayer\u7684\u8f93\u51fa\u7ed3\u679c\u77e9\u9635":11,"\u4e2d\u6bcf\u4e2apod\u7684ip\u5730\u5740":27,"\u4e2d\u6bcf\u5c42\u7684\u6570\u503c\u7edf\u8ba1":33,"\u4e2d\u7528\u4e8e\u5b58\u50a8\u6570\u636e\u7684":20,"\u4e2d\u7684":20,"\u4e2d\u7684\u4e00\u884c":4,"\u4e2d\u7684\u4ee3\u7801\u4f5c\u4e3a\u5b9e\u4f8b":21,"\u4e2d\u7684\u504f\u79fb":19,"\u4e2d\u7684\u5bf9\u5e94\u5206\u652f\u5373\u53ef":4,"\u4e2d\u7684\u76f8\u5173\u811a\u672c":20,"\u4e2d\u7684\u8d77\u59cb\u504f\u79fb":19,"\u4e2d\u83b7\u53d6":27,"\u4e2d\u8bbe\u7f6e\u7684\u6240\u6709\u8282\u70b9":23,"\u4e2d\u8be6\u7ec6\u4ecb\u7ecd":6,"\u4e2d\u914d\u7f6e\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":42,"\u4e34\u65f6\u53d8\u91cf\u7b49\u7b49":11,"\u4e3a":[19,42],"\u4e3a\u4e86\u4f7f\u8bc4\u5ba1\u4eba\u5728\u8bc4\u5ba1\u4ee3\u7801\u65f6\u66f4\u597d\u5730\u4e13\u6ce8\u4e8e\u4ee3\u7801\u672c\u8eab":4,"\u4e3a\u4e86\u4fdd\u8bc1\u6548\u7387":6,"\u4e3a\u4e86\u4fdd\u8bc1gpu\u9a71\u52a8\u80fd\u591f\u5728\u955c\u50cf\u91cc\u9762\u6b63\u5e38\u8fd0\u884c":1,"\u4e3a\u4e86\u51cf\u5c11\u751f\u6210\u94fe\u63a5\u5e93\u7684\u5927\u5c0f\u628a":17,"\u4e3a\u4e86\u548c\u7528\u6237\u7cfb\u7edf\u517c\u5bb9":18,"\u4e3a\u4e86\u5c01\u88c5\u80fd\u591f\u6b63\u786e\u5de5\u4f5c":6,"\u4e3a\u4e86\u63cf\u8ff0\u65b9\u4fbf":41,"\u4e3a\u4e86\u65b9\u4fbf\u5927\u5bb6":4,"\u4e3a\u4e86\u65b9\u4fbf\u5927\u5bb6\u7684\u90e8\u7f72":24,"\u4e3a\u4e86\u7f16\u8bd1paddlepaddl":0,"\u4e3a\u4e86\u8fbe\u5230\u6027\u80fd\u6700\u4f18":37,"\u4e3a\u4ec0\u4e48\u7528":0,"\u4e3a\u4f7f\u7528c":20,"\u4e3a\u4f8b":12,"\u4e3a\u53c2\u6570\u77e9\u9635\u7684\u5bbd\u5ea6":13,"\u4e3a\u5b83\u4eec\u9644\u52a0\u4e0a\u5e8f\u5217\u4fe1\u606f\u5c06\u53d8\u6210\u5e8f\u5217\u8f93\u5165":19,"\u4e3a\u5bb9\u5668\u5185\u6267\u884c\u7684\u547d\u4ee4":1,"\u4e3a\u60a8\u505a\u6027\u80fd\u8c03\u4f18\u63d0\u4f9b\u4e86\u65b9\u5411":37,"\u4e3a\u65b9\u4fbf\u4f5c\u4e1a\u542f\u52a8\u63d0\u4f9b\u4e86\u4e24\u4e2a\u72ec\u7279\u7684\u547d\u4ee4\u9009\u9879":23,"\u4e3a\u6b64":26,"\u4e3a\u6bcf\u4e00\u4e2a":[19,20],"\u4e3a\u6bcf\u4e00\u4e2a\u8f93\u5165":[19,20],"\u4e3a\u8f93\u51fa\u5206\u914d\u5185\u5b58":6,"\u4e3aoutput_\u7533\u8bf7\u5185\u5b58":6,"\u4e3b\u8981\u4e3a\u5f00\u53d1\u8005\u4f7f\u7528":33,"\u4e3b\u8981\u5305\u62ec\u56db\u79cd\u7c7b\u578b":14,"\u4e3b\u8981\u539f\u56e0":39,"\u4e3b\u8981\u539f\u56e0\u5305\u62ec\u4e24\u4e2a\u65b9\u9762":11,"\u4e3e\u4e00\u4e2a\u4f8b\u5b50":13,"\u4e3e\u4f8b":11,"\u4e3e\u4f8b\u8bf4\u660e":39,"\u4e4b\u524d":4,"\u4e4b\u540e":[6,14,21],"\u4e4b\u540e\u4f7f\u7528":6,"\u4e4b\u540e\u4f7f\u7528\u77e9\u9635\u8fd0\u7b97\u51fd\u6570\u6765\u8ba1\u7b97":6,"\u4e4b\u540e\u518d\u7528\u7f51\u9875\u8fde\u5230http":7,"\u4e4b\u540e\u521d\u59cb\u5316\u6240\u6709\u7684\u6743\u91cd\u77e9\u9635":6,"\u4e4b\u540e\u624d\u80fd\u5f00\u59cb\u7f16\u8bd1\u7684\u6b65\u9aa4":0,"\u4e4b\u7c7b\u7684\u7a0b\u5e8f\u6765\u7f16\u8bd1\u6e90\u7801":0,"\u4e4b\u95f4\u7684\u8fd0\u7b97\u662f\u72ec\u7acb\u7684":41,"\u4e58\u4e0a\u8f93\u51fa\u7684\u68af\u5ea6":6,"\u4e58\u9664\u7b49\u65f6\u5019":11,"\u4e5f":39,"\u4e5f\u4e0d\u5b58\u5728\u4e00\u4e2asubseq\u76f4\u63a5\u751f\u6210\u4e0b\u4e00\u4e2asubseq\u7684\u60c5\u51b5":41,"\u4e5f\u4e0d\u80fd\u63a5\u6536\u5e8f\u5217\u6570\u636e\u4f5c\u4e3a\u8f93\u5165":12,"\u4e5f\u4f1a\u5360\u7528\u78c1\u76d8":0,"\u4e5f\u53ef\u4ee5\u4f7f\u7528":4,"\u4e5f\u53ef\u4ee5\u5229\u7528paddlepaddl":7,"\u4e5f\u53ef\u4ee5\u662f\u4e00\u4e2a\u8bcd\u8bed":41,"\u4e5f\u53ef\u4ee5\u662f\u5728\u4efb\u52a1\u542f\u52a8\u524d\u4e0b\u8f7d\u5230\u672c\u5730\u7684":21,"\u4e5f\u53ef\u4ee5\u76f4\u63a5\u5728\u7f51\u9875\u9884\u89c8\u6587\u6863":7,"\u4e5f\u53ef\u4ee5\u8bf4\u662f\u67d0\u4e9b\u7279\u5b9a\u6307\u4ee4\u7684\u4f7f\u7528\u60c5\u51b5":37,"\u4e5f\u53ef\u4ee5\u901a\u8fc7\u4fee\u6539":27,"\u4e5f\u5c31\u662f":4,"\u4e5f\u5c31\u662f\u7a7a\u8f93\u5165":19,"\u4e5f\u5c31\u662f\u81ea\u5df1\u7528\u6237\u540d\u4e0b\u7684":4,"\u4e5f\u5c31\u662f\u8bf4":[19,33,35],"\u4e5f\u5c31\u662fpaddlepaddle\u4e2d\u7684\u4e00\u7ef4\u6574\u578b\u6570\u7ec4":19,"\u4e5f\u63cf\u8ff0\u4e86\u5bb9\u5668\u9700\u8981\u4f7f\u7528\u7684\u5b58\u50a8\u5377\u6302\u8f7d\u7684\u60c5\u51b5":27,"\u4e5f\u652f\u6301cpu\u7684\u6027\u80fd\u5206\u6790":37,"\u4e5f\u662f\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217":39,"\u4e5f\u662fdecoder\u5faa\u73af\u5c55\u5f00\u7684\u4f9d\u636e":41,"\u4e5f\u6ca1\u7528":8,"\u4e7e":39,"\u4e86":[0,39],"\u4e86\u89e3\u60a8\u7684\u786c\u4ef6":37,"\u4e86\u89e3\u66f4\u591a\u7ec6\u8282":42,"\u4e86\u89e3\u66f4\u591a\u8be6\u7ec6\u4fe1\u606f":42,"\u4e8c\u7ef4\u6d6e\u70b9\u578b\u77e9\u9635":19,"\u4e8c\u7ef4\u6d6e\u70b9\u6570\u77e9\u9635":19,"\u4e8c\u7ef4\u77e9\u9635":20,"\u4e8c\u7ef4\u77e9\u9635\u53ef\u4ee5\u8868\u793a\u884c\u5411\u91cf\u548c\u5217\u5411\u91cf":19,"\u4e8c\u8005\u8bed\u610f\u4e0a\u5b8c\u5168\u4e00\u81f4":39,"\u4e8e\u662f":19,"\u4e94\u661f\u7ea7":39,"\u4ea4\u901a":39,"\u4ea4\u901a\u4fbf\u5229":39,"\u4eab\u53d7\u60a8\u7684\u65c5\u7a0b":1,"\u4ec0\u4e48\u662f":0,"\u4ec5\u5728\u8fdc\u7a0b\u7a00\u758f\u8bad\u7ec3\u65f6\u6709\u6548":6,"\u4ec5\u5bf9\u7a00\u758f\u6570\u636e\u6709\u6548":6,"\u4ec5\u652f\u6301\u6574\u578b\u503c":19,"\u4ec5\u7528\u4e8e\u5b58\u50a8\u6574\u578b\u503c":20,"\u4ecb\u7ecd\u4e86\u4e00\u79cd\u901a\u8fc7ssh\u8fdc\u7a0b\u5206\u53d1\u4efb\u52a1":27,"\u4ecb\u7ecd\u4f7f\u7528paddlepaddl":21,"\u4ece":[9,37],"\u4ece0\u5230num":33,"\u4ece0\u5f00\u59cb\u7684\u6574\u6570":21,"\u4ece\u4e00\u4e2aword\u751f\u6210\u4e0b\u4e00\u4e2aword":41,"\u4ece\u5185\u6838\u51fd\u6570\u7684\u89d2\u5ea6":37,"\u4ece\u6a21\u578b\u6587\u4ef6\u5c06\u9884\u8bad\u7ec3\u53c2\u6570\u8f7d\u5165":13,"\u4ece\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65\u6765\u770b":39,"\u4ece\u6e90\u7801\u4e2d\u6784\u5efa\u7528\u4e8e\u7f16\u8bd1paddlepaddle\u7684docker\u955c\u50cf":0,"\u4ece\u6e90\u7801\u7f16\u8bd1":2,"\u4ece\u78c1\u76d8\u52a0\u8f7d\u9884\u6d4b\u6a21\u578b":20,"\u4ece\u800c\u53ef\u4ee5\u505a\u4e00\u4e9b\u4e0e\u8ba1\u7b97\u91cd\u53e0\u7684\u5de5\u4f5c":6,"\u4ece\u800c\u5f15\u53d1\u5176\u4ed6\u8282\u70b9\u65e0\u6cd5\u8fde\u63a5\u5bfc\u81f4":9,"\u4ece\u8bed\u4e49\u4e0a\u770b":41,"\u4ece\u8d77\u59cb\u7aef\u53e3\u76d1\u542c\u591a\u4e2a\u7aef\u53e3\u7528\u4e8e\u901a\u4fe1":21,"\u4ece\u8f93\u5165\u6570\u636e\u4e0a\u770b":39,"\u4ecestart":33,"\u4ed3\u5e93\u7684\u8fdc\u7a0b\u4e3b\u673a":4,"\u4ed6\u4eec\u5206\u522b\u662f":39,"\u4ed6\u4eec\u5728\u81ea\u5df1\u7684":0,"\u4ed6\u4eec\u5728paddle\u7684\u6587\u6863\u548capi\u4e2d\u662f\u4e00\u4e2a\u6982\u5ff5":39,"\u4ee3\u66ff":27,"\u4ee3\u7801\u4e2d9":39,"\u4ee3\u7801\u53c2\u8003":21,"\u4ee3\u7801\u5982\u4e0b":[11,12,13,42],"\u4ee3\u7801\u6ce8\u91ca\u8bf7\u9075\u5b88":4,"\u4ee3\u7801\u7247\u6bb5\u5982\u4e0b":19,"\u4ee3\u7801\u793a\u4f8b\u5982\u4e0b":20,"\u4ee3\u8868\u5bbf\u4e3b\u673a\u76ee\u5f55":27,"\u4ee5":12,"\u4ee5\u4e0a":4,"\u4ee5\u4e0a\u4e24\u79cd\u65b9\u5f0f\u53ea\u9700\u9009\u62e9\u5176\u4e00\u5373\u53ef":20,"\u4ee5\u4e0b\u4ee3\u7801\u7247\u6bb5\u5b9a\u4e49":42,"\u4ee5\u4e0b\u5c06\u4e00\u4e00\u4ecb\u7ecd":24,"\u4ee5\u4e0b\u6307\u4ee4\u80fd\u68c0\u67e5linux\u7535\u8111\u662f\u5426\u652f\u6301avx":1,"\u4ee5\u4e0b\u6307\u5357\u4ecb\u7ecd\u4e86\u5982\u4f55\u4f7f\u7528openmpi\u6765\u642d\u5efapaddlepaddle\u7684\u96c6\u7fa4\u8bad\u7ec3\u4efb\u52a1":24,"\u4ee5\u4e0b\u6307\u5357\u5c55\u793a\u4e86paddlepaddle\u5bf9kubernetes\u7684\u652f\u6301":24,"\u4ee5\u4e0b\u64cd\u4f5c\u5747\u5728head\u8282\u70b9\u4e2d\u6267\u884c":28,"\u4ee5\u4e0b\u6559\u7a0b\u5c06\u6307\u5bfc\u60a8\u63d0\u4ea4\u4ee3\u7801":4,"\u4ee5\u4ea4\u4e92\u5f0f\u7684\u65b9\u5f0f\u6267\u884c\u6216\u8c03\u8bd5\u60a8\u7684\u4ee3\u7801":1,"\u4ee5\u4f7f\u7528adam\u7b97\u6cd5\u4e3a\u4f8b":13,"\u4ee5\u4fbf\u83b7\u5f97\u8bad\u7ec3\u6570\u636e\u7684\u4f4d\u7f6e\u548c\u83b7\u53d6\u73af\u5883\u53d8\u91cf\u914d\u7f6e":21,"\u4ee5\u4fdd\u8bc1\u68af\u5ea6\u7684\u6b63\u786e\u8ba1\u7b97":6,"\u4ee5\u4fdd\u8bc1\u68af\u5ea6\u8ba1\u7b97\u7684\u6b63\u786e\u6027":6,"\u4ee5\u4fdd\u8bc1\u7f16\u8bd1\u9ad8\u6548":0,"\u4ee5\u51cf\u5c0fsdk\u7684\u4f53\u79ef":18,"\u4ee5\u53ca":[6,19],"\u4ee5\u53ca\u4f7f\u7528\u5b50\u5e8f\u5217\u6765\u5b9a\u4e49\u5206\u7ea7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u67b6\u6784":42,"\u4ee5\u53ca\u5207\u6362\u673a\u5668\u65f6\u9700\u8981\u65b0\u5b89\u88c5\u7684\u8f9b\u82e6":0,"\u4ee5\u53ca\u53cc\u5c42\u5e8f\u5217":38,"\u4ee5\u53ca\u5982\u4f55\u89e3\u6790\u795e\u7ecf\u7f51\u7edc\u524d\u5411\u8ba1\u7b97\u7684\u8f93\u51fa\u7ed3\u679c":19,"\u4ee5\u53ca\u7b2c\u4e09\u65b9\u4f9d\u8d56\u94fe\u63a5\u5e93\u548c\u5934\u6587\u4ef6":17,"\u4ee5\u53ca\u8ba1\u7b97\u903b\u8f91\u5728\u5e8f\u5217\u4e0a\u7684\u5faa\u73af\u5c55\u5f00":41,"\u4ee5\u53ca\u8f93\u5165\u7684\u68af\u5ea6":6,"\u4ee5\u53carelu":6,"\u4ee5\u5b9e\u73b0\u5bf9\u6a21\u578b\u8bad\u7ec3\u6216\u9884\u6d4b\u6d41\u7a0b\u7684\u63a7\u5236":34,"\u4ee5\u8f93\u51fa":11,"\u4ee5\u9017\u53f7\u95f4\u9694":33,"\u4ee5\u907f\u514d\u94fe\u63a5\u4e0d\u5fc5\u8981\u7684\u5e93":17,"\u4ee5embedding\u5c42\u4e3a\u4f8b":13,"\u4ee5lstm\u4e3a\u4f8b":12,"\u4ef7\u683c":39,"\u4efb\u4f55\u65f6\u5019\u5982\u679c\u9700\u8981\u6d6e\u70b9\u578b\u6570\u7ec4":19,"\u4efb\u52a1\u6765\u7ec8\u6b62\u96c6\u7fa4\u4f5c\u4e1a":23,"\u4efb\u610f\u5c06\u4e00\u4e9b\u6570\u636e\u7ec4\u5408\u6210\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217":39,"\u4f18\u5316\u5668\u5219\u7528\u94fe\u5f0f\u6cd5\u5219\u6765\u5bf9\u6bcf\u4e2a\u53c2\u6570\u8ba1\u7b97\u635f\u5931\u51fd\u6570\u7684\u68af\u5ea6":6,"\u4f1a\u4f7f\u7528":20,"\u4f1a\u5148\u8fdb\u884c\u53c2\u6570\u7684\u521d\u59cb\u5316\u4e0e\u89e3\u6790":27,"\u4f1a\u5171\u4eab\u53c2\u6570":13,"\u4f1a\u5173\u8054\u53c2\u6570":12,"\u4f1a\u52a0\u8f7d\u4e0a\u4e00\u8f6e\u7684\u53c2\u6570":33,"\u4f1a\u53d8\u6210\u8bcd\u8868\u4e2d\u7684\u4f4d\u7f6e":39,"\u4f1a\u542f\u52a8pserver\u4e0etrainer\u8fdb\u7a0b":27,"\u4f1a\u5728":7,"\u4f1a\u5728\u5f53\u524d\u76ee\u5f55\u751f\u6210\u4e24\u4e2a\u5b50\u76ee\u5f55":7,"\u4f1a\u5927\u4e0d\u76f8\u540c":21,"\u4f1a\u5bf9\u6bcf\u4e00\u4e2a\u6fc0\u6d3b\u6682\u5b58\u4e00\u4e9b\u6570\u636e":11,"\u4f1a\u5bf9\u8bad\u7ec3\u6027\u80fd\u9020\u6210\u5f71\u54cd":11,"\u4f1a\u5bf9\u8fd9\u7c7b\u8f93\u5165\u8fdb\u884c\u62c6\u89e3":41,"\u4f1a\u5c06\u6bcf\u4e2a\u65f6\u95f4\u6b65\u7684\u8f93\u51fa\u62fc\u63a5":41,"\u4f1a\u5c06\u7b2c\u4e00\u4e2a":11,"\u4f1a\u6210\u4e3astep\u51fd\u6570\u7684\u8f93\u5165":41,"\u4f1a\u6267\u884c":0,"\u4f1a\u628a\u8bad\u7ec3\u96c6\u548c\u6d4b\u8bd5\u96c6\u5206\u522b\u5206\u5272\u6210\u591a\u4e2a\u6587\u4ef6":21,"\u4f1a\u62a5\u5982\u4e0b\u7684\u9519\u8bef":11,"\u4f1a\u62a5\u9519":41,"\u4f1a\u72ec\u7acb\u62e5\u6709\u4e00\u4efd\u8bad\u7ec3\u597d\u7684\u6a21\u578b":20,"\u4f1a\u76f8\u5e94\u5730\u6539\u53d8\u8f93\u51fa\u7684\u5c3a\u5bf8":6,"\u4f1a\u81ea\u52a8\u5173\u95ed\u5bf9\u5e94\u7684issu":4,"\u4f1a\u81ea\u52a8\u5728\u7f16\u8bd1\u65f6\u4e0b\u8f7d":0,"\u4f1a\u83b7\u53d6\u5f53\u524dnamespace\u4e0b\u7684\u6240\u6709pod":27,"\u4f1a\u88ab":21,"\u4f1a\u88ab\u62c6\u89e3\u4e3a\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":41,"\u4f1a\u88ab\u62c6\u89e3\u4e3a\u975e\u5e8f\u5217":41,"\u4f1a\u901a\u8fc7\u5224\u6570\u636e\u662f\u5426\u9644\u5e26\u6709\u5e8f\u5217\u4fe1\u606f\u6765\u5224\u65ad\u4e00\u4e2a\u5411\u91cf":19,"\u4f1a\u9020\u6210\u90ae\u4ef6\u707e\u96be":4,"\u4f20\u7ed9dataprovider\u7684\u67d0\u4e00\u4e2aargs\u8fc7\u5927":13,"\u4f20\u9012\u7ed9\u914d\u7f6e\u6587\u4ef6\u7684\u53c2\u6570":33,"\u4f46\u4e0d\u7528\u4e8e\u8ba1\u7b97\u68af\u5ea6":6,"\u4f46\u4e0d\u9700\u8981\u63d0\u524d\u521b\u5efa":33,"\u4f46\u4e8e\u53cc\u5c42\u5e8f\u5217\u7684lstm\u6765\u8bf4":39,"\u4f46\u53ef\u4ee5\u83b7\u53d6":11,"\u4f46\u548c\u5355\u5c42rnn\u4e0d\u540c":39,"\u4f46\u5b50\u53e5\u542b\u6709\u7684\u8bcd\u8bed\u6570\u53ef\u4ee5\u4e0d\u76f8\u7b49":41,"\u4f46\u5c3d\u91cf\u8bf7\u4fdd\u6301\u7f16\u8bd1\u548c\u8fd0\u884c\u4f7f\u7528\u7684cudnn\u662f\u540c\u4e00\u4e2a\u7248\u672c":0,"\u4f46\u5e8f\u5217\u8f93\u51fa\u65f6":39,"\u4f46\u622a\u65ad\u65f6\u673a\u4e0d\u540c":11,"\u4f46\u662f":[11,39],"\u4f46\u662f\u5927\u90e8\u5206\u53c2\u6570\u662f\u4e3a\u5f00\u53d1\u8005\u63d0\u4f9b\u7684":32,"\u4f46\u662f\u5b50\u5e8f\u5217\u7684\u6570\u76ee\u5fc5\u987b\u4e00\u6837":39,"\u4f46\u662f\u5e76\u4e0d\u80fd\u4fdd\u8bc1\u53c2\u6570\u540c\u6b65\u66f4\u65b0":22,"\u4f46\u662f\u652f\u6301avx\u6307\u4ee4\u96c6":4,"\u4f46\u662f\u6bcf\u4e2a\u6837\u672c\u4ec5\u5305\u542b\u51e0\u4e2a\u8bcd":35,"\u4f46\u662f\u7a81\u7136\u6709\u4e00\u4e2a10000\u957f\u7684\u5e8f\u5217":11,"\u4f46\u662f\u865a\u62df\u7684\u4e0d\u4ec5\u4ec5\u662f":0,"\u4f46\u662fbatch":11,"\u4f46\u6709\u503c\u7684\u5730\u65b9\u5fc5\u987b\u4e3a1":14,"\u4f46\u6709\u503c\u7684\u90e8\u5206\u53ef\u4ee5\u662f\u4efb\u4f55\u6d6e\u70b9\u6570":14,"\u4f46\u7531\u4e8ecuda\u5e93\u901a\u5e38\u9700\u8981cento":3,"\u4f4d\u7f6e":39,"\u4f4f":39,"\u4f5c\u4e3a\u4e0b\u4e00\u4e2a\u5b50\u53e5memory\u7684\u521d\u59cb\u72b6\u6001":39,"\u4f5c\u4e3a\u4f8b\u5b50\u6f14\u793a\u5982\u4f55\u914d\u7f6e\u590d\u6742\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u6a21\u578b":42,"\u4f5c\u4e3a\u53c2\u6570\u7684id":13,"\u4f5c\u4e3a\u5f53\u524d\u65f6\u523b\u8f93\u5165":41,"\u4f5c\u4e3a\u7edf\u8ba1\u7684\u57fa\u672c\u5355\u4f4d":19,"\u4f5c\u4e3a\u8c03\u7528":20,"\u4f5c\u4e3a\u8f93\u5165":19,"\u4f5c\u4e3a\u8f93\u51fa":42,"\u4f5c\u4e3aboot_layer\u4f20\u7ed9\u4e0b\u4e00\u4e2a\u5b50\u53e5\u7684memori":39,"\u4f5c\u7528":38,"\u4f60\u53ef\u4ee5\u5c06\u7f51\u7edc\u914d\u7f6e\u6210\u67d0\u4e9b\u5c42\u4f7f\u7528gpu\u8ba1\u7b97":35,"\u4f60\u8fd8\u53ef\u4ee5\u901a\u8fc7\u8fd0\u884cdjango\u6846\u67b6\u76f4\u63a5\u6fc0\u6d3b\u5de5\u5177\u7684\u670d\u52a1\u5668":7,"\u4f60\u9700\u8981\u4e00\u4e9b\u66f4\u590d\u6742\u7684\u5355\u5143\u6d4b\u8bd5\u6765\u4fdd\u8bc1\u4f60\u5b9e\u73b0\u7684\u7f51\u7edc\u5c42\u662f\u6b63\u786e\u7684":6,"\u4f60\u9700\u8981\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d\u6307\u5b9a\u8bbe\u5907\u7684id\u53f7":35,"\u4f60\u9700\u8981\u5728\u914d\u7f6ecmake\u65f6\u5c06":6,"\u4f60\u9700\u8981\u628a\u8be5\u6587\u4ef6\u52a0\u5165":6,"\u4f7f\u4e4b\u53d8\u4e3a\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217\u8f93\u5165":19,"\u4f7f\u4e4b\u53d8\u4e3a\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217\u8f93\u5165":19,"\u4f7f\u5f97\u5355\u5143\u6d4b\u8bd5\u6709\u4e00\u4e2a\u5e72\u51c0\u7684\u73af\u5883":8,"\u4f7f\u5f97\u642d\u6a21\u578b\u65f6\u66f4\u65b9\u4fbf":6,"\u4f7f\u68af\u5ea6\u7684\u63d0\u4ea4\u548c\u53c2\u6570\u7684\u66f4\u65b0\u6309\u7167\u987a\u5e8f\u65b9\u5f0f\u6267\u884c":22,"\u4f7f\u7528":[6,11,12,13,17,19,20,33,37,39,41,42],"\u4f7f\u75280\u53f7\u548c1\u53f7gpu\u8ba1\u7b97fc2\u5c42":35,"\u4f7f\u75280\u53f7gpu\u8ba1\u7b97fc2\u5c42":35,"\u4f7f\u75281\u53f7gpu\u8ba1\u7b97fc3\u5c42":35,"\u4f7f\u75282\u53f7\u548c3\u53f7gpu\u8ba1\u7b97fc3\u5c42":35,"\u4f7f\u7528\u4e00\u4e2a\u5c3a\u5ea6\u4e3a":6,"\u4f7f\u7528\u4e00\u4e2a\u8bcd\u524d\u4e24\u4e2a\u8bcd\u548c\u540e\u4e24\u4e2a\u8bcd":11,"\u4f7f\u7528\u4e0a\u6587\u521b\u5efa\u7684yaml\u6587\u4ef6\u521b\u5efakubernet":26,"\u4f7f\u7528\u4e0b\u9762\u7684\u547d\u4ee4\u6765\u8fd0\u884c\u5b83":7,"\u4f7f\u7528\u4e86\u540c\u6837\u7684parameter\u548cbia":13,"\u4f7f\u7528\u4ee5\u4e0a\u8bad\u7ec3\u597d\u7684\u6a21\u578b\u8fdb\u884c\u9884\u6d4b":14,"\u4f7f\u7528\u53c2\u6570":[0,21],"\u4f7f\u7528\u591a\u5757\u663e\u5361\u8bad\u7ec3":11,"\u4f7f\u7528\u591a\u7ebf\u7a0b\u8bad\u7ec3":11,"\u4f7f\u7528\u5b66\u4e60\u5b8c\u6210\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u6a21\u578b\u751f\u6210\u5e8f\u5217":42,"\u4f7f\u7528\u5bb9\u5668\u65b9\u5f0f\u8fd0\u884c\u8bad\u7ec3\u4efb\u52a1\u7684kubernet":27,"\u4f7f\u7528\u6211\u4eec\u4e4b\u524d\u6784\u9020\u7684\u955c\u50cf":26,"\u4f7f\u7528\u663e\u5361\u8bad\u7ec3":11,"\u4f7f\u7528\u6848\u4f8b":34,"\u4f7f\u7528\u73af\u5883\u53d8\u91cf":21,"\u4f7f\u7528\u8005\u4e0d\u9700\u8981\u5173\u5fc3":33,"\u4f7f\u7528\u8005\u53ea\u9700\u8981\u5173\u6ce8\u4e8e\u8bbe\u8ba1rnn\u5728\u4e00\u4e2a\u65f6\u95f4\u6b65\u4e4b\u5185\u5b8c\u6210\u7684\u8ba1\u7b97":41,"\u4f7f\u7528\u8005\u65e0\u9700\u5173\u5fc3\u8fd9\u4e2a\u53c2\u6570":33,"\u4f7f\u7528\u8005\u901a\u5e38\u65e0\u9700\u5173\u5fc3":33,"\u4f7f\u7528\u8be5learning_rate_schedule\u65f6":13,"\u4f7f\u7528\u8fd9\u79cd\u65b9\u5f0f":[20,39],"\u4f7f\u7528\u8fdc\u7a0b\u7a00\u758f\u65b9\u5f0f\u8bad\u7ec3\u65f6":6,"\u4f7f\u7528c":17,"\u4f7f\u7528checkgrad\u6a21\u5f0f\u65f6\u7684\u53c2\u6570\u53d8\u5316\u5927\u5c0f":33,"\u4f7f\u7528cpu\u4e24\u7ebf\u7a0b\u8ba1\u7b97fc4\u5c42":35,"\u4f7f\u7528cpu\u8ba1\u7b97fc4\u5c42":35,"\u4f7f\u7528docker":1,"\u4f7f\u7528docker\u5b89\u88c5\u548c\u8fd0\u884cpaddlepaddle\u53ef\u4ee5\u65e0\u9700\u8003\u8651":1,"\u4f7f\u7528docker\u5b89\u88c5\u8fd0\u884c":2,"\u4f7f\u7528docker\u5c31\u4e0d\u7528\u914d\u7f6e\u4ea4\u53c9\u7f16\u8bd1\u73af\u5883\u4e86":0,"\u4f7f\u7528docker\u6784\u5efapaddlepaddle\u7684\u6587\u6863":7,"\u4f7f\u7528fabric\u542f\u52a8\u96c6\u7fa4\u8bad\u7ec3":24,"\u4f7f\u7528init":35,"\u4f7f\u7528lstm\u4f5c\u4e3aencod":39,"\u4f7f\u7528memory\u7684rnn\u5b9e\u73b0\u4fbf\u5982\u4e0b\u56fe\u6240\u793a":39,"\u4f7f\u7528model":35,"\u4f7f\u7528openblas\u7684\u955c\u50cf":1,"\u4f7f\u7528paddlepaddl":[17,20],"\u4f7f\u7528pip\u5b89\u88c5":2,"\u4f7f\u7528rdma\u8fd8\u662ftcp\u4f20\u8f93\u534f\u8bae":33,"\u4f7f\u8be5\u5c42\u7684\u53c2\u6570\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u4fdd\u6301\u4e0d\u53d8":13,"\u4f86":39,"\u4f8b\u5982":[0,6,11,12,14,19,21,27,32,33,35,37,39,42],"\u4f8b\u5982\u4e0b\u9762\u4ee3\u7801":11,"\u4f8b\u5982\u4e5f\u53ef\u5728\u7a0b\u5e8f\u8fd0\u884c\u8fc7\u7a0b\u4e2d\u518d\u52a0\u8f7d\u53e6\u5916\u4e00\u4e2a\u6a21\u578b":20,"\u4f8b\u5982\u4f7f\u7528":11,"\u4f8b\u5982\u542b\u6709\u591a\u4e2a\u901a\u9053\u7684\u56fe\u7247":19,"\u4f8b\u5982\u5c06\u7b2c\u4e00\u6761\u6570\u636e\u8f6c\u5316\u4e3a":39,"\u4f8b\u5982\u6587\u672c\u5206\u7c7b\u4e2d":39,"\u4f8b\u5982\u672c\u4f8b\u4e2d\u7684\u4e24\u4e2a\u7279\u5f81":39,"\u4f8b\u5982\u673a\u5668\u4e0a\u67094\u5757gpu":11,"\u4f8b\u5982output\u76ee\u5f55\u4e0b\u5c31\u5b58\u653e\u4e86\u8f93\u51fa\u7ed3\u679c":27,"\u4f8b\u5982sigmoid":6,"\u4f8b\u5b50\u4e2d\u4e3a3\u4e2a":21,"\u4f8b\u5b50\u4e2d\u662f":6,"\u4f8b\u5b50\u4e2d\u662f0":6,"\u4f8b\u5b50\u4e2d\u662f100":6,"\u4f8b\u5b50\u4e2d\u662f4096":6,"\u4f8b\u5b50\u4e2d\u662f8192":6,"\u4f8b\u5b50\u4e2d\u662ffc":6,"\u4f8b\u5b50\u4e2d\u662fsoftmax":6,"\u4f9bpaddlepaddle\u52a0\u8f7d":33,"\u4f9d\u8d56":[0,3],"\u4f9d\u8d56\u73af\u5883\u5373\u53ef\u8fd0\u884c":1,"\u4f9d\u8d56libpython2":0,"\u4fbf\u5229":39,"\u4fbf\u548c\u5355\u5c42rnn\u914d\u7f6e\u4e2d\u7684":39,"\u4fbf\u5b9c":39,"\u4fdd\u5b58\u6a21\u578b\u53c2\u6570\u7684\u76ee\u5f55":33,"\u4fdd\u5b58\u7684\u53c2\u6570\u4e5f\u662ffloat\u7c7b\u578b":13,"\u4fdd\u5b58\u7f51\u7edc\u5c42\u8f93\u51fa\u7ed3\u679c\u7684\u76ee\u5f55":33,"\u4fdd\u5b58\u9884\u6d4b\u7ed3\u679c\u7684\u6587\u4ef6\u540d":33,"\u4fdd\u6301\u5c3d\u91cf\u5c11\u7684commit":4,"\u4fdd\u8bc1\u4f7f\u7528gpu\u8bad\u7ec3\u65f6\u4e5f\u53ef\u4ee5\u83b7\u5f97":11,"\u4fe1\u53f7\u6765\u81ea\u52a8\u7ec8\u6b62\u5b83\u542f\u52a8\u7684\u6240\u6709\u8fdb\u7a0b":23,"\u4fe1\u606f":19,"\u4fee\u6539":26,"\u4fee\u6539\u542f\u52a8\u811a\u672c\u540e":26,"\u4fee\u6539\u6210\u66f4\u5feb\u7684\u7248\u672c":37,"\u503c\u5f97\u6ce8\u610f\u7684\u662f":[4,39],"\u503c\u5f97\u6df1\u5165\u5206\u6790":37,"\u503c\u7c7b\u578b":35,"\u5047\u5982\u6211\u4eec\u662f\u4e09\u5206\u7c7b\u95ee\u9898":13,"\u5047\u8bbe":6,"\u5047\u8bbe\u60a8\u5df2\u7ecf\u5728\u5f53\u524d\u76ee\u5f55":1,"\u5047\u8bbe\u635f\u5931\u51fd\u6570\u662f":6,"\u5047\u8bbe\u7b2c\u4e00\u4e2alayer\u7684\u8f93\u51faa\u662f\u4e00\u4e2a":11,"\u504f\u7f6e\u53c2\u6570\u7684\u5927\u5c0f":6,"\u505c\u6b62\u52a0\u8f7d\u6570\u636e":33,"\u505c\u7535":39,"\u5143\u7d20":38,"\u5143\u7d20\u4e4b\u95f4\u7684\u987a\u5e8f\u662f\u5e8f\u5217\u6240\u643a\u5e26\u7684\u91cd\u8981\u4fe1\u606f":19,"\u5143\u7d20\u4e4b\u95f4\u7684\u987a\u5e8f\u662f\u91cd\u8981\u7684\u8f93\u5165\u4fe1\u606f":38,"\u5148\u5378\u8f7d\u4e4b\u524d\u7684\u7248\u672c":0,"\u5148\u627e\u51fa\u53c2\u6570":12,"\u5148\u67e5\u770b\u4e00\u4e0b\u662f\u5426\u66fe\u7ecf\u5b89\u88c5\u8fc7paddl":8,"\u5168\u5bb6":39,"\u5168\u8fde\u63a5\u5c42\u4ee5\u4e00\u4e2a\u7ef4\u5ea6\u4e3a":6,"\u5168\u8fde\u63a5\u5c42\u6ca1\u6709\u7f51\u7edc\u5c42\u914d\u7f6e\u7684\u8d85\u53c2\u6570":6,"\u5168\u8fde\u63a5\u5c42\u7684\u5b9e\u73b0\u4f4d\u4e8e":6,"\u5168\u8fde\u63a5\u5c42\u7684\u6bcf\u4e2a\u8f93\u51fa\u90fd\u8fde\u63a5\u5230\u4e0a\u4e00\u5c42\u7684\u6240\u6709\u7684\u795e\u7ecf\u5143\u4e0a":6,"\u5168\u8fde\u63a5\u5c42python\u5c01\u88c5\u7684\u4f8b\u5b50\u4e2d\u5305\u542b\u4e0b\u9762\u51e0\u6b65":6,"\u516c\u5f0f":1,"\u5171\u4eab\u5b58\u50a8\u6302\u5728\u7684\u8def\u5f84":27,"\u5173\u4e8e\u4ec0\u4e48\u662f":19,"\u5173\u4e8e\u65f6\u95f4\u5e8f\u5217":39,"\u5173\u4e8e\u6784\u5efa\u548c\u6d4b\u8bd5\u7684\u66f4\u591a\u4fe1\u606f":4,"\u5173\u4e8eavx":1,"\u5173\u4e8ec":18,"\u5173\u4e8elstm":12,"\u5173\u4e8epaddlepaddle\u7684\u5206\u5e03\u5f0f\u8bad\u7ec3":27,"\u5173\u4e8epaddlepaddle\u7684\u66f4\u591a\u4f7f\u7528\u65b9\u6cd5\u8bf7\u53c2\u8003":14,"\u5173\u4e8eunbound":41,"\u5173\u952e\u8bcd\u5305\u62ec":4,"\u5176\u4e2d":[6,11,13,14,42],"\u5176\u4e2d\u5305\u542b\u4e86\u7528\u6237\u7684\u8bad\u7ec3\u7a0b\u5e8f":21,"\u5176\u4e2d\u6bcf\u4e2a\u5143\u7d20\u662f\u53cc\u5c42\u5e8f\u5217\u4e2d\u6bcf\u4e2asubseq\u6700\u540e\u4e00\u4e2a":38,"\u5176\u4e2dcheckgrad\u4e3b\u8981\u4e3a\u5f00\u53d1\u8005\u4f7f\u7528":33,"\u5176\u4e2dmean\u548cstd\u662f\u8bad\u7ec3\u914d\u7f6e\u4e2d\u7684\u53c2\u6570":33,"\u5176\u4e2dx\u8868\u793a\u8f93\u5165\u6570\u636e\u662f\u4e00\u4e2a\u7ef4\u5ea6\u4e3a2\u7684\u7a20\u5bc6\u5411\u91cf":14,"\u5176\u4ed6\u4eba\u53ef\u4ee5\u590d\u73b0\u95ee\u9898\u4ee5\u4fbf\u5e2e\u52a9":0,"\u5176\u4ed6\u5185\u5b58\u6742\u9879":11,"\u5176\u4ed6\u5185\u5b58\u6742\u9879\u662f\u6307paddlepaddle\u672c\u8eab\u6240\u7528\u7684\u4e00\u4e9b\u5185\u5b58":11,"\u5176\u4ed6\u6240\u6709\u5c42\u90fd\u4f1a\u4f7f\u7528gpu\u8ba1\u7b97":35,"\u5176\u4ed6\u7684\u4f9d\u8d56\u8f6f\u4ef6":0,"\u5176\u4ed6\u9ad8\u7ea7\u529f\u80fd\u5305\u62ec\u5b9a\u4e49\u591a\u4e2amemori":42,"\u5176\u4f1a\u81ea\u52a8\u88ab\u52a0\u5165\u7f16\u8bd1\u5217\u8868":6,"\u5176\u5b83\u53ef\u9009\u7f16\u8bd1\u9009\u9879\u6309\u9700\u8fdb\u884c\u8bbe\u5b9a":17,"\u5176\u5b83layer\u7684\u8f93\u51fa":41,"\u5176\u5b9e\u4e5f\u662f\u548c\u6bcf\u4e2amini":11,"\u5176\u6b21":39,"\u5176\u8bf4\u660e\u5982\u4e0b":39,"\u5176\u8f93\u51fa\u88ab\u7528\u4f5cmemory\u7684\u521d\u59cb\u503c":42,"\u5176name\u7531\u53c2\u6570":12,"\u5177\u4f53\u4f7f\u7528\u65b9\u6cd5\u4e3a":11,"\u5177\u4f53\u505a\u6cd5\u8bf7\u53c2\u8003":0,"\u5177\u4f53\u53ef\u4ee5\u53c2\u8003":[6,11],"\u5177\u4f53\u53ef\u53c2\u8003\u6587\u6863":41,"\u5177\u4f53\u60c5\u51b5\u56e0\u4eba\u800c\u5f02":37,"\u5177\u4f53\u64cd\u4f5c\u5982\u4e0b":8,"\u5177\u4f53\u6b65\u9aa4\u5982\u4e0b":8,"\u5177\u4f53\u7684\u89e3\u51b3\u65b9\u6cd5\u662f":8,"\u5177\u4f53\u8bf7\u53c2\u8003":4,"\u5177\u4f53\u8bf7\u89c1":4,"\u5177\u6709\u76f8\u540c\u7684\u7ed3\u679c\u4e86":39,"\u5185":42,"\u5185\u5b58":37,"\u5185\u5b58\u4e0d\u8db3":9,"\u5185\u5b58\u5bb9\u9650\u9608\u503c":33,"\u5185\u5bb9\u5982\u4e0b":26,"\u5185\u5c42\u5e8f\u5217\u5728":19,"\u5185\u5c42inner_step\u7684recurrent_group\u548c\u5355\u5c42\u5e8f\u5217\u7684\u51e0\u4e4e\u4e00\u6837":39,"\u5185\u5df2\u7ecf\u5305\u542bpaddlepaddle\u7684\u6267\u884c\u7a0b\u5e8f\u4f46\u662f\u8fd8\u6ca1\u4e0a\u8ff0\u529f\u80fd":27,"\u5185\u7f6e\u7684":20,"\u5185\u90e8":[20,27],"\u5185\u90e8\u7531":[19,20],"\u518d\u505a\u4e00\u5b9a\u7684reshap":12,"\u518d\u5199\u5165\u7f51\u7edc\u53c2\u6570":13,"\u518d\u5b89\u88c5":[3,8],"\u518d\u5bf9\u6bcf\u4e00\u4e2a\u5355\u5c42\u65f6\u95f4\u5e8f\u5217\u8fdb\u884c\u5904\u7406":39,"\u518d\u5bf9\u6bcf\u4e00\u53e5\u8bdd\u7684\u7f16\u7801\u5411\u91cf\u7528lstm\u7f16\u7801\u6210\u4e00\u4e2a\u6bb5\u843d\u7684\u5411\u91cf":39,"\u518d\u5bf9\u8fd9\u4e2a\u6bb5\u843d\u5411\u91cf\u8fdb\u884c\u5206\u7c7b":39,"\u518d\u5c06\u66f4\u65b0\u540e\u7684\u53c2\u6570\u4e0b\u53d1\u5230\u6bcf\u4e2a\u8ba1\u7b97\u8282\u70b9":22,"\u518d\u6307\u5b9a":0,"\u518d\u6b21\u5bf9\u4ee3\u7801\u8fdb\u884c\u6027\u80fd\u5206\u6790":37,"\u518d\u7528\u8fd9\u4e2a\u68af\u5ea6\u53bb\u548c":6,"\u518d\u901a\u8fc7\u51fd\u6570":27,"\u518d\u91cd\u65b0\u5b89\u88c5":0,"\u5199\u5165\u6587\u4ef6\u4e2d":20,"\u5199\u68af\u5ea6\u68c0\u67e5\u5355\u5143\u6d4b\u8bd5\u662f\u4e00\u4e2a\u9a8c\u8bc1\u65b0\u5b9e\u73b0\u7684\u5c42\u662f\u5426\u6b63\u786e\u7684\u76f8\u5bf9\u7b80\u5355\u7684\u529e\u6cd5":6,"\u51c6\u5907":39,"\u51c6\u5907\u60a8\u7684\u8ba1\u7b97\u96c6\u7fa4":31,"\u51c6\u5907\u8bad\u7ec3\u6570\u636e":28,"\u51c6\u5907\u8bad\u7ec3\u6570\u636e\u548c\u9a8c\u8bc1\u6570\u636e\u96c6":21,"\u51c6\u5907\u9884\u6d4b\u6a21\u578b\u548c":20,"\u51c6\u5907\u9884\u6d4b\u6a21\u578b\u90e8\u5206":20,"\u51cf\u5c0f\u5e8f\u5217\u7684\u957f\u5ea6":11,"\u51cf\u5c0f\u8fd9\u4e2a\u5185\u5b58\u6c60\u5373\u53ef\u51cf\u5c0f\u5185\u5b58\u5360\u7528":11,"\u51cf\u5c0fbatch":11,"\u51e0\u53f0\u5230\u51e0\u5343\u53f0\u89c4\u6a21":31,"\u51fa\u53bb\u73a9":39,"\u51fa\u5dee":39,"\u51fa\u6765":39,"\u51fa\u73b0":8,"\u51fa\u73b0\u4ee5\u4e0b\u9519\u8bef":13,"\u51fa\u73b0\u8be5\u9519\u8bef\u7684\u539f\u56e0\u4e00\u822c\u662f\u7528\u6237\u5bf9\u4e0d\u540clayer\u7684\u53c2\u6570":12,"\u51fa\u73b0\u8fd9\u4e2a\u95ee\u9898\u7684\u4e3b\u8981\u539f\u56e0\u662f":[3,8],"\u51fd\u6570":[6,19,37,42],"\u51fd\u6570\u5047\u8bbe":42,"\u51fd\u6570\u52a0\u5230\u4ee3\u7801\u4e2d":37,"\u51fd\u6570\u53ea\u5173\u6ce8\u4e8ernn\u4e00\u4e2a\u65f6\u95f4\u6b65\u4e4b\u5185\u7684\u8ba1\u7b97":41,"\u51fd\u6570\u5f97\u5230\u7684\u68af\u5ea6\u53bb\u5bf9\u6bd4":6,"\u51fd\u6570\u5fc5\u987b\u5148\u8c03\u7528\u57fa\u7c7b\u4e2d\u7684\u51fd\u6570":6,"\u51fd\u6570\u5fc5\u987b\u8fd4\u56de\u4e00\u4e2a\u6216\u591a\u4e2alayer\u7684\u8f93\u51fa":41,"\u51fd\u6570\u6307\u51fa\u4e86\u5728\u8bad\u7ec3\u65f6\u9700\u8981\u4ece\u53c2\u6570\u670d\u52a1\u5668\u53d6\u51fa\u7684\u884c":6,"\u51fd\u6570\u6765\u5c06\u4fe1\u606f\u8f93\u51fa\u5230\u754c\u9762\u4e2d":37,"\u51fd\u6570\u7684\u5b9e\u73b0\u662f\u6b63\u786e\u7684":6,"\u51fd\u6570\u7684\u5f00\u5934\u5fc5\u987b\u8c03\u7528":6,"\u51fd\u6570\u80fd\u591f\u5c06\u4f7f\u7528":20,"\u5206\u4e3a":20,"\u5206\u522b\u4e3a\u6570\u636e\u8f93\u5165\u6dfb\u52a0\u5916\u5c42\u5e8f\u5217\u548c\u5185\u5c42\u5e8f\u5217\u7684\u5e8f\u5217\u4fe1\u606f":19,"\u5206\u522b\u4ece\u8bcd\u8bed\u548c\u53e5\u5b50\u7ea7\u522b\u7f16\u7801\u8f93\u5165\u6570\u636e":41,"\u5206\u522b\u4f7f\u7528\u5355\u53cc\u5c42rnn\u4f5c\u4e3a\u7f51\u7edc\u914d\u7f6e\u7684\u6a21\u578b":39,"\u5206\u522b\u5b9a\u4e49\u5b50\u53e5\u7ea7\u522b\u548c\u8bcd\u8bed\u7ea7\u522b\u4e0a\u9700\u8981\u5b8c\u6210\u7684\u8fd0\u7b97":41,"\u5206\u522b\u662f":38,"\u5206\u522b\u662frnn\u72b6\u6001\u548c\u8f93\u5165\u7684\u53d8\u6362\u77e9\u9635":42,"\u5206\u522b\u662fsentences\u548clabel":39,"\u5206\u522b\u662fwords\u548clabel":39,"\u5206\u522b\u8ba1\u7b97\u6bcf\u4e2a\u53c2\u6570\u7684\u68af\u5ea6":6,"\u5206\u522b\u8fdb\u884c\u5e8f\u5217\u64cd\u4f5c":39,"\u5206\u5e03\u5f0f\u8bad\u7ec3":36,"\u5206\u5e03\u5f0f\u8bad\u7ec3\u67b6\u6784\u5982\u4e0b\u56fe\u6240\u793a":22,"\u5206\u652f":4,"\u5206\u652f\u4e0a":4,"\u5206\u652f\u4e0a\u521b\u5efa\u65b0\u5206\u652f":4,"\u5206\u652f\u540d":4,"\u5206\u652f\u89c4\u8303":4,"\u5206\u6790\u5f97\u5230\u7684\u4fe1\u606f\u7528\u4e8e\u534f\u52a9\u8fdb\u884c\u7a0b\u5e8f\u7684\u4f18\u5316":37,"\u5206\u7c7b\u4efb\u52a1\u4e2d\u7c7b\u522b\u6807\u7b7e":19,"\u5206\u914d\u5230\u5f53\u524d\u6570\u636e\u5757\u6837\u672c\u6570\u7684\u56db\u5206\u4e4b\u4e00":33,"\u5207\u6362\u5230":4,"\u5207\u6362\u5230\u6240\u5efa\u5206\u652f":4,"\u5217\u5143\u7d20\u6392\u5217\u6210\u7684\u77e9\u5f62\u9635\u5217":19,"\u5217\u8868\u5982\u4e0b":14,"\u5219\u4e0d\u9700\u8981\u91cd\u5199\u8be5\u51fd\u6570":6,"\u5219\u4f1a\u4f7f\u7528openblas\u4f5c\u4e3ablas\u5e93":0,"\u5219\u4f7f\u7528\u540c\u6b65\u8bad\u7ec3":33,"\u5219\u4f7f\u7528\u8be5\u53c2\u6570\u4f5c\u4e3a\u9ed8\u8ba4\u503c":33,"\u5219\u5e76\u4e0d\u4f1a\u7b49\u5f85\u6240\u6709trainer\u63d0\u4ea4\u68af\u5ea6\u624d\u66f4\u65b0\u53c2\u6570":22,"\u5219\u603b\u4f1a\u663e\u793a\u963b\u9694\u6458\u8981\u4fe1\u606f":33,"\u5219\u662f\u5e26gui\u7684nvidia\u53ef\u89c6\u5316\u6027\u80fd\u5206\u6790\u5de5\u5177":37,"\u5219\u663e\u793a\u963b\u9694\u6027\u80fd\u7684\u6458\u8981\u4fe1\u606f":33,"\u5219\u9700\u8981\u4f7f\u7528\u7b49\u4e8e\u6743\u91cd\u53c2\u6570\u89c4\u6a21\u5927\u7ea65\u500d\u7684\u5185\u5b58":11,"\u5219\u9700\u8981\u5728\u672c\u673a\u5b89\u88c5\u4e0b\u9762\u7ae0\u8282\u5217\u51fa\u7684":0,"\u5219\u9700\u8981\u624b\u52a8\u62f7\u8d1d\u5c5e\u4e8e\u6bcf\u4e2atrainer\u8282\u70b9\u7684\u8bad\u7ec3\u6570\u636e\u5230\u5bf9\u5e94\u7684\u8282\u70b9\u4e0a":21,"\u521b\u5efa":[19,20],"\u521b\u5efa\u4e00\u4e2a":16,"\u521b\u5efa\u4e00\u4e2akubernet":27,"\u521b\u5efa\u5e76\u5207\u6362\u5230\u65b0\u5206\u652f":4,"\u521b\u5efa\u6210\u529f\u540e":27,"\u521b\u5efa\u65e5\u5fd7\u76ee\u5f55":28,"\u521b\u5efa\u7a00\u758f\u77e9\u9635\u65f6\u9700\u8981\u663e\u793a\u5730\u6307\u5b9a\u77e9\u9635\u7684":19,"\u521b\u5efaissu":2,"\u521d\u59cb\u5316\u504f\u7f6e\u5411\u91cf":6,"\u521d\u59cb\u5316\u6743\u91cd\u8868":6,"\u521d\u59cb\u5316\u6a21\u578b\u7684\u8def\u5f84":33,"\u521d\u59cb\u5316\u7236\u7c7b":6,"\u521d\u59cb\u5316biases_":6,"\u521d\u59cb\u72b6\u6001":41,"\u5220\u9664":4,"\u5229\u7528\u5206\u5e03\u5f0f\u8bad\u7ec3\u9a7e\u9a6d\u66f4\u591a\u7684\u8ba1\u7b97\u8d44\u6e90":11,"\u5229\u7528\u66f4\u591a\u7684\u8ba1\u7b97\u8d44\u6e90\u53ef\u4ee5\u5206\u4e3a\u4ee5\u4e0b\u51e0\u4e2a\u65b9\u5f0f\u6765\u8fdb\u884c":11,"\u5229\u7528\u8fd9\u79cd\u7279\u6027":41,"\u5229\u843d":39,"\u522b\u4eba\u5e2e\u4e86\u5fd9":4,"\u522b\u5fd8\u4e86":0,"\u5230":[8,42],"\u5230\u6307\u5b9a\u6587\u4ef6\u4e2d":20,"\u5230\u672c\u5730":4,"\u5236\u4f5c\u65b0\u955c\u50cf\u6765\u5b8c\u6210\u4ee5\u4e0a\u7684\u5de5\u4f5c":27,"\u5236\u4f5cpaddlepaddle\u955c\u50cf":27,"\u5237\u7259":39,"\u524d\u4e00\u7bc7\u6587\u7ae0\u4ecb\u7ecd\u4e86\u5982\u4f55\u5728kubernetes\u96c6\u7fa4\u4e0a\u542f\u52a8\u4e00\u4e2a\u5355\u673apaddlepaddle\u8bad\u7ec3\u4f5c\u4e1a":27,"\u524d\u53f0":39,"\u524d\u5411\u4f20\u64ad":6,"\u524d\u5411\u4f20\u64ad\u7ed9\u5b9a\u8f93\u5165":6,"\u524d\u5411\u548c\u540e\u5411":6,"\u524d\u5411\u8ba1\u7b97\u4e4b\u540epaddlepaddle\u5185\u90e8\u5df2\u7ecf\u5206\u914d":20,"\u524d\u8005\u5728":11,"\u524d\u8005\u622a\u65ad\u53ef\u5b66\u4e60\u53c2\u6570\u7684\u68af\u5ea6":11,"\u524d\u81ea\u52a8\u68c0\u67e5\u4e00\u4e9b\u57fa\u672c\u4e8b\u5b9c":4,"\u524d\u9988":22,"\u52a0\u4e0a\u504f\u7f6e\u5411\u91cf":6,"\u52a0\u5165":37,"\u52a0\u6743\u548c\u7528\u6765\u751f\u6210":42,"\u52a0\u6743\u7f16\u7801\u5411\u91cf":42,"\u52a0\u8f7d\u5177\u4f53\u7f51\u7edc\u53c2\u6570":13,"\u52a0\u8f7d\u6a21\u578b\u53ef\u5176\u5b83\u591a\u79cd\u65b9\u5f0f":20,"\u52a0\u8f7d\u6a21\u578b\u9700\u540c\u65f6\u6307\u5b9a":20,"\u52a0\u8f7d\u9884\u6d4b\u6a21\u578b":20,"\u52a0\u8f7d\u9884\u8bad\u7ec3\u53c2\u6570":13,"\u52a0\u8f7dtest":33,"\u52a0\u901f\u7f16\u8bd1":0,"\u52a0\u901fpaddlepaddle\u8bad\u7ec3\u53ef\u4ee5\u8003\u8651\u4ece\u4ee5\u4e0b\u51e0\u4e2a\u65b9\u9762":11,"\u52a8\u6001\u5e93":17,"\u52a9\u624b":6,"\u5305\u542b\u4f46\u4e0d\u9650\u4e8e":0,"\u5305\u542b\u6d4b\u8bd5\u6570\u636e\u96c6\u7684\u76ee\u5f55":21,"\u5305\u542b\u8bad\u7ec3\u6570\u636e\u7684\u76ee\u5f55":21,"\u5305\u62ec":[17,33],"\u5305\u62ec\u4e86\u7f16\u8bd1\u51fa\u7684paddlepaddle\u5934\u6587\u4ef6\u548c\u94fe\u63a5\u5e93":17,"\u5305\u62ec\u5b57\u7b26\u4e32\u5206\u914d":11,"\u5305\u62ec\u751f\u6210cpu":0,"\u5305\u62ec\u795e\u7ecf\u7f51\u7edc\u62d3\u6251\u7ed3\u6784":14,"\u5305\u62ecbool":35,"\u5305\u7684\u65b9\u6cd5\u662f":8,"\u533a\u522b\u662f\u540c\u65f6\u5904\u7406\u4e86\u4e24\u4e2a\u8f93\u5165":39,"\u533a\u522b\u662frnn\u4f7f\u7528\u4e24\u5c42\u5e8f\u5217\u6a21\u578b":39,"\u5341\u4e00":39,"\u534e\u6da6\u4e07\u5bb6":39,"\u5355\u4f4d\u662fmb":33,"\u5355\u5143\u6d4b\u8bd5\u4f1a\u5f15\u7528site":8,"\u5355\u5143\u6d4b\u8bd5checkgrad_ep":32,"\u5355\u53cc\u5c42\u5e8f\u5217\u7684\u53e5\u5b50\u662f\u4e00\u6837\u7684":39,"\u5355\u53cc\u5c42rnn":40,"\u5355\u5c42":41,"\u5355\u5c42\u4e0d\u7b49\u957frnn":39,"\u5355\u5c42\u548c\u53cc\u5c42\u5e8f\u5217\u7684\u4f7f\u7528\u548c\u793a\u4f8b2\u4e2d\u7684\u793a\u4f8b\u7c7b\u4f3c":39,"\u5355\u5c42\u5e8f\u5217":[19,38],"\u5355\u5c42\u5e8f\u5217\u7684\u6bcf\u4e2a\u5143\u7d20":38,"\u5355\u5c42\u5e8f\u5217\u7b2ci\u4e2a\u5143\u7d20":38,"\u5355\u5c42\u6216\u53cc\u5c42":38,"\u5355\u5c42\u65f6\u95f4\u5e8f\u5217":39,"\u5355\u5c42rnn":[39,41],"\u5355\u5c42rnn\u548c\u53cc\u5c42rnn\u7684\u7f51\u7edc\u914d\u7f6e":39,"\u5355\u673acpu\u8bad\u7ec3":11,"\u5355\u673agpu\u8bad\u7ec3":11,"\u5355\u6b65\u51fd\u6570":42,"\u5355\u6b65\u51fd\u6570\u548c\u8f93\u51fa\u51fd\u6570\u5728":42,"\u5355\u6b65\u51fd\u6570\u548c\u8f93\u51fa\u51fd\u6570\u90fd\u975e\u5e38\u7b80\u5355":42,"\u5355\u6b65\u51fd\u6570\u7684\u5b9e\u73b0\u5982\u4e0b\u6240\u793a":42,"\u5355\u8fdb\u5355\u51fa":41,"\u536b\u751f":39,"\u5373":[7,11,12,27],"\u5373\u4e0a\u8ff0\u4ee3\u7801\u4e2d\u7684\u7b2c19\u884c":39,"\u5373\u4e0b\u8f7d\u5931\u8d25":8,"\u5373\u4e0d\u9700\u8981\u4f7f\u7528memori":39,"\u5373\u4e3a\u4e00\u4e2a\u65f6\u95f4\u6b65":39,"\u5373\u4e3a\u5355\u5c42rnn\u5e8f\u5217\u7684\u4f7f\u7528\u4ee3\u7801":39,"\u5373\u4e3a\u65f6\u95f4\u5e8f\u5217\u7684\u8f93\u5165":39,"\u5373\u4e3a\u8fd9\u4e2a\u53cc\u5c42rnn\u7684\u7f51\u7edc\u7ed3\u6784":39,"\u5373\u4e8c\u7ef4\u6570\u7ec4":39,"\u5373\u4f7f\u7528":12,"\u5373\u4f7f\u95f4\u9694\u5f88\u5c0f":33,"\u5373\u4fbf\u662f":0,"\u5373\u4fbf\u8bbe\u7f6e":8,"\u5373\u521d\u59cb\u72b6\u6001\u4e3a0":41,"\u5373\u5355\u65f6\u95f4\u6b65\u6267\u884c\u7684\u51fd\u6570":42,"\u5373\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217":39,"\u5373\u53cc\u5c42rnn\u7684\u6bcf\u4e2a\u72b6\u6001":41,"\u5373\u53ef":4,"\u5373\u53ef\u4ee5\u6781\u5927\u7684\u52a0\u901f\u6570\u636e\u8f7d\u5165\u6d41\u7a0b":11,"\u5373\u53ef\u5f00\u59cb\u4e0b\u8f7d":3,"\u5373\u53ef\u5f00\u59cb\u4e0b\u9762\u7684\u6b65\u9aa4":1,"\u5373\u5728\u53cc\u5c42\u5e8f\u5217\u7684\u539f\u59cb\u6570\u636e\u4e2d":39,"\u5373\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d":11,"\u5373\u5927\u90e8\u5206\u503c\u4e3a0":14,"\u5373\u5c06\u4e00\u6bb5\u8bdd\u8fdb\u884c\u5206\u7c7b":39,"\u5373\u5c06nchw\u8f6c\u6362\u6210nhwc":12,"\u5373\u5f53\u524d\u65f6\u95f4\u6b65\u4e0b\u7684\u795e\u7ecf\u7f51\u7edc\u4f9d\u8d56\u524d\u4e00\u4e2a\u65f6\u95f4\u6b65\u795e\u7ecf\u7f51\u7edc\u4e2d\u67d0\u4e00\u4e2a\u795e\u7ecf\u5143\u8f93\u51fa":39,"\u5373\u628a\u5355\u5c42rnn\u751f\u6210\u540e\u7684subseq\u7ed9\u62fc\u63a5\u6210\u4e00\u4e2a\u65b0\u7684\u53cc\u5c42seq":41,"\u5373\u6574\u4e2a\u53cc\u5c42group\u662f\u5c06\u524d\u4e00\u4e2a\u5b50\u53e5\u7684\u6700\u540e\u4e00\u4e2a\u5411\u91cf":39,"\u5373\u6574\u4e2a\u8f93\u5165\u5e8f\u5217":38,"\u5373\u6574\u6570\u6570\u7ec4":39,"\u5373\u65f6\u95f4\u9012\u5f52\u795e\u7ecf\u7f51\u7edc":39,"\u5373\u662f\u8de8\u8d8a\u65f6\u95f4\u6b65\u7684\u7f51\u7edc\u8fde\u63a5":39,"\u5373\u7279\u5f81\u7684\u6570\u7ec4":39,"\u5373\u7f51\u5361\u540d":27,"\u5373\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u51fa\u73b0nan\u6216\u8005inf":11,"\u5373\u8bbe\u7f6e":11,"\u5373\u8fd0\u884c\u8bad\u7ec3\u7a0b\u5e8f":1,"\u5373define_py_data_sources2\u5e94\u6539\u4e3a":13,"\u5373input":41,"\u5373rnn\u4e4b\u95f4\u6709\u4e00\u6b21\u5d4c\u5957\u5173\u7cfb":39,"\u5378\u8f7dpaddlepaddle\u5305":8,"\u538b\u7f29\u6210\u4e00\u4e2a\u5411\u91cf":39,"\u539f\u56e0":[4,8],"\u539f\u56e0\u5728\u4e8e\u6ca1\u6709\u628a\u673a\u5668\u4e0acuda\u76f8\u5173\u7684\u9a71\u52a8\u548c\u5e93\u6620\u5c04\u5230\u5bb9\u5668\u5185\u90e8":8,"\u539f\u56e0\u662f\u6bcf\u4e2a\u56de\u590d\u90fd\u4f1a\u53d1\u9001\u4e00\u5c01\u90ae\u4ef6":4,"\u53bb\u8fc7":39,"\u53c2\u6570":[0,6,11,20,21,27,32],"\u53c2\u6570\u5171\u4eab\u7684\u914d\u7f6e\u793a\u4f8b\u4e3a":13,"\u53c2\u6570\u548c\u73af\u5883\u53d8\u91cf":21,"\u53c2\u6570\u670d\u52a1\u5668":[22,32],"\u53c2\u6570\u670d\u52a1\u5668\u4e4b\u95f4\u4e0d\u76f8\u4e92\u4f9d\u8d56":22,"\u53c2\u6570\u670d\u52a1\u5668\u4e5f\u4e0d\u4f1a\u7b49\u5f85\u8ba1\u7b97\u8282\u70b9\u5168\u90e8\u90fd\u63d0\u4ea4\u68af\u5ea6\u4e4b\u540e\u624d\u5f00\u59cb\u4e0b\u4e00\u6b65":22,"\u53c2\u6570\u670d\u52a1\u5668\u63a5\u6536\u4ece\u8ba1\u7b97\u8282\u70b9\u4e0a\u4f20\u7684\u68af\u5ea6":22,"\u53c2\u6570\u670d\u52a1\u5668\u7684\u53c2\u6570\u5206\u5757\u5927\u5c0f":33,"\u53c2\u6570\u670d\u52a1\u5668\u7684\u76d1\u542c\u7aef\u53e3":33,"\u53c2\u6570\u670d\u52a1\u5668\u7684\u7f51\u7edc\u8bbe\u5907\u540d\u79f0":33,"\u53c2\u6570\u670d\u52a1\u5668\u7684ip\u5730\u5740":33,"\u53c2\u6570\u670d\u52a1\u5668\u7a00\u758f\u66f4\u65b0\u7684\u53c2\u6570\u5206\u5757\u5927\u5c0f":33,"\u53c2\u6570\u6765\u63a7\u5236\u7f13\u5b58\u65b9\u6cd5":11,"\u53c2\u6570\u6982\u8ff0":34,"\u53c2\u6570\u7684\u4e2a\u6570\u548c\u53c2\u6570\u5217\u8868":20,"\u53c2\u6570\u7684\u89e3\u6790":27,"\u53c2\u6570\u8bbe\u7f6e":10,"\u53c2\u6570\u8bbe\u7f6e\u4e86\u5916\u5c42":39,"\u53c2\u6570\u8bf4\u660e":21,"\u53c2\u6570\u8bf4\u660e\u5bb9\u5668\u5df2\u4ea4\u4e92\u5f0f\u8fd0\u884c":1,"\u53c2\u6570\u8f93\u5165":11,"\u53c2\u6570\u9700\u8981\u5b9e\u73b0":42,"\u53c2\u7167\u4e0a\u8ff0\u6b65\u9aa4\u66f4\u65b0":4,"\u53c2\u8003":1,"\u53c2\u8003\u4e0b\u8ff0\u53ef\u9009\u6b65\u9aa4":0,"\u53c2\u8003\u5f3a\u8c03\u90e8\u5206":37,"\u53c2\u8003\u65f6\u95f4\u5e8f\u5217":39,"\u53c2\u8003\u6837\u4f8b\u6570\u636e\u51c6\u5907\u811a\u672c":21,"\u53c2\u8003\u955c\u50cf\u7684":27,"\u53c8":39,"\u53c8\u662f\u4e00\u4e2a\u5355\u5c42\u7684\u5e8f\u5217":38,"\u53c8\u8981\u4fdd\u8bc1\u6570\u636e\u662f\u968f\u673a\u7684":11,"\u53ca":6,"\u53cc\u5411\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u9690\u85cf\u72b6\u6001":42,"\u53cc\u5c42":41,"\u53cc\u5c42\u4e0d\u7b49\u957frnn":39,"\u53cc\u5c42\u5e8f\u5217":[19,38],"\u53cc\u5c42\u5e8f\u5217\u5728\u5904\u7406\u957f\u5e8f\u5217\u7684\u4efb\u52a1\u6216\u662f\u6784\u5efa\u5c42\u7ea7\u6a21\u578b\u65f6\u4f1a\u53d1\u6325\u4f5c\u7528":19,"\u53cc\u5c42\u5e8f\u5217\u6216\u5355\u5c42\u5e8f\u5217":38,"\u53cc\u5c42\u5e8f\u5217\u6570\u636e\u4e00\u5171\u67094\u4e2a\u6837\u672c":39,"\u53cc\u5c42\u5e8f\u5217\u662f\u4e00\u4e2a\u5d4c\u5957\u7684\u5e8f\u5217":38,"\u53cc\u5c42\u5e8f\u5217\u662fpaddlepaddle\u652f\u6301\u7684\u4e00\u79cd\u975e\u5e38\u7075\u6d3b\u7684\u6570\u636e\u7ec4\u7ec7\u65b9\u5f0f":41,"\u53cc\u5c42\u5e8f\u5217\u6bcf\u4e2asubseq\u4e2d\u6bcf\u4e2a\u5143\u7d20":38,"\u53cc\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u53d8\u6210\u4e00\u4e2a0\u5c42\u5e8f\u5217":38,"\u53cc\u5c42\u5e8f\u5217\u9700\u8981\u8bbe\u7f6e\u5206\u522b\u4e3a\u5916\u5c42\u5e8f\u5217\u548c\u5185\u5c42\u5e8f\u5217\u5206\u522b\u8bbe\u7f6e":19,"\u53cc\u5c42\u6216\u8005\u5355\u5c42":38,"\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217\u7684dataprovider\u7684\u4ee3\u7801":39,"\u53cc\u5c42rnn":41,"\u53cc\u5c42rnn\u6570\u636e\u968f\u610f\u52a0\u4e86\u4e00\u4e9b\u9694\u65ad":39,"\u53cc\u5c42rnn\u987e\u540d\u601d\u4e49":39,"\u53cc\u8fdb\u5355\u51fa":41,"\u53cc\u8fdb\u53cc\u51fa":41,"\u53cd\u5411\u4f20\u64ad":6,"\u53cd\u5411\u4f20\u64ad\u6839\u636e\u8f93\u51fa\u7684\u68af\u5ea6":6,"\u53d1\u6563\u5230\u4e86\u4e00\u4e2a\u6570\u503c\u7279\u522b\u5927\u7684\u5730\u65b9":11,"\u53d1\u884c\u548c\u7ef4\u62a4":4,"\u53d1\u9001\u53c2\u6570\u7684\u7aef\u53e3\u53f7":33,"\u53d6\u503c\u76f8\u540c\u7684layer":12,"\u53d6\u5176\u4e2d\u4e00\u4e2a\u6a21\u578bparams_pass_90":14,"\u53d8\u6362\u77e9\u9635":6,"\u53e3\u5934":39,"\u53e5\u5b50\u662f\u7531\u8bcd\u8bed\u6784\u6210\u7684\u5e8f\u5217":19,"\u53e6\u4e00\u4e2a\u662f\u5185\u5b58\u64cd\u4f5c\u91cf":37,"\u53e6\u4e00\u4e2a\u662f\u6bcf\u6761\u5e8f\u5217":11,"\u53e6\u4e00\u79cd\u65b9\u5f0f\u662f\u5c06\u7f51\u7edc\u5c42\u5212\u5206\u5230\u4e0d\u540c\u7684gpu\u4e0a\u53bb\u8ba1\u7b97":35,"\u53e6\u5916":[0,39],"\u53e6\u5916\u6700\u65b0\u7684pip\u5b98\u65b9\u6e90\u4e2d\u7684\u5b89\u88c5\u5305\u9ed8\u8ba4\u662fmanylinux1\u6807\u51c6":3,"\u53ea\u4f5c\u4e3aread":41,"\u53ea\u4fdd\u5b58\u6700\u540e\u4e00\u8f6e\u7684\u53c2\u6570":33,"\u53ea\u5728\u7b2c\u4e00\u6b21cmake\u7684\u65f6\u5019\u6709\u6548":0,"\u53ea\u5bf9\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u8fdb\u884c\u5e8f\u5217\u5316":20,"\u53ea\u5c06\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u8fdb\u884c\u5e8f\u5217\u5316":20,"\u53ea\u662f\u53cc\u5c42\u5e8f\u5217\u5c06\u5176\u53c8\u505a\u4e86\u5b50\u5e8f\u5217\u5212\u5206":39,"\u53ea\u6709":39,"\u53ea\u6709\u5f53\u8bbe\u7f6e\u4e86spars":33,"\u53ea\u7528\u4e8e\u5728\u5e8f\u5217\u751f\u6210\u4efb\u52a1\u4e2d\u6307\u5b9a\u8f93\u5165\u6570\u636e":41,"\u53ea\u7559\u4e0b\u6838\u5fc3\u8ba1\u7b97\u5c42":20,"\u53ea\u80fd\u5728recurrent_group\u4e2d\u4f5c\u4e3astep":12,"\u53ea\u80fd\u6309\u884c\u8ba1\u7b97":12,"\u53ea\u80fd\u6d4b\u8bd5\u5355\u4e2a\u6a21\u578b":35,"\u53ea\u80fd\u8bbf\u95ee\u5b83\u4eec\u7684\u8f93\u51fa\u503c":12,"\u53ea\u8981\u4e00\u7cfb\u5217\u7279\u5f81\u6570\u636e\u4e2d\u7684":39,"\u53ea\u8981\u51fa\u73b0\u6d6e\u70b9\u6570\u5f02\u5e38":11,"\u53ea\u8bfbmemory\u8f93\u5165":41,"\u53ea\u9488\u5bf9\u5185\u5b58":11,"\u53ea\u9700\u4e2d\u65ad":23,"\u53ea\u9700\u5728\u7f16\u8bd1\u65f6\u9700\u914d\u5236\u4e0b\u9762\u8fd9\u4e9b\u7f16\u8bd1\u9009\u9879":17,"\u53ea\u9700\u7528\u60a8\u5b9a\u4e49\u7684\u76ee\u5f55\u4fee\u6539":23,"\u53ea\u9700\u8981":42,"\u53ea\u9700\u8981\u8bbe\u7f6e\u884c\u504f\u79fb":19,"\u53ea\u9700\u8981\u94fe\u63a5":17,"\u53ea\u9700\u8fdb\u884c\u524d\u5411\u8ba1\u7b97\u800c\u65e0\u9700\u8c03\u7528\u53cd\u5411\u8ba1\u7b97":20,"\u53ef\u4ee5":[1,4,7,39],"\u53ef\u4ee5\u4ece":1,"\u53ef\u4ee5\u4ece\u6211\u4eec\u7684ci\u7cfb\u7edf\u4e2d\u4e0b\u8f7d\u6700\u65b0\u7684whl\u5b89\u88c5\u5305\u548cc":3,"\u53ef\u4ee5\u4f30\u8ba1\u51fa\u5982\u679c\u6a21\u578b\u91c7\u7528\u4e0d\u53d8\u7684\u8f93\u51fa\u6700\u5c0f\u7684cost0\u662f\u591a\u5c11":13,"\u53ef\u4ee5\u4f7f\u7528":[13,20],"\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u7684\u547d\u4ee4\u66f4\u65b0\u60a8\u7684pip":3,"\u53ef\u4ee5\u4f7f\u7528\u5982\u4e0b\u4ee3\u7801":13,"\u53ef\u4ee5\u4f7f\u7528\u76f8\u5e94\u6570\u636e\u7c7b\u578b\u7684":13,"\u53ef\u4ee5\u4f7f\u7528\u8be5\u53c2\u6570":33,"\u53ef\u4ee5\u4f7f\u7528kubernetes\u7684\u547d\u4ee4\u884c\u5de5\u5177\u521b\u5efajob":27,"\u53ef\u4ee5\u5148\u4f7f\u7528":12,"\u53ef\u4ee5\u51cf\u5c11\u7f13\u5b58\u6c60\u7684\u5927\u5c0f":11,"\u53ef\u4ee5\u521b\u5efa\u4e00\u4e2a":26,"\u53ef\u4ee5\u52a0\u901fpaddlepaddle\u7684\u8ba1\u7b97":1,"\u53ef\u4ee5\u53c2\u8003":[0,1,4,39,42],"\u53ef\u4ee5\u53c2\u8003\u4e0b\u9762\u7684\u6b65\u9aa4\u6392\u67e5":9,"\u53ef\u4ee5\u53c2\u8003paddlepaddl":14,"\u53ef\u4ee5\u542b\u6709\u4e00\u6761\u6216\u591a\u6761\u6837\u672c":19,"\u53ef\u4ee5\u544a\u8bc9\u60a8\u67d0\u4e2a\u64cd\u4f5c\u5230\u5e95\u82b1\u4e86\u591a\u957f\u65f6\u95f4":37,"\u53ef\u4ee5\u5728":[0,23],"\u53ef\u4ee5\u5728\u5171\u4eab\u5b58\u50a8\u4e0a\u67e5\u770b\u8f93\u51fa\u7684\u65e5\u5fd7\u548c\u6a21\u578b":27,"\u53ef\u4ee5\u5728\u8fd9\u4e2a":4,"\u53ef\u4ee5\u5728event_handler\u4e2d":11,"\u53ef\u4ee5\u5b8c\u6210\u795e\u7ecf\u7f51\u7edc\u7684sgd\u65b9\u6cd5\u7684\u8bad\u7ec3":22,"\u53ef\u4ee5\u5c06memory\u7406\u89e3\u4e3a\u4e00\u4e2a\u65f6\u5ef6\u64cd\u4f5c":41,"\u53ef\u4ee5\u5c1d\u8bd5\u4ee5\u4e0b\u7684\u65b9\u6cd5":1,"\u53ef\u4ee5\u5e2e\u60a8\u63d0\u4f9b\u4e00\u4e9b\u5b9a\u4f4d\u6027\u80fd\u74f6\u9888\u7684\u5efa\u8bae":37,"\u53ef\u4ee5\u5e76\u884c\u7f16\u8bd1\u5417":0,"\u53ef\u4ee5\u5feb\u901f\u5728\u672c\u5730\u542f\u52a8\u4e00\u4e2a\u5305\u542b\u4e86paddlepaddle\u5b98\u65b9book\u6559\u7a0b\u7684jupyt":1,"\u53ef\u4ee5\u6267\u884c":[3,8],"\u53ef\u4ee5\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\u7f16\u8bd1\u751f\u6210\u6587\u6863":7,"\u53ef\u4ee5\u628a\u5b83\u60f3\u8c61\u4e3a\u4e00\u4e2a\u7c7b\u4f3c":0,"\u53ef\u4ee5\u6307\u5b9a\u540c\u65f6\u6267\u884cgpu\u4e0a\u7684\u5355\u5143\u6d4b\u8bd5":0,"\u53ef\u4ee5\u6307\u5b9a\u54ea\u4e00\u4e2a\u8f93\u5165\u548c\u8f93\u51fa\u5e8f\u5217\u4fe1\u606f\u4e00\u81f4":39,"\u53ef\u4ee5\u6307\u5b9a\u5f00\u542f\u81ea\u52a8\u68c0\u6d4bsm\u67b6\u6784":0,"\u53ef\u4ee5\u6309\u7167\u4e0b\u9762\u7684\u65b9\u6cd5":0,"\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":[38,41],"\u53ef\u4ee5\u662f\u4e00\u4e2a\u975e\u5e8f\u5217":41,"\u53ef\u4ee5\u662f\u4ece\u5206\u5e03\u5f0f\u5b58\u50a8\u6302\u8f7d\u8fc7\u6765\u7684":21,"\u53ef\u4ee5\u662f\u4ee5\u4e0b\u51e0\u79cd":6,"\u53ef\u4ee5\u662f\u6574\u578b":19,"\u53ef\u4ee5\u663e\u793a\u5730\u6307\u5b9a\u4e00\u4e2alayer\u7684\u8f93\u51fa\u7528\u4e8e\u521d\u59cb\u5316memori":41,"\u53ef\u4ee5\u6709\u4ee5\u4e0b\u4e24\u79cd":41,"\u53ef\u4ee5\u6709\u6548\u51cf\u5c0f\u7f51\u7edc\u7684\u963b\u585e":33,"\u53ef\u4ee5\u67e5\u770b":27,"\u53ef\u4ee5\u67e5\u770b\u6b64pod\u8fd0\u884c\u7684\u5bbf\u4e3b\u673a":26,"\u53ef\u4ee5\u6d4b\u8bd5\u591a\u4e2a\u6a21\u578b":35,"\u53ef\u4ee5\u7528":0,"\u53ef\u4ee5\u7528\u5982\u4e0b\u547d\u4ee4":4,"\u53ef\u4ee5\u7528\u6765\u8ba1\u7b97cpu\u51fd\u6570\u6216cuda\u5185\u6838\u7684\u65f6\u95f4\u6d88\u8017":37,"\u53ef\u4ee5\u76f4\u63a5\u8fd0\u884c":20,"\u53ef\u4ee5\u7701\u7565\u6b65\u9aa43\u4e2d":0,"\u53ef\u4ee5\u770b\u4f5c\u662f\u4e00\u4e2a\u975e\u5e8f\u5217\u8f93\u5165":38,"\u53ef\u4ee5\u770b\u51fa":22,"\u53ef\u4ee5\u7cbe\u786e\u8bf4\u660e\u4e00\u4e2a\u957f\u8017\u65f6\u64cd\u4f5c\u7684\u5177\u4f53\u539f\u56e0":37,"\u53ef\u4ee5\u8003\u8651\u4f7f\u7528\u4e00\u4e9b\u4f18\u5316\u7b97\u6cd5":11,"\u53ef\u4ee5\u8054\u7cfbop":9,"\u53ef\u4ee5\u8054\u7cfbop\u662f\u5426\u53ef\u4ee5\u66f4\u6362\u96c6\u7fa4\u6216\u5347\u7ea7\u5f53\u524d\u96c6\u7fa4":9,"\u53ef\u4ee5\u83b7\u53d6\u7f51\u7edc\u4e2d\u5b9a\u4e49\u7684\u4efb\u610f\u591a\u4e2a":20,"\u53ef\u4ee5\u88c5\u7684\u662f":0,"\u53ef\u4ee5\u8bbf\u95ee\u7531recurr":12,"\u53ef\u4ee5\u8f7b\u677e\u5730\u5b8c\u6210\u795e\u7ecf\u7f51\u7edc\u914d\u7f6e":14,"\u53ef\u4ee5\u8fd0\u884c":21,"\u53ef\u4ee5\u9009\u5728\u5728\u5f53\u524d\u673a\u5668\u5b89\u88c5\u4e5f\u53ef\u4ee5\u62f7\u8d1d\u5230\u76ee\u6807\u673a\u5668\u5b89\u88c5":0,"\u53ef\u4ee5\u9009\u62e9\u662f\u5426\u4f7f\u7528\u53c2\u6570":35,"\u53ef\u4ee5\u901a\u8fc7":4,"\u53ef\u4ee5\u901a\u8fc7\u4fee\u6539\u8fd9\u4e24\u4e2a\u51fd\u6570\u6765\u5b9e\u73b0\u590d\u6742\u7684\u7f51\u7edc\u914d\u7f6e":42,"\u53ef\u4ee5\u901a\u8fc7\u5728":11,"\u53ef\u4ee5\u901a\u8fc7\u7f51\u9875\u6d4f\u89c8":1,"\u53ef\u4ee5\u901a\u8fc7\u8fd9\u4e2a\u8f93\u51fa\u6765\u5b8c\u6210\u81ea\u5b9a\u4e49\u7684\u8bc4\u4f30\u6307\u6807\u8ba1\u7b97\u7b49\u529f\u80fd":11,"\u53ef\u4ee5\u91cd\u547d\u540d\u8fd9\u4e2awhl\u5305\u4e3a":[3,8],"\u53ef\u53c2\u8003":20,"\u53ef\u5728":17,"\u53ef\u7528\u4e8e\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d\u89e3\u6790\u8fd9\u4e9b\u53c2\u6570":35,"\u53ef\u76f4\u63a5\u8fd0\u884c":20,"\u53ef\u80fd\u4f1a\u5bfc\u81f4\u51fa\u9519":27,"\u53ef\u80fd\u7684\u4ee3\u7801\u4e3a":11,"\u53ef\u80fd\u7684\u539f\u56e0\u662f":13,"\u53ef\u80fd\u7684\u60c5\u51b5\u4e0b":37,"\u53ef\u80fd\u9700\u8981\u6ce8\u610f\u7ed9\u8fd9\u4e2a\u865a\u62df\u673a\u591a\u5206\u914d\u4e00\u4e9b":0,"\u53ef\u9009":[0,6,20,21],"\u53ef\u9009\u6b65\u9aa4":0,"\u53ef\u9009\u7684\u4e0d\u540c\u7f16\u8bd1\u73af\u5883docker\u955c\u50cf":0,"\u53ef\u9009\u914d\u7f6e\u9009\u9879":17,"\u53ef\u901a\u8fc7pip\u4e00\u952e\u5b89\u88c5":2,"\u53ef\u914d\u7f6e\u4e3a":17,"\u53ef\u91c7\u7528\u7b2c\u4e8c\u79cd\u65b9\u5f0f":12,"\u5403":39,"\u5403\u996d":39,"\u5404\u65b9\u9762":39,"\u5408":39,"\u5408\u5e76\u5165\u4e00\u4e2a\u6587\u4ef6":20,"\u5408\u5e76\u6a21\u578b\u6587\u4ef6":20,"\u5408\u7406":39,"\u540c\u65f6":[8,11,37],"\u540c\u65f6\u4e5f\u4f1a\u8bfb\u53d6\u76f8\u5173\u8def\u5f84\u53d8\u91cf\u6765\u8fdb\u884c\u641c\u7d22":0,"\u540c\u65f6\u4e5f\u53ef\u4ee5\u52a0\u901f\u5f00\u59cb\u8bad\u7ec3\u524d\u6570\u636e\u8f7d\u5165\u7684\u8fc7\u7a0b":11,"\u540c\u65f6\u4e5f\u53ef\u4ee5\u901a\u8fc7":4,"\u540c\u65f6\u4e5f\u80fd\u591f\u5f15\u5165\u66f4\u52a0\u590d\u6742\u7684\u8bb0\u5fc6\u673a\u5236":41,"\u540c\u65f6\u5176\u5185\u90e8\u5b9e\u73b0\u53ef\u4ee5\u907f\u514d\u7eafcpu\u7248\u672cpaddlepaddle\u5728\u6267\u884c\u672c\u8bed\u53e5\u65f6\u53d1\u751f\u5d29\u6e83":37,"\u540c\u65f6\u5728\u5185\u5b58\u91cc\u76f4\u63a5\u968f\u5373\u9009\u53d6\u6570\u636e\u6765\u505ashuffl":11,"\u540c\u65f6\u5c06\u53c2\u6570\u521d\u59cb\u5316\u4e3a":13,"\u540c\u65f6\u7528\u6237\u9700\u8981\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d\u6307\u5b9a":35,"\u540c\u65f6\u8bbe\u7f6e\u5185\u5b58\u7f13\u5b58\u529f\u80fd":11,"\u540c\u65f6\u8f93\u51fa\u5e8f\u5217\u5c42\u548c\u975e\u5e8f\u5217\u5c42":11,"\u540c\u6837":14,"\u540c\u6837\u4e5f\u53ef\u4ee5\u5728\u6d4b\u8bd5\u6a21\u5f0f\u4e2d\u6307\u5b9a\u6a21\u578b\u8def\u5f84":33,"\u540c\u6837\u53ef\u4ee5\u6269\u5c55\u5230\u53cc\u5c42\u5e8f\u5217\u7684\u5904\u7406\u4e0a":41,"\u540c\u6b65\u6267\u884c\u64cd\u4f5c\u7684\u7ebf\u7a0b\u6570":33,"\u540e":[0,4,13,27],"\u540e\u5411\u4f20\u64ad":6,"\u540e\u5411\u4f20\u64ad\u7ed9\u5b9a\u8f93\u51fa\u7684\u68af\u5ea6":6,"\u540e\u7f00\u4e3a":21,"\u540e\u8005\u5728\u6fc0\u6d3b\u51fd\u6570\u53cd\u5411\u8ba1\u7b97\u65f6\u88ab\u8c03\u7528":11,"\u540e\u8005\u622a\u65ad\u56de\u4f20\u7ed9\u524d\u5c42\u7684\u68af\u5ea6":11,"\u540e\u9762\u7684gradient":21,"\u540e\u9988":22,"\u5411\u91cf":19,"\u5411\u91cfenable_parallel_vector":32,"\u5417":0,"\u5426\u5219\u4f1a\u628a":4,"\u5426\u5219\u4f7f\u7528\u591a\u673a\u8bad\u7ec3":33,"\u5426\u5219\u4f7f\u7528cpu\u6a21\u5f0f":33,"\u5426\u5219\u4f7f\u7528gpu":35,"\u5426\u5219\u5b83\u4ee5\u4e00\u4e2a\u5e8f\u5217\u8f93\u5165":42,"\u5426\u5219\u9891\u7e41\u7684\u591a\u8282\u70b9\u5de5\u4f5c\u7a7a\u95f4\u90e8\u7f72\u53ef\u80fd\u4f1a\u5f88\u9ebb\u70e6":23,"\u542b\u6709\u5e8f\u5217\u4fe1\u606f\u548c\u5b50\u5e8f\u5217\u4fe1\u606f\u7684\u7a20\u5bc6\u5411\u91cf":6,"\u542b\u6709\u5e8f\u5217\u4fe1\u606f\u7684\u6574\u6570":6,"\u542b\u6709\u5e8f\u5217\u4fe1\u606f\u7684\u7a20\u5bc6\u5411\u91cf":6,"\u542f\u52a8\u4e00\u4e2a\u6d4b\u8bd5\u96c6\u7fa4":23,"\u542f\u52a8\u53c2\u6570\u8bf4\u660e":22,"\u542f\u52a8\u5bb9\u5668\u5f00\u59cb\u8bad\u7ec3":27,"\u542f\u52a8\u5e76\u884c\u5411\u91cf\u7684\u9608\u503c":33,"\u542f\u52a8\u5feb\u901f\u5e94\u7b54":33,"\u542f\u52a8\u8bad\u7ec3\u4efb\u52a1":28,"\u542f\u7528\u68af\u5ea6\u53c2\u6570\u7684\u9608\u503c":33,"\u5440":39,"\u5468\u56f4":39,"\u547d\u4ee4\u4e3a":[8,26],"\u547d\u4ee4\u521b\u5efa\u65b0\u955c\u50cf":26,"\u547d\u4ee4\u53ef\u4ee5\u8bbe\u7f6e":0,"\u547d\u4ee4\u6709\u65f6\u5019\u4f1a\u4ea7\u751f\u4e00\u4e9b\u4e2d\u95f4\u7ed3\u679c":0,"\u547d\u4ee4\u770b\u5230\u505c\u6b62\u540e\u4f46\u662f\u6ca1\u6709\u5220\u9664\u7684":0,"\u547d\u4ee4\u7f16\u8bd1\u6e90\u7801\u5373\u53ef":0,"\u547d\u4ee4\u884c\u53c2\u6570\u8bbe\u7f6e":36,"\u547d\u4ee4\u8bbe\u7f6e\u8be5\u7c7b\u7f16\u8bd1\u9009\u9879":0,"\u547d\u4ee4\u9009\u9879\u5e76\u4e14":23,"\u547d\u4ee4\u91cc\u90fd\u7528\u4e86":0,"\u547d\u540d\u4e3a":4,"\u548c":[0,4,6,7,11,12,13,17,19,21,22,23,35,37,39,42],"\u548c\u4e00\u4e2a\u5df2\u7ecf\u5206\u8bcd\u540e\u7684\u53e5\u5b50":39,"\u548c\u4e09\u79cd\u5e8f\u5217\u6a21\u5f0f":14,"\u548c\u4e2d\u6587\u6587\u6863":7,"\u548c\u4e4b\u524d\u51cf\u5c0f\u901a\u8fc7\u51cf\u5c0f\u7f13\u5b58\u6c60\u6765\u51cf\u5c0f\u5185\u5b58\u5360\u7528\u7684\u539f\u7406\u4e00\u81f4":11,"\u548c\u504f\u7f6e\u5411\u91cf":6,"\u548c\u5185\u5b58":0,"\u548c\u5217\u53f7":19,"\u548c\u53cc\u5c42\u5e8f\u5217\u542b\u6709subseq":38,"\u548c\u5e8f\u5217\u4e2d\u542b\u6709\u5143\u7d20\u7684\u6570\u76ee\u540c":38,"\u548c\u5f02\u6b65\u968f\u673a\u68af\u5ea6\u4e0b\u964d":22,"\u548c\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u8f93\u5165":42,"\u548c\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u76f4\u63a5\u8fd0\u884c\u7684":0,"\u548c\u793a\u4f8b2\u4e2d\u7684\u914d\u7f6e\u7c7b\u4f3c":39,"\u548c\u90e8\u5206layer":41,"\u548cpool":38,"\u548cpserver\u4e4b\u95f4\u7528\u4e8e\u7a00\u758f\u7c7b\u578b\u53c2\u6570\u901a\u4fe1\u7684\u7aef\u53e3\u4e2a\u6570":21,"\u54c1\u8d28":39,"\u54ea\u4e9b\u4e0d\u662f":39,"\u5546\u52a1":39,"\u554a":39,"\u56db\u79cd\u6570\u636e\u7c7b\u578b":14,"\u56e0\u4e3a\u4e0a\u8ff0\u7279\u70b9":18,"\u56e0\u4e3a\u5168\u8fde\u63a5\u5c42\u7684\u6fc0\u6d3b\u53ef\u4ee5\u662fsoftmax":6,"\u56e0\u4e3a\u53c2\u6570":35,"\u56e0\u4e3a\u5b83\u4eec\u7684\u8ba1\u7b97\u6548\u7387\u6bd4":42,"\u56e0\u4e3a\u5b83\u6bd4":42,"\u56e0\u4e3a\u5b98\u65b9\u955c\u50cf":27,"\u56e0\u4e3a\u6211\u4eec\u4f1a\u628a\u6240\u6709\u7f16\u8bd1\u5de5\u5177\u90fd\u5b89\u88c5\u8fdb\u4e00\u4e2a":0,"\u56e0\u4e3a\u6e90\u7801\u5c31\u5728\u672c\u673a\u4e0a":0,"\u56e0\u4e3a\u8f93\u5165\u6570\u636e\u53ef\u80fd\u6709\u591a\u79cd\u7ed3\u6784":18,"\u56e0\u4e3apython\u7684\u641c\u7d22\u8def\u5f84\u662f\u4f18\u5148\u5df2\u7ecf\u5b89\u88c5\u7684python\u5305":8,"\u56e0\u6b64":[6,39,41],"\u56e0\u6b64\u53cc\u5c42\u5e8f\u5217\u7684\u914d\u7f6e\u4e2d":39,"\u56e0\u6b64\u5b83\u662finteger_value_sub_sequ":39,"\u56e0\u6b64\u6211\u4eec\u91c7\u7528\u8f93\u51fa\u7684\u52a0\u6743\u548c":6,"\u56e0\u6b64\u7528\u6237\u5e76\u4e0d\u9700\u8981\u5173\u5fc3\u5b83\u4eec":32,"\u56e0\u6b64\u9519\u8bef\u7684\u4f7f\u7528\u4e8c\u8fdb\u5236\u53d1\u884c\u7248\u53ef\u80fd\u4f1a\u5bfc\u81f4\u8fd9\u79cd\u9519\u8bef":8,"\u56fd\u5185\u7528\u6237\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u7684\u955c\u50cf\u6e90\u6765\u52a0\u901f\u8bbf\u95ee":1,"\u56fe1":[19,20],"\u56fe2":19,"\u56fe\u8868":1,"\u5728":[0,4,19,20,21,38,39,42],"\u5728\u4e00\u4e2a\u529f\u80fd\u9f50\u5168\u7684kubernetes\u673a\u7fa4\u91cc":26,"\u5728\u4e00\u4e2a\u53c2\u6570\u7684\u68af\u5ea6\u88ab\u66f4\u65b0\u540e":6,"\u5728\u4e00\u4e9b\u5206\u5e03\u5f0f\u7cfb\u7edf\u4e2d":21,"\u5728\u4e00\u8f6e\u4e2d\u6bcfsave":33,"\u5728\u4e0a\u9762\u4ee3\u7801\u4e2d":39,"\u5728\u4e0b\u4e00\u7bc7\u4e2d":26,"\u5728\u4e0d\u540c\u96c6\u7fa4\u4e2d\u8fd0\u884c":22,"\u5728\u4e4b\u540e\u7684":11,"\u5728\u4e86\u89e3docker\u7684\u57fa\u672c\u4f7f\u7528\u65b9\u6cd5\u4e4b\u540e":1,"\u5728\u4efb\u610f\u65f6\u95f4\u67d0\u4e00\u53f0\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u4fdd\u5b58\u7684\u53c2\u6570\u53ef\u80fd\u6bd4\u53e6\u4e00\u53f0\u8981\u66f4\u65b0":22,"\u5728\u4f7f\u7528\u4e0d\u540c\u7684\u5206\u5e03\u5f0f\u8ba1\u7b97\u5e73\u53f0\u65f6":21,"\u5728\u4f7f\u7528\u540c\u6b65sgd\u8bad\u7ec3\u795e\u7ecf\u7f51\u7edc\u65f6":22,"\u5728\u4f7f\u7528\u65f6":12,"\u5728\u4f7f\u7528\u8be5\u6587\u6863\u4e4b\u524d":14,"\u5728\u4f7f\u7528c":17,"\u5728\u4f7f\u7528paddlepaddl":17,"\u5728\u5168\u8fde\u63a5\u5c42\u4e2d":6,"\u5728\u51c6\u5907\u53d1\u8d77":4,"\u5728\u51fd\u6570":27,"\u5728\u5206\u5e03\u5f0f\u73af\u5883\u4e2d\u6d4b\u8bd5":33,"\u5728\u5206\u5e03\u5f0f\u8bad\u7ec3\u4e2d":33,"\u5728\u521b\u5efaparameters\u540e":13,"\u5728\u5355\u5c42\u6570\u636e\u7684\u57fa\u7840\u4e0a":39,"\u5728\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u52a0\u8f7d\u548c\u4fdd\u5b58\u53c2\u6570":33,"\u5728\u53c2\u6570\u670d\u52a1\u5668\u7ec8\u7aef\u6bcflog":33,"\u5728\u53cc\u5c42rnn\u4e2d\u7684\u7ecf\u5178\u60c5\u51b5\u662f\u5c06\u5185\u5c42\u7684\u6bcf\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217\u6570\u636e":39,"\u5728\u53cd\u5411\u4f20\u9012\u7684\u65f6\u5019":11,"\u5728\u53d8\u6362\u65f6\u9700\u8981\u5c06\u8f93\u5165\u5e8f\u5217\u4f20\u5165":39,"\u5728\u542f\u52a8job\u4e4b\u524d":27,"\u5728\u56de\u590d\u8bc4\u5ba1\u4eba\u610f\u89c1\u65f6":4,"\u5728\u56fe\u50cf\u4efb\u52a1\u4e2d":12,"\u5728\u591acpu\u8bad\u7ec3\u65f6\u5171\u4eab\u8be5\u53c2\u6570":33,"\u5728\u5b8c\u6210\u4e00\u5b9a\u91cf\u6570\u636e\u7684\u8bad\u7ec3\u540e":22,"\u5728\u5b8c\u6210\u795e\u7ecf\u7f51\u7edc\u7684\u642d\u5efa\u4e4b\u540e":14,"\u5728\u5b9a\u4e49\u8f93\u5165layer\u4e4b\u540e":14,"\u5728\u5b9e\u9645\u5e94\u7528\u4e2d":12,"\u5728\u5bb9\u5668\u4e2d\u7f16\u8f91\u4ee3\u7801":1,"\u5728\u5bb9\u5668\u521b\u5efa\u540e":27,"\u5728\u5bf9\u5bb9\u5668\u7684\u63cf\u8ff0":27,"\u5728\u5c42\u4e2d\u6307\u5b9a":35,"\u5728\u5e8f\u5217\u751f\u6210\u4efb\u52a1\u4e2d":41,"\u5728\u5f02\u6b65sgd\u4e2d":22,"\u5728\u5f53\u524d":11,"\u5728\u5f53\u524d\u7684\u5b9e\u73b0\u65b9\u5f0f\u4e0b":6,"\u5728\u5f97\u5230":27,"\u5728\u6211\u4eec\u7684\u4f8b\u5b50\u4e2d":42,"\u5728\u63d0\u4ea4":4,"\u5728\u642d\u5efa\u795e\u7ecf\u7f51\u7edc\u7684\u8fc7\u7a0b\u4e2d":14,"\u5728\u65e0\u7279\u6b8a\u9700\u6c42\u60c5\u51b5\u4e0b":17,"\u5728\u672c\u4f8b\u4e2d":[4,35,39],"\u5728\u672c\u6559\u7a0b\u4e2d":42,"\u5728\u672c\u793a\u4f8b\u4e2d":39,"\u5728\u672c\u8282\u4e2d":42,"\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b":11,"\u5728\u6811\u7684\u6bcf\u4e00\u5c42\u4e0a":33,"\u5728\u6b64":[32,35],"\u5728\u6bcf\u4e2a\u65f6\u95f4\u6b65\u4e2d":42,"\u5728\u6bcf\u4e2a\u65f6\u95f4\u6b65\u7684\u5b50\u5e8f\u5217\u957f\u5ea6\u53ef\u4ee5\u4e0d\u76f8\u7b49":39,"\u5728\u6bcf\u4e2a\u65f6\u95f4\u6b65\u957f":42,"\u5728\u6bcf\u4e2apod\u4e0a\u90fd\u901a\u8fc7volume\u65b9\u5f0f\u6302\u8f7d\u5206\u5e03\u5f0f\u6587\u4ef6\u7cfb\u7edf\u7684\u4e00\u4e2a\u76ee\u5f55\u7528\u4e8e\u4fdd\u5b58\u8bad\u7ec3\u6570\u636e\u548c\u8f93\u51fa\u7ed3\u679c":27,"\u5728\u6d4b\u8bd5\u9636\u6bb5":33,"\u5728\u6e90\u7801\u76ee\u5f55\u6811\u7684\u6839\u76ee\u5f55\u4e2d\u8fd0\u884c":4,"\u5728\u751f\u6210\u65f6":42,"\u5728\u76f8\u5e94\u7684\u4f18\u5316\u7b97\u6cd5\u91cc\u8bbe\u7f6elearning_rate_schedule\u53ca\u76f8\u5173\u53c2\u6570":13,"\u5728\u76f8\u5e94layer\u7684":12,"\u5728\u795e\u7ecf\u7f51\u7edc\u4e2d\u7b49\u4e8e\u4e00\u6b21\u9884\u6d4b\u5904\u7406\u7684\u6837\u672c\u6570":19,"\u5728\u7a0b\u5e8f\u5b9e\u73b0\u4e2d\u90fd\u4f1a\u8f6c\u5316\u4e3a\u4e8c\u7ef4\u77e9\u9635":19,"\u5728\u7ebf\u4e0a\u7cfb\u7edf\u4e2d":21,"\u5728\u7ec4\u5408\u65f6":14,"\u5728\u7ec4\u7ec7\u795e\u7ecf\u7f51\u7edc\u8f93\u5165":20,"\u5728\u7ec4\u7ec7\u795e\u7ecf\u7f51\u7edc\u8f93\u5165\u65f6":19,"\u5728\u7ec8\u7aef\u6267\u884c":20,"\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d":6,"\u5728\u81ea\u7136\u8bed\u8a00\u5904\u7406\u4efb\u52a1\u4e2d":38,"\u5728\u8bad\u7ec3\u4e2d":42,"\u5728\u8bad\u7ec3\u4e4b\u524d":27,"\u5728\u8bad\u7ec3\u65f6":26,"\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d":27,"\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u6bcfshow":33,"\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u83b7\u5f97\u53c2\u6570\u7684\u6743\u91cd\u548c\u68af\u5ea6":11,"\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u83b7\u5f97\u67d0\u4e00\u4e2alayer\u7684output":11,"\u5728\u8be5\u793a\u4f8b\u4e2d":13,"\u5728\u8be5\u914d\u7f6e\u76847":39,"\u5728\u8c03\u7528":20,"\u5728\u8c03\u7528c":20,"\u5728\u8f6f\u4ef6\u5de5\u7a0b\u7684\u8303\u7574\u91cc":37,"\u5728\u8f93\u51fa\u7684\u8fc7\u7a0b\u4e2d":41,"\u5728\u8fd0\u884c\u65f6\u5c06\u795e\u7ecf\u7f51\u7edc\u7684\u591a\u4e2a\u53ef\u5b66\u4e60\u53c2\u6570\u653e\u5728\u540c\u4e00\u4e2a\u76ee\u5f55\u4e2d":20,"\u5728\u8fd9\u4e00\u90e8\u5206":34,"\u5728\u8fd9\u4e2a\u4f8b\u5b50\u91cc":[6,26],"\u5728\u8fd9\u4e2a\u51fd\u6570\u4e2d":39,"\u5728\u8fd9\u4e2a\u6559\u7a0b\u4e2d":37,"\u5728\u8fd9\u4e2a\u6a21\u578b\u4e2d":42,"\u5728\u8fd9\u4e9blayer\u4e2d":39,"\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b":[6,42],"\u5728\u8fd9\u79cd\u7ed3\u6784\u4e2d":41,"\u5728\u8fd9\u7bc7\u6587\u6863\u91cc":26,"\u5728\u8fd9\u7bc7\u6587\u7ae0\u91cc":27,"\u5728\u8fd9\u91cc":41,"\u5728\u8fd9\u91cc\u6211\u4eec\u4f7f\u7528\u5168\u8fde\u63a5\u5c42\u4f5c\u4e3a\u4f8b\u5b50\u6765\u5c55\u793a\u5b9e\u73b0\u65b0\u7f51\u7edc\u5c42\u6240\u9700\u8981\u7684\u56db\u4e2a\u6b65\u9aa4":6,"\u5728\u8fdb\u884c\u5206\u5e03\u5f0f\u8bad\u7ec3\u65f6":21,"\u5728\u8fdb\u884c\u7f51\u7edc\u914d\u7f6e\u4e4b\u524d":14,"\u5728\u91c7\u7528sgd":13,"\u5728\u96c6\u7fa4\u4e0a\u8bad\u7ec3\u4e00\u4e2a\u7a00\u758f\u6a21\u578b\u9700\u8981\u52a0\u4e0a\u4e0b\u9762\u7684\u53c2\u6570":35,"\u5728\u975e\u5e8f\u5217\u8f93\u5165\u65f6":11,"\u5728build\u76ee\u5f55\u4e0b\u6267\u884c":8,"\u5728c":19,"\u5728cmake\u7684\u547d\u4ee4\u884c\u4e2d":0,"\u5728hpc\u9886\u57df\u4f7f\u7528\u975e\u5e38\u7684\u5e7f\u6cdb":24,"\u5728openmpi\u96c6\u7fa4\u4e2d\u542f\u52a8\u8bad\u7ec3":24,"\u5728paddl":27,"\u5728paddle\u4e2d":35,"\u5728paddlepaddl":19,"\u5728paddlepaddle\u4e2d":[14,41],"\u5728paddlepaddle\u4e2d\u4f7f\u7528dropout\u6709\u4e24\u79cd\u65b9\u5f0f":12,"\u5728paddlepaddle\u4e2d\u5305\u542b\u4ee5\u4e0b":12,"\u5728paddlepaddle\u5185\u90e8":[19,20],"\u5728paddlepaddle\u7684\u6587\u6863\u4e2d":39,"\u5728step\u51fd\u6570\u4e2d\u5b9a\u4e49":41,"\u5728step\u51fd\u6570\u4e2d\u5b9a\u4e49memori":41,"\u5728trainer":35,"\u5728trainer\u4e2d\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u53d6\u6a21\u7684\u65b9\u6cd5\u4e3a\u6bcf\u4e2atrainer\u5206\u914d\u8bad\u7ec3\u6570\u636e\u6587\u4ef6":21,"\u5730\u6bb5":39,"\u5730\u7406\u4f4d\u7f6e":39,"\u5730\u94c1\u7ad9":39,"\u5747\u4f1a\u5b58\u653e\u4e8e":17,"\u5747\u5300\u5206\u5e03":13,"\u5747\u5300\u5206\u5e03\u7684\u8303\u56f4\u662f":33,"\u5747\u6709\u4e09\u4e2a\u5b50\u5e8f\u5217":39,"\u5747\u6709\u4e24\u7ec4\u7279\u5f81":39,"\u57fa\u4e8e\u53cc\u5c42\u5e8f\u5217\u8f93\u5165":41,"\u57fa\u672c\u4f7f\u7528\u6982\u5ff5":[15,20],"\u57fa\u7840\u4e0a":19,"\u586b\u5199":4,"\u589e\u52a0\u4e86\u4e00\u6761cd\u547d\u4ee4":26,"\u589e\u52a0\u5982\u4e0b\u53c2\u6570":35,"\u589e\u52a0\u68af\u5ea6\u68c0\u6d4b\u7684\u5355\u5143\u6d4b\u8bd5":6,"\u5904\u7406\u5668\u6709\u4e24\u4e2a\u5173\u952e\u6027\u80fd\u9650\u5236":37,"\u5904\u7406\u7684\u8f93\u5165\u5e8f\u5217\u4e3b\u8981\u5206\u4e3a\u4ee5\u4e0b\u4e09\u79cd\u7c7b\u578b":41,"\u5907\u6ce8":37,"\u590d\u6742\u5ea6\u6216\u65f6\u95f4\u590d\u6742\u5ea6":37,"\u5916\u5c42\u5e8f\u5217\u5728":19,"\u5916\u5c42memory\u662f\u4e00\u4e2a\u5143\u7d20":39,"\u5916\u5c42outer_step\u4e2d":39,"\u591a\u4e2a":20,"\u591a\u4e2a\u5c42\u7684\u8f93\u51fa\u77e9\u9635\u7684\u9ad8\u5ea6\u4e0d\u4e00\u81f4\u5bfc\u81f4\u62fc\u63a5\u5931\u8d25":11,"\u591a\u4e2a\u6392\u6210\u4e00\u5217\u7684\u5143\u7d20":19,"\u591a\u4e2a\u8f93\u51fa\u5c42\u5904\u7406\u591a\u4e2a\u4e0d\u540c\u957f\u5ea6\u7684\u5e8f\u5217":11,"\u591a\u4e2aip\u4f7f\u7528":21,"\u591a\u53e5\u8bdd\u8fdb\u4e00\u6b65\u6784\u6210\u4e86\u6bb5\u843d":41,"\u591a\u673a\u8bad\u7ec3":11,"\u591a\u7528\u4e8e\u81ea\u7136\u8bed\u8a00\u5904\u7406\u4efb\u52a1":20,"\u591a\u8f6e\u5bf9\u8bdd\u7b49\u66f4\u4e3a\u590d\u6742\u7684\u8bed\u8a00\u6570\u636e":41,"\u5927\u4e8e\u7b49\u4e8e\u4e00\u4e2a":20,"\u5927\u591a\u6570\u5c42\u4e0d\u9700\u8981\u8fdc\u7a0b\u7a00\u758f\u8bad\u7ec3\u51fd\u6570":6,"\u5927\u591a\u6570\u5c42\u9700\u8981\u8bbe\u7f6e\u4e3a":6,"\u5927\u591a\u6570\u7f51\u7edc\u5c42\u4e0d\u9700\u8981\u652f\u6301\u8fdc\u7a0b\u7a00\u758f\u66f4\u65b0":6,"\u5927\u5bb6\u53ef\u4ee5\u7528\u628a\u5f00\u53d1\u5de5\u5177\u5b89\u88c5\u8fdb\u5165":0,"\u5927\u5bb6\u53ef\u4ee5\u901a\u8fc7\u5b83\u9605\u8bfb\u6559\u7a0b":1,"\u5927\u5c0f\u4e0d\u4e00\u6837\u65f6":11,"\u5927\u6982\u82b1\u5341\u5206\u949f\u770b\u4e00\u4e0b":0,"\u5929":39,"\u5929\u4e00\u5e7f\u573a":39,"\u5929\u4e00\u9601":39,"\u5934\u4fe1\u606f\u4e2d":13,"\u5934\u6587\u4ef6\u4e2d\u628a\u53c2\u6570\u5b9a\u4e49\u4e3a\u7c7b\u7684\u6210\u5458\u53d8\u91cf":6,"\u5934\u6587\u4ef6\u5982\u4e0b":6,"\u597d":39,"\u597d\u5403":39,"\u5982":[4,35,42],"\u5982\u4e0b":21,"\u5982\u4e0b\u56fe\u6240\u793a":[37,39],"\u5982\u4e0b\u6240\u793a":35,"\u5982\u4f55\u5b9e\u73b0\u65b0\u7684\u7f51\u7edc\u5c42":5,"\u5982\u4f55\u8d21\u732e\u4ee3\u7801":5,"\u5982\u4f55\u8d21\u732e\u6587\u6863":5,"\u5982\u679c\u4e00\u4e2a\u7f51\u7edc\u5c42\u9700\u8981\u914d\u7f6e\u7684\u8bdd":6,"\u5982\u679c\u4e0d\u4e3a0":33,"\u5982\u679c\u4e0d\u4f7f\u7528\u5206\u5e03\u5f0f\u5b58\u50a8":21,"\u5982\u679c\u4e0d\u60f3\u4f7f\u7528":7,"\u5982\u679c\u4e0d\u6536\u655b":13,"\u5982\u679c\u4e3a0":33,"\u5982\u679c\u4e3a\u5426\u5219\u662f\u7528openbla":0,"\u5982\u679c\u4e3afals":33,"\u5982\u679c\u4e3atrue":33,"\u5982\u679c\u4e4b\u540e\u60f3\u8981\u91cd\u65b0\u8bbe\u7f6e":0,"\u5982\u679c\u4ec5\u4ec5\u4fee\u6539\u4e00\u4e2a\u6587\u4ef6\u4f46\u63d0\u4ea4\u4e86\u5341\u51e0\u4e2acommit":4,"\u5982\u679c\u4ecd\u7136\u5b58\u5728\u95ee\u9898":3,"\u5982\u679c\u4ed4\u7ec6\u8bbe\u7f6e\u7684\u8bdd":33,"\u5982\u679c\u4f60\u53ea\u9700\u8981\u4f7f\u7528\u7b80\u5355\u7684rnn":42,"\u5982\u679c\u4f60\u60f3\u4f7f\u7528\u8fd9\u4e9b\u7279\u6027":35,"\u5982\u679c\u4f60\u60f3\u8981\u4fdd\u5b58\u67d0\u4e9b\u5c42\u7684\u7279\u5f81\u56fe":33,"\u5982\u679c\u4f60\u6b63\u5728\u5904\u7406\u5e8f\u5217\u6807\u8bb0\u4efb\u52a1":42,"\u5982\u679c\u4f60\u8981\u4e3a\u4e86\u6d4b\u8bd5\u800c\u589e\u52a0\u65b0\u7684\u6587\u4ef6":6,"\u5982\u679c\u4f7f\u7528":20,"\u5982\u679c\u4f7f\u7528\u81ea\u884c":0,"\u5982\u679c\u4f7f\u7528mkl\u5e76\u4e14\u673a\u5668\u542b\u6709avx2\u6307\u4ee4\u96c6":0,"\u5982\u679c\u5173\u95edmkl":0,"\u5982\u679c\u51fa\u73b0\u4ee5\u4e0bpython\u76f8\u5173\u7684\u5355\u5143\u6d4b\u8bd5\u90fd\u8fc7\u4e0d\u4e86\u7684\u60c5\u51b5":8,"\u5982\u679c\u53c2\u6570\u4fdd\u5b58\u4e0b\u6765\u7684\u6a21\u578b\u76ee\u5f55":11,"\u5982\u679c\u53d1\u73b0\u6700\u65e9\u7684\u62a5\u9519\u5c31\u662f\u7f51\u7edc\u901a\u4fe1\u7684\u95ee\u9898":9,"\u5982\u679c\u540c\u65f6\u4f7f\u7528":21,"\u5982\u679c\u5728\u5b89\u88c5\u8fc7\u7a0b\u4e2d\u9047\u5230\u4e86\u95ee\u9898":2,"\u5982\u679c\u5728\u70b9\u51fb\u4e0b\u9762\u94fe\u63a5\u65f6\u51fa\u73b0\u5982\u4e0b\u767b\u9646\u754c\u9762":3,"\u5982\u679c\u5728\u7f16\u8bd1":17,"\u5982\u679c\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d\u672a\u8bbe\u7f6easync":33,"\u5982\u679c\u5728\u8bad\u7ec3\u671f\u95f4\u540c\u65f6\u53d1\u8d77\u53e6\u5916\u4e00\u4e2a\u8fdb\u7a0b\u8fdb\u884c\u6d4b\u8bd5":33,"\u5982\u679c\u5728\u8bad\u7ec3\u914d\u7f6e\u4e2d\u8bbe\u7f6ebatch":33,"\u5982\u679c\u5728\u8bad\u7ec3nlp\u76f8\u5173\u6a21\u578b\u65f6":13,"\u5982\u679c\u5c06\u8fd9\u4e2a\u5185\u5b58\u6c60\u51cf\u5c0f":11,"\u5982\u679c\u5c0f\u4e8e75m":8,"\u5982\u679c\u5df2\u7ecf\u6709pod\u8fd0\u884c":27,"\u5982\u679c\u5e0c\u671b\u53ef\u4ee5\u5728\u540e\u53f0\u8fd0\u884cpserver\u7a0b\u5e8f":21,"\u5982\u679c\u5f53\u524dmpi\u96c6\u7fa4\u5e76\u4e0d\u652f\u6301\u4efb\u52a1\u72ec\u5360\u6a21\u5f0f":9,"\u5982\u679c\u60a8\u5728\u4f7f\u7528window":1,"\u5982\u679c\u60a8\u60f3\u8981\u66f4\u6df1\u5165\u4e86\u89e3deep":1,"\u5982\u679c\u60a8\u671f\u671b\u5728\u7f16\u8bd1\u5b8c\u6210\u540e\u7acb\u5373\u6267\u884c\u6240\u6709\u7684\u5355\u5143\u6d4b\u8bd5":0,"\u5982\u679c\u60a8\u6ca1\u6709\u542c\u8bf4":0,"\u5982\u679c\u60a8\u7684\u7535\u8111\u4e0d\u652f\u6301avx":1,"\u5982\u679c\u60a8\u7684\u95ee\u9898\u672a\u5728\u6b64\u5904":10,"\u5982\u679c\u60a8\u7684gpu\u7406\u8bba\u53ef\u4ee5\u8fbe\u52306":37,"\u5982\u679c\u60a8\u9009\u62e9\u4e0d\u4f7f\u7528docker\u955c\u50cf":0,"\u5982\u679c\u60f3\u4f7f\u7528\u53ef\u89c6\u5316\u7684\u5206\u6790\u5668":37,"\u5982\u679c\u60f3\u5f88\u597d\u7684\u7406\u89e3\u7a0b\u5e8f\u7684\u884c\u4e3a":37,"\u5982\u679c\u60f3\u8981\u4e86\u89e3\u53cc\u5c42rnn\u5728\u5177\u4f53\u95ee\u9898\u4e2d\u7684\u4f7f\u7528":39,"\u5982\u679c\u60f3\u8981\u542f\u7528paddlepaddle\u7684\u5185\u7f6e\u5b9a\u65f6\u5668":37,"\u5982\u679c\u60f3\u8be6\u7ec6\u4e86\u89e3":24,"\u5982\u679c\u6211\u77e5\u9053\u5185\u6838\u82b1\u4e8610ms\u6765\u79fb\u52a81gb\u6570\u636e":37,"\u5982\u679c\u6307\u5b9a\u4e862\u4e2alayer\u4f5c\u4e3a\u8f93\u51fa\u5c42":11,"\u5982\u679c\u63d0\u793a\u6b63\u786e":7,"\u5982\u679c\u652f\u6301\u589e\u52a0\u6b64\u53c2\u6570\u63d0\u4ea4":9,"\u5982\u679c\u662f\u4e00\u4e2a\u5e8f\u5217\u8f93\u5165":19,"\u5982\u679c\u662f\u7528\u7f16\u8bd1\u65f6\u6307\u5b9acpu\u7248\u672c":17,"\u5982\u679c\u6709\u591a\u4e2a\u8f93\u5165":41,"\u5982\u679c\u6709\u591a\u4e2a\u8f93\u5165\u5e8f\u5217":41,"\u5982\u679c\u6709\u9700\u8981\u4fee\u6539\u7684\u5730\u65b9":4,"\u5982\u679c\u671f\u671b\u6267\u884c\u5176\u4e2d\u4e00\u4e2a\u5355\u5143\u6d4b\u8bd5":0,"\u5982\u679c\u672a\u8bbe\u7f6e":33,"\u5982\u679c\u672a\u8bbe\u7f6egpu":35,"\u5982\u679c\u673a\u5668\u4e2d\u5df2\u7ecf\u5b89\u88c5\u8fc7paddlepaddl":0,"\u5982\u679c\u67d0\u4e00\u5757\u6839\u672c\u5c31\u4e0d\u600e\u4e48\u8017\u65f6":37,"\u5982\u679c\u68c0\u67e5\u5230\u5206\u914d\u5728\u4e0d\u540c\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u7684\u53c2\u6570\u7684\u5206\u5e03\u4e0d\u5747\u5300\u6b21\u6570\u5927\u4e8echeck":33,"\u5982\u679c\u6ca1\u6709\u5b89\u88c5nvidia":1,"\u5982\u679c\u6ca1\u6709\u5b9a\u4e49memori":41,"\u5982\u679c\u6ca1\u8fc7":4,"\u5982\u679c\u6d88\u606f\u6570\u636e\u592a\u5c0f":33,"\u5982\u679c\u7528\u516c\u7528\u7684\u7535\u8111\u5f00\u53d1":0,"\u5982\u679c\u7528\u6237\u4e0d\u9700\u8981\u8bbf\u95eelstm\u7684\u4e2d\u95f4\u53d8\u91cf":12,"\u5982\u679c\u7528\u6237\u60f3\u8981\u81ea\u5b9a\u4e49\u521d\u59cb\u5316\u65b9\u5f0f":13,"\u5982\u679c\u7528\u81ea\u5df1\u7684\u7535\u8111\u5f00\u53d1":0,"\u5982\u679c\u771f\u60f3\u6316\u6398\u5185\u6838\u6df1\u5904\u7684\u67d0\u4e2a\u79d8\u5bc6":37,"\u5982\u679c\u795e\u7ecf\u7f51\u7edc\u6709\u591a\u4e2a\u8f93\u5165\u6216\u8005\u591a\u4e2a\u8f93\u51fa":[19,20],"\u5982\u679c\u7a0b\u5e8f\u5d29\u6e83\u4f60\u4e5f\u53ef\u4ee5\u624b\u52a8\u7ec8\u6b62":23,"\u5982\u679c\u7cfb\u7edf\u5b89\u88c5\u4e86\u591a\u4e2apython\u7248\u672c":8,"\u5982\u679c\u7cfb\u7edf\u652f\u6301":[3,8],"\u5982\u679c\u7cfb\u7edf\u652f\u6301\u7684\u662f":[3,8],"\u5982\u679c\u7f16\u8bd1\u65f6\u6307\u5b9a\u7f16\u8bd1cpu\u7248\u672c":17,"\u5982\u679c\u7f16\u8bd1\u65f6\u6307\u5b9a\u7f16\u8bd1gpu\u7248\u672c":17,"\u5982\u679c\u7f51\u7edc\u5c42\u4e0d\u9700\u8981\u8fdc\u7a0b\u7a00\u758f\u66f4\u65b0":6,"\u5982\u679c\u7f51\u7edc\u67b6\u6784\u7b80\u5355":42,"\u5982\u679c\u8981\u542f\u7528gpu":31,"\u5982\u679c\u8981\u8fd0\u884c\u6240\u6709\u7684\u5355\u5143\u6d4b\u8bd5":4,"\u5982\u679c\u89e3\u51b3\u4e86\u67d0\u4e2aissue\u7684\u95ee\u9898":4,"\u5982\u679c\u8bad\u7ec3\u4e00\u4e2apass":13,"\u5982\u679c\u8bad\u7ec3\u8fc7\u7a0b\u7684\u7684cost\u660e\u663e\u9ad8\u4e8e\u8fd9\u4e2a\u5e38\u6570\u8f93\u51fa\u7684cost":13,"\u5982\u679c\u8bbe\u7f6e\u8be5\u53c2\u6570":33,"\u5982\u679c\u8bc4\u5ba1\u610f\u89c1\u6bd4\u8f83\u591a":4,"\u5982\u679c\u8f93\u5165\u662f\u5e8f\u5217\u6570\u636e":19,"\u5982\u679c\u8f93\u51fa\u662f\u4e00\u4e2a\u5e8f\u5217":19,"\u5982\u679c\u8f93\u51fa\u662fno":1,"\u5982\u679c\u8fd0\u884c":8,"\u5982\u679c\u8fd8\u4e0d\u884c":8,"\u5982\u679c\u95ee\u9898\u6ca1\u6709\u5f97\u5230\u89e3\u51b3":2,"\u5982\u679c\u9700\u8981":17,"\u5982\u679c\u9700\u8981\u5728c\u7ef4\u5ea6\u8ba1\u7b97softmax":12,"\u5982\u679c\u9700\u8981\u5b89\u88c5\u652f\u6301gpu\u7684\u7248\u672c":[3,16],"\u5982\u679c\u9700\u8981\u6269\u5927\u77e9\u9635":6,"\u5982\u679c\u9700\u8981\u7f29\u51cf\u77e9\u9635":6,"\u5982\u679c\u9700\u8981\u83b7\u53d6":3,"\u5982\u679clearning_rate\u592a\u5927":13,"\u5982\u679clearning_rate\u592a\u5c0f":13,"\u5982\u679cpaddlepaddle\u5305\u5df2\u7ecf\u5728python\u7684sit":8,"\u5982\u6bcf\u4e2a\u6587\u4ef6\u53ea\u6709\u4e00\u4e2a":4,"\u5982\u795e\u7ecf\u5143\u6fc0\u6d3b\u503c\u7b49":11,"\u5982\u8981build\u8fd9\u4e2a\u5f00\u53d1\u955c\u50cf":4,"\u5982\u9ad8\u4eae\u90e8\u5206":37,"\u5982train":21,"\u5b50":39,"\u5b50\u53e5":41,"\u5b50\u53e5\u7684\u5355\u8bcd\u6570\u548c\u6307\u5b9a\u7684\u4e00\u4e2a\u8f93\u5165\u5e8f\u5217\u4e00\u81f4":41,"\u5b57\u6bb5\u4e2d":27,"\u5b57\u6bb5\u4e3a\u4f8b":11,"\u5b57\u6bb5\u7684\u53d6\u503c":19,"\u5b57\u6bb5\u8868\u793a\u5bb9\u5668\u7684\u73af\u5883\u53d8\u91cf":27,"\u5b57\u6bb5\u8868\u793a\u8fd9\u4e2ajob\u4f1a\u540c\u65f6\u5f00\u542f3\u4e2apaddlepaddle\u8282\u70b9":27,"\u5b58\u50a8":[19,20],"\u5b58\u50a8\u6d6e\u70b9\u7c7b\u578b\u8f93\u5165":20,"\u5b58\u50a8\u7684\u538b\u7f29\u6587\u4ef6":20,"\u5b58\u6570\u6570\u636e":19,"\u5b66\u4e60":0,"\u5b66\u4e60\u7387\u4e3a":13,"\u5b81\u6ce2":39,"\u5b83\u5305\u542b\u4ee5\u4e0b\u51e0\u6b65":6,"\u5b83\u5305\u542b\u4ee5\u4e0b\u53c2\u6570":6,"\u5b83\u53eb\u505a":42,"\u5b83\u53ef\u4ee5\u5e2e\u52a9\u51cf\u5c11\u5206\u53d1\u5ef6\u8fdf":23,"\u5b83\u53ef\u4ee5\u5e2e\u52a9\u6211\u4eec\u683c\u5f0f\u5316\u6e90\u4ee3\u7801":4,"\u5b83\u53ef\u4ee5\u6307\u6d4b\u91cf\u4e00\u4e2a\u7a0b\u5e8f\u7684\u7a7a\u95f4":37,"\u5b83\u53ef\u80fd\u6709\u4e0d\u6b62\u4e00\u4e2a\u6743\u91cd":6,"\u5b83\u5b9a\u4e49\u4e86":42,"\u5b83\u5b9a\u4e49\u89e3\u7801\u7f51\u7edc\u7684":42,"\u5b83\u5c06\u88ab\u5206\u53d1\u5230":23,"\u5b83\u5e76\u4e0d\u662f\u4e00\u4e2a\u5b8c\u6574\u7684recurr":12,"\u5b83\u5e94\u8be5\u6253\u5370\u51fa\u9884\u6d4b\u4f4f\u623f\u6570\u636e\u7684\u6e05\u5355":16,"\u5b83\u652f\u6301\u591a\u7ebf\u7a0b\u66f4\u65b0":6,"\u5b83\u662finteger_value\u7c7b\u578b\u7684":39,"\u5b83\u662finteger_value_sequence\u7c7b\u578b\u7684":39,"\u5b83\u6709\u52a9\u4e8e\u5e2e\u52a9\u9891\u7e41\u4fee\u6539\u548c\u8bbf\u95ee\u5de5\u4f5c\u533a\u6587\u4ef6\u7684\u7528\u6237\u51cf\u5c11\u8d1f\u62c5":23,"\u5b83\u7684":42,"\u5b83\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20":38,"\u5b83\u7684\u8f93\u5165\u4e0e\u7ecf\u8fc7\u5b66\u4e60\u7684\u53c2\u6570\u505a\u5185\u79ef\u5e76\u52a0\u4e0a\u504f\u7f6e":6,"\u5b83\u9996\u5148\u8c03\u7528\u57fa\u6784\u9020\u51fd\u6570":6,"\u5b89\u6392":39,"\u5b89\u88c5\u4e0e\u7f16\u8bd1":43,"\u5b89\u88c5\u4e0e\u7f16\u8bd1c":18,"\u5b89\u88c5\u540e":1,"\u5b89\u88c5\u597ddocker\u4e4b\u540e\u53ca\u53ef\u7528\u4ee5\u4e0b\u547d\u4ee4\u542f\u52a8\u5de5\u5177":7,"\u5b89\u88c5\u597ddocker\u4e4b\u540e\u53ef\u4ee5\u4f7f\u7528\u6e90\u7801\u76ee\u5f55\u4e0b\u7684\u811a\u672c\u6784\u5efa\u6587\u6863":7,"\u5b89\u88c5\u5b8c\u6210\u4e4b\u540e":31,"\u5b89\u88c5\u6587\u6863":14,"\u5b89\u88c5\u65b9\u5f0f\u6765\u5feb\u901f\u5b89\u88c5paddlepaddl":31,"\u5b89\u9759":39,"\u5b8c\u6210":4,"\u5b8c\u6210\u4e0a\u8ff0\u51c6\u5907\u4e4b\u540e":20,"\u5b8c\u6210\u4efb\u610f\u7684\u8fd0\u7b97\u903b\u8f91":41,"\u5b8c\u6210\u540evolume\u4e2d\u7684\u6587\u4ef6\u5185\u5bb9\u5927\u81f4\u5982\u4e0b":27,"\u5b8c\u6210\u5728windows\u4e0a\u5b89\u88c5\u548c\u4f7f\u7528dock":1,"\u5b8c\u6210\u5b89\u88c5":3,"\u5b8c\u6210\u76f8\u5e94\u7684\u8ba1\u7b97":38,"\u5b8c\u6210paddlepaddle\u7684\u5b89\u88c5":14,"\u5b8c\u6574\u4ee3\u7801\u53ef\u4ee5\u53c2\u8003\u793a\u4f8b":11,"\u5b8c\u6574\u4ee3\u7801\u53ef\u4ee5\u67e5\u770b":20,"\u5b8c\u6574\u6e90\u7801\u53ef\u53c2\u8003":13,"\u5b8c\u6574\u7684\u53c2\u6570\u77e9\u9635\u88ab\u5206\u5e03\u5728\u4e0d\u540c\u7684\u53c2\u6570\u670d\u52a1\u5668\u4e0a":6,"\u5b8c\u6574\u7684\u914d\u7f6e\u6587\u4ef6\u5728":42,"\u5b98\u65b9\u6587\u6863":0,"\u5b9a\u4e49\u4e00\u4e2a\u65f6\u95f4\u6b65\u4e4b\u5185rnn\u5355\u5143\u5b8c\u6210\u7684\u8ba1\u7b97":41,"\u5b9a\u4e49\u4e86\u4e00\u4e2a\u53ea\u8bfb\u7684memori":41,"\u5b9a\u4e49\u4e86lstm\u5355\u5143\u5728\u4e00\u4e2a\u65f6\u95f4\u6b65\u5185\u7684\u8ba1\u7b97\u8fc7\u7a0b":12,"\u5b9a\u4e49\u5728\u5916\u5c42":41,"\u5b9a\u4e49\u5f02\u6b65\u8bad\u7ec3\u7684\u957f\u5ea6":33,"\u5b9a\u4e49\u6e90\u8bed\u53e5\u7684\u6570\u636e\u5c42":42,"\u5b9a\u4e49\u7684\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784":20,"\u5b9a\u4e49\u89e3\u7801\u5668\u7684memori":42,"\u5b9a\u4e49\u8f93\u51fa\u51fd\u6570":42,"\u5b9a\u4e49\u95e8\u63a7\u5faa\u73af\u5355\u5143\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u5355\u6b65\u51fd\u6570":42,"\u5b9d\u5854\u7684\u5e95\u7aef\u9700\u8981\u575a\u5b9e\u7684\u57fa\u5ea7\u6765\u652f\u6491":14,"\u5b9e\u73b0\u4e24\u4e2a\u5b8c\u5168\u7b49\u4ef7\u7684\u5168\u8fde\u63a5rnn":39,"\u5b9e\u73b0\u524d\u5411\u4f20\u64ad\u7684\u90e8\u5206\u6709\u4e0b\u9762\u51e0\u4e2a\u6b65\u9aa4":6,"\u5b9e\u73b0\u5355\u6b65\u51fd\u6570":42,"\u5b9e\u73b0\u540e\u5411\u4f20\u64ad\u7684\u90e8\u5206\u6709\u4e0b\u9762\u51e0\u4e2a\u6b65\u9aa4":6,"\u5b9e\u73b0\u6784\u9020\u51fd\u6570":6,"\u5b9e\u73b0\u7684":12,"\u5b9e\u73b0\u7ec6\u8282":6,"\u5b9e\u73b0\u7f51\u7edc\u5c42\u7684\u524d\u5411\u4f20\u64ad":6,"\u5b9e\u73b0\u7f51\u7edc\u5c42\u7684\u540e\u5411\u4f20\u64ad":6,"\u5b9e\u73b0\u8bcd\u8bed\u548c\u53e5\u5b50\u4e24\u4e2a\u7ea7\u522b\u7684\u53cc\u5c42rnn\u7ed3\u6784":41,"\u5b9e\u73b0\u8be5\u5c42\u7684c":6,"\u5b9e\u9645\u4e0a\u4f7f\u7528\u4e86":12,"\u5b9e\u9645\u4e0a\u9700\u8981\u7684\u8f93\u51fa\u7ed3\u679c\u662f\u4e24\u4e2a\u77e9\u9635":11,"\u5ba2\u6237":39,"\u5bb6":39,"\u5bb9\u5668\u8fd0\u884c\u90fd\u8fd0\u884c":27,"\u5bbd\u5ea6":19,"\u5bbd\u5ea6\u4e3a":19,"\u5bbd\u5ea6\u7b49\u4e8e\u914d\u7f6e\u4e2dlayer\u7684s":11,"\u5bc4\u5b58\u5668\u4f7f\u7528\u60c5\u51b5\u548c\u5171\u4eab\u5185\u5b58\u4f7f\u7528\u60c5\u51b5\u80fd\u8ba9\u6211\u4eec\u5bf9gpu\u7684\u6574\u4f53\u4f7f\u7528\u6709\u66f4\u597d\u7684\u7406\u89e3":37,"\u5bf9":[20,39],"\u5bf9\u4e00\u4e2a5\u7ef4\u975e\u5e8f\u5217\u7684\u7a00\u758f01\u5411\u91cf":14,"\u5bf9\u4e00\u4e2a5\u7ef4\u975e\u5e8f\u5217\u7684\u7a00\u758f\u6d6e\u70b9\u5411\u91cf":14,"\u5bf9\u4e8e":42,"\u5bf9\u4e8e\u4e0d\u540c\u7684\u8bad\u7ec3\u4efb\u52a1":21,"\u5bf9\u4e8e\u4e24\u79cd\u4e0d\u540c\u7684\u8f93\u5165\u6570\u636e\u7c7b\u578b":39,"\u5bf9\u4e8e\u4e60\u60ef\u4f7f\u7528windows\u548cmacos\u7684\u5f00\u53d1\u8005\u6765\u8bf4":0,"\u5bf9\u4e8e\u5355\u5c42rnn":39,"\u5bf9\u4e8e\u5355\u5c42rnn\u7684\u6570\u636e\u4e00\u5171\u6709\u4e24\u4e2a\u6837\u672c":39,"\u5bf9\u4e8e\u53cc\u5c42rnn":39,"\u5bf9\u4e8e\u540c\u6837\u7684\u6570\u636e":39,"\u5bf9\u4e8e\u56fd\u5185\u7528\u6237":1,"\u5bf9\u4e8e\u6211\u4eec\u652f\u6301\u7684\u5168\u90e8\u77e9\u9635\u64cd\u4f5c":6,"\u5bf9\u4e8e\u6709\u5b9a\u5236\u5316\u4e8c\u8fdb\u5236\u6587\u4ef6\u9700\u6c42\u7684\u7528\u6237":2,"\u5bf9\u4e8e\u672c\u6837\u4f8b\u4ee3\u7801":21,"\u5bf9\u4e8e\u6bb5\u843d\u7684\u6587\u672c\u5206\u7c7b":39,"\u5bf9\u4e8e\u6bcf\u4e00\u4e2a\u5355\u5c42rnn\u7684\u6570\u636e":39,"\u5bf9\u4e8e\u8fd9\u6837\u7684\u9700\u6c42":20,"\u5bf9\u4e8e\u914d\u5907\u6709\u6ce8\u610f\u529b\u673a\u5236\u7684\u89e3\u7801\u5668":42,"\u5bf9\u4e8enchw":12,"\u5bf9\u4ee3\u7801\u8fdb\u884c\u6027\u80fd\u5206\u6790":37,"\u5bf9\u4f7f\u7528\u7684\u4e2d\u95f4\u53d8\u91cf\u548c\u8d44\u6e90\u8fdb\u884c\u6e05\u7406\u548c\u91ca\u653e":20,"\u5bf9\u5168\u8fde\u63a5\u5c42\u6765\u8bf4":6,"\u5bf9\u52a0\u8f7d\u9884\u8bad\u7ec3\u53c2\u6570\u7684\u5c42":13,"\u5bf9\u53cc\u5c42\u5e8f\u5217\u6765\u8bb2":19,"\u5bf9\u5df2\u7ecfpush\u5230\u8fdc\u7a0b\u4ed3\u5e93\u7684\u591a\u4e2acommit":4,"\u5bf9\u5e94\u4e00\u4e2a\u5b50\u53e5":41,"\u5bf9\u5e94\u4e00\u4e2a\u8bcd":41,"\u5bf9\u5e94\u4e8e\u8c03\u7528c":19,"\u5bf9\u5e94\u7740\u4e0a\u6587\u63d0\u5230\u7684\u4e00\u7ef4\u6574\u578b\u6570\u7ec4":19,"\u5bf9\u5e94\u7740\u4e0a\u6587\u63d0\u5230\u7684\u4e8c\u7ef4\u6d6e\u70b9\u578b\u77e9\u9635":19,"\u5bf9\u63a8\u8350\u914d\u7f6e\u4e2d\u7684\u9009\u9879\u5efa\u8bae\u6309\u7167\u8bbe\u7f6e":17,"\u5bf9\u6bcf\u4e2a\u8f93\u5165":6,"\u5bf9\u6bcf\u4e2a\u8f93\u5165\u4e58\u4e0a\u53d8\u6362\u77e9\u9635":6,"\u5bf9\u6fc0\u6d3b\u6c42\u5bfc":6,"\u5bf9\u795e\u7ecf\u7f51\u7edc\u6765\u8bf4":19,"\u5bf9\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u8fdb\u884c\u5e8f\u5217\u5316":20,"\u5bf9\u8bc4\u5ba1\u610f\u89c1\u4e0d\u540c\u610f\u7684":4,"\u5bf9\u8bc4\u5ba1\u610f\u89c1\u540c\u610f\u4e14\u6309\u5176\u4fee\u6539\u5b8c\u7684":4,"\u5bf9\u8c61":13,"\u5bf9\u8c61\u5206\u914d\u7a7a\u95f4":20,"\u5bf9\u8f93\u5165\u6570\u636e\u7684\u683c\u5f0f\u505a\u6e05\u6670\u7b80\u6d01\u7684\u5c01\u88c5":18,"\u5bf9\u8f93\u51fa\u7684\u5408\u5e76":41,"\u5bf9\u9762":39,"\u5bf9sparse_binary_vector\u548csparse_float_vector":14,"\u5bfc\u81f4\u4e86\u6d6e\u70b9\u6570\u6ea2\u51fa":11,"\u5bfc\u81f4\u53c2\u6570\u6536\u655b\u5230\u4e86\u4e00\u4e9b\u5947\u5f02\u7684\u60c5\u51b5":11,"\u5bfc\u81f4\u53c2\u6570\u7d2f\u52a0":11,"\u5bfc\u81f4\u7f16\u8bd1paddlepaddle\u5931\u8d25":8,"\u5bfc\u81f4\u8bad\u7ec3\u65f6\u95f4\u8fc7\u957f":13,"\u5bfc\u81f4mklml\u5e93\u4e0b\u8f7d\u4e0d\u6210\u529f":8,"\u5c01\u88c5\u4e86":37,"\u5c01\u88c5\u8be5\u5c42\u7684python\u63a5\u53e3":6,"\u5c06":[13,37],"\u5c06\u4e0a\u4e00\u65f6\u95f4\u6b65\u6240\u751f\u6210\u7684\u8bcd\u7684\u5411\u91cf\u6765\u4f5c\u4e3a\u5f53\u524d\u65f6\u95f4\u6b65\u7684\u8f93\u5165":42,"\u5c06\u4f1a\u4f18\u5148\u4f7f\u7528":21,"\u5c06\u4f1a\u81ea\u52a8\u8ba1\u7b97\u51fa\u4e00\u4e2a\u5408\u9002\u7684\u503c":33,"\u5c06\u4f1a\u88ab\u629b\u5f03":21,"\u5c06\u5176\u8bbe\u7f6e\u6210":11,"\u5c06\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217\u6570\u636e\u5148\u53d8\u6362\u6210\u5355\u5c42\u65f6\u95f4\u5e8f\u5217\u6570\u636e":39,"\u5c06\u542b\u6709\u5b50\u53e5":41,"\u5c06\u542b\u6709\u8bcd\u8bed\u7684\u53e5\u5b50\u5b9a\u4e49\u4e3a\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":41,"\u5c06\u56fe\u7247\u5206\u7c7b\u5230":20,"\u5c06\u591a\u53e5\u8bdd\u770b\u6210\u4e00\u4e2a\u6574\u4f53\u540c\u65f6\u4f7f\u7528encoder\u538b\u7f29":39,"\u5c06\u591a\u53f0\u673a\u5668\u7684\u6d4b\u8bd5\u7ed3\u679c\u5408\u5e76":33,"\u5c06\u5b57\u5178\u7684\u5730\u5740\u4f5c\u4e3aargs\u4f20\u7ed9dataprovid":13,"\u5c06\u5b83\u4eec\u653e\u5728\u540c\u4e00\u76ee\u5f55\u4e2d":20,"\u5c06\u5bf9\u5e94\u6570\u636e\u5c42\u7684\u7ef4\u6570\u8bbe\u7f6e\u6210\u4e00\u4e2a\u5927\u4e8e\u8f93\u5165\u6570\u636e\u7ef4\u6570\u7684\u503c\u7528\u4e8e\u5360\u4f4d\u5373\u53ef":12,"\u5c06\u5e8f\u5217\u5316\u7ed3\u679c\u5199\u5165\u4e00\u4e2a\u6587\u4ef6\u5185":20,"\u5c06\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u524d\u5411\u548c\u53cd\u5411\u90e8\u5206\u6df7\u5408\u5728\u4e00\u8d77":42,"\u5c06\u6570\u636e\u5207\u5206\u6210\u591a\u4efd":21,"\u5c06\u65b0\u5efa\u7684\u6743\u91cd\u52a0\u5165\u6743\u91cd\u8868":6,"\u5c06\u660e\u6587\u53c2\u6570\u8f6c\u5316\u4e3apaddlepaddle\u53ef\u52a0\u8f7d\u7684\u6a21\u578b\u53c2\u6570\u65f6":13,"\u5c06\u672c\u5730\u7684\u4fee\u6539\u63a8\u9001\u5230":4,"\u5c06\u6b64\u76ee\u5f55\u6302\u8f7d\u4e3a\u5bb9\u5668\u7684":27,"\u5c06\u73af\u5883\u53d8\u91cf\u8f6c\u6362\u6210paddle\u7684\u547d\u4ee4\u884c\u53c2\u6570":27,"\u5c06\u7ed3\u679c\u4fdd\u5b58\u5230\u6b64\u76ee\u5f55\u91cc":27,"\u5c06\u7f51\u7edc\u7ed3\u6784\u5b9a\u4e49\u548c\u8bad\u7ec3\u7ed3\u675f\u5b58\u50a8\u4e0b\u6765\u7684\u6a21\u578b\u53c2\u6570\u6587\u4ef6":20,"\u5c06\u8bad\u7ec3\u6587\u4ef6\u4e0e\u5207\u5206\u597d\u7684\u6570\u636e\u4e0a\u4f20\u5230\u5171\u4eab\u5b58\u50a8":27,"\u5c06\u8df3\u8fc7\u5206\u53d1\u9636\u6bb5\u76f4\u63a5\u542f\u52a8\u6240\u6709\u8282\u70b9\u7684\u96c6\u7fa4\u4f5c\u4e1a":23,"\u5c06\u8fd9\u79cd\u8de8\u8d8a\u65f6\u95f4\u6b65\u7684\u8fde\u63a5\u7528\u4e00\u4e2a\u7279\u6b8a\u7684\u795e\u7ecf\u7f51\u7edc\u5355\u5143\u5b9e\u73b0":39,"\u5c06\u8fdc\u7a0b\u4ed3\u5e93":4,"\u5c06\u900f\u660e":23,"\u5c06\u9700\u8981\u8f93\u51fa\u7684\u5c42\u4f5c\u4e3a":11,"\u5c06cuda\u5e93\u548clinux\u8bbe\u5907\u6302\u8f7d\u5230docker\u5bb9\u5668\u5185":1,"\u5c06ip\u6392\u5e8f\u751f\u6210\u7684\u5e8f\u53f7\u4f5c\u4e3atrain":27,"\u5c06node\u8282\u70b9\u7684ip\u5730\u5740\u4fdd\u5b58\u5230machines\u6587\u4ef6\u4e2d":28,"\u5c06paddlepaddle\u4fdd\u5b58\u7684\u6a21\u578b\u53c2\u6570\u8fd8\u539f\u56de\u660e\u6587\u65f6":13,"\u5c06recurr":12,"\u5c1a\u53ef":39,"\u5c31":39,"\u5c31\u4f1a\u5728\u5b8c\u6210\u7f16\u8bd1\u4e4b\u540e":0,"\u5c31\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u7684\u547d\u4ee4\u5f00\u59cb\u6267\u884c\u8bad\u7ec3":1,"\u5c31\u53ef\u4ee5\u6309":0,"\u5c31\u5c06\u8fd9\u4e9b\u5c42\u52a0\u5165\u4e00\u4e2apython":20,"\u5c31\u5f88\u5bb9\u6613\u5bfc\u81f4\u5185\u5b58\u8d85\u9650":11,"\u5c31\u662f":39,"\u5c31\u662f\u7528\u4e8e\u5c55\u793a\u4e0a\u8ff0\u5206\u6790\u5de5\u5177\u7684\u7528\u6cd5":37,"\u5c31\u662fpaddlepaddle\u4e2d\u6240\u6307\u7684":19,"\u5c31\u8fd9\u4e48\u7b80\u5355":1,"\u5c31\u901a\u5e38\u7684gpu\u6027\u80fd\u5206\u6790\u6765\u8bf4":37,"\u5c31\u9700\u8981\u9009\u62e9\u4f7f\u7528no":1,"\u5c42\u524d\u5411\u8ba1\u7b97\u7684\u7ed3\u679c":20,"\u5c42\u548c\u8f93\u5165\u7684\u914d\u7f6e":6,"\u5c42\u6b21\u5316\u7684rnn":41,"\u5c42\u7684\u540d\u79f0\u4e0e":42,"\u5c42\u7684\u5927\u5c0f":6,"\u5c42\u7684\u7c7b\u578b":6,"\u5c42\u7684\u8f93\u51fa\u88ab\u7528\u4f5c\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684":42,"\u5c45\u7136":39,"\u5c55\u793a\u4e86\u4e00\u4e2a\u542b\u67094\u4e2a\u5e8f\u5217\u7684":19,"\u5c55\u793a\u4e86\u90e8\u5206\u547d\u4ee4\u884c\u53c2\u6570\u7684\u4f7f\u7528":34,"\u5c5e\u4e8e\u8fd9\u4e00\u7c7b\u7684\u5b9e\u73b0":12,"\u5de5\u4f5c\u6a21\u5f0f":33,"\u5de5\u4f5c\u7a7a\u95f4\u4e2d\u7684":23,"\u5de5\u4f5c\u7a7a\u95f4\u5e94\u5982\u4e0b\u6240\u793a":21,"\u5de5\u5177\u670d\u52a1\u5668\u5c06\u8bfb\u53d6\u73af\u5883\u53d8\u91cf":7,"\u5de5\u5177\u6765\u7ba1\u7406":4,"\u5de5\u5177\u6765\u7f16\u8bd1\u6587\u6863":7,"\u5df2\u6253\u5f00":4,"\u5df2\u7ecf\u5728\u96c6\u7fa4\u63d0\u4ea4\u73af\u5883\u4e2d\u5b8c\u6210\u8bbe\u7f6e":33,"\u5e02\u9762\u4e0a\u5df2\u7ecf\u6709nvidia\u6216\u7b2c\u4e09\u65b9\u63d0\u4f9b\u7684\u4f17\u591a\u5de5\u5177":37,"\u5e0c\u671b\u80fd\u591f\u5c06\u5e8f\u5217\u5316\u540e\u7684\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u548c\u8bad\u7ec3\u597d\u7684\u6a21\u578b\u53c2\u6570\u6253\u5305\u8fdb\u4e00\u4e2a\u6587\u4ef6":20,"\u5e2e\u52a9\u6211\u4eec\u5b8c\u6210\u5bf9\u8f93\u5165\u5e8f\u5217\u7684\u62c6\u5206":41,"\u5e2e\u52a9\u6211\u4eec\u66f4\u597d\u5730\u63cf\u8ff0\u6bb5\u843d":41,"\u5e2e\u52a9\u6211\u4eec\u6784\u9020\u4e00\u4e9b\u590d\u6742\u7684\u8f93\u5165\u4fe1\u606f":38,"\u5e38\u5e38\u51fa\u73b0":8,"\u5e38\u7528\u4e8e\u81ea\u7136\u8bed\u8a00\u5904\u7406\u4efb\u52a1":19,"\u5e38\u89c1\u95ee\u9898\u89e3\u7b54":2,"\u5e72\u51c0":39,"\u5e76\u4e0d\u4fdd\u8bc1":6,"\u5e76\u4e0d\u662f\u4f7f\u7528\u53cc\u5c42rnn\u89e3\u51b3\u5b9e\u9645\u7684\u95ee\u9898":39,"\u5e76\u4e0d\u662fkubernetes\u4e2d\u7684node\u6982\u5ff5":27,"\u5e76\u4e0d\u771f\u6b63":[19,20],"\u5e76\u4e0d\u771f\u6b63\u7684\u548c":39,"\u5e76\u4e0d\u96be":0,"\u5e76\u4e14":42,"\u5e76\u4e14\u4e5f\u53ef\u4ee5\u5728windows\u7684docker\u4e2d\u8fd0\u884c":1,"\u5e76\u4e14\u5185\u5c42\u7684\u5e8f\u5217\u64cd\u4f5c\u4e4b\u95f4\u72ec\u7acb\u65e0\u4f9d\u8d56":39,"\u5e76\u4e14\u52a0\u4e0a\u4e0b\u9762\u7684\u547d\u4ee4\u884c\u53c2\u6570":35,"\u5e76\u4e14\u5305\u62ecunit":4,"\u5e76\u4e14\u53ef\u80fd\u4f1a\u52a0\u901f\u8bad\u7ec3\u8fc7\u7a0b":11,"\u5e76\u4e14\u542f\u52a8\u8bad\u7ec3":27,"\u5e76\u4e14\u5c55\u793a\u4e86\u5982\u4f55\u5229\u7528paddlepaddle\u6765\u89e3\u51b3\u4e00\u4e2a\u7ecf\u5178\u7684\u7ebf\u6027\u56de\u5f52\u95ee\u9898":14,"\u5e76\u4e14\u67e5\u8be2paddlepaddle\u5355\u5143\u6d4b\u8bd5\u7684\u65e5\u5fd7":8,"\u5e76\u4e14\u7f16\u8bd1\u80fd\u901a\u8fc7\u4ee3\u7801\u6837\u5f0f\u68c0\u67e5":4,"\u5e76\u4e14\u8f93\u51fa\u4e00\u4e2a":4,"\u5e76\u4e14\u9700\u8981\u91cd\u5199\u57fa\u7c7b\u4e2d\u7684\u4ee5\u4e0b\u51e0\u4e2a\u865a\u51fd\u6570":6,"\u5e76\u4e14softmax\u5c42\u7684\u4e24\u4e2a\u8f93\u5165\u4e5f\u4f7f\u7528\u4e86\u540c\u6837\u7684\u53c2\u6570":13,"\u5e76\u4f7f\u7528":23,"\u5e76\u4fdd\u5b58\u8f93\u51fa\u5230\u4e00\u4e2a\u65e5\u5fd7\u6587\u4ef6":21,"\u5e76\u5177\u5907\u4ee5\u4e0b\u7279\u70b9":18,"\u5e76\u521b\u5efa\u4e86\u4e00\u4e2a\u65b0\u6587\u4ef6":4,"\u5e76\u521b\u5efaoptim":14,"\u5e76\u53ef\u4ee5\u5728\u5927\u591a\u6570\u4e3b\u6d41\u7684linux\u64cd\u4f5c\u7cfb\u7edf\u4ee5\u53camacos\u4e0a\u6267\u884c":3,"\u5e76\u548c\u53c2\u6570\u670d\u52a1\u5668\u901a\u4fe1":22,"\u5e76\u5728\u4e58\u79ef\u7ed3\u679c\u4e0a\u518d\u52a0\u4e0a\u7ef4\u5ea6\u4e3a":6,"\u5e76\u5728\u6700\u5f00\u59cb\u521d\u59cb\u5316\u4e3a\u8d77\u59cb\u8bcd":42,"\u5e76\u5728\u7c7b\u6784\u5efa\u51fd\u6570\u4e2d\u628a\u5b83\u653e\u5165\u4e00\u4e2a\u7c7b\u6210\u5458\u53d8\u91cf\u91cc":6,"\u5e76\u5728\u8be5layer\u91cc\u91c7\u7528\u7b2c\u4e00\u79cd\u65b9\u5f0f\u8bbe\u7f6e":12,"\u5e76\u5904\u7406\u4e0e\u4e4b\u76f8\u5173\u7684\u6240\u6709\u7ec6\u8282":20,"\u5e76\u5b89\u88c5\u4e86python":8,"\u5e76\u5b89\u88c5\u6700\u65b0":3,"\u5e76\u5b89\u88c5\u6709python2":16,"\u5e76\u5b8c\u6210\u53c2\u6570\u4f18\u5316\u66f4\u65b0":22,"\u5e76\u5bf9\u6bd4\u662f\u5426\u548c\u6b63\u5728\u5b89\u88c5\u7684\u540e\u7f00\u4e00\u81f4":8,"\u5e76\u5bf9\u76f8\u5e94\u7684\u53c2\u6570\u8c03\u7528":6,"\u5e76\u5c06\u5176\u6295\u5c04\u5230":42,"\u5e76\u5c06\u8be5layer\u4e0a\u4e00\u65f6\u95f4\u6b65\u7684\u8f93\u51fa\u4f5c\u4e3a\u81ea\u8eab\u5f53\u524d\u65f6\u95f4\u6b65\u7684\u8f93\u51fa":12,"\u5e76\u624b\u52a8\u751f\u6210download\u6210\u529f\u6807\u7b7e":8,"\u5e76\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4":1,"\u5e76\u628a\u8fd9\u4e2a\u5305\u542b\u4e86\u8bad\u7ec3\u6570\u636e\u7684container\u4fdd\u5b58\u4e3a\u4e00\u4e2a\u65b0\u7684\u955c\u50cf":26,"\u5e76\u66f4\u6362job":9,"\u5e76\u6839\u636e\u5206\u5e03\u5f0f\u8bad\u7ec3\u5e76\u53d1\u6570":21,"\u5e76\u68c0\u67e5\u548c\u9700\u5b89\u88c5\u7684\u5305\u662f\u5426\u5339\u914d":3,"\u5e76\u7c98\u8d34\u6b64python\u4ee3\u7801":16,"\u5e76\u81ea\u52a8\u4e0b\u8f7d\u5b89\u88c5\u4f9d\u8d56\u8f6f\u4ef6":3,"\u5e76\u884c\u5730\u6267\u884c\u6a21\u578b\u7684\u8bad\u7ec3":22,"\u5e76\u884c\u5730\u63a5\u6536\u68af\u5ea6\u548c\u66f4\u65b0\u53c2\u6570":22,"\u5e76\u89c2\u5bdf\u7ed3\u679c":37,"\u5e76\u8bb0\u5f55\u5b83\u7684\u7f16\u53f7":4,"\u5e76\u8fdb\u884c\u521d\u59cb\u5316\u64cd\u4f5c":14,"\u5e8a\u4e0a\u7528\u54c1":39,"\u5e8a\u57ab":39,"\u5e8f\u5217\u4e2d\u542b\u6709\u5143\u7d20\u7684\u6570\u76ee\u540c":38,"\u5e8f\u5217\u4e2d\u7684\u4e00\u4e2a\u5143\u7d20":19,"\u5e8f\u5217\u4e2d\u7684\u5143\u7d20\u662f\u8bcd\u8bed":19,"\u5e8f\u5217\u4e2d\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20\u53c8\u662f\u4e00\u4e2a\u5e8f\u5217":19,"\u5e8f\u5217\u4e2d\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u975e\u5e8f\u5217":19,"\u5e8f\u5217\u4fe1\u606f":19,"\u5e8f\u5217\u5316\u795e\u7ecf\u7f51\u7edc\u6a21\u578b\u914d\u7f6e":20,"\u5e8f\u5217\u5316\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u65f6":20,"\u5e8f\u5217\u5316\u7ed3\u679c\u4f1a\u5199\u5165\u5f53\u524d\u8fd0\u884c\u76ee\u5f55\u4e0b\u7684":20,"\u5e8f\u5217\u6570\u636e\u662f\u81ea\u7136\u8bed\u8a00\u5904\u7406\u4efb\u52a1\u9762\u5bf9\u7684\u4e00\u79cd\u4e3b\u8981\u8f93\u5165\u6570\u636e\u7c7b\u578b":41,"\u5e8f\u5217\u662f\u4e00\u79cd\u5e38\u89c1\u7684\u6570\u636e\u7c7b\u578b":38,"\u5e8f\u5217\u751f\u6210\u4efb\u52a1\u5927\u591a\u9075\u5faaencod":41,"\u5e8f\u5217\u751f\u6210\u4efb\u52a1\u7684\u8f93\u5165":41,"\u5e8f\u5217\u7684\u6bcf\u4e2a\u5143\u7d20\u662f\u539f\u6765\u53cc\u5c42\u5e8f\u5217\u6bcf\u4e2asubseq\u5143\u7d20\u7684\u5e73\u5747\u503c":38,"\u5e8f\u5217\u8f93\u5165":19,"\u5e8f\u5217\u8f93\u5165\u65f6\u7b49\u4e8e":11,"\u5e8f\u5217\u8f93\u5165\u793a\u610f\u56fe":19,"\u5e93\u6709\u81ea\u5df1\u72ec\u7acb\u7684\u52a8\u6001\u5e93\u6587\u4ef6":17,"\u5e94\u7528\u524d\u5411\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":42,"\u5e94\u7528\u53cd\u5411\u9012\u5f52\u795e\u7ecf\u7f51\u7edc":42,"\u5e94\u80fd\u53cd\u6620\u5f53\u524dcommit\u7684\u5185\u5bb9":4,"\u5e94\u8be5":39,"\u5e94\u8be5\u4e0e\u5b83\u7684memory\u540d\u5b57\u76f8\u540c":42,"\u5e94\u8be5\u8bf4\u8c22\u8c22":4,"\u5e94\u8be5\u964d\u4f4e\u5b66\u4e60\u7387":13,"\u5e95\u5c42\u8fdb\u7a0b":23,"\u5efa\u7acb\u4e00\u4e2a":4,"\u5efa\u8bae":4,"\u5efa\u8bae\u5c06\u8be5\u53c2\u6570\u8bbe\u4e3atrue":33,"\u5f00\u53d1\u4eba\u5458\u4f7f\u7528":4,"\u5f00\u53d1\u5206\u652f":3,"\u5f00\u53d1\u6807\u51c6":43,"\u5f00\u53d1\u8005\u4f7f\u7528":0,"\u5f00\u53d1\u955c\u50cf":4,"\u5f00\u53d1\u9884\u6d4b\u5e8f":20,"\u5f00\u53d1\u9884\u6d4b\u7a0b\u5e8f\u94fe\u63a5":17,"\u5f00\u542f":0,"\u5f00\u5934\u7684\u90e8\u5206":21,"\u5f00\u5934\u90e8\u5206\u6307\u5b9a":21,"\u5f00\u59cb\u6807\u8bb0":42,"\u5f00\u59cb\u795e\u7ecf\u7f51\u7edc\u7684":22,"\u5f00\u59cb\u9636\u6bb5":37,"\u5f02\u6b65\u968f\u673a\u68af\u5ea6\u4e0b\u964d":32,"\u5f02\u6b65sgd\u66f4\u65b0\u7684\u6b65\u957f\u63a7\u5236":21,"\u5f15\u5bfc\u5c42":42,"\u5f15\u7528memory\u5f97\u5230\u8fd9layer\u4e0a\u4e00\u65f6\u523b\u8f93\u51fa":41,"\u5f3a\u70c8\u63a8\u8350":39,"\u5f52\u4e00\u5316\u6982\u7387\u5411\u91cf":42,"\u5f53":35,"\u5f53\u4e00\u4e2a":19,"\u5f53\u4e0a\u8ff0\u63a5\u53e3\u7b2c4\u4e2a\u53c2\u6570":19,"\u5f53\u4f60\u6267\u884c\u547d\u4ee4":6,"\u5f53\u4fdd\u5b58\u7684\u7f51\u7edc\u53c2\u6570\u4e3afloat\u7c7b\u578b\u65f6\u4e3a4":13,"\u5f53\u524d\u65f6\u95f4\u6b65\u5904\u7684memory\u7684\u8f93\u51fa\u4f5c\u4e3a\u4e0b\u4e00\u65f6\u95f4\u6b65memory\u7684\u8f93\u5165":42,"\u5f53\u524d\u7684\u5b66\u4e60\u7387\u4e3a\u6240\u8bbe\u7f6e":13,"\u5f53\u524d\u7684\u5b9e\u73b0\u65b9\u5f0f\u4e0b":6,"\u5f53\u524d\u7684\u8f93\u5165y\u548c\u4e0a\u4e00\u4e2a\u65f6\u95f4\u6b65\u7684\u8f93\u51farnn_state\u505a\u4e86\u4e00\u4e2a\u5168\u94fe\u63a5":39,"\u5f53\u524d\u8bad\u7ec3\u4efb\u52a1\u542f\u52a8\u7684pserver\u7684ip\u5217\u8868":21,"\u5f53\u524d\u8bad\u7ec3\u4efb\u52a1pserver\u603b\u6570":21,"\u5f53\u524d\u8bad\u7ec3\u4efb\u52a1trainer\u603b\u6570":21,"\u5f53\u524dtrainer\u7684\u7ebf\u7a0b\u6570\u76ee":21,"\u5f53\u5728\u7f51\u7edc\u5c42\u914d\u7f6e\u4e2d\u8bbe\u7f6e":33,"\u5f53\u5728\u8bad\u7ec3\u914d\u7f6e\u4e2d\u8bbe\u7f6e":33,"\u5f53\u5df2\u8bad\u7ec3\u6837\u672c\u6570\u5927\u4e8e1000\u5c0f\u4e8e\u7b49\u4e8e2000\u65f6":13,"\u5f53\u5df2\u8bad\u7ec3\u6837\u672c\u6570\u5927\u4e8e2000\u65f6":13,"\u5f53\u5df2\u8bad\u7ec3\u6837\u672c\u6570\u5c0f\u4e8e\u7b49\u4e8e1000\u65f6":13,"\u5f53\u5df2\u8bad\u7ec3pass\u6570\u5927\u4e8e1\u5c0f\u4e8e\u7b49\u4e8e2\u65f6":13,"\u5f53\u5df2\u8bad\u7ec3pass\u6570\u5927\u4e8e2\u65f6":13,"\u5f53\u5df2\u8bad\u7ec3pass\u6570\u5c0f\u4e8e\u7b49\u4e8e1\u65f6":13,"\u5f53\u6211\u4eec\u8bad\u7ec3\u5b8c\u4e00\u4e2a\u795e\u7ecf\u7f51\u7edc\u6a21\u578b\u4e4b\u540e":18,"\u5f53\u6240\u6709pod\u90fd\u5904\u4e8erunning\u72b6\u6001":27,"\u5f53\u6a21\u578b\u53c2\u6570\u4e0d\u5b58\u5728\u65f6":33,"\u5f53\u6a21\u5f0f\u4e3a":33,"\u5f53\u7136":[1,37],"\u5f53\u7136\u53ef\u4ee5":0,"\u5f53\u7528\u6237\u6ca1\u6709\u663e\u5f0f\u8bbe\u5b9a\u65f6":12,"\u5f53\u7f51\u7edc\u5c42\u7528\u4e00\u4e2a\u6279\u6b21\u505a\u8bad\u7ec3\u65f6":6,"\u5f53\u89e3\u8bfb\u6bcf\u4e00\u4e2a":42,"\u5f53\u8d85\u8fc7\u8be5\u9608\u503c\u65f6":33,"\u5f53\u8f93\u5165\u662f\u7ef4\u5ea6\u5f88\u9ad8\u7684\u7a00\u758f\u6570\u636e\u65f6":35,"\u5f53\u975e\u5e8f\u5217\u8f93\u5165\u65f6":19,"\u5f53n1":11,"\u5f62\u6210recurr":41,"\u5f62\u6210recurrent\u8fde\u63a5":41,"\u5f88":39,"\u5f88\u591a":[0,39],"\u5f88\u5b89\u9759":39,"\u5f88\u5e72\u51c0":39,"\u5f88\u65b9\u4fbf":39,"\u5f88\u6709\u53ef\u80fd\u5b9e\u9645\u5e94\u7528\u5c31\u662f\u6ca1\u6709\u6309\u7167\u60a8\u7684\u9884\u671f\u60c5\u51b5\u8fd0\u884c":37,"\u5f88\u6709\u53ef\u80fd\u662f\u975e\u72ec\u5360\u65b9\u5f0f\u6267\u884c\u5bfc\u81f4\u7684\u7aef\u53e3\u51b2\u7a81":9,"\u5f97":39,"\u5f97\u5230\u9884\u6d4b\u7ed3\u679c\u7684\u8fc7\u7a0b":18,"\u5faa\u73af\u5c55\u5f00\u7684\u6bcf\u4e2a\u65f6\u95f4\u6b65\u603b\u662f\u80fd\u591f\u5f15\u7528\u6240\u6709\u8f93\u5165":41,"\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u4e2d":42,"\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u4f5c\u4e3a\u4f7f\u7528":42,"\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u548c":42,"\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u5728\u6bcf\u4e2a\u65f6\u95f4\u6b65\u9aa4\u987a\u5e8f\u5730\u5904\u7406\u5e8f\u5217":42,"\u5faa\u73af\u7f51\u7edc\u4ece":42,"\u5fc5\u9009":21,"\u5fc5\u987b":6,"\u5fc5\u987b\u5148\u6267\u884c\u7b2c2\u6b65":0,"\u5fc5\u987b\u5c06\u524d\u4e00\u4e2a\u5b50\u53e5\u7684\u6700\u540e\u4e00\u4e2a\u5143\u7d20":39,"\u5fc5\u987b\u6307\u5411\u4e00\u4e2apaddlepaddle\u5b9a\u4e49\u7684lay":41,"\u5fc5\u987b\u6307\u5b9a\u4e3a":20,"\u5fc5\u987b\u662f\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":41,"\u5fc5\u987b\u662f\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":38,"\u5fc5\u987b\u7531\u53ea\u8bfbmemory\u7684":42,"\u5fc5\u987b\u914d\u7f6e\u4e3a":17,"\u5fc5\u987b\u914d\u7f6e\u9009\u9879":17,"\u5feb":39,"\u5feb\u901f\u5f00\u59cb":15,"\u6027\u4ef7\u6bd4":39,"\u6027\u80fd\u5206\u6790":37,"\u6027\u80fd\u5206\u6790\u5de5\u5177\u662f\u7528\u4e8e\u7ed9\u5e94\u7528\u7a0b\u5e8f\u7684\u6027\u80fd\u505a\u5b9a\u91cf\u5206\u6790\u7684":37,"\u6027\u80fd\u5206\u6790\u662f\u6027\u80fd\u4f18\u5316\u7684\u5173\u952e\u4e00\u6b65":37,"\u6027\u80fd\u548c\u628a\u7f16\u8bd1\u5de5\u5177\u5b89\u88c5\u5728\u672c\u673a\u8fd0\u884c\u4e00\u6837":0,"\u6027\u80fd\u8c03\u4f18":32,"\u603b\u4f53\u6765\u8bf4":39,"\u60a8\u4e5f\u53ef\u4ee5\u8fdb\u5165\u5230docker\u5bb9\u5668\u4e2d":1,"\u60a8\u4f1a\u5728\u63a5\u4e0b\u6765\u7684\u90e8\u5206\u4e2d\u83b7\u5f97\u66f4\u591a\u7684\u7ec6\u8282\u4ecb\u7ecd":37,"\u60a8\u53ef\u4ee5\u4ece\u4e0b\u9762\u7684\u8868\u683c\u4e2d\u627e\u5230\u9700\u8981\u7684\u7248\u672c":3,"\u60a8\u53ef\u4ee5\u4efb\u610f\u4f7f\u7528\u4e00\u4e2a\u6216\u4e24\u4e2a\u6765\u5bf9\u611f\u5174\u8da3\u7684\u4ee3\u7801\u6bb5\u505a\u6027\u80fd\u5206\u6790":37,"\u60a8\u53ef\u4ee5\u5728":[1,24],"\u60a8\u53ef\u4ee5\u5728\u5bb9\u5668\u4e2d\u6267\u884c":1,"\u60a8\u53ef\u4ee5\u5bfc\u5165":37,"\u60a8\u53ef\u4ee5\u6309\u7167\u4e0b\u9762\u7684\u6b65\u9aa4\u5728openmpi\u96c6\u7fa4\u4e2d\u63d0\u4ea4paddle\u8bad\u7ec3\u4efb\u52a1":28,"\u60a8\u53ef\u4ee5\u91c7\u7528\u4e0b\u9762\u4e94\u4e2a\u6b65\u9aa4":37,"\u60a8\u53ef\u80fd\u9700\u8981\u4fee\u6539":21,"\u60a8\u5c06\u4e86\u89e3\u5982\u4f55":42,"\u60a8\u5c31\u80fd\u83b7\u5f97\u5982\u4e0b\u7684\u5206\u6790\u7ed3\u679c":37,"\u60a8\u6309\u5982\u4e0b\u6b65\u9aa4\u64cd\u4f5c\u5373\u53ef":37,"\u60a8\u6700\u597d\u5148\u786e\u8ba4":37,"\u60a8\u9996\u5148\u9700\u8981\u5728\u76f8\u5173\u4ee3\u7801\u6bb5\u4e2d\u52a0\u5165":37,"\u60f3\u4e86\u89e3\u66f4\u591apaddlepaddl":7,"\u610f\u5473\u7740\u4e0d\u540c\u65f6\u95f4\u6b65\u7684\u8f93\u5165\u90fd\u662f\u76f8\u540c\u7684\u503c":42,"\u610f\u601d\u662f\u4e0d\u4f7f\u7528\u5e73\u5747\u53c2\u6570\u6267\u884c\u6d4b\u8bd5":33,"\u610f\u601d\u662f\u4e0d\u4fdd\u5b58\u7ed3\u679c":33,"\u610f\u601d\u662f\u4f7f\u7528\u7b2ctest":33,"\u610f\u601d\u662f\u5728gpu\u6a21\u5f0f\u4e0b\u4f7f\u75284\u4e2agpu":33,"\u611f\u89c9":39,"\u6210\u529f\u7f16\u8bd1\u540e":17,"\u6210\u529f\u8bad\u7ec3\u4e14\u9000\u51fa\u7684pod\u6570\u76ee\u4e3a3\u65f6":27,"\u6211\u4eec\u4e0d\u80fd\u901a\u8fc7\u5e38\u89c4\u7684\u68af\u5ea6\u68c0\u67e5\u7684\u65b9\u5f0f\u6765\u8ba1\u7b97\u68af\u5ea6":6,"\u6211\u4eec\u4e3b\u8981\u4f1a\u4ecb\u7ecdnvprof\u548cnvvp":37,"\u6211\u4eec\u4e5f\u652f\u6301\u5728aws\u4e0a\u90e8\u7f72paddlepaddl":24,"\u6211\u4eec\u4ec5\u4ec5\u5bf9\u795e\u7ecf\u7f51\u7edc\u7684\u8f93\u5165\u8fdb\u884c\u4e86\u63cf\u8ff0":14,"\u6211\u4eec\u4ec5\u6709\u4e00\u4e2a\u8f93\u5165":6,"\u6211\u4eec\u4ecb\u7ecd\u5982\u4f55\u5728":26,"\u6211\u4eec\u4ecb\u7ecd\u5982\u4f55\u5728kubernetes\u96c6\u7fa4\u4e0a\u8fdb\u884c\u5206\u5e03\u5f0fpaddlepaddle\u8bad\u7ec3\u4f5c\u4e1a":27,"\u6211\u4eec\u4ee5\u624b\u5199\u6570\u5b57\u8bc6\u522b\u4efb\u52a1\u4e3a\u4f8b\u8fdb\u884c\u4ecb\u7ecd":20,"\u6211\u4eec\u4f1a\u53ca\u65f6\u8fdb\u884c\u56de\u590d":10,"\u6211\u4eec\u4f1a\u5bf9\u6bcf\u4e2a\u8bad\u7ec3\u4efb\u52a1\u90fd\u4f1a\u5728\u6bcf\u4e2a\u8282\u70b9\u4e0a\u521b\u5efa\u4e00\u4e2a\u5de5\u4f5c\u7a7a\u95f4":21,"\u6211\u4eec\u4f1a\u7ee7\u7eed\u4f7f\u7528\u73b0\u6709\u7684\u5185\u5b58\u5757":6,"\u6211\u4eec\u4f1a\u91cd\u65b0\u5206\u914d\u5185\u5b58":6,"\u6211\u4eec\u4f7f\u7528":6,"\u6211\u4eec\u4f7f\u7528\u4e0d\u540c\u7684layer\u8fdb\u884c\u7ec4\u5408":14,"\u6211\u4eec\u4f7f\u7528\u4e86":39,"\u6211\u4eec\u4f7f\u7528paddl":21,"\u6211\u4eec\u5047\u8bbe\u4e00\u53f0\u673a\u5668\u4e0a\u67094\u4e2agpu":35,"\u6211\u4eec\u5373\u53ef\u5b8c\u6210\u795e\u7ecf\u7f51\u7edc\u7684\u642d\u5efa":14,"\u6211\u4eec\u53ea\u6f14\u793a\u4e00\u4e2a\u5355\u673a\u4f5c\u4e1a":26,"\u6211\u4eec\u53ea\u9700\u8981\u4f7f\u7528lstm":39,"\u6211\u4eec\u53ea\u9700\u8981\u8fd0\u884c\u4e0b\u9762\u547d\u4ee4\u628a\u7f16\u8bd1\u597d\u7684paddlepaddle\u6253\u5305\u6210\u4e00\u4e2a":4,"\u6211\u4eec\u53ea\u9700\u8981\u914d\u7f6e":0,"\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u5176\u4ed6layer\u8fdb\u884c\u7ec4\u5408":14,"\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u5b83\u6765\u751f\u6210\u5e8f\u5217":42,"\u6211\u4eec\u53ef\u4ee5\u521b\u5efatrainer\u6765\u5bf9\u7f51\u7edc\u8fdb\u884c\u8bad\u7ec3":14,"\u6211\u4eec\u53ef\u4ee5\u5728":4,"\u6211\u4eec\u53ef\u4ee5\u5b9a\u4e49\u5982\u4e0b\u7684layer\u7ec4\u5408":14,"\u6211\u4eec\u53ef\u4ee5\u5b9a\u4e49\u5982\u4e0blayer\u6765\u63cf\u8ff0\u795e\u7ecf\u7f51\u7edc\u7684\u8f93\u5165":14,"\u6211\u4eec\u53ef\u4ee5\u6309\u7167\u5982\u4e0b\u5c42\u6b21\u5b9a\u4e49\u975e\u5e8f\u5217":38,"\u6211\u4eec\u53ef\u4ee5\u8bbe\u8ba1\u642d\u5efa\u4e00\u4e2a\u7075\u6d3b\u7684":41,"\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u65e5\u5fd7\u67e5\u770b\u5bb9\u5668\u8bad\u7ec3\u7684\u60c5\u51b5":27,"\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u8bbe\u7f6e":21,"\u6211\u4eec\u540c\u6837\u63d0\u4f9b\u4e86\u4ece\u6e90\u7801\u7f16\u8bd1\u5b89\u88c5paddlepaddle\u7684\u65b9\u6cd5":2,"\u6211\u4eec\u5728\u51fd\u6570\u7684\u7ed3\u5c3e\u8fd4\u56de":42,"\u6211\u4eec\u5bf9\u6a21\u578b\u8fdb\u884c\u4e86\u4ee5\u4e0b\u66f4\u6539":42,"\u6211\u4eec\u5c06":27,"\u6211\u4eec\u5c06\u4e00\u6bb5\u8bdd\u770b\u6210\u53e5\u5b50\u7684\u6570\u7ec4":39,"\u6211\u4eec\u5c06\u4ecb\u7ecd\u5982\u4f55\u542f\u52a8\u5206\u5e03\u5f0f\u8bad\u7ec3\u4f5c\u4e1a":26,"\u6211\u4eec\u5c06\u4f7f\u7528":42,"\u6211\u4eec\u5c06\u4f7f\u7528\u7b80\u5355\u7684":42,"\u6211\u4eec\u5c06\u539f\u59cb\u6570\u636e\u7684\u6bcf\u4e00\u7ec4":39,"\u6211\u4eec\u5c06\u5b83\u4eec\u5212\u5206\u4e3a\u4e0d\u540c\u7684\u7c7b\u522b":32,"\u6211\u4eec\u5c06\u795e\u7ecf\u7f51\u7edc\u4e00\u6b21\u8ba1\u7b97\u63a5\u53d7\u7684\u6240\u6709\u8f93\u5165\u6837\u672c\u79f0\u4e4b\u4e3a\u4e00\u4e2a":19,"\u6211\u4eec\u5c06\u8bad\u7ec3\u7ed3\u675f\u540e\u5b58\u50a8\u4e0b\u6765\u7684\u6a21\u578b\u8f6c\u6362\u6210\u9884\u6d4b\u6a21\u578b":20,"\u6211\u4eec\u5c31\u5b8c\u6210\u4e86\u4e00\u6b21\u4ee3\u7801\u8d21\u732e\u7684\u8fc7\u7a0b":4,"\u6211\u4eec\u5df2\u7ecf\u5b9e\u73b0\u4e86\u5927\u591a\u6570\u5e38\u7528\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u67b6\u6784":42,"\u6211\u4eec\u5efa\u8bae\u4f60\u4e3a\u4f60\u7684python\u5c01\u88c5\u5b9e\u73b0\u4e00\u4e2a":6,"\u6211\u4eec\u5efa\u8bae\u4f60\u5728\u5199\u65b0\u7f51\u7edc\u5c42\u65f6\u628a\u6d4b\u8bd5\u4ee3\u7801\u653e\u5165\u65b0\u7684\u6587\u4ef6\u4e2d":6,"\u6211\u4eec\u5efa\u8bae\u4f7f\u7528\u7b2c\u4e8c\u7c7b\u5b9e\u73b0":12,"\u6211\u4eec\u63a8\u8350\u4f7f\u7528":[1,31],"\u6211\u4eec\u63a8\u8350\u4f7f\u7528\u6700\u65b0\u7248\u672c\u7684cudnn":0,"\u6211\u4eec\u63a8\u8350\u5728docker\u4e2d\u8fd0\u884cpaddlepaddl":2,"\u6211\u4eec\u63d0\u4f9b\u4e86\u4f7f\u7528fabric":24,"\u6211\u4eec\u63d0\u4f9b\u4e86\u52a0\u901f\u8bbf\u95ee\u7684\u955c\u50cf\u6e90":1,"\u6211\u4eec\u63d0\u4f9b\u4e86\u591a\u79cd\u7684\u96c6\u7fa4\u90e8\u7f72\u65b9\u5f0f":24,"\u6211\u4eec\u63d0\u4f9b\u4e86\u5982\u4e0b\u6307\u5357":18,"\u6211\u4eec\u63d0\u4f9b\u53ef\u4ee5\u76f4\u63a5\u8fd0\u884cpaddlepaddl":1,"\u6211\u4eec\u662f\u5bf9\u6bcf\u4e00\u4e2a\u5b50\u5e8f\u5217\u53d6\u6700\u540e\u4e00\u4e2a\u5143\u7d20":39,"\u6211\u4eec\u6709\u4e00\u4e2a\u5e8f\u5217\u4f5c\u4e3a\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u72b6\u6001":42,"\u6211\u4eec\u7684":0,"\u6211\u4eec\u7684\u6807\u51c6\u5f00\u53d1\u6d41\u7a0b\u662f\u628a\u8fd9\u4e9b\u5de5\u5177\u90fd\u88c5\u8fdb\u4e00\u4e2adocker":4,"\u6211\u4eec\u770b\u4e00\u4e0b\u5355\u5c42rnn\u7684\u914d\u7f6e":39,"\u6211\u4eec\u770b\u4e00\u4e0b\u8bed\u4e49\u76f8\u540c\u7684\u53cc\u5c42rnn\u7684\u7f51\u7edc\u914d\u7f6e":39,"\u6211\u4eec\u771f\u8bda\u5730\u611f\u8c22\u60a8\u7684\u8d21\u732e":4,"\u6211\u4eec\u79f0\u4e4b\u4e3a\u4e00\u4e2a0\u5c42\u7684\u5e8f\u5217":38,"\u6211\u4eec\u8fd8\u53ef\u4ee5\u767b\u5f55\u5230\u5bbf\u4e3b\u673a\u4e0a\u67e5\u770b\u8bad\u7ec3\u7ed3\u679c":26,"\u6211\u4eec\u8fd8\u5c06\u7f16\u7801\u5411\u91cf\u6295\u5c04\u5230":42,"\u6211\u4eec\u9009\u53d6\u5355\u53cc\u5c42\u5e8f\u5217\u914d\u7f6e\u4e2d\u7684\u4e0d\u540c\u90e8\u5206":39,"\u6211\u4eec\u901a\u5e38\u5c06\u4e00\u53e5\u8bdd\u7406\u89e3\u6210\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217":39,"\u6211\u4eec\u901a\u8fc7\u8bfb\u53d6":27,"\u6211\u4eec\u9700\u8981":0,"\u6211\u4eec\u9700\u8981\u5236\u4f5c\u4e00\u4e2a\u5305\u542b\u8bad\u7ec3\u6570\u636e\u7684paddlepaddle\u955c\u50cf":26,"\u6211\u4eec\u9700\u8981\u5728\u96c6\u7fa4\u7684\u6240\u6709\u8282\u70b9\u4e0a\u5b89\u88c5":31,"\u6211\u4eec\u9700\u8981\u8ba1\u7b97":6,"\u6211\u4eec\u9996\u5148\u9700\u8981\u6839\u636e\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u6765\u521b\u5efa\u6240\u9700\u8981\u4f18\u5316\u7684paramet":14,"\u6211\u5220\u9664\u4e86":4,"\u6211\u53ef\u4ee5\u7528":0,"\u6211\u53ef\u4ee5\u9009\u62e9\u4e0d\u7528docker\u5417":0,"\u6216":[19,37],"\u6216\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":38,"\u6216\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u53d8\u6210\u4e00\u4e2a0\u5c42\u5e8f\u5217":38,"\u6216\u4e00\u4e2a\u5411\u91cf":41,"\u6216\u5355\u5c42\u5e8f\u5217\u7ecf\u8fc7\u8fd0\u7b97\u53d8\u6210\u4e00\u4e2a0\u5c42\u5e8f\u5217":38,"\u6216\u662f\u5728\u81ea\u7136\u8bed\u8a00\u5904\u7406\u4efb\u52a1\u4e2d\u8868\u793a\u8bcd\u8bed\u5728\u5b57\u5178\u4e2d\u7684\u5e8f\u53f7":19,"\u6216\u6700\u5927\u503c":38,"\u6216\u79f0\u4f5cweight":11,"\u6216\u7b2c\u4e00\u4e2a":38,"\u6216\u7b2c\u4e00\u4e2a\u5143\u7d20":38,"\u6216\u7f16\u5199\u7a0b\u5e8f\u65f6":21,"\u6216\u8005":[0,4,11,19,37,38,39],"\u6216\u8005\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":41,"\u6216\u8005\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":[38,41],"\u6216\u8005\u4e5f\u53ef\u4ee5\u4f7f\u7528\u4e3a\u4e0a\u8ff0\u53ef\u9009\u6b65\u9aa4\u6784\u5efa\u7684\u955c\u50cf":0,"\u6216\u8005\u4ece\u5de5\u5177\u7684\u754c\u9762\u91cc\u8fd0\u884c\u60a8\u7684\u5e94\u7528":37,"\u6216\u8005\u5236\u4f5c\u548c\u5206\u4eab\u5e26\u6709\u4ee3\u7801":1,"\u6216\u8005\u53cd\u5411\u5730\u4ece":42,"\u6216\u8005\u53ef\u88abdns\u89e3\u6790\u7684\u4e3b\u673a\u540d":31,"\u6216\u8005\u5728cpu\u6a21\u5f0f\u4e0b\u4f7f\u75284\u4e2a\u7ebf\u7a0b":33,"\u6216\u8005\u5df2\u7ecf\u5728\u96c6\u7fa4\u63d0\u4ea4\u73af\u5883\u4e2d\u81ea\u52a8\u8bbe\u7f6e":32,"\u6216\u8005\u5f15\u8d77\u884c\u65f6\u9519\u8bef":19,"\u6216\u8005\u6570\u7ec4\u7684\u6570\u7ec4\u8fd9\u4e2a\u6982\u5ff5":39,"\u6216\u8005\u662f\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":38,"\u6216\u8005\u662f\u51fd\u6570\u8c03\u7528\u7684\u9891\u7387\u548c\u8017\u65f6\u7b49":37,"\u6216\u8005\u66f4\u65e9":13,"\u6216\u8005\u6bcf\u4e00\u4e2a\u7cfb\u5217\u91cc\u7684\u7279\u5f81\u6570\u636e":39,"\u6216\u8005\u76f4\u63a5\u6254\u6389\u975e\u5e38\u957f\u7684\u5e8f\u5217":11,"\u6216\u8005\u8f93\u5165\u6570\u636e\u5c3a\u5ea6\u8fc7\u5927":11,"\u6216\u8005\u8fd0\u884c":8,"\u6216\u8005\u91c7\u7528\u5e76\u884c\u8ba1\u7b97\u6765\u52a0\u901f\u67d0\u4e9b\u5c42\u7684\u66f4\u65b0":35,"\u6216gpu":33,"\u622a\u65ad\u5bf9\u8c61\u4e0d\u540c":11,"\u623f":39,"\u623f\u95f4":39,"\u6240\u4ee5":[1,11],"\u6240\u4ee5\u4e0d\u80fd\u91c7\u7528\u7b2c\u4e00\u79cd\u65b9\u5f0f\u5728\u8fd9\u51e0\u4e2alayer\u91cc\u8bbe\u7f6e":12,"\u6240\u4ee5\u505a\u6cd5\u53ef\u4ee5\u6709\u4e24\u79cd":11,"\u6240\u4ee5\u53ef\u4ee5\u7b80\u5316\u5bf9\u73af\u5883\u7684\u8981\u6c42":26,"\u6240\u4ee5\u5916\u5c42\u8f93\u51fa\u7684\u5e8f\u5217\u5f62\u72b6":39,"\u6240\u4ee5\u5bf9":39,"\u6240\u4ee5\u5f00\u53d1\u8005\u9700\u8981\u6839\u636e\u81ea\u5df1\u8bad\u7ec3\u4efb\u52a1\u7684\u5b9e\u9645\u573a\u666f\u5b8c\u6210\u8bad\u7ec3\u6570\u636e\u7684\u5206\u5272\u548c":21,"\u6240\u4ee5\u6027\u80fd\u4e5f\u5c31\u9010\u6b65\u53d8\u6210\u4e86\u6df1\u5ea6\u5b66\u4e60\u9886\u57df\u6700\u91cd\u8981\u7684\u6307\u6807":37,"\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u5728\u8fd9\u4e2a\u57fa\u7840\u4e0a":27,"\u6240\u4ee5\u6211\u4eec\u786e\u4fdd\u53d1\u5e03\u7684\u4e8c\u8fdb\u5236\u5305\u53ef\u4ee5\u652f\u6301\u4e3b\u6d41\u7684linux\u64cd\u4f5c\u7cfb\u7edf":3,"\u6240\u4ee5\u6211\u4eec\u9700\u8981\u5c06\u8f93\u5165\u6570\u636e\u6807\u8bb0\u6210":39,"\u6240\u4ee5\u6211\u4eec\u9ed8\u8ba4\u4f7f\u7528cento":3,"\u6240\u4ee5\u76f8\u6bd4\u4e8erecurr":12,"\u6240\u4ee5\u8fd9\u4e00\u6b65\u662f\u5fc5\u8981\u7684":6,"\u6240\u5bf9\u5e94\u7684\u8bcd\u8868index\u6570\u7ec4":39,"\u6240\u6709\u4ee3\u7801\u5fc5\u987b\u5177\u6709\u5355\u5143\u6d4b\u8bd5":4,"\u6240\u6709\u53c2\u6570\u7f6e\u4e3a\u96f6":33,"\u6240\u6709\u547d\u4ee4\u884c\u9009\u9879\u53ef\u4ee5\u8bbe\u7f6e\u4e3a":23,"\u6240\u6709\u7684":[4,6],"\u6240\u6709\u7684\u5355\u6d4b\u90fd\u4f1a\u88ab\u6267\u884c\u4e00\u6b21":6,"\u6240\u6709\u7684\u64cd\u4f5c\u90fd\u662f\u9488\u5bf9\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65\u6765\u8fdb\u884c\u7684":39,"\u6240\u6709\u7684python\u5c01\u88c5\u90fd\u4f7f\u7528":6,"\u6240\u6709\u7684python\u5c01\u88c5\u90fd\u5728":6,"\u6240\u6709\u7f51\u7edc\u5c42\u7684\u68af\u5ea6\u68c0\u67e5\u5355\u6d4b\u90fd\u4f4d\u4e8e":6,"\u6240\u6709\u8f93\u5165\u5e8f\u5217\u5e94\u8be5\u6709\u76f8\u540c\u7684\u957f\u5ea6":42,"\u624b\u5199\u6570\u5b57\u8bc6\u522b":20,"\u624b\u5199\u6570\u5b57\u8bc6\u522b\u4efb\u52a1\u5b9a\u4e49\u4e86\u4e00\u4e2a\u542b\u6709":20,"\u624b\u52a8\u4e0b\u8f7d\u4e14\u89e3\u538b\u7f29":8,"\u624b\u52a8\u4e0b\u8f7d\u5e76\u5b89\u88c5":8,"\u624d\u53ef\u4ee5\u5b89\u88c5":3,"\u624d\u80fd\u4fdd\u8bc1\u548c\u5355\u5c42\u5e8f\u5217\u7684\u914d\u7f6e\u4e2d":39,"\u624d\u80fd\u53d1\u6325\u5176\u5168\u90e8\u80fd\u529b":37,"\u6253\u5f00":37,"\u6253\u5f00\u6d4f\u89c8\u5668\u8bbf\u95ee\u5bf9\u5e94\u76ee\u5f55\u4e0b\u7684index":7,"\u6267\u884c":[16,17,23],"\u6267\u884c\u4e0a\u8ff0\u4ee3\u7801\u751f\u6210makefile\u6587\u4ef6\u540e":17,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u4ee5\u542f\u52a83\u4e2a\u8282\u70b9\u7684openmpi\u96c6\u7fa4\u548c\u4e00\u4e2a":28,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u5373\u53ef\u5728\u5f53\u524d\u673a\u5668\u4e0a\u5b89\u88c5paddlepaddle\u7684\u8fd0\u884c\u65f6\u73af\u5883":3,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u53ef\u4ee5\u67e5\u770b\u5df2\u7ecf\u5b89\u88c5\u7684\u7248\u672c":31,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u5b8c\u6210\u5feb\u901f\u5b89\u88c5":16,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u7f16\u8bd1cpu":0,"\u6267\u884c\u4e0b\u9762\u7684\u547d\u4ee4\u83b7\u53d6\u6700\u65b0\u7684paddlepaddl":1,"\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\u542f\u52a8\u4f7f\u7528python\u7f16\u5199\u7684trainer\u7a0b\u5e8f":21,"\u6267\u884c\u4ee5\u4e0b\u64cd\u4f5c":42,"\u6267\u884c\u4ee5\u4e0b\u7684\u547d\u4ee4\u542f\u52a8\u4e00\u4e2a\u53c2\u6570\u670d\u52a1\u5668\u5e76\u7b49\u5f85\u548c\u8ba1\u7b97\u8282\u70b9\u7684\u6570\u636e\u4ea4\u4e92":21,"\u6267\u884c\u60a8\u7684\u4ee3\u7801":37,"\u627e\u5230":[0,42],"\u627e\u5230\u4ee5\u4e0a\u76f8\u5173\u7684\u4f8b\u5b50":24,"\u627e\u5230\u6700\u65e9\u62a5\u9519\u7684\u5730\u65b9":9,"\u627e\u5230\u8fd0\u884c\u6162\u7684\u539f\u56e0":37,"\u627e\u5230\u8fd0\u884c\u6162\u7684\u90e8\u5206":37,"\u628a":6,"\u628a\u5de5\u5177\u548c\u914d\u7f6e\u90fd\u5b89\u88c5\u5728\u4e00\u4e2a":0,"\u628a\u8bad\u7ec3\u6570\u636e\u76f4\u63a5\u653e\u5728":26,"\u628a\u8fd9\u4e9b\u5de5\u5177\u5b89\u88c5\u5230\u672c\u673a":0,"\u6295\u5c04\u53cd\u5411rnn\u7684\u7b2c\u4e00\u4e2a\u5b9e\u4f8b\u5230":42,"\u6295\u5c04\u7f16\u7801\u5411\u91cf\u5230":42,"\u62c6\u6210\u4ee5\u4e0a\u4e24\u4e2a\u9759\u6001\u94fe\u63a5\u5e93":17,"\u62c6\u89e3":41,"\u62c6\u89e3\u6210\u7684\u6bcf\u4e00\u53e5\u8bdd\u518d\u901a\u8fc7\u4e00\u4e2alstm\u7f51\u7edc":39,"\u62f7\u8d1d\u5230numpi":11,"\u62f7\u8d1d\u5fc5\u8981\u7684\u6587\u4ef6\u5230head\u8282\u70b9":28,"\u62f7\u8d1d\u8bad\u7ec3\u6570\u636e\u5230\u5404\u81ea\u7684\u8282\u70b9":28,"\u62f7\u8d1d\u8bad\u7ec3\u6587\u4ef6\u5230\u5bb9\u5668\u5185":27,"\u62f7\u8d1d\u8bad\u7ec3\u7a0b\u5e8f\u548c\u5b57\u5178\u6587\u4ef6\u5230\u6bcf\u53f0mpi\u8282\u70b9":28,"\u62fc\u63a5":11,"\u6302\u8f7d\u5230\u5bb9\u5668\u5185\u90e8\u7684":1,"\u6302\u8f7d\u6216\u4e0b\u8f7d\u7684\u8bad\u7ec3\u6570\u636e\u5206\u7247":21,"\u6307\u5411\u4e00\u4e2alayer":41,"\u6307\u5b9a":[11,12,41,42],"\u6307\u5b9a\u4e00\u53f0\u673a\u5668\u4e0a\u4f7f\u7528\u7684\u7ebf\u7a0b\u6570":33,"\u6307\u5b9a\u4e3a":19,"\u6307\u5b9a\u4f7f\u75282":11,"\u6307\u5b9a\u52a0\u8f7d\u7684\u65b9\u5f0f":33,"\u6307\u5b9a\u5c06\u5f53\u524d\u8def\u5f84":1,"\u6307\u5b9a\u7684\u5185\u5bb9\u5b58\u50a8\u5e93\u8fd0\u884c\u547d\u4ee4":7,"\u6307\u5b9a\u7684\u8f93\u5165\u4e0d\u4f1a\u88ab":41,"\u6307\u5b9a\u8981\u8f93\u51fa\u7684\u5b57\u6bb5\u8fdb\u884c\u8f93\u51fa":11,"\u6307\u5b9a\u9700\u8981\u4f7f\u7528\u7684\u5bb9\u5668":1,"\u6307\u5b9acudnn\u7684\u6700\u5927\u5de5\u4f5c\u7a7a\u95f4\u5bb9\u9650":33,"\u6307\u5bf9\u4e8e\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217\u8f93\u5165\u6570\u636e":39,"\u6307\u793a\u4f7f\u7528\u54ea\u4e2agpu\u6838":33,"\u6307\u793a\u5728\u7b80\u5355\u7684recurrentlayer\u5c42\u7684\u8ba1\u7b97\u4e2d\u662f\u5426\u4f7f\u7528\u6279\u5904\u7406\u65b9\u6cd5":33,"\u6307\u793a\u5f53\u6307\u5b9a\u8f6e\u7684\u6d4b\u8bd5\u6a21\u578b\u4e0d\u5b58\u5728\u65f6":33,"\u6307\u793a\u662f\u5426\u4f7f\u7528\u591a\u7ebf\u7a0b\u6765\u8ba1\u7b97\u4e00\u4e2a\u795e\u7ecf\u7f51\u7edc":33,"\u6307\u793a\u662f\u5426\u5f00\u542f\u53c2\u6570\u670d\u52a1\u5668":33,"\u6307\u793a\u662f\u5426\u663e\u793a\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u7684\u7a00\u758f\u53c2\u6570\u5206\u5e03\u7684\u65e5\u5fd7\u7ec6\u8282":33,"\u6307\u793a\u662f\u5426\u68c0\u67e5\u6240\u6709\u53c2\u6570\u670d\u52a1\u5668\u4e0a\u7684\u7a00\u758f\u53c2\u6570\u7684\u5206\u5e03\u662f\u5747\u5300\u7684":33,"\u6309\u542f\u53d1\u5f0f\u635f\u5931\u7684\u5927\u5c0f\u9012\u589e\u6392\u5e8f":33,"\u6309\u7167\u4e0b\u9762\u6b65\u9aa4\u5373\u53ef":27,"\u6309\u7167\u5177\u4f53\u5b9e\u73b0\u65b9\u5f0f\u53ef\u4ee5\u5f52\u7eb3\u4e3a2\u7c7b":12,"\u6309\u7167\u57fa\u672c\u6570\u636e\u7c7b\u578b\u5728paddlepaddle\u5185\u90e8\u7684\u5b9a\u4e49\u548c\u5b9e\u73b0":19,"\u6309\u94ae":4,"\u633a":39,"\u633a\u597d":39,"\u635f\u5931\u51fd\u6570\u5c42":20,"\u6362":39,"\u6392\u6210\u4e00\u5217\u7684\u591a\u4e2a\u5143\u7d20":38,"\u63a5\u4e0a\u4e00\u4e2a\u5168\u8fde\u63a5\u5c42":14,"\u63a5\u4e0a\u5e73\u65b9\u8bef\u5dee\u5c42":14,"\u63a5\u4e0b\u6765\u53ef\u4ee5\u8003\u8651\u4e0b\u65f6\u95f4\u7ebf\u7684\u5206\u6790":37,"\u63a5\u4e0b\u6765\u5c31\u53ef\u4ee5\u4f7f\u7528":37,"\u63a5\u4e0b\u6765\u6211\u4eec\u521b\u5efa\u4e00\u4e2a\u539f\u59cb":4,"\u63a5\u4e0b\u6765\u6211\u4eec\u53d6\u6d88\u5bf9":4,"\u63a5\u4e0b\u6765\u7b49\u5f85":4,"\u63a5\u53e3":20,"\u63a5\u53e3\u5b8c\u6210\u795e\u7ecf\u7f51\u7edc\u7684\u524d\u5411\u8ba1\u7b97":20,"\u63a5\u53e3\u5bf9\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u548c\u8bad\u7ec3\u597d\u7684\u53c2\u6570\u8fdb\u884c\u5e8f\u5217\u5316":20,"\u63a5\u53e3\u6709\u4e00\u4e2a":11,"\u63a5\u53e3\u7684":11,"\u63a5\u53e3\u8bf4\u660e\u8bf7\u67e5\u770b":19,"\u63a5\u6536\u5230\u8db3\u591f\u7684gradient":21,"\u63a5\u7740\u5bf9\u6240\u6709\u53c2\u6570\u7684\u4f7f\u7528\u573a\u5408\u8fdb\u884c\u6982\u8ff0\u548c\u5206\u7c7b":34,"\u63a5\u7740\u7f16\u8bd1\u5373\u53ef":8,"\u63a7\u5236":33,"\u63a8\u5bfc\u8be5\u5c42\u524d\u5411\u548c\u540e\u5411\u4f20\u9012\u7684\u65b9\u7a0b":6,"\u63a8\u8350":39,"\u63a8\u8350\u4f7f\u7528\u6b64\u65b9\u5f0f":17,"\u63a8\u8350\u4f7f\u7528centos\u7684devtools2":0,"\u63a8\u8350\u6e05\u7406\u6574\u4e2a\u7f16\u8bd1\u76ee\u5f55":0,"\u63a8\u8350\u8bbe\u7f6e\u4e3a":17,"\u63a8\u8350\u914d\u7f6e\u4e3a":17,"\u63a8\u8350\u914d\u7f6e\u9009\u9879":17,"\u63a8\u9001\u5230\u8fdc\u7a0b\u4ed3\u5e93":4,"\u63cf\u8ff0\u7684\u9ed8\u8ba4\u5165\u53e3\u7a0b\u5e8f":0,"\u63cf\u8ff0\u95ee\u9898":4,"\u63d0\u4ea4\u65b9\u5f0f\u53c2\u89c1":7,"\u63d0\u4ea4pull":4,"\u63d0\u4f9b":23,"\u63d0\u4f9b\u4e86\u4e00\u4e2a\u542f\u52a8\u811a\u672c":27,"\u63d0\u4f9b\u4e86\u547d\u4ee4\u6837\u4f8b\u6765\u8fd0\u884c":23,"\u63d0\u4f9b\u4e86\u81ea\u52a8\u5316\u811a\u672c\u6765\u542f\u52a8\u4e0d\u540c\u8282\u70b9\u4e2d\u7684\u6240\u6709":23,"\u63d0\u4f9b\u51e0\u4e4e\u6240\u6709\u8bad\u7ec3\u7684\u5185\u90e8\u8f93\u51fa\u65e5\u5fd7":23,"\u63d0\u4f9b\u6269\u5c55\u7684\u957f\u5ea6\u4fe1\u606f":38,"\u63d0\u4f9b\u8bad\u7ec3\u8fc7\u7a0b\u7684":23,"\u63d0\u793a":8,"\u641c\u7d22\u4ee3\u7801\u5e93":7,"\u642d\u5efa\u795e\u7ecf\u7f51\u7edc\u5c31\u50cf\u4f7f\u7528\u79ef\u6728\u642d\u5efa\u5b9d\u5854\u4e00\u6837":14,"\u64cd\u4f5c":39,"\u64cd\u4f5c\u7cfb\u7edf":[0,3],"\u652f\u6301\u4e24\u79cd\u5e8f\u5217\u7c7b\u578b":19,"\u652f\u6301\u53cc\u5c42\u5e8f\u5217\u4f5c\u4e3a\u8f93\u5165\u7684layer":[40,41],"\u652f\u6301\u5927\u89c4\u6a21\u96c6\u7fa4\u751f\u4ea7\u73af\u5883\u7684\u5b8c\u6574\u96c6\u7fa4\u65b9\u6848":24,"\u652f\u6301\u7ef4\u6570\u53ef\u53d8\u7684\u6570\u636e\u8f93\u5165":12,"\u6539\u53d8\u7ef4\u5ea6\u987a\u5e8f":12,"\u653e\u5728\u8fd9\u4e2a\u76ee\u5f55\u91cc\u7684\u6587\u4ef6\u5176\u5b9e\u662f\u4fdd\u5b58\u5230\u4e86mfs\u4e0a":27,"\u653e\u5fc3":39,"\u6545\u800c\u662f\u4e00\u4e2a\u5355\u5c42\u65f6\u95f4\u5e8f\u5217":39,"\u6559\u7a0b":1,"\u6570":41,"\u6570\u5b66\u5e93":17,"\u6570\u5fc5\u987b\u4e25\u683c\u76f8\u7b49":41,"\u6570\u636e":[19,20],"\u6570\u636e\u4e2d0":13,"\u6570\u636e\u5206\u7247":22,"\u6570\u636e\u63d0\u4f9b\u5668":32,"\u6570\u636e\u8f93\u5165":[19,41],"\u6570\u636e\u96c6":20,"\u6570\u76ee":35,"\u6574\u4e2a\u5b89\u88c5\u8fc7\u7a0b\u8017\u65f6\u8f83\u957f":2,"\u6574\u4f53":39,"\u6574\u4f53\u4f7f\u7528\u6d41\u7a0b":20,"\u6574\u4f53\u6570\u636e\u548c\u539f\u59cb\u6570\u636e\u5b8c\u5168\u4e00\u6837":39,"\u6574\u4f53\u7684\u7ed3\u6784\u56fe\u5982\u4e0b":27,"\u6574\u578b\u6570\u7ec4":19,"\u6574\u6570":6,"\u6574\u6570\u6807\u7b7e":14,"\u6574\u6d01":39,"\u6587\u4ef6":[4,19,26],"\u6587\u4ef6\u4e2d":[20,27],"\u6587\u4ef6\u4e3a":11,"\u6587\u4ef6\u4e4b\u5916":4,"\u6587\u4ef6\u540d\u4e3a\u4efb\u610f\u6587\u4ef6\u540d":21,"\u6587\u4ef6\u59390":27,"\u6587\u4ef6\u5de5\u5177\u662f\u4f7f\u7528docker":7,"\u6587\u4ef6\u7684\u6539\u53d8":4,"\u6587\u4ef6\u7684\u8def\u5f84\u6765\u52a0\u8f7d\u9884\u6d4b\u6a21\u578b":20,"\u6587\u4ef6model":35,"\u6587\u5b57\u7684\u4ea4\u4e92\u5f0f\u6587\u6863":1,"\u6587\u6863":8,"\u6587\u6863\u90fd\u662f\u901a\u8fc7":7,"\u6587\u7ae0":27,"\u65b0":39,"\u65b0\u5efa\u4e00\u4e2a\u6743\u91cd":6,"\u65b0\u624b\u5165\u95e8":43,"\u65b9\u4fbf":39,"\u65b9\u4fbf\u4f7f\u7528":18,"\u65b9\u4fbf\u5206\u4eab\u8fd0\u884c\u65f6\u73af\u5883":2,"\u65b9\u4fbf\u6392\u67e5\u4ee5\u53ca\u5feb\u901f\u5b9a\u4f4d\u95ee\u9898":11,"\u65b9\u4fbf\u63d0\u4ea4\u96c6\u7fa4\u8bad\u7ec3\u4efb\u52a1":24,"\u65b9\u5f0f1":11,"\u65b9\u5f0f2":11,"\u65b9\u5f0f\u5c06\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u548c\u8bad\u7ec3\u597d\u7684\u53c2\u6570\u5e8f\u5217\u5316\u5230\u4e00\u4e2a\u6587\u4ef6":20,"\u65b9\u6cd5\u4e00":35,"\u65b9\u6cd5\u4e09":35,"\u65b9\u6cd5\u4e8c":35,"\u65c1\u8fb9":39,"\u65e0":39,"\u65e0\u5ef6\u8fdf":33,"\u65e0\u9700\u5173\u5fc3\u548c\u5904\u7406\u5e8f\u5217\u4fe1\u606f":19,"\u65e0\u9700\u5355\u72ec\u5b89\u88c5\u7b2c\u4e09\u65b9\u4f9d\u8d56":2,"\u65e0\u9700\u63d0\u4f9b\u975e\u96f6\u5143\u7684\u503c":19,"\u65e0\u9700\u9644\u52a0\u5e8f\u5217\u4fe1\u606f":19,"\u65e5\u5fd7\u62a5\u9519\u4e3a\u7f51\u7edc\u901a\u4fe1\u7c7b\u9519\u8bef":9,"\u65e9\u9910":39,"\u65f6":[6,11,13,17,19,27,33,38,42],"\u65f6\u4f7f\u7528openblas\u6570\u5b66\u5e93":17,"\u65f6\u5019":39,"\u65f6\u5982\u4f55\u7ec4\u7ec7\u8f93\u5165\u6570\u636e":19,"\u65f6\u88ab\u8bad\u7ec3\u7684":6,"\u65f6\u8bbe\u5907id\u53f7\u7684\u5206\u914d":35,"\u65f6\u95f4":39,"\u65f6\u95f4\u6b65\u7684\u6982\u5ff5":39,"\u65f6\u987b\u4ece\u7b2c17\u5b57\u8282\u5f00\u59cb":13,"\u6613\u4e8e\u95ee\u9898\u7684\u590d\u73b0":2,"\u6620\u5c04\u4e3a":0,"\u6620\u5c04\u5230\u4e00\u4e2a\u7ef4\u5ea6\u4e3a":6,"\u662f":[3,8,39],"\u662f\u4e00\u4e2a\u51681\u7684\u5411\u91cf":6,"\u662f\u4e00\u4e2a\u5185\u7f6e\u7684\u5b9a\u65f6\u5668\u5c01\u88c5":37,"\u662f\u4e00\u4e2a\u52a8\u6001\u7a0b\u5e8f\u5206\u6790\u7684\u672f\u8bed":37,"\u662f\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":38,"\u662f\u4e00\u4e2a\u53cc\u5c42\u7684\u5e8f\u5217":38,"\u662f\u4e00\u4e2a\u5c01\u88c5\u5bf9\u8c61":37,"\u662f\u4e00\u4e2a\u5f88\u6709\u7528\u7684\u53c2\u6570":35,"\u662f\u4e00\u4e2a\u65b9\u4fbf\u7684\u7a0b\u5e8f\u90e8\u7f72\u548c\u7ba1\u7406\u5de5\u5177":24,"\u662f\u4e00\u4e2a\u975e\u7ebf\u6027\u7684":6,"\u662f\u4e00\u4e2aunbound":41,"\u662f\u4e00\u6761\u65f6\u95f4\u5e8f\u5217":14,"\u662f\u4e00\u6b21\u9884\u6d4b\u63a5\u53d7\u7684\u6837\u672c\u6570\u76ee":19,"\u662f\u4e00\u79cd\u4efb\u610f\u590d\u6742\u7684rnn\u5355\u5143":41,"\u662f\u4e0d\u5305\u62ec\u6e90\u7801\u7684":26,"\u662f\u4f7f\u5f97\u8981\u5171\u4eab\u7684\u53c2\u6570\u4f7f\u7528\u540c\u6837\u7684":13,"\u662f\u4f7f\u7528mkl\u6570\u5b66\u5e93":17,"\u662f\u504f\u5dee":42,"\u662f\u5411\u91cf":6,"\u662f\u5426\u4e3a\u5f02\u6b65sgd\u66f4\u65b0\u6a21\u5f0f":21,"\u662f\u5426\u4ec5\u7f16\u8bd1capi":0,"\u662f\u5426\u4ee5\u9006\u5e8f\u5904\u7406\u8f93\u5165\u5e8f\u5217":41,"\u662f\u5426\u4f7f\u7528\u53cc\u7cbe\u5ea6\u6d6e\u70b9\u6570":0,"\u662f\u5426\u4f7f\u7528\u65e7\u7684remoteparameterupdat":33,"\u662f\u5426\u4f7f\u7528\u6743\u91cd":6,"\u662f\u5426\u4f7f\u7528mkl\u6570\u5b66\u5e93":0,"\u662f\u5426\u5185\u5d4cpython\u89e3\u91ca\u5668":0,"\u662f\u5426\u542f\u7528gpu\u8bad\u7ec3":21,"\u662f\u5426\u5c06\u5168\u5c40\u79cd\u5b50\u5e94\u7528\u4e8e\u672c\u5730\u7ebf\u7a0b\u7684\u968f\u673a\u6570":33,"\u662f\u5426\u5f00\u542f\u5355\u5143\u6d4b\u8bd5":0,"\u662f\u5426\u6253\u5370\u7248\u672c\u4fe1\u606f":33,"\u662f\u5426\u652f\u6301gpu":0,"\u662f\u5426\u663e\u793a":33,"\u662f\u5426\u7a00\u758f":6,"\u662f\u5426\u7f16\u8bd1\u4e2d\u82f1\u6587\u6587\u6863":0,"\u662f\u5426\u7f16\u8bd1\u542b\u6709avx\u6307\u4ee4\u96c6\u7684paddlepaddle\u4e8c\u8fdb\u5236\u6587\u4ef6":0,"\u662f\u5426\u7f16\u8bd1\u65f6\u8fdb\u884c\u4ee3\u7801\u98ce\u683c\u68c0\u67e5":0,"\u662f\u5426\u7f16\u8bd1go\u8bed\u8a00\u7684\u53ef\u5bb9\u9519paramet":0,"\u662f\u5426\u7f16\u8bd1python\u7684swig\u63a5\u53e3":0,"\u662f\u5426\u8fd0\u884c\u65f6\u52a8\u6001\u52a0\u8f7dcuda\u52a8\u6001\u5e93":0,"\u662f\u5426\u9700\u8981\u7b49\u5f85\u8be5\u8f6e\u6a21\u578b\u53c2\u6570":33,"\u662f\u56e0\u4e3a\u8fd9\u4e2a\u6d41\u7a0b\u6bd4\u5176\u4ed6\u65b9\u6cd5\u90fd\u66f4\u7b80\u4fbf":0,"\u662f\u5728paddlepaddle\u4e2d\u6784\u9020\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u65f6\u6700\u91cd\u8981\u7684\u6982\u5ff5":42,"\u662f\u5b58\u6709\u4e00\u7cfb\u5217\u53d8\u6362\u77e9\u9635\u7684\u6743\u91cd":6,"\u662f\u5b58\u6709\u504f\u7f6e\u5411\u91cf\u7684\u6743\u91cd":6,"\u662f\u5f00\u542favx\u7f16\u8bd1\u7684":1,"\u662f\u5f85\u6269\u5c55\u7684\u6570\u636e":38,"\u662f\u6210\u719f\u7684\u9ad8\u6027\u80fd\u5e76\u884c\u8ba1\u7b97\u6846\u67b6":24,"\u662f\u6211\u4eec":4,"\u662f\u6307\u4e00\u7cfb\u5217\u7684\u7279\u5f81\u6570\u636e":39,"\u662f\u6307recurrent_group\u7684\u591a\u4e2a\u8f93\u5165\u5e8f\u5217":39,"\u662f\u6570\u636e\u8f93\u5165":42,"\u662f\u6709\u610f\u4e49\u7684":39,"\u662f\u6784\u5efa\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u6700\u91cd\u8981\u7684\u5de5\u5177":42,"\u662f\u6ca1\u6709\u540d\u5b57\u7684":0,"\u662f\u7684":0,"\u662f\u77e9\u9635":6,"\u662f\u795e\u7ecf\u7f51\u7edc\u5b9a\u4e49\u65f6":19,"\u662f\u7f51\u7edc\u5c42\u5b9e\u4f8b\u7684\u540d\u5b57\u6807\u8bc6\u7b26":6,"\u662f\u7f51\u7edc\u5c42\u7684\u6807\u8bc6\u7b26":6,"\u662f\u7f51\u7edc\u5c42\u7684\u7c7b\u578b":6,"\u662f\u7f51\u7edc\u5c42\u8f93\u51fa\u7684\u5927\u5c0f":6,"\u662f\u8be5\u5c42\u7684\u6807\u8bc6\u7b26":6,"\u662f\u8be5\u5c42\u7684\u7c7b\u540d":6,"\u662f\u8be5\u7f51\u7edc\u5c42\u7684":6,"\u662f\u8f93\u5165":42,"\u662f\u8fd9\u4e00\u7c7b\u7684":12,"\u662f\u8fdb\u884c\u8ba1\u7b97\u7684\u57fa\u672c\u5355\u4f4d":19,"\u662f\u9700\u8981\u4e86\u89e3\u54ea\u4e9b\u6b65\u9aa4\u62d6\u6162\u4e86\u6574\u4f53":37,"\u662fdecoder\u7684\u6570\u636e\u8f93\u5165":41,"\u662fgoogle\u5f00\u6e90\u7684\u5bb9\u5668\u96c6\u7fa4\u7684\u8c03\u5ea6\u6846\u67b6":24,"\u662fnvidia\u6027\u80fd\u5206\u6790\u5de5\u5177":37,"\u662fpaddlepaddle\u4e2d\u5355\u5c42\u5e8f\u5217\u548c\u53cc\u5c42\u5e8f\u5217\u5b58\u50a8\u793a\u610f\u56fe":19,"\u662fpaddlepaddle\u652f\u6301\u7684\u4e00\u79cd\u4efb\u610f\u590d\u6742\u7684rnn\u5355\u5143":41,"\u662fpython\u5c01\u88c5\u7684\u7c7b\u540d":6,"\u662frnn\u72b6\u6001":42,"\u665a":39,"\u6682\u4e0d\u8003\u8651\u5728\u5185":11,"\u6682\u65e0":3,"\u6682\u65f6\u4e0d\u652f\u6301python3":3,"\u66f4\u522b\u63d0\u7b80\u5316\u95ee\u9898\u590d\u73b0\u5e26\u6765\u7684\u597d\u5904\u4e86":0,"\u66f4\u591a\u5173\u4e8edocker\u7684\u5b89\u88c5\u4e0e\u4f7f\u7528":8,"\u66f4\u597d\u5730\u5b8c\u6210\u4e00\u4e9b\u590d\u6742\u7684\u8bed\u8a00\u7406\u89e3\u4efb\u52a1":41,"\u66f4\u5feb":42,"\u66f4\u65b0":8,"\u66f4\u65b0\u53ef\u80fd\u5bfc\u81f4\u9700\u8981\u65b0\u7684\u5f00\u53d1\u5de5\u5177":0,"\u66f4\u65b0\u6a21\u5f0f":11,"\u66f4\u65b0\u7684\u6587\u6863\u4ee5pr\u7684\u5f62\u5f0f\u63d0\u4ea4\u5230github\u4e2d":7,"\u66f4\u65b0\u7f51\u7edc\u53c2\u6570\u65f6\u5e94\u7528":11,"\u66f4\u65b9\u4fbf\u7684\u8bbe\u7f6e\u65b9\u5f0f":13,"\u66f4\u8be6\u7ec6\u7684\u5b89\u88c5\u548c\u7f16\u8bd1\u65b9\u6cd5\u53c2\u8003":16,"\u66f4\u8fdb\u4e00\u6b65":41,"\u66f4\u9ad8":42,"\u66ff\u6211\u4eec\u5b8c\u6210\u4e86\u539f\u59cb\u8f93\u5165\u6570\u636e\u7684\u62c6\u5206":41,"\u6700":39,"\u6700\u4e3b\u8981\u7684\u5de5\u4f5c\u5c31\u662f\u89e3\u6790\u51fa":27,"\u6700\u540e":[1,4,6,21],"\u6700\u540e\u4e00\u4e2a":38,"\u6700\u540e\u4e00\u5c42cost\u4e2d\u8bb0\u5f55\u4e86\u795e\u7ecf\u7f51\u7edc\u7684\u6240\u6709\u62d3\u6251\u7ed3\u6784":14,"\u6700\u540e\u6211\u4eec\u4f7f\u7528\u94fe\u5f0f\u6cd5\u5219\u8ba1\u7b97":6,"\u6700\u540e\u7684\u6267\u884c\u811a\u672c\u7684\u547d\u4ee4":0,"\u6700\u540e\u7ed9\u51fa\u7ec6\u8282\u63cf\u8ff0":34,"\u6700\u540e\u8ba1\u7b97softmax":12,"\u6700\u5c11\u663e\u793a\u591a\u5c11\u4e2a\u8282\u70b9":33,"\u6700\u65b0\u7684\u4ee3\u7801":4,"\u6700\u65b0\u7684paddlepaddl":[1,8],"\u6700\u7ec8":6,"\u6700\u7ec8\u5b9e\u73b0\u4e00\u4e2a\u5c42\u6b21\u5316\u7684\u590d\u6742rnn":41,"\u6700\u7ec8\u6211\u4eec\u53ef\u4ee5\u8c03\u7528trainer\u7684train\u65b9\u6cd5\u542f\u52a8\u8bad\u7ec3":14,"\u6700\u7ec8\u7684\u8f93\u51fa\u7ed3\u679c":41,"\u6708\u6e56":39,"\u6709":39,"\u6709\u4e24\u79cd\u65b9\u6cd5":0,"\u6709\u4e9b\u5c42\u53ef\u80fd\u9700\u8981\u9ad8\u7cbe\u5ea6\u6765\u4fdd\u8bc1\u68af\u5ea6\u68c0\u67e5\u5355\u6d4b\u6b63\u786e\u6267\u884c":6,"\u6709\u4e9b\u5c42\u6216\u8005\u6fc0\u6d3b\u9700\u8981\u505a\u5f52\u4e00\u5316\u4ee5\u4fdd\u8bc1\u5b83\u4eec\u7684\u8f93\u51fa\u7684\u548c\u662f\u4e00\u4e2a\u5e38\u6570":6,"\u6709\u4e9b\u7279\u5f81\u7684\u53d6\u503c\u8fbe\u5230\u6570\u767e\u4e07":11,"\u6709\u4eba\u7528\u865a\u62df\u673a\u6765\u7c7b\u6bd4":0,"\u6709\u5173":39,"\u6709\u5173\u7ebf\u6027\u56de\u5f52\u7684\u5b9e\u9645\u5e94\u7528":14,"\u6709\u52a9\u4e8e\u5728\u8bad\u7ec3\u65f6\u89c2\u5bdf\u5177\u4f53\u6570\u503c":11,"\u6709\u52a9\u4e8e\u8bca\u65ad\u5206\u5e03\u5f0f\u9519\u8bef":23,"\u6709\u591a\u96be":0,"\u6709\u7684\u65f6\u5019\u7b80\u7b80\u5355\u5355\u7684\u6539\u53d8\u5c31\u80fd\u5728\u6027\u80fd\u4e0a\u4ea7\u751f\u660e\u663e\u7684\u4f18\u5316\u6548\u679c":37,"\u6709\u7684\u8bdd\u9700\u8981\u5148\u5378\u8f7d":8,"\u670d\u52a1":39,"\u670d\u52a1\u5458":39,"\u670d\u52a1\u5668\u4e4b\u95f4\u53ef\u4ee5\u901a\u8fc7\u5c40\u57df\u7f51":31,"\u672a\u6307\u5b9a\u6309\u7167double\u7cbe\u5ea6\u7f16\u8bd1":13,"\u672c\u4f8b\u4e2d\u7684\u539f\u59cb\u6570\u636e\u4e00\u5171\u670910\u4e2a\u6837\u672c":39,"\u672c\u5730":[3,8],"\u672c\u5730\u6d4b\u8bd5":32,"\u672c\u5730\u8bad\u7ec3":[19,32],"\u672c\u5730\u8bad\u7ec3\u4e0e\u9884\u6d4b":10,"\u672c\u5730\u8bad\u7ec3\u7684\u5b9e\u9a8c":35,"\u672c\u6559\u7a0b\u5c06\u6307\u5bfc\u4f60\u5982\u4f55\u5728":42,"\u672c\u6587\u4e2d\u6240\u6709\u7684\u4f8b\u5b50":39,"\u672c\u6587\u4e2d\u7684\u4f8b\u5b50\u91cc":0,"\u672c\u6587\u4e2d\u793a\u4f8b\u6240\u4f7f\u7528\u7684\u5355\u5143\u6d4b\u8bd5\u6587\u4ef6\u662f":39,"\u672c\u6587\u4ee5paddlepaddle\u7684\u53cc\u5c42rnn\u5355\u5143\u6d4b\u8bd5\u4e3a\u793a\u4f8b":39,"\u672c\u6587\u5c06\u4ecb\u7ecd\u5728kubernetes\u5bb9\u5668\u7ba1\u7406\u5e73\u53f0\u4e0a\u5feb\u901f\u6784\u5efapaddlepaddle\u5bb9\u5668\u96c6\u7fa4":27,"\u672c\u6587\u6863\u5bf9\u5173\u4e8epaddlepaddle\u7684\u4e00\u4e9b\u5e38\u89c1\u95ee\u9898\u63d0\u4f9b\u4e86\u89e3\u7b54":10,"\u672c\u6765":39,"\u672c\u6b21\u8bad\u7ec3\u6587\u4ef6\u6240\u5728\u76ee\u5f55":27,"\u672c\u6b21\u8bad\u7ec3\u7684yaml\u6587\u4ef6\u53ef\u4ee5\u5199\u6210":27,"\u672c\u6b21\u8bad\u7ec3\u8981\u6c42\u67093\u4e2apaddlepaddle\u8282\u70b9":27,"\u672c\u793a\u4f8b\u4e2d\u4f7f\u7528\u7684\u539f\u59cb\u6570\u636e\u5982\u4e0b":39,"\u672c\u793a\u4f8b\u610f\u56fe\u4f7f\u7528\u5355\u5c42rnn\u548c\u53cc\u5c42rnn\u5b9e\u73b0\u4e24\u4e2a\u5b8c\u5168\u7b49\u4ef7\u7684\u5168\u8fde\u63a5rnn":39,"\u672c\u8282\u5c06\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528paddlepaddle\u5728\u4e0d\u540c\u7684\u96c6\u7fa4\u6846\u67b6\u4e0b\u5b8c\u6210\u5206\u5e03\u5f0f\u8bad\u7ec3":22,"\u673a\u5668\u7684\u8bbe\u5907":35,"\u6743\u91cd\u66f4\u65b0\u7684\u68af\u5ea6":33,"\u6765":39,"\u6765\u4e3a\u4e00\u4e2a":19,"\u6765\u4ee3\u66ff":4,"\u6765\u4f20\u8f93\u7f51\u7edc\u914d\u7f6e\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7f51\u7edc\u7ed3\u6784\u548c\u76f8\u5173\u53c2\u6570":20,"\u6765\u4f7f\u7528dropout":12,"\u6765\u4f7f\u7528dropout\u7684":12,"\u6765\u505a\u68af\u5ea6\u68c0\u67e5":6,"\u6765\u5206\u6790\u6267\u884c\u6587\u4ef6":37,"\u6765\u521d\u59cb\u5316\u53c2\u6570":13,"\u6765\u542f\u52a8\u548c":0,"\u6765\u5b58\u50a8":19,"\u6765\u5b58\u50a8\u6570\u636e":[19,20],"\u6765\u5b8c\u6210\u524d\u5411\u548c\u53cd\u5411\u8ba1\u7b97":20,"\u6765\u5b8c\u6210\u7f51\u7edc\u7684\u8bad\u7ec3":14,"\u6765\u5b9a\u4e49\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":42,"\u6765\u5b9e\u9645\u5b58\u50a8\u6570\u636e":[19,20],"\u6765\u5bf9\u6bd4\u5206\u6790\u4e24\u8005\u8bed\u4e49\u76f8\u540c\u7684\u539f\u56e0":39,"\u6765\u5f97\u5230\u67d0\u4e2a\u7279\u5b9a\u53c2\u6570\u7684\u68af\u5ea6\u77e9\u9635":6,"\u6765\u63cf\u8ff0\u8f93\u5165":19,"\u6765\u642d\u5efa\u795e\u7ecf\u7f51\u7edc":14,"\u6765\u6ce8\u518c\u8be5\u5c42":6,"\u6765\u6df7\u5408\u4f7f\u7528gpu\u548ccpu\u8ba1\u7b97\u7f51\u7edc\u5c42\u7684\u53c2\u6570":35,"\u6765\u6e05\u7406\u8fd9\u4e9b\u5185\u5bb9":0,"\u6765\u7279\u6307":19,"\u6765\u7279\u6307\u8c03\u7528paddlepaddl":20,"\u6765\u7279\u6307paddlepaddl":20,"\u6765\u7279\u6307paddlepaddle\u4e2d\u7684\u4e00\u7ef4\u6574\u578b\u6570\u7ec4":19,"\u6765\u7279\u6307paddlepaddle\u4e2d\u7684\u4e8c\u7ef4\u6d6e\u70b9\u578b\u77e9\u9635":19,"\u6765\u7279\u6307paddlepaddle\u4e2d\u795e\u7ecf\u7f51\u7edc\u8ba1\u7b97\u5c42\u4e00\u4e2a\u8f93\u5165":19,"\u6765\u786e\u5b9a\u7a00\u758f\u77e9\u9635\u7684\u5185\u5bb9":19,"\u6765\u83b7\u5f97\u8f93\u51fa\u7684\u68af\u5ea6":6,"\u6765\u8868\u793a":42,"\u6765\u8868\u793a\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":42,"\u6765\u89e3\u51b3\u4e0a\u9762\u7684\u95ee\u9898":11,"\u6765\u8ba1\u7b97\u68af\u5ea6":6,"\u6765\u8bb0\u5f55\u8f93\u5165":19,"\u6765\u8bb2\u89e3\u5982\u4f55\u4f7f\u7528\u53cc\u5c42rnn":39,"\u6765\u8bbe\u7f6e":13,"\u6765\u8bfb\u53d6\u4e00\u4e2a":19,"\u6765\u8c03\u6574":4,"\u6765\u8c03\u7528":0,"\u6765\u8fd0\u884c\u6027\u80fd\u5206\u6790\u548c\u8c03\u4f18":37,"\u6765\u8fd0\u884c\u955c\u50cf":1,"\u6765\u9884\u6d4b\u8fd9\u4e2a\u4e2d\u95f4\u7684\u8bcd":11,"\u676f\u5b50":39,"\u6784\u5efa\u7684\u955c\u50cf":0,"\u6784\u6210\u4e00\u4e2a\u5e8f\u5217":19,"\u6784\u6210\u4e86\u8f93\u51fa\u53cc\u5c42\u5e8f\u5217\u7684\u7b2ci\u4e2a":38,"\u6784\u9020":27,"\u67d0\u4e00\u4e2a\u795e\u7ecf\u5143\u7684\u4e00\u4e2a\u8f93\u5165\u4e3a\u4e0a\u4e00\u4e2a\u65f6\u95f4\u6b65\u7f51\u7edc\u4e2d\u67d0\u4e00\u4e2a\u795e\u7ecf\u5143\u7684\u8f93\u51fa":39,"\u67d0\u4e9b\u53c2\u6570\u53ea\u53ef\u7528\u4e8e\u7279\u5b9a\u7684\u5c42\u4e2d":32,"\u67e5\u627e\u7b54\u6848\u6216\u76f4\u63a5\u63d0":10,"\u67e5\u770b":4,"\u67e5\u770b\u5305\u7684\u5927\u5c0f":8,"\u67e5\u770b\u5f53\u524d\u72b6\u6001":4,"\u67e5\u770b\u5f53\u524d\u8fdc\u7a0b\u4ed3\u5e93\u7684\u540d\u5b57":4,"\u67e5\u770b\u6587\u4ef6\u5177\u4f53\u88ab\u4fee\u6539\u7684\u5185\u5bb9":4,"\u67e5\u770b\u662f\u5426\u662f\u5176\u4ed6\u9519\u8bef\u5f15\u53d1\u7684\u62a5\u9519":9,"\u67e5\u770bjob\u7684\u8be6\u7ec6\u60c5\u51b5":26,"\u6807\u51c6":3,"\u6807\u51c6\u5dee\u4e3a":13,"\u6807\u8bc6\u662f\u5426\u4e3a\u8fde\u7eed\u7684batch\u8ba1\u7b97":33,"\u6838\u4e00\u6837\u591a\u7684\u8fdb\u7a0b\u6765\u5e76\u884c\u7f16\u8bd1":0,"\u6838\u5fc3\u4ee3\u7801\u7f16\u8bd1\u6210\u94fe\u63a5\u5e93":17,"\u6839\u636e\u4f60\u7684\u4efb\u52a1":35,"\u6839\u636e\u524d\u6587\u7684\u63cf\u8ff0":27,"\u6839\u636e\u7f51\u7edc\u914d\u7f6e\u4e2d\u7684":33,"\u6839\u636e\u8fd9\u4e9b\u53c2\u6570\u7684\u4f7f\u7528\u573a\u5408":32,"\u6839\u636e\u9ed8\u8ba4\u503c\u9012\u589e":33,"\u6839\u636e\u9ed8\u8ba4\u7aef\u53e3\u53f7\u9012\u589e":33,"\u6839\u636ejob\u5bf9\u5e94\u7684pod\u4fe1\u606f":26,"\u6839\u636eport":21,"\u683c\u5f0f":33,"\u683c\u5f0f\u5b58\u50a8":19,"\u68af\u5ea6\u4f1a\u5c31\u5730":6,"\u68af\u5ea6\u4f1a\u6709\u566a\u58f0":22,"\u68af\u5ea6\u53c2\u6570\u7684\u5206\u5757\u6570\u76ee":33,"\u68af\u5ea6\u5c31\u53ef\u4ee5\u901a\u8fc7\u8fd9\u4e2a\u65b9\u7a0b\u8ba1\u7b97\u5f97\u5230":6,"\u68af\u5ea6\u670d\u52a1\u5668\u7684\u6570\u91cf":33,"\u68af\u5ea6\u68c0\u67e5\u5355\u5143\u6d4b\u8bd5\u901a\u8fc7\u6709\u9650\u5dee\u5206\u6cd5\u6765\u9a8c\u8bc1\u4e00\u4e2a\u5c42\u7684\u68af\u5ea6":6,"\u68af\u5ea6\u68c0\u67e5\u7684\u8f93\u5165\u6570\u636e\u7684\u6279\u6b21\u5927\u5c0f":6,"\u697c\u5c42":39,"\u6982\u5ff5\u4e0a":20,"\u6982\u5ff5\u4e0a\u53ef\u4ee5\u5c06":19,"\u6a21\u578b\u4e00\u76f4\u4e0d\u6536\u655b":11,"\u6a21\u578b\u4e2d\u6240\u6709\u53ef\u5b66\u4e60\u53c2\u6570\u4f1a\u88ab\u5b58\u4e3a\u4e00\u4e2a\u538b\u7f29\u6587\u4ef6":20,"\u6a21\u578b\u6587\u4ef6\u5c06\u88ab\u5199\u5165\u8282\u70b9":23,"\u6a21\u578b\u6765\u6307\u5bfc\u4f60\u5b8c\u6210\u8fd9\u4e9b\u6b65\u9aa4":42,"\u6a21\u578b\u6f14\u793a\u5982\u4f55\u914d\u7f6e\u590d\u6742\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u6a21\u578b":42,"\u6a21\u578b\u7684\u4ee3\u7801\u53ef\u4ee5\u5728":42,"\u6a21\u578b\u7684\u7f16\u7801\u5668\u90e8\u5206\u5982\u4e0b\u6240\u793a":42,"\u6a21\u578b\u7ed3\u6784":34,"\u6a21\u578b\u8bad\u7ec3\u7b49\u4efb\u52a1":14,"\u6a21\u578b\u914d\u7f6e":10,"\u6a21\u578b\u9884\u6d4bsdk\u9700\u8981\u5355\u72ec\u8bbe\u8ba1":18,"\u6a2a\u5411\u62fc\u63a5":11,"\u6b21":39,"\u6b22\u8fce\u5411paddlepaddle\u793e\u533a\u53cd\u9988\u95ee\u9898":2,"\u6b22\u8fce\u901a\u8fc7":4,"\u6b63\u5728\u7b49\u5f85\u672a\u5b8c\u6210\u7684\u4efb\u52a1":8,"\u6b63\u5e38\u60c5\u51b5\u4e0b\u662f75m":8,"\u6b63\u786e\u7684\u89e3\u51b3\u65b9\u6cd5\u662f":8,"\u6b63\u8d1f\u5bf9\u9a8c\u8bc1":32,"\u6b64\u5904\u90fd\u4e3a2":39,"\u6b64\u5916":[0,4,12],"\u6b64\u6559\u7a0b\u5c06\u5411\u60a8\u5206\u6b65\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528\u5185\u7f6e\u7684\u5b9a\u65f6\u5de5\u5177":37,"\u6b64\u65b9\u6cd5\u4e0d\u80fd\u83b7\u53d6":11,"\u6b64\u65f6\u53ef\u4ee5\u5728\u8c03\u7528infer\u63a5\u53e3\u65f6\u901a\u8fc7\u8bbe\u7f6e":11,"\u6b64\u65f6\u53ef\u4ee5\u8df3\u8fc7paddlepaddle\u6a21\u578b\u53c2\u6570\u6587\u4ef6\u7684\u5934\u4fe1\u606f":13,"\u6b64\u76ee\u5f55":20,"\u6b64\u793a\u4f8b":20,"\u6b64\u7c7b\u62a5\u9519\u901a\u5e38\u662f\u7531\u4e8e\u67d0\u4e00\u4e2a\u8282\u70b9\u7684\u9519\u8bef\u5bfc\u81f4\u8fd9\u4e2a\u8282\u70b9\u7684\u8bad\u7ec3\u8fdb\u7a0b\u9000\u51fa":9,"\u6b65\u9aa4":11,"\u6bb5\u843d\u53ef\u4ee5\u770b\u4f5c\u662f\u4e00\u4e2a\u5d4c\u5957\u7684\u53cc\u5c42\u7684\u5e8f\u5217":41,"\u6bb5\u843d\u662f\u7531\u53e5\u5b50\u6784\u6210\u7684\u5e8f\u5217":19,"\u6bcf\u4e00\u4e2a":20,"\u6bcf\u4e00\u4e2a\u5916\u5c42\u5e8f\u5217\u53c8\u542b\u6709\u82e5\u5e72\u4e2a\u5185\u5c42\u5e8f\u5217":19,"\u6bcf\u4e00\u4e2a\u5e8f\u5217\u5728\u6574\u4e2a":19,"\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65":39,"\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65\u4e4b\u95f4\u7684\u795e\u7ecf\u7f51\u7edc\u5177\u6709\u4e00\u5b9a\u7684\u76f8\u5173\u6027":39,"\u6bcf\u4e00\u4e2a\u8282\u70b9\u90fd\u6709\u76f8\u540c\u7684\u65e5\u5fd7\u7ed3\u6784":23,"\u6bcf\u4e00\u4e2a\u8f93\u5165":[19,20],"\u6bcf\u4e00\u4e2alayer\u8f93\u51fa\u77e9\u9635\u7684\u9ad8\u5ea6":11,"\u6bcf\u4e00\u7ec4\u5185\u7684\u6240\u6709\u53e5\u5b50\u548clabel":39,"\u6bcf\u4e00\u884c\u5143\u7d20\u5728":19,"\u6bcf\u4e2a\u5143\u7d20\u662f\u4e00\u4e2a0\u5c42\u5e8f\u5217":38,"\u6bcf\u4e2a\u5143\u7d20\u662f\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":38,"\u6bcf\u4e2a\u5355\u5c42rnn":41,"\u6bcf\u4e2a\u53c2\u6570\u670d\u52a1\u5668\u53ea\u4fdd\u5b58\u6574\u4e2a\u795e\u7ecf\u7f51\u7edc\u6240\u6709\u53c2\u6570\u7684\u4e00\u90e8\u5206":22,"\u6bcf\u4e2a\u53e5\u5b50\u53c8\u662f\u5355\u8bcd\u7684\u6570\u7ec4":39,"\u6bcf\u4e2a\u53e5\u5b50\u90fd\u4ee5\u5f00\u59cb\u6807\u8bb0\u5f00\u5934":42,"\u6bcf\u4e2a\u53e5\u5b50\u90fd\u4ee5\u7ed3\u675f\u6807\u8bb0\u7ed3\u5c3e":42,"\u6bcf\u4e2a\u5b50\u5e8f\u5217\u957f\u5ea6\u53ef\u4ee5\u4e0d\u4e00\u81f4":39,"\u6bcf\u4e2a\u5c42\u5728\u5176":6,"\u6bcf\u4e2a\u6279\u6b21\u6570\u636e":33,"\u6bcf\u4e2a\u65f6\u95f4\u6b65\u4e4b\u5185\u7684\u8fd0\u7b97\u662f\u72ec\u7acb\u7684":41,"\u6bcf\u4e2a\u65f6\u95f4\u6b65\u90fd\u7528\u4e86\u4e0a\u4e00\u4e2a\u65f6\u95f4\u6b65\u7684\u8f93\u51fa\u7ed3\u679c":39,"\u6bcf\u4e2a\u6743\u91cd\u5bf9\u5e94\u4e00\u4e2a\u8f93\u5165":6,"\u6bcf\u4e2a\u6837\u672c\u7531\u4e24\u90e8\u5206\u7ec4\u6210":39,"\u6bcf\u4e2a\u6837\u672c\u95f4\u7528\u7a7a\u884c\u5206\u5f00":39,"\u6bcf\u4e2a\u72b6\u6001":41,"\u6bcf\u4e2a\u7ebf\u7a0b":33,"\u6bcf\u4e2a\u7ebf\u7a0b\u5206\u914d\u5230128\u4e2a\u6837\u672c\u7528\u4e8e\u8bad\u7ec3":33,"\u6bcf\u4e2a\u8bad\u7ec3\u8282\u70b9\u5fc5\u987b\u6307\u5b9a\u4e00\u4e2a\u552f\u4e00\u7684id\u53f7":33,"\u6bcf\u4e2a\u8f93\u5165\u90fd\u662f\u4e00\u4e2a":6,"\u6bcf\u4e2a\u8f93\u51fa\u8282\u70b9\u90fd\u8fde\u63a5\u5230\u6240\u6709\u7684\u8f93\u5165\u8282\u70b9\u4e0a":6,"\u6bcf\u4e2a\u90e8\u5206\u5206\u522b\u7ed9\u6bcf\u4e2atrainer\u4f7f\u7528":22,"\u6bcf\u4e2acommit\u53ea\u505a\u4e86\u5c11\u91cf\u7684\u4fee\u6539":4,"\u6bcf\u4e2apod\u5305\u542b\u4e00\u4e2apaddlepaddle\u5bb9\u5668":27,"\u6bcf\u4e2atrainer\u542f\u52a8\u540e\u8bfb\u53d6\u5207\u5206\u597d\u7684\u4e00\u90e8\u5206\u6570\u636e":22,"\u6bcf\u4e2atrainer\u7684\u552f\u4e00id":21,"\u6bcf\u4e2atrainer\u8fdb\u7a0b\u9700\u8981\u80fd\u591f\u8bfb\u53d6\u5c5e\u4e8e\u81ea\u5df1\u7684\u4e00\u4efd\u6570\u636e":21,"\u6bcf\u53f0\u670d\u52a1\u5668\u5177\u6709\u96c6\u7fa4\u4e2d\u552f\u4e00\u7684ip\u5730\u5740":31,"\u6bcf\u5c42\u4e0a\u53ea\u80fd\u4fdd\u5b58\u56fa\u5b9a\u6570\u76ee\u4e2a\u6700\u597d\u7684\u72b6\u6001":33,"\u6bcf\u5c42\u4f7f\u7528\u7684gpu\u53f7\u4f9d\u8d56\u4e8e\u53c2\u6570train":35,"\u6bcf\u6279\u6b21":33,"\u6bcf\u6b21\u63d0\u4ea4\u4ee3\u7801":4,"\u6bcf\u6b21\u63d0\u4ea4\u65f6":4,"\u6bcf\u884c\u8868\u793a\u4e00\u4e2a\u6279\u6b21\u4e2d\u7684\u5355\u4e2a\u8f93\u5165":6,"\u6bcf\u8f6e\u4f1a\u5c06\u6570\u636e\u96c6\u4e2d\u7684\u6240\u6709\u8bad\u7ec3\u6837\u672c\u4f7f\u7528\u4e00\u6b21":33,"\u6bcf\u8f6e\u7ed3\u675f\u65f6\u5bf9\u6240\u6709\u6d4b\u8bd5\u6570\u636e\u8fdb\u884c\u6d4b\u8bd5":33,"\u6bcf\u8f6e\u90fd\u4f1a\u4fdd\u5b58\u9884\u6d4b\u7ed3\u679c":33,"\u6bcf\u8fd0\u884c\u591a\u5c11\u4e2a\u6279\u6b21\u6267\u884c\u4e00\u6b21\u7a00\u758f\u53c2\u6570\u5206\u5e03\u7684\u68c0\u67e5":33,"\u6bcfdot":33,"\u6bcflog":33,"\u6bcfsave":33,"\u6bcftest":33,"\u6bd4\u5982":[0,1,4,9,11],"\u6bd4\u5982\u4e00\u53e5\u8bdd\u4e2d\u7684\u6bcf\u4e00\u4e2a\u5355\u8bcd":39,"\u6bd4\u5982\u5728":1,"\u6bd4\u5982\u5982\u679c\u8981build\u4e00\u4e2a\u4e0d\u4f9d\u8d56gpu":4,"\u6bd4\u5982\u8bbe\u7f6e\u4e00\u4e2a\u5168\u8fde\u63a5\u5c42\u7684\u53c2\u6570\u521d\u59cb\u5316\u65b9\u5f0f\u548cbias\u521d\u59cb\u5316\u65b9\u5f0f":13,"\u6bd4\u5982cento":3,"\u6bd4\u5982fpe":9,"\u6bd4\u5982ide\u914d\u7f6e\u91cc":4,"\u6bd4\u5982pil\u5e93\u7b49":21,"\u6c34\u6e29":39,"\u6c49\u5ead":39,"\u6ca1":39,"\u6ca1\u6709\u627e\u5230\u548c\u5f53\u524d\u7cfb\u7edf\u5339\u914d\u7684paddlepaddle\u5b89\u88c5\u5305":[3,8],"\u6ce8":[0,1,19],"\u6ce8\u610f":[0,6,7,11,14,20,21,27,42],"\u6ce8\u610f\u4e0a\u8ff0\u547d\u4ee4\u4e2d":27,"\u6ce8\u610f\u4e8b\u9879":19,"\u6ce8\u610f\u5230\u6211\u4eec\u5df2\u7ecf\u5047\u8bbe\u673a\u5668\u4e0a\u67094\u4e2agpu":35,"\u6ce8\u610fnode":27,"\u6cf3\u6c60":39,"\u6d41":39,"\u6d41\u7a0b\u6765\u63d0\u4ea4\u4ee3\u7801":4,"\u6d44":39,"\u6d4b\u8bd5":4,"\u6d4b\u8bd5\u65f6\u6307\u5b9a\u7684\u5b58\u50a8\u6a21\u578b\u5217\u8868\u7684\u6587\u4ef6":33,"\u6d4b\u8bd5\u662f":4,"\u6d4b\u8bd5\u7684\u6a21\u578b\u5305\u62ec\u4ece\u7b2cm\u8f6e\u5230\u7b2cn":35,"\u6d4b\u8bd5model_list":32,"\u6d4b\u8bd5save_dir":32,"\u6d6e\u70b9\u578b\u7a00\u758f\u77e9\u9635":19,"\u6d6e\u70b9\u578b\u7a20\u5bc6\u77e9\u9635":19,"\u6d6e\u70b9\u5f02\u5e38\u901a\u5e38\u7684\u539f\u56e0\u662f\u6d6e\u70b9\u6570\u6ea2\u51fa":11,"\u6d6e\u70b9\u6570":19,"\u6d6e\u70b9\u6570\u5411\u91cf\u7b49":19,"\u6d6e\u70b9\u7a00\u758f\u6570\u636e":6,"\u6df1\u5ea6\u5b66\u4e60\u7b97\u6cd5\u7684\u5b9e\u73b0\u6709\u7740\u591a\u6837\u5316\u7684\u7279\u70b9":34,"\u6df7\u5408\u5f53\u524d\u8bcd\u5411\u91cf\u548cattention\u52a0\u6743\u7f16\u7801\u5411\u91cf":42,"\u6dfb\u52a0\u542f\u52a8\u811a\u672c":27,"\u6dfb\u52a0\u5e8f\u5217\u4fe1\u606f":19,"\u6e05\u7406\u548c\u7ed3\u675f":20,"\u6e05\u7406\u6389\u8001\u65e7\u7684paddlepaddle\u5b89\u88c5\u5305":8,"\u6e29\u99a8":39,"\u6e90\u4ee3\u7801\u683c\u5f0f":4,"\u6e90\u5e8f\u5217":42,"\u6e90\u7801\u4e2d\u6784\u5efa\u7528\u4e8e\u7f16\u8bd1paddlepaddle\u7684docker\u955c\u50cf":0,"\u6e90\u7801\u6811\u6839\u76ee\u5f55":0,"\u6f5c\u5728\u4f1a\u5f15\u8d77\u672a\u5b9a\u4e49\u884c\u4e3a":19,"\u6fc0\u6d3b":6,"\u6fc0\u6d3b\u65b9\u7a0b":6,"\u6fc0\u6d3b\u7684\u7c7b\u578b":6,"\u70b9\u51fb":3,"\u70b9\u51fb\u8fd9\u91cc":7,"\u70ed\u60c5":39,"\u7136\u540e":[23,37],"\u7136\u540e\u4e0b\u8f7d\u4f18\u5316\u66f4\u65b0\u540e\u7684\u795e\u7ecf\u7f51\u7edc\u53c2\u6570":22,"\u7136\u540e\u4ea4\u7ed9step\u51fd\u6570":41,"\u7136\u540e\u5355\u51fb":4,"\u7136\u540e\u53ef\u4ee5\u4ecehead\u8282\u70b9ssh\u65e0\u5bc6\u7801\u767b\u5f55\u5230openmpi\u7684\u6bcf\u4e2a\u8282\u70b9\u4e0a":28,"\u7136\u540e\u53ef\u4ee5\u4f7f\u7528\u547d\u4ee4\u884c\u5de5\u5177\u521b\u5efajob":27,"\u7136\u540e\u5728\u4e0b\u4e00\u4e2a\u65f6\u95f4\u6b65\u8f93\u5165\u7ed9\u53e6\u4e00\u4e2a\u795e\u7ecf\u5143":39,"\u7136\u540e\u5728\u6d4f\u89c8\u5668\u4e2d\u8f93\u5165\u4ee5\u4e0b\u7f51\u5740":1,"\u7136\u540e\u5728dataprovider\u91cc\u9762\u6839\u636e\u8be5\u5730\u5740\u52a0\u8f7d\u5b57\u5178":13,"\u7136\u540e\u5b89\u88c5paddle\u7684python\u73af\u5883":8,"\u7136\u540e\u5b9a\u4e49":42,"\u7136\u540e\u5c06\u6784\u5efa\u6210\u529f\u7684\u955c\u50cf\u4e0a\u4f20\u5230\u955c\u50cf\u4ed3\u5e93":27,"\u7136\u540e\u5c06\u8fd9\u4e9blayer\u7684\u53c2\u6570":12,"\u7136\u540e\u6240\u6709\u7528":4,"\u7136\u540e\u6253\u5370\u8f93\u51fa":14,"\u7136\u540e\u63d0\u4ea4\u65b0\u6dfb\u52a0\u7684":4,"\u7136\u540e\u70b9\u51fb":4,"\u7136\u540e\u7533\u660e\u4e00\u4e2a\u5b58\u50a8\u5377":27,"\u7136\u540e\u89c2\u5bdf\u5230\u8f93\u51fa\u7684\u53d8\u5316\u4e3a":6,"\u7136\u540e\u901a\u8fc7\u51fd\u6570":27,"\u7136\u540e\u901a\u8fc7\u81ea\u8eab\u7684ip\u5730\u5740\u5728":27,"\u7136\u540e\u91cd\u65b0cmake\u5373\u53ef":8,"\u7136\u800c":[33,42],"\u7248\u672c":[0,3],"\u7248\u672c\u4e3acpu_avx_mkl":1,"\u7248\u672c\u4e3acpu_avx_openbla":[3,16],"\u7248\u672c\u5728":4,"\u7248\u672c\u8bf4\u660e":3,"\u7279\u522b\u662f\u5728lstm\u7b49rnn\u4e2d":11,"\u7279\u6307":20,"\u73af\u5883\u51c6\u5907":22,"\u73af\u5883\u53d8\u91cf":21,"\u73af\u5883\u53d8\u91cf\u4e2d":17,"\u73af\u5883\u53d8\u91cf\u6765\u6307\u5b9a\u7279\u5b9a\u7684gpu":11,"\u7406\u89e3":0,"\u7406\u89e3\u4e3a\u4e00\u4e2a\u4e00\u7ef4\u7684\u6574\u578b\u6570\u7ec4":19,"\u751a\u81f3\u80fd\u89e3\u91ca\u4e3a\u4ec0\u4e48\u67d0\u4e2a\u64cd\u4f5c\u82b1\u4e86\u5f88\u957f\u65f6\u95f4":37,"\u751f\u4ea7\u955c\u50cf":4,"\u751f\u6210":27,"\u751f\u6210\u540e\u7684\u6587\u6863\u5206\u522b\u5b58\u50a8\u5728\u7f16\u8bd1\u76ee\u5f55\u7684":7,"\u751f\u6210\u5e8f\u5217\u7684\u6700\u5927\u957f\u5ea6":42,"\u751f\u6210\u7684\u6570\u636e\u5c06\u4f1a\u5b58\u50a8\u5728\u8fd9\u4e2avolume\u4e0b":27,"\u751f\u6210\u7684\u6570\u636e\u7f13\u5b58\u5728\u5185\u5b58\u91cc":11,"\u751f\u6210\u7f51\u7edc\u5c42\u914d\u7f6e":6,"\u751f\u6210\u81ea\u5df1\u76ee\u5f55\u4e0b\u7684\u4ed3\u5e93":4,"\u7528\u4e8e\u521d\u59cb\u5316\u53c2\u6570\u548c\u8bbe\u7f6e":6,"\u7528\u4e8e\u5c06\u53c2\u6570\u4f20\u9012\u7ed9\u7f51\u7edc\u914d\u7f6e":35,"\u7528\u4e8e\u6307\u5b9a\u5176\u8981\u5173\u8054\u7684layer":12,"\u7528\u4e8e\u6307\u5b9a\u7f51\u7edc\u914d\u7f6e\u6587\u4ef6":33,"\u7528\u4e8e\u7a00\u758f\u7c7b\u578b\u53c2\u6570\u901a\u4fe1\u7684\u7aef\u53e3\u4e2a\u6570":21,"\u7528\u4e8e\u7a00\u758f\u8bad\u7ec3\u4e2d":33,"\u7528\u4e8e\u83b7\u53d6\u7279\u5b9alayer\u4e0a\u4e00\u65f6\u95f4\u6b65\u7684\u8f93\u51fa":12,"\u7528\u4e8e\u89e3\u51b3\u4e0a\u8ff0\u95ee\u9898":18,"\u7528\u4e8e\u8ba1\u7b97\u7f16\u7801\u5411\u91cf\u7684\u52a0\u6743\u548c":42,"\u7528\u4e8e\u8bad\u7ec3\u795e\u7ecf\u7f51\u7edc\u7684\u6570\u636e":22,"\u7528\u53cc\u5411\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7f16\u7801":42,"\u7528\u591a\u5bf9\u6548\u679c\u5b8c\u5168\u76f8\u540c\u7684":39,"\u7528\u6237\u53ea\u9700\u5b9a\u4e49rnn\u5728\u4e00\u4e2a\u65f6\u95f4\u6b65\u5185\u5b8c\u6210\u7684\u8ba1\u7b97":41,"\u7528\u6237\u53ef\u4ee5\u5206\u522b\u67e5\u770b\u6700\u65b0\u7684":7,"\u7528\u6237\u53ef\u4ee5\u53c2\u8003sphinx\u6559\u7a0b\u8fdb\u884c\u4e66\u5199":7,"\u7528\u6237\u53ef\u4ee5\u81ea\u5b9a\u4e49beam":33,"\u7528\u6237\u53ef\u4ee5\u8bbe\u7f6e":35,"\u7528\u6237\u53ef\u5728\u8c03\u7528cmake\u7684\u65f6\u5019\u8bbe\u7f6e\u5b83\u4eec":0,"\u7528\u6237\u5728\u4f7f\u7528\u8fd9\u4e00\u7c7brecurr":12,"\u7528\u6237\u5728\u4f7f\u7528paddlepaddl":8,"\u7528\u6237\u5c06\u53c2\u6570\u8f7d\u5165":13,"\u7528\u6237\u5c06\u914d\u7f6e\u4e0e\u8bad\u7ec3\u6570\u636e\u5207\u5206\u597d\u653e\u5728\u5206\u5e03\u5f0f\u6587\u4ef6\u7cfb\u7edf\u9884\u5148\u5206\u914d\u597d\u7684\u76ee\u5f55\u4e2d":27,"\u7528\u6237\u5f3a\u5236\u6307\u5b9a\u7279\u5b9a\u7684python\u7248\u672c":8,"\u7528\u6237\u7684\u96c6\u7fa4\u73af\u5883\u4e0d\u5c3d\u76f8\u540c":24,"\u7528\u6237\u901a\u8fc7\u53c2\u6570":[12,13],"\u7528\u6237\u9700\u8981\u5728\u7f51\u7edc\u914d\u7f6e\u4e2d\u6307\u5b9a":35,"\u7528\u6237\u9700\u8981\u6307\u5b9a\u672c\u673a\u4e0apython\u7684\u8def\u5f84":8,"\u7528\u6765\u4ece\u53c2\u6570\u670d\u52a1\u5668\u9884\u53d6\u53c2\u6570\u77e9\u9635\u76f8\u5e94\u7684\u884c":6,"\u7528\u8fd9\u4e2a\u955c\u50cf\u521b\u5efa\u7684\u5bb9\u5668\u9700\u8981\u6709\u4ee5\u4e0b\u4e24\u4e2a\u529f\u80fd":27,"\u7531":[12,19,41],"\u7531\u4e8e":17,"\u7531\u4e8e\u5b83\u5185\u90e8\u5305\u542b\u4e86\u6bcf\u7ec4\u6570\u636e\u4e2d\u7684\u6240\u6709\u53e5\u5b50":39,"\u7531\u4e8e\u6211\u4eec\u60f3\u8981\u7684\u53d8\u6362\u662f\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217":39,"\u7531\u4e8e\u6211\u4eec\u652f\u6301\u8bad\u7ec3\u6570\u636e\u6709\u4e0d\u540c\u7684\u6279\u6b21\u5927\u5c0f":6,"\u7531\u4e8estep":41,"\u7531\u8bcd\u8bed\u6784\u6210\u7684\u53e5\u5b50":38,"\u7531\u94fe\u63a5\u65b9\u5f0f\u51b3\u5b9a":17,"\u7535\u8111":39,"\u767b\u5f55\u5230head\u8282\u70b9":28,"\u7684":[3,4,19,20,21,23,27,39],"\u7684\u4e00\u4e2a\u7b80\u5355\u8c03\u7528\u5982\u4e0b":41,"\u7684\u4e3a0":33,"\u7684\u4efb\u4e00\u4e00\u79cd":11,"\u7684\u4f7f\u7528\u793a\u4f8b\u5982\u4e0b":38,"\u7684\u504f\u7f6e\u5411\u91cf":6,"\u7684\u5171\u4eab\u5df2\u7ecf\u52a0\u8f7d\u7684\u9884\u6d4b\u6a21\u578b":20,"\u7684\u5185\u5b58":11,"\u7684\u5185\u5bb9\u6765\u5b9a\u5236imag":27,"\u7684\u5185\u6838block\u4f7f\u7528\u60c5\u51b5":37,"\u7684\u53c2\u6570\u4f7f\u4e4b\u652f\u6301\u5f02\u6b65sgd\u66f4\u65b0":21,"\u7684\u53cd\u5411\u4f20\u64ad\u5c06\u4f1a\u6253\u5370\u65e5\u5fd7\u4fe1\u606f":33,"\u7684\u53d8\u6362\u77e9\u9635":6,"\u7684\u540d\u79f0\u76f8\u540c":42,"\u7684\u5411\u91cf":6,"\u7684\u542f\u52a8\u53c2\u6570":27,"\u7684\u542f\u52a8\u53c2\u6570\u5e76\u6267\u884c\u8fdb\u7a0b":27,"\u7684\u5730\u65b9":4,"\u7684\u5747\u5300\u5206\u5e03":13,"\u7684\u591a\u79cd\u5b89\u88c5\u65b9\u5f0f":31,"\u7684\u5de5\u4f5c\u6d41\u7a0b\u5982\u56fe1\u6240\u793a":20,"\u7684\u5e73\u5747\u503c":38,"\u7684\u5e8f\u5217":19,"\u7684\u5e8f\u5217\u5f62\u72b6\u4e00\u81f4":39,"\u7684\u5f00\u53d1\u5de5\u4f5c\u90fd\u5e94\u8be5\u5728\u4e00\u4e2a\u65b0\u7684\u5206\u652f\u4e0a\u5b8c\u6210":4,"\u7684\u5f00\u53d1\u6d41\u7a0b":0,"\u7684\u63a5\u53e3\u8bf7\u67e5\u770b":19,"\u7684\u63cf\u8ff0\u8bf4\u660e\u4e2d":4,"\u7684\u6570\u76ee\u4e00\u81f4":38,"\u7684\u6587\u4ef6\u4e5f\u5e26\u5230\u65b0\u5206\u652f\u4e0a":4,"\u7684\u65b9\u7a0b":6,"\u7684\u65f6\u95f4\u6b65\u4fe1\u606f\u6210\u6b63\u6bd4":11,"\u7684\u66f4\u8be6\u7ec6\u51c6\u786e\u7684\u5b9a\u4e49":39,"\u7684\u6700\u5c0f\u503c":33,"\u7684\u6700\u65b0\u4ee3\u7801\u5e76\u66f4\u65b0\u5f53\u524d\u5206\u652f":4,"\u7684\u67b6\u6784\u7684\u793a\u4f8b":42,"\u7684\u6837\u5f0f":4,"\u7684\u6838\u5fc3\u662f\u8bbe\u8ba1step\u51fd\u6570\u7684\u8ba1\u7b97\u903b\u8f91":41,"\u7684\u6bb5\u843d\u5b9a\u4e49\u4e3a\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":41,"\u7684\u6bcf\u4e2a\u8fdb\u7a0b\u90fd\u53ef\u4ee5\u4ececeph\u8bfb\u53d6\u6570\u636e":26,"\u7684\u6e90\u7801\u4ee5\u53ca\u751f\u6210\u6587\u6863\u9700\u8981\u591a\u79cd\u5f00\u53d1\u5de5\u5177":4,"\u7684\u72b6\u6001":41,"\u7684\u77e9\u9635":[6,11],"\u7684\u7a20\u5bc6\u5411\u91cf\u4f5c\u4e3a\u8f93\u5165":6,"\u7684\u7a20\u5bc6\u77e9\u9635":19,"\u7684\u7a20\u5bc6\u77e9\u9635\u662f\u4e00\u4e2a\u7531":19,"\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570":20,"\u7684\u7b2ci\u4e2a\u503c":6,"\u7684\u7b2cj\u4e2a\u503c":6,"\u7684\u7cfb\u7edf":0,"\u7684\u7f16\u5199":21,"\u7684\u8bdd":11,"\u7684\u8f93\u5165":41,"\u7684\u8f93\u51fa":[11,37],"\u7684\u8f93\u51fa\u4fe1\u606f\u5165\u624b\u662f\u4e2a\u4e0d\u9519\u7684\u9009\u62e9":37,"\u7684\u8f93\u51fa\u51fd\u6570\u8fd4\u56de\u7684\u662f\u4e0b\u4e00\u4e2a\u65f6\u523b\u8f93\u51fa\u8bcd\u7684":42,"\u7684\u8f93\u51fa\u683c\u5f0f":39,"\u7684\u8f93\u51fa\u88ab\u7528\u4f5c":42,"\u7684\u8f93\u51fab\u662f\u4e00\u4e2a":11,"\u7684\u8fd0\u884c\u73af\u5883":0,"\u7684\u8fdc\u7a0b\u4ed3\u5e93\u7684\u540d\u5b57":4,"\u7684\u96c6\u88c5\u7bb1\u6280\u672f":0,"\u7684\u9875\u9762\u5220\u9664\u8fdc\u7a0b\u4ed3\u5e93\u7684\u5206\u652f":4,"\u7684docker\u955c\u50cf":1,"\u7684linux\u670d\u52a1\u5668\u7ec4\u6210":31,"\u76d1\u542c\u7684\u7aef\u53e3\u4e2a\u6570":21,"\u76ee\u524d":41,"\u76ee\u524d\u4f7f\u7528":4,"\u76ee\u524d\u63d0\u4f9b\u4e09\u79cd\u94fe\u63a5\u65b9\u5f0f":17,"\u76ee\u524d\u652f\u6301\u4e24\u79cd":38,"\u76ee\u524d\u652f\u6301cento":16,"\u76ee\u524d\u652f\u6301fail":33,"\u76ee\u524d\u8be5\u53c2\u6570\u4ec5\u7528\u4e8eaucvalidationlayer\u548cpnpairvalidationlayer\u5c42":33,"\u76ee\u524d\u8fd8\u672a\u652f\u6301":41,"\u76ee\u524dpaddlepaddle\u7684develop\u5206\u652f\u7684\u6587\u6863\u662f\u81ea\u52a8\u89e6\u53d1\u66f4\u65b0\u7684":7,"\u76ee\u5f55":[0,1,23,26,27],"\u76ee\u5f55\u4e0b":[6,23],"\u76ee\u5f55\u4e0b\u7684\u4ee3\u7801\u793a\u4f8b":20,"\u76ee\u5f55\u4e0b\u7684python\u5305":8,"\u76ee\u5f55\u4e2d":[17,20,23],"\u76ee\u5f55\u4e2d\u7684":37,"\u76ee\u5f55\u4e2dpaddl":27,"\u76ee\u5f55\u5c31\u6210\u4e3a\u4e86\u5171\u4eab\u5b58\u50a8":27,"\u76ee\u6807\u5411\u91cf":42,"\u76f4\u5230\u8bad\u7ec3\u6536\u655b\u4e3a\u6b62":13,"\u76f4\u63a5\u5347\u7ea7\u5230\u66f4\u65b0\u7684\u7248\u672c":0,"\u76f4\u63a5\u8fd0\u884c":1,"\u76f8\u540c\u540d\u5b57\u7684\u53c2\u6570":13,"\u76f8\u5bf9":39,"\u76f8\u5f53":39,"\u76f8\u6bd4\u4e8e\u6a21\u578b\u8bad\u7ec3":18,"\u770b\u5f53\u524dmpi\u96c6\u7fa4\u662f\u5426\u652f\u6301resourc":9,"\u77a7":16,"\u77e9\u9635":32,"\u77e9\u9635\u4e2d\u6bcf\u4e2a\u5143\u7d20\u7684\u503c\u968f\u673a\u751f\u6210":19,"\u77e9\u9635\u662f\u5426\u662f\u4e00\u4e2a\u5e8f\u5217":19,"\u77e9\u9635\u7684\u9ad8\u5ea6":19,"\u77e9\u9635\u91cc\u7684\u5143\u7d20\u662f\u6d6e\u70b9\u6570":19,"\u786e\u4fdd\u7f16\u8bd1\u5668\u9009\u9879":4,"\u78c1\u76d8\u4e0d\u591f":0,"\u78c1\u76d8\u7a7a\u95f4\u4e0d\u8db3\u7b49":9,"\u793a\u4f8b":[11,13,20],"\u793a\u4f8b3\u5bf9\u4e8e\u5355\u5c42rnn\u548c\u53cc\u5c42rnn\u6570\u636e\u5b8c\u5168\u76f8\u540c":39,"\u793a\u4f8b3\u7684\u914d\u7f6e\u4f7f\u7528\u4e86\u5355\u5c42rnn\u548c\u53cc\u5c42rnn":39,"\u793a\u4f8b3\u7684\u914d\u7f6e\u5206\u522b\u4e3a":39,"\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b":[11,20],"\u793a\u4f8b\u5982\u4e0b":13,"\u793a\u4f8b\u7a0b\u5e8f":21,"\u795e\u7ecf\u7f51\u7edc\u4e2d\u4e00\u4e2a\u8ba1\u7b97\u5c42\u7684\u8f93\u5165":19,"\u795e\u7ecf\u7f51\u7edc\u4e2d\u4e00\u4e2a\u8ba1\u7b97\u5c42\u7684\u8f93\u5165\u8f93\u51fa\u88ab\u7ec4\u7ec7\u4e3a\u4e00\u4e2a":20,"\u795e\u7ecf\u7f51\u7edc\u4e5f\u9700\u8981\u4e00\u4e9b\u7279\u5b9a\u7684layer\u4f5c\u4e3a\u8f93\u5165\u63a5\u53e3":14,"\u795e\u7ecf\u7f51\u7edc\u53c2\u6570\u4ee5\u53ca\u8fed\u4ee3\u65b9\u7a0b":14,"\u795e\u7ecf\u7f51\u7edc\u5728\u8bad\u7ec3\u7684\u65f6\u5019":11,"\u795e\u7ecf\u7f51\u7edc\u6a21\u578b\u7ed3\u6784\u548c\u8bad\u7ec3\u597d\u7684\u6a21\u578b\u5c06\u88ab\u5e8f\u5217\u5316\u5408\u5e76\u5165\u4e00\u4e2a\u6587\u4ef6":20,"\u795e\u7ecf\u7f51\u7edc\u7684\u7f51\u7edc\u7ed3\u6784\u4e2d\u5177\u6709\u6709\u5411\u73af\u7ed3\u6784":39,"\u795e\u7ecf\u7f51\u7edc\u7684\u8bad\u7ec3\u672c\u8eab\u662f\u4e00\u4e2a\u975e\u5e38\u6d88\u8017\u5185\u5b58\u548c\u663e\u5b58\u7684\u5de5\u4f5c":11,"\u79bb":39,"\u79f0\u4e3a":[4,42],"\u79f0\u4e4b\u4e3a":19,"\u79f0\u4e4b\u4e3a\u53cc\u5c42\u5e8f\u5217\u7684\u4e00\u4e2a\u5b50\u5e8f\u5217":38,"\u79f0\u4e4b\u4e3a\u96c6\u675f\u5927\u5c0f":33,"\u79fb\u52a8\u7aef\u9884\u6d4b":19,"\u7a00\u758f\u6570\u636e\u7684\u683c\u5f0f":6,"\u7a00\u758f\u66f4\u65b0\u7684\u7aef\u53e3\u6570\u91cf":27,"\u7a00\u758f\u768401\u5411\u91cf":14,"\u7a00\u758f\u7684\u5411\u91cf":14,"\u7a00\u758f\u77e9\u9635":19,"\u7a00\u758f\u77e9\u9635\u4f7f\u7528":19,"\u7a00\u758f\u77e9\u9635\u53ca\u76f8\u5173\u7684\u63a5\u53e3":19,"\u7a00\u758f\u77e9\u9635\u5b58\u50a8\u793a\u610f\u56fe":19,"\u7a00\u758f\u77e9\u9635\u7684\u4e58\u79ef\u5e94\u7528\u4e8e\u524d\u5411\u4f20\u64ad\u8fc7\u7a0b":35,"\u7a0b\u5e8f\u4ece\u6b64\u76ee\u5f55\u62f7\u8d1d\u6587\u4ef6\u5230\u5bb9\u5668\u5185\u8fdb\u884c\u8bad\u7ec3":27,"\u7a0b\u5e8f\u4f9d\u8d56":21,"\u7a0b\u5e8f\u505c\u6b62":33,"\u7a0b\u5e8f\u76f4\u63a5\u9000\u51fa":33,"\u7a20\u5bc6\u5411\u91cf":6,"\u7a20\u5bc6\u66f4\u65b0\u7684\u7aef\u53e3\u6570\u91cf":27,"\u7a20\u5bc6\u7684\u6d6e\u70b9\u6570\u5411\u91cf":14,"\u7a20\u5bc6\u77e9\u9635":19,"\u7a97\u6237":39,"\u7acb\u523b\u9000\u51fa":11,"\u7acb\u5373\u6267\u884c\u5355\u5143\u6d4b\u8bd5":0,"\u7aef\u53e3":9,"\u7aef\u6570\u636e\u7c7b\u578b":19,"\u7aef\u8bfb\u53d6\u6570\u636e":11,"\u7b2c":39,"\u7b2c\u4e00\u4e2a":4,"\u7b2c\u4e00\u4e2a\u6837\u672c\u540c\u65f6encode\u4e24\u6761\u6570\u636e\u6210\u4e24\u4e2a\u5411\u91cf":39,"\u7b2c\u4e00\u5929":39,"\u7b2c\u4e00\u6b65\u9700\u8c03\u7528":20,"\u7b2c\u4e00\u7ae0\u8282":14,"\u7b2c\u4e09\u65b9\u4f9d\u8d56\u5e93\u9700\u8981\u6309\u7167\u4e0e\u65b9\u5f0f2\u540c\u6837\u65b9\u6cd5\u663e\u793a\u5730\u8fdb\u884c\u94fe\u63a5":17,"\u7b2c\u4e09\u65b9\u94fe\u63a5\u5e93\u548c\u5934\u6587\u4ef6":17,"\u7b2c\u4e8c\u4e2a":11,"\u7b2c\u4e8c\u7c7b":12,"\u7b2ci\u884c\u7b2cj\u5217\u7684\u6570\u503c":6,"\u7b49":[9,20],"\u7b49\u4e8e\u6837\u672c\u6570":11,"\u7b49\u53c2\u6570":27,"\u7b49\u7b2c\u4e09\u65b9\u5e93":17,"\u7b80\u5355\u6765\u8bf4":37,"\u7b80\u5355\u7684\u5168\u8fde\u63a5\u7f51\u7edc":13,"\u7b80\u5355\u7684\u6027\u80fd\u5206\u6790":37,"\u7b80\u5355\u7684yaml\u6587\u4ef6\u5982\u4e0b":26,"\u7b80\u76f4":39,"\u7b97\u6cd5":[11,42],"\u7b97\u6cd5\u4e2d\u7684beam\u5927\u5c0f":42,"\u7ba1\u7406\u4e86\u6bcf\u4e2a\u8ba1\u7b97\u5c42\u8f93\u51fa\u7684\u5b58\u50a8\u7a7a\u95f4":20,"\u7ba1\u7406\u7684\u65b9\u6cd5":24,"\u7c7b\u4f3c":38,"\u7c7b\u4f5c\u4e3a\u53c2\u6570\u7684\u62bd\u8c61":6,"\u7c7b\u522b\u4e2d\u7684\u53c2\u6570\u53ef\u7528\u4e8e\u6240\u6709\u573a\u5408":32,"\u7c7b\u522b\u6807\u7b7e\u4e4b\u4e00":20,"\u7c7b\u522b\u6807\u7b7e\u5c42":20,"\u7c7b\u578b":[19,33],"\u7c7b\u578b\u53ef\u4ee5\u662fpaddlepaddle\u652f\u6301\u7684\u4efb\u610f\u8f93\u5165\u6570\u636e\u7c7b\u578b":38,"\u7c7b\u578b\u662fnumpy\u7684ndarrai":11,"\u7c7b\u578b\u662fsparse_binary_vector":14,"\u7c7b\u578b\u662fsparse_float_vector":14,"\u7c7b\u578b\u7684":39,"\u7c7b\u578b\u8fd8\u662f":19,"\u7c7b\u7684\u5bf9\u8c61":20,"\u7c7b\u7684\u6784\u9020\u51fd\u6570\u548c\u6790\u6784\u51fd\u6570":6,"\u7c7b\u9700\u8981\u5b9e\u73b0\u521d\u59cb\u5316":6,"\u7cfb\u7edf\u4f1a\u63d0\u4f9b\u4e00\u4e2a\u5206\u5e03\u5f0f\u5b58\u50a8\u670d\u52a1":21,"\u7ebf\u7a0bid\u53f7":35,"\u7ec6\u8282\u63cf\u8ff0":34,"\u7ecf\u5e38\u4f1a\u6d88\u8017\u657010gb\u7684\u5185\u5b58\u548c\u6570gb\u7684\u663e\u5b58":11,"\u7ecf\u8fc7\u6a21\u578b\u5904\u7406\u4e4b\u540e":18,"\u7ed3\u675f\u6807\u8bb0":42,"\u7ed3\u675f\u9884\u6d4b\u4e4b\u540e":20,"\u7ed3\u6784\u4f53":[19,20],"\u7ed3\u679c\u4f1a\u5199\u5165\u5f53\u524d\u8fd0\u884c\u76ee\u5f55\u4e0b\u7684":20,"\u7ed9":39,"\u7ed9\u4e2a\u7b80\u5355\u7684":4,"\u7ed9\u5b9aencoder\u8f93\u51fa\u548c\u5f53\u524d\u8bcd":41,"\u7ef4\u57fa\u767e\u79d1\u4e2d\u6587\u9875\u9762":39,"\u7ef4\u57fa\u767e\u79d1\u9875\u9762":39,"\u7ef4\u7a7a\u95f4":42,"\u7ef4\u7a7a\u95f4\u5b8c\u6210":42,"\u7f13\u5b58\u6c60\u7684\u51cf\u5c0f":11,"\u7f16\u5199":1,"\u7f16\u5199\u4e86\u4e00\u4e2apaddlepaddle\u7684\u7a0b\u5e8f":1,"\u7f16\u5199\u5b8cyaml\u6587\u4ef6\u540e":27,"\u7f16\u5199\u672c\u6b21\u8bad\u7ec3\u7684yaml\u6587\u4ef6":27,"\u7f16\u5199\u7684\u90e8\u5206":3,"\u7f16\u53f7\u4ece0\u5f00\u59cb":11,"\u7f16\u7801\u5411\u91cf":42,"\u7f16\u7801\u5668\u8f93\u51fa":42,"\u7f16\u7801\u6e90\u5e8f\u5217":42,"\u7f16\u8bd1":[1,4],"\u7f16\u8bd1\u51fa\u7684paddlepaddle\u9884\u6d4b\u5e93\u548c\u5934\u6587\u4ef6":17,"\u7f16\u8bd1\u53ca\u5b89\u88c5":2,"\u7f16\u8bd1\u540e\u7684\u6587\u4ef6\u5c06\u88ab\u5b58\u50a8\u5728\u5de5\u4f5c\u76ee\u5f55":7,"\u7f16\u8bd1\u5b89\u88c5\u4e0e\u5355\u5143\u6d4b\u8bd5":10,"\u7f16\u8bd1\u5b8c\u6210\u4e4b\u540e":7,"\u7f16\u8bd1\u5b8c\u6210\u540e\u4f1a\u5728build":0,"\u7f16\u8bd1\u6210\u529f\u540e\u5728":17,"\u7f16\u8bd1\u6210\u52a8\u6001\u5e93":33,"\u7f16\u8bd1\u751f\u6210":7,"\u7f16\u8bd1paddlepaddl":0,"\u7f51\u7edc\u5c42\u53ef\u4ee5\u6709\u591a\u4e2a\u8f93\u5165":6,"\u7f51\u7edc\u5c42\u7684\u6807\u8bc6\u7b26\u4e3a":6,"\u7f51\u7edc\u5c42\u7684\u7c7b\u578b":6,"\u7f51\u7edc\u5c42\u7684\u7ec6\u8282\u53ef\u4ee5\u901a\u8fc7\u4e0b\u9762\u8fd9\u4e9b\u4ee3\u7801\u7247\u6bb5\u6765\u6307\u5b9a":6,"\u7f51\u7edc\u5c42\u7684\u8f93\u51fa\u662f\u7ecf\u8fc7\u6fc0\u6d3b\u51fd\u6570\u4e4b\u540e\u7684\u503c":33,"\u7f51\u7edc\u5c42\u914d\u7f6e\u5305\u542b\u4ee5\u4e0b\u51e0\u9879":6,"\u7f51\u7edc\u63a5\u53d7\u4e00\u5e45\u56fe\u7247\u4f5c\u4e3a\u8f93\u5165":20,"\u7f51\u7edc\u7ed3\u6784\u7684\u5e8f\u5217\u5316\u7ed3\u679c\u548c\u6a21\u578b\u53c2\u6570\u5b58\u50a8\u76ee\u5f55":20,"\u7f51\u7edc\u901a\u4fe1":6,"\u7f51\u901f\u6216ssl\u94fe\u63a5\u539f\u56e0":8,"\u800c":[12,42],"\u800c\u4e0d\u662f\u5728layer\u91cc\u5b9e\u73b0":12,"\u800c\u4e0d\u662f\u6e90\u7801\u76ee\u5f55\u91cc":8,"\u800c\u4e0d\u662f\u7279\u5f81\u7684\u96c6\u5408":39,"\u800c\u4e0d\u662f\u76f8\u5bf9":19,"\u800c\u4e0d\u662fc":19,"\u800c\u4e14\u4e2a\u6570\u5e76\u4e0d\u786e\u5b9a":21,"\u800c\u4e14\u5305\u542b\u4e86c":3,"\u800c\u4e14cento":3,"\u800c\u4e4b\u524d\u7684\u53c2\u6570\u5c06\u4f1a\u88ab\u5220\u9664":33,"\u800c\u4ece\u5e94\u7528\u7684\u89d2\u5ea6":37,"\u800c\u4f18\u5316\u6027\u80fd\u7684\u9996\u8981\u4efb\u52a1":37,"\u800c\u5176\u4ed6\u5c42\u4f7f\u7528cpu\u8ba1\u7b97":35,"\u800c\u53cc\u5c42rnn\u662f\u53ef\u4ee5\u5904\u7406\u8fd9\u79cd\u8f93\u5165\u6570\u636e\u7684\u7f51\u7edc\u7ed3\u6784":39,"\u800c\u53ea\u9700\u8981\u83b7\u5f97recurr":12,"\u800c\u5b89\u88c5\u5305":[3,8],"\u800c\u5b89\u88c5\u5305\u662f":[3,8],"\u800c\u5bf9\u4e8e\u53cc\u5c42\u5e8f\u5217":39,"\u800c\u5bf9\u4e8e\u6bcf\u4e00\u4e2a\u5185\u5c42\u7279\u5f81\u6570\u636e\u800c\u8a00":39,"\u800c\u5c06\u8fd9\u4e2a\u6bb5\u843d\u7684\u6bcf\u4e00\u53e5\u8bdd\u7528lstm\u7f16\u7801\u6210\u4e00\u4e2a\u5411\u91cf":39,"\u800c\u5f53\u524d\u5df2\u7ecf\u67095":37,"\u800c\u662f\u5c06\u8f93\u5165":[19,20],"\u800c\u662f\u76f4\u63a5\u4ece\u5185\u5b58\u7684\u7f13\u5b58\u91cc\u8bfb\u53d6\u6570\u636e":11,"\u800c\u66f4\u6df1\u5165\u7684\u5206\u6790":37,"\u800c\u6709\u4e9b\u53c2\u6570\u9700\u8981\u5728\u96c6\u7fa4\u591a\u673a\u8bad\u7ec3\u4e2d\u4f7f\u7528\u7b49":32,"\u800c\u6e90\u5e8f\u5217\u7684\u7f16\u7801\u5411\u91cf\u53ef\u4ee5\u88ab\u65e0\u8fb9\u754c\u7684memory\u8bbf\u95ee":42,"\u800c\u795e\u7ecf\u7f51\u7edc\u662f\u6211\u4eec\u8981\u642d\u5efa\u7684\u5b9d\u5854":14,"\u800c\u7a00\u758f\u66f4\u65b0\u5728\u53cd\u5411\u4f20\u64ad\u4e4b\u540e\u7684\u6743\u91cd\u66f4\u65b0\u65f6\u8fdb\u884c":35,"\u800c\u8fd9\u4e00\u53e5\u8bdd\u5c31\u53ef\u4ee5\u8868\u793a\u6210\u8fd9\u4e9b\u4f4d\u7f6e\u7684\u6570\u7ec4":39,"\u800c\u8fd9\u6bcf\u4e00\u4e2a\u6570\u7ec4\u5143\u7d20":39,"\u800c\u975e\u76f4\u63a5\u56de\u590d\u7684\u65b9\u5f0f":4,"\u800c\u975e\u9759\u6001\u52a0\u8f7dcuda\u52a8\u6001\u5e93":0,"\u800crnn\u662f\u6700\u6d41\u884c\u7684\u9009\u62e9":41,"\u800ctrainer\u9700\u8981\u8bfb\u53d6\u8bad\u7ec3\u6570\u636e\u8fdb\u884c\u8bad\u7ec3":14,"\u800cy_predict\u662f\u63a5\u6536x\u4f5c\u4e3a\u8f93\u5165":14,"\u8054\u901a":31,"\u80fd\u591f\u5904\u7406\u53cc\u5c42\u5e8f\u5217":41,"\u80fd\u591f\u5bf9\u53cc\u5411\u5e8f\u5217\u8fdb\u884c\u5904\u7406\u7684\u6709":41,"\u80fd\u591f\u8bb0\u5f55\u4e0a\u4e00\u4e2asubseq":41,"\u80fd\u591f\u9488\u5bf9cpu\u548cgpu\u7684\u8ba1\u7b97\u505a\u66f4\u591a\u4f18\u5316":12,"\u80fd\u83b7\u53d6":23,"\u811a\u672c":[0,20],"\u811a\u672c\u5f00\u59cb\u65f6":27,"\u811a\u672c\u96c6\u6210\u4e86\u5e8f\u5217\u5316\u795e\u7ecf\u7f51\u7edc\u7ed3\u6784\u7684\u8fc7\u7a0b":20,"\u81ea\u52a8\u5173\u95ed\u5bf9\u5e94\u7684":4,"\u81ea\u52a8\u5730\u5c06\u8fd9\u4e9b\u9009\u9879\u5e94\u7528\u5230":23,"\u81ea\u52a8\u5b8c\u6210\u8fd9\u4e00\u8fc7\u7a0b":41,"\u81ea\u52a8\u751f\u6210":7,"\u81ea\u52a8\u83b7\u53d6\u4e0a\u4e00\u4e2a\u751f\u6210\u7684\u8bcd":42,"\u81ea\u7136\u4e5f\u5c31\u6709\u7ba1\u7406\u5458\u6743\u9650":0,"\u81ea\u7136\u8bed\u8a00\u4e2d\u7684\u53e5\u5b50\u662f\u4e00\u4e2a\u5e8f\u5217":19,"\u81ea\u7136\u8bed\u8a00\u4e2d\u7684\u6bb5\u843d\u662f\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":19,"\u81ea\u7136\u8bed\u8a00\u5904\u7406\u7b49":35,"\u81f3\u5c11\u5305\u542bgcc_3":3,"\u81f3\u5c11\u5305\u542bglibcxx_3":3,"\u81f3\u6b64":[4,39],"\u8212\u9002":39,"\u8282\u70b9":[28,31],"\u82e5":6,"\u82e5\u5728paddlepaddle\u7f16\u8bd1\u65f6":13,"\u82e5\u5e72\u4e2a\u53e5\u5b50\u6784\u6210\u4e00\u4e2a\u6bb5\u843d":38,"\u82e5\u6709\u4e0d\u4e00\u81f4\u4e4b\u5904":37,"\u82e5\u6709\u5fc5\u8981":6,"\u82e5\u8981\u5bf9\u8fd9\u51e0\u4e2alayer\u4f7f\u7528dropout":12,"\u82e5\u8f93\u51fa\u662f\u5355\u5c42\u5e8f\u5217":38,"\u82e5\u8f93\u51fa\u662f\u53cc\u5c42\u5e8f\u5217":38,"\u82f1\u6587\u6587\u6863":7,"\u82f1\u6587\u6587\u6863\u76ee\u5f55":7,"\u8303\u56f4":35,"\u83b7\u53d6":4,"\u83b7\u53d6\u53ef\u9009\u7684tag":1,"\u83b7\u53d6\u5f53\u524d\u7cfb\u7edf\u652f\u6301\u7684\u5b89\u88c5\u5305\u683c\u5f0f":3,"\u83b7\u53d6\u5f53\u524d\u7cfb\u7edf\u652f\u6301\u7684python\u5305\u7684\u540e\u7f00":8,"\u83b7\u53d6\u6e90\u7801":0,"\u83b7\u53d6\u8f93\u51fa\u65f6":20,"\u83b7\u53d6trainer":27,"\u83b7\u5f97\u53c2\u6570\u5c3a\u5bf8":6,"\u83b7\u5f97\u5728\u6a21\u578b\u914d\u7f6e\u4e2d\u67d0\u4e00\u5c42\u7684name":11,"\u83b7\u5f97\u57fa\u672c\u7684docker\u5b89\u88c5\u548c\u4f7f\u7528\u65b9\u6cd5":1,"\u83b7\u5f97\u5f53\u524dmini":11,"\u83b7\u5f97\u7684\u503c\u7c7b\u578b\u5747\u4e3a":11,"\u83b7\u5f97\u8ba1\u7b97\u7ed3\u679c":20,"\u83b7\u5f97\u8fd9\u4e9b\u8282\u70b9\u7684ip\u5730\u5740":23,"\u83b7\u5f97head\u548cnode\u8282\u70b9\u7684ip\u5730\u5740":28,"\u865a\u62df\u673a\u4e0a":0,"\u867d\u7136\u5f02\u6b65sgd\u65b9\u5f0f\u4f1a\u63d0\u9ad8\u53c2\u6570\u66f4\u65b0\u5e76\u884c\u5ea6":22,"\u867d\u7136paddle\u770b\u8d77\u6765\u5305\u542b\u4e86\u4f17\u591a\u53c2\u6570":32,"\u884c":19,"\u884c\u504f\u79fb":19,"\u8865\u5145\u4e0a\u6b21\u7684commit":4,"\u8868\u660e\u4e86\u8fd9\u4e9b\u884c\u7684\u6807\u53f7":6,"\u8868\u660e\u8fd9\u4e2a\u5c42\u7684\u4e00\u4e2a\u5b9e\u4f8b\u662f\u5426\u9700\u8981\u504f\u7f6e":6,"\u8868\u793a\u4e3adeviceid":35,"\u8868\u793a\u5c06\u5916\u5c42\u7684outer_mem\u4f5c\u4e3a\u5185\u5c42memory\u7684\u521d\u59cb\u72b6\u6001":39,"\u8868\u793a\u5f53\u524d\u96c6\u7fa4\u4f5c\u4e1a\u7684\u8282\u70b9":23,"\u8868\u793a\u7684\u504f\u79fb\u662f\u4ee5":19,"\u8868\u793a\u8bcd\u8bed\u5728\u8bcd\u5178\u4e2d\u7684\u5e8f\u53f7":19,"\u8868\u793a\u8bfb\u8005\u6240\u4f7f\u7528\u7684docker\u955c\u50cf\u4ed3\u5e93\u5730\u5740":27,"\u8868\u793a\u8fd9\u4e2ajob\u7684\u540d\u5b57":27,"\u88ab":4,"\u88ab\u5207\u5206\u6210\u591a\u4e2a\u90e8\u5206":22,"\u88ab\u6269\u5c55\u4e3a\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":38,"\u88ab\u653e\u5728":6,"\u88ab\u79f0\u4e3a":42,"\u8981\u4f7f\u7528\u547d\u4ee4\u884c\u5206\u6790\u5de5\u5177":37,"\u8981\u5728\u5df2\u6709\u7684kubernetes\u96c6\u7fa4\u4e0a\u8fdb\u884cpaddlepaddle\u7684\u5206\u5e03\u5f0f\u8bad\u7ec3":27,"\u8981\u6c42\u5355\u5c42\u5e8f\u5217\u542b\u6709\u5143\u7d20\u7684\u6570\u76ee":38,"\u8981\u751f\u6210\u7684\u76ee\u6807\u5e8f\u5217":41,"\u8981\u8c03\u7528":6,"\u89c6\u9891\u7b49":19,"\u89e3\u51b3\u529e\u6cd5\u662f":8,"\u89e3\u51b3\u65b9\u6848\u662f":13,"\u89e3\u6790\u73af\u5883\u53d8\u91cf\u5f97\u5230":27,"\u89e3\u7801\u5668\u4f7f\u7528":42,"\u89e3\u7801\u5668\u57fa\u4e8e\u7f16\u7801\u6e90\u5e8f\u5217\u548c\u6700\u540e\u751f\u6210\u7684\u76ee\u6807\u8bcd\u9884\u6d4b\u4e0b\u4e00\u76ee\u6807\u8bcd":42,"\u89e3\u7801\u5668\u662f\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":42,"\u8ba1\u7b97":[22,42],"\u8ba1\u7b97\u504f\u7f6e\u7684\u68af\u5ea6":6,"\u8ba1\u7b97\u53cd\u5411rnn\u7684\u7b2c\u4e00\u4e2a\u5b9e\u4f8b":42,"\u8ba1\u7b97\u53d8\u6362\u77e9\u9635\u7684\u5927\u5c0f\u548c\u683c\u5f0f":6,"\u8ba1\u7b97\u5f53\u524d\u5c42\u6743\u91cd\u7684\u68af\u5ea6":6,"\u8ba1\u7b97\u6548\u7387\u66f4\u9ad8":12,"\u8ba1\u7b97\u6bcf\u4e2a\u8bcd\u7684\u8bcd\u5411\u91cf":42,"\u8ba1\u7b97\u6fc0\u6d3b\u51fd\u6570\u7684\u68af\u5ea6":6,"\u8ba1\u7b97\u7684\u7ec6\u8282\u5c06\u5728\u4e0b\u9762\u7684\u5c0f\u8282\u7ed9\u51fa":6,"\u8ba1\u7b97\u8282\u70b9":22,"\u8ba1\u7b97\u8282\u70b9\u4e4b\u95f4\u4e5f\u4e0d\u4f1a\u76f8\u4e92\u4f9d\u8d56":22,"\u8ba1\u7b97\u8f6c\u6362\u77e9\u9635\u548c\u8f93\u5165\u7684\u68af\u5ea6":6,"\u8ba1\u7b97\u8f93\u5165\u548c\u53c2\u6570\u7684\u68af\u5ea6":6,"\u8ba1\u7b97\u8f93\u5165\u5c42\u7684\u504f\u5dee":6,"\u8ba1\u7b97\u8f93\u51fa":6,"\u8ba1\u7b97\u96c6\u7fa4\u901a\u5e38\u7531\u4e00\u7ec4":31,"\u8bad\u7ec3":32,"\u8bad\u7ec3\u5931\u8d25\u65f6\u53ef\u4ee5\u68c0\u67e5\u9519\u8bef\u65e5\u5fd7":23,"\u8bad\u7ec3\u597d\u4e00\u4e2a\u6df1\u5c42\u795e\u7ecf\u7f51\u7edc\u901a\u5e38\u8981\u8017\u8d39\u975e\u5e38\u957f\u7684\u65f6\u95f4":37,"\u8bad\u7ec3\u597d\u7684\u6a21\u578b\u9ed8\u8ba4\u4fdd\u5b58\u5728\u5f53\u524d\u8fd0\u884c\u76ee\u5f55\u4e0b\u7684":20,"\u8bad\u7ec3\u6570\u636e\u6709\u95ee\u9898":11,"\u8bad\u7ec3\u6570\u636e\u683c\u5f0f\u548c\u8bad\u7ec3\u7a0b\u5e8f\u7684":21,"\u8bad\u7ec3\u65f6":27,"\u8bad\u7ec3\u6a21\u578b\u540e":42,"\u8bad\u7ec3\u7a0b\u5e8f":21,"\u8bad\u7ec3\u7b56\u7565\u7b49\u7b49\u8fd9\u4e9b\u90fd\u662f\u5e38\u89c1\u7684\u53d8\u5316\u56e0\u7d20":34,"\u8bad\u7ec3\u7ed3\u675f\u540e\u67e5\u770b\u8f93\u51fa\u7ed3\u679c":27,"\u8bad\u7ec3\u8282\u70b9\u6570\u91cf":27,"\u8bad\u7ec3\u8bed\u8a00\u6a21\u578b\u8ddd\u79bb":11,"\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u53c2\u6570\u6216\u8005\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u7684\u68af\u5ea6\u5c3a\u5ea6\u8fc7\u5927":11,"\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u6d4b\u8bd5test_period":32,"\u8bad\u7ec3\u8fc7\u7a0b\u662f\u5426\u4e3a\u672c\u5730\u6a21\u5f0f":33,"\u8bad\u7ec3\u8fc7\u7a0b\u662f\u5426\u4f7f\u7528gpu":33,"\u8bad\u7ec3\u914d\u7f6e\u4e2d\u7684\u8bbe\u5907\u5c5e\u6027\u5c06\u4f1a\u65e0\u6548":33,"\u8bad\u7ec3dot_period":32,"\u8bb0\u5fc6\u6a21\u5757":42,"\u8bbe\u4e3a\u5df2\u90e8\u7f72\u7684\u5de5\u4f5c\u7a7a\u95f4\u76ee\u5f55":23,"\u8bbe\u4e3a\u672c\u5730":23,"\u8bbe\u5b9a":12,"\u8bbe\u7f6e":[0,11,12,21],"\u8bbe\u7f6e\u4e3a":6,"\u8bbe\u7f6e\u4e3a\u4e0d\u540c\u7684\u503c":12,"\u8bbe\u7f6e\u4e3atrue\u4f7f\u7528\u672c\u5730\u8bad\u7ec3\u6216\u8005\u4f7f\u7528\u96c6\u7fa4\u4e0a\u7684\u4e00\u4e2a\u8282\u70b9":33,"\u8bbe\u7f6e\u4e3atrue\u4f7f\u7528gpu\u6a21\u5f0f":33,"\u8bbe\u7f6e\u4e86\u76f8\u540c\u7684\u53d6\u503c":12,"\u8bbe\u7f6e\u5176\u53c2\u6570\u5c5e\u6027":13,"\u8bbe\u7f6e\u53c2\u6570\u7684\u540d\u5b57":13,"\u8bbe\u7f6e\u547d\u4ee4\u884c\u53c2\u6570":11,"\u8bbe\u7f6e\u5b66\u4e60\u7387\u8870\u51cf\u56e0\u5b50\u5206\u6bb5\u51fd\u6570":13,"\u8bbe\u7f6e\u5e8f\u5217\u4fe1\u606f\u7684\u63a5\u53e3":19,"\u8bbe\u7f6e\u6210":13,"\u8bbe\u7f6e\u6210\u4e00\u4e2a\u5c0f\u4e00\u4e9b\u7684\u503c":11,"\u8bbe\u7f6e\u8f93\u51fa\u7684\u5c3a\u5bf8":6,"\u8bbe\u7f6e\u9ed8\u8ba4\u8bbe\u5907\u53f7\u4e3a0":35,"\u8bbe\u7f6egpu":33,"\u8bbf\u95eekubernetes\u7684\u63a5\u53e3\u6765\u67e5\u8be2\u6b64job\u5bf9\u5e94\u7684\u6240\u6709pod\u4fe1\u606f":27,"\u8bc4\u5ba1\u4eba\u4e00\u822c\u4e0d\u505a\u8bc4\u5ba1":4,"\u8bc4\u5ba1\u4eba\u7684\u6bcf\u4e2a\u610f\u89c1\u90fd\u5fc5\u987b\u56de\u590d":4,"\u8bc4\u5ba1\u4eba\u9700\u8981\u9010\u4e00\u67e5\u770b\u6bcf\u4e2acommit\u624d\u80fd\u77e5\u9053\u505a\u4e86\u54ea\u4e9b\u4fee\u6539":4,"\u8bc4\u8bba\u6846\u4e2d\u52a0\u4e0a":4,"\u8bd5\u7740\u8ba9\u8f93\u51fa\u7684\u5206\u6790\u6570\u636e\u548c\u7406\u8bba\u503c\u5bf9\u5e94":37,"\u8be5\u53c2\u6570\u5728\u7f51\u7edc\u914d\u7f6e\u7684output":33,"\u8be5\u53c2\u6570\u5728\u96c6\u7fa4\u63d0\u4ea4\u73af\u5883\u4e2d\u81ea\u52a8\u8bbe\u7f6e":33,"\u8be5\u53c2\u6570\u5df2\u7ecf\u5728\u96c6\u7fa4\u63d0\u4ea4\u73af\u5883\u4e2d\u5b8c\u6210\u8bbe\u7f6e":33,"\u8be5\u53c2\u6570\u5fc5\u987b\u80fd\u88abflag":33,"\u8be5\u53c2\u6570\u6307\u793a\u662f\u5426\u6253\u5370\u65e5\u5fd7\u622a\u65ad\u4fe1\u606f":33,"\u8be5\u53c2\u6570\u6307\u793a\u662f\u5426\u6253\u5370\u9519\u8bef\u622a\u65ad\u65e5\u5fd7":33,"\u8be5\u53c2\u6570\u7528\u4e8e\u6307\u5b9a\u52a8\u6001\u5e93\u8def\u5f84":33,"\u8be5\u53c2\u6570\u7684\u610f\u601d\u662f\u8bad\u7ec3num":33,"\u8be5\u53c2\u6570\u9ed8\u8ba4\u4e3anull":33,"\u8be5\u5c42\u4ec5\u9700\u8981\u8fd9\u4e9b\u975e\u96f6\u6837\u672c\u4f4d\u7f6e\u6240\u5bf9\u5e94\u7684\u53d8\u6362\u77e9\u9635\u7684\u90a3\u4e9b\u884c":6,"\u8be5\u622a\u65ad\u4f1a\u5f71\u54cd":33,"\u8be5\u6279\u6b21\u7684\u8f93\u5165\u4e2d\u4ec5\u6709\u4e00\u4e2a\u5b50\u96c6\u662f\u975e\u96f6\u7684":6,"\u8be5\u63a5\u53e3\u53ef\u7528\u4e8e\u9884\u6d4b\u548c\u5b9a\u5236\u5316\u8bad\u7ec3":0,"\u8be5\u63a5\u53e3\u63a5\u53d7\u4e24\u4e2a\u53c2\u6570":20,"\u8be5\u6570\u76ee\u662f\u63d0\u524d\u5b9a\u4e49\u597d\u7684":33,"\u8be5\u65b9\u5f0f\u5177\u6709\u4ee5\u4e0b\u4f18\u52bf":2,"\u8be5\u6a21\u578b\u7684\u8bf4\u660e\u5982\u4e0b\u56fe\u6240\u793a":42,"\u8be5\u7c7b\u7684\u5b9e\u73b0\u7ec6\u8282\u5728":6,"\u8be5\u8bed\u53e5\u4f1a\u4e3a\u6bcf\u4e2a\u5c42\u521d\u59cb\u5316\u5176\u6240\u9700\u8981\u7684\u53d8\u91cf\u548c\u8fde\u63a5":6,"\u8be5layer\u662f\u901a\u8fc7\u53c2\u6570":12,"\u8be6\u7ec6\u4ecb\u7ecd\u53ef\u4ee5\u53c2\u8003":39,"\u8be6\u7ec6\u4fe1\u606f\u8bf7\u68c0\u67e5":23,"\u8be6\u7ec6\u53c2\u8003":0,"\u8be6\u7ec6\u53ef\u53c2\u8003":4,"\u8be6\u7ec6\u6587\u6863\u53c2\u8003":11,"\u8be6\u7ec6\u7684cmake\u4f7f\u7528\u65b9\u6cd5\u53ef\u4ee5\u53c2\u8003":0,"\u8be6\u7ec6\u89c1":38,"\u8be6\u7ec6\u89e3\u91ca\u8fd9\u4e9b\u53c2\u6570\u7684\u5c5e\u6027\u548c\u610f\u4e49":34,"\u8be6\u7ec6\u8bf7\u4e86\u89e3":24,"\u8bf4\u660e":[0,3,19],"\u8bf4\u660e\u63d0\u4ea4\u7684\u4ee3\u7801\u5b58\u5728\u95ee\u9898":4,"\u8bf4\u660e\u8fd9\u4e2a\u5c42\u7684\u8f93\u5165":6,"\u8bf7\u4e0d\u8981\u5fd8\u8bb0\u63d0\u524d\u5728\u7269\u7406\u673a\u4e0a\u5b89\u88c5gpu\u6700\u65b0\u9a71\u52a8":1,"\u8bf7\u4fdd\u8bc1travi":4,"\u8bf7\u5148\u5c1d\u8bd5\u5728\u4e0b\u9762\u7684\u9875\u9762\u5bfb\u627e\u7b54\u6848":2,"\u8bf7\u53c2\u7167\u4ee5\u4e0b\u6559\u7a0b":2,"\u8bf7\u53c2\u7167\u7f51\u7edc\u914d\u7f6e\u7684\u6587\u6863\u4e86\u89e3\u66f4\u8be6\u7ec6\u7684\u4fe1\u606f":35,"\u8bf7\u53c2\u8003":[6,8,11,14,20,39],"\u8bf7\u53c2\u8003\u6b64":20,"\u8bf7\u53c2\u89c1":4,"\u8bf7\u53c2\u9605":42,"\u8bf7\u5728\u8be5pull":4,"\u8bf7\u5728\u8f93\u5165\u65f6\u8fdb\u884c\u5408\u6cd5\u6027\u68c0\u67e5":19,"\u8bf7\u60a8\u5230":10,"\u8bf7\u60a8\u6bcf\u6b21\u63d0\u4ea4\u4ee3\u7801\u65f6":4,"\u8bf7\u60a8\u9075\u5b88\u4ee5\u4e0b\u7ea6\u5b9a":4,"\u8bf7\u6307\u5b9a\u7684paddlepaddle\u5de5\u4f5c\u76ee\u5f55\u7ed9\u73af\u5883\u53d8\u91cf":7,"\u8bf7\u6307\u5b9a\u8be5\u76ee\u5f55":33,"\u8bf7\u6839\u636e\u673a\u5668\u914d\u7f6e\u548c\u7cfb\u7edf\u9009\u62e9\u5bf9\u5e94\u7684\u5b89\u88c5\u5305":2,"\u8bf7\u68c0\u67e5python\u7248\u672c\u662f\u5426\u4e3a2":3,"\u8bf7\u6ce8\u610f":[26,42],"\u8bf7\u6ce8\u610f\u662f\u5426\u9700\u8981\u4fee\u6539\u7f51\u7edc\u7ed3\u6784":20,"\u8bf7\u6ce8\u610f\u6bcf\u4e2acommit\u7684\u540d\u79f0":4,"\u8bf7\u6ce8\u610fcommit\u7684\u6570\u91cf":4,"\u8bf7\u76f4\u63a5\u586b\u51450":13,"\u8bf7\u770b\u4e0b\u9762\u7684\u4f8b\u5b50":35,"\u8bf7\u786e\u4fdd":4,"\u8bf7\u7ed9\u51fa\u603b\u4f53\u7684\u4fee\u6539\u60c5\u51b5":4,"\u8bf7\u7ed9\u51fa\u60a8\u81ea\u5df1\u7684\u53cd\u9a73\u7406\u7531":4,"\u8bf7\u9009\u62e9\u5408\u9002\u7684\u8bcd\u6c47":4,"\u8bf7\u9009\u62e9\u6b63\u786e\u7684\u7248\u672c":8,"\u8bf7\u9075\u5b88":4,"\u8bf7\u91c7\u7528":4,"\u8bf7\u9605\u8bfb\u4ee5\u4e0b\u6307\u5357":24,"\u8bf8\u5982\u56fe\u50cf\u5206\u7c7b":35,"\u8bfb\u53d6\u9700\u8981\u7684\u7ed3\u679c\u5373\u53ef":19,"\u8bfb\u53d6volume\u4e2d\u7684\u6570\u636e\u8fdb\u884c\u8fd9\u6b21\u5206\u5e03\u5f0f\u8bad\u7ec3":27,"\u8bfb\u8005\u53ef\u4ee5\u67e5\u770b":27,"\u8bfb\u8005\u9700\u8981\u66ff\u6362\u6210\u81ea\u5df1\u4f7f\u7528\u7684\u4ed3\u5e93\u5730\u5740":27,"\u8c03\u7528":[6,20],"\u8c03\u7528\u7684\u4e00\u4e9b\u7528\u6237\u5b9a\u4e49\u7684\u5e93\u51fd\u6570":21,"\u8c03\u7528\u8be5\u51fd\u6570\u540e":6,"\u8c03\u7528c":[19,20],"\u8d21\u732e\u6587\u6863":7,"\u8d77":39,"\u8d77\u59cb\u5b58\u50a8\u5730\u5740\u4ee5\u6570\u636e\u7684\u5b58\u50a8\u5927\u5c0f\u4e3a\u5355\u4f4d\u7684\u504f\u79fb":19,"\u8df3\u8f6c\u5230":4,"\u8df3\u8fc7":11,"\u8f6c\u5316\u65b9\u6cd5\u5728\u76f8\u5e94\u7684\u9886\u57df\u90fd\u6709\u901a\u7528\u89e3\u51b3\u65b9\u6848":19,"\u8f83":39,"\u8f93\u5165":[18,20,38,42],"\u8f93\u5165\u548c\u8f93\u51fa\u90fd\u662f\u5355\u5c42\u5e8f\u5217":41,"\u8f93\u5165\u548c\u8f93\u51fa\u90fd\u662f\u53cc\u5c42\u5e8f\u5217":41,"\u8f93\u5165\u5e8f\u5217\u4e2d\u5143\u7d20\u7684\u603b\u6570":11,"\u8f93\u5165\u6570\u636e\u4e3a\u4e00\u4e2a\u5b8c\u6574\u7684\u65f6\u95f4\u5e8f\u5217":39,"\u8f93\u5165\u6570\u636e\u4e3a\u5728\u5355\u5c42rnn\u6570\u636e\u91cc\u9762":39,"\u8f93\u5165\u6570\u636e\u53ef\u5206\u4e3a":19,"\u8f93\u5165\u6570\u636e\u6574\u4f53\u4e0a\u662f\u4e00\u4e2a\u65f6\u95f4\u5e8f\u5217":39,"\u8f93\u5165\u6570\u636e\u7684\u5b57\u5178\u7ef4\u6570\u662f1\u767e\u4e07":35,"\u8f93\u5165\u6570\u636e\u7c7b\u578b":19,"\u8f93\u5165\u662f\u5426\u662f\u8f6c\u7f6e\u7684":6,"\u8f93\u5165\u662f\u7531\u4e00\u4e2alist\u4e2d\u7684\u7f51\u7edc\u5c42\u5b9e\u4f8b\u7684\u540d\u5b57\u7ec4\u6210\u7684":6,"\u8f93\u5165\u7684\u540d\u5b57":6,"\u8f93\u5165\u7684\u5927\u5c0f":6,"\u8f93\u5165\u7684\u7c7b\u578b":6,"\u8f93\u5165\u9700\u8981\u9884\u6d4b\u7684\u5411\u91cf\u7ec4":14,"\u8f93\u51fa":[20,38,42],"\u8f93\u51fa\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":41,"\u8f93\u51fa\u4e00\u4e2a\u53cc\u5c42\u5e8f\u5217":41,"\u8f93\u51fa\u4fe1\u606f\u6709\u673a\u5730\u7ec4\u7ec7\u5728\u4e00\u8d77":19,"\u8f93\u51fa\u51fd\u6570":42,"\u8f93\u51fa\u521b\u5efa":[19,20],"\u8f93\u51fa\u5e8f\u5217\u7684\u7c7b\u578b":38,"\u8f93\u51fa\u5e8f\u5217\u7684\u8bcd\u8bed\u6570\u548c\u8f93\u5165\u5e8f\u5217\u4e00\u81f4":41,"\u8f93\u51fa\u6240\u643a\u5e26\u7684\u5e8f\u5217\u4fe1\u606f":19,"\u8f93\u51fa\u6570\u636e\u662f\u5728\u4e0a\u6587\u4ecb\u7ecd\u7684":19,"\u8f93\u51fa\u6570\u636e\u6709\u673a\u5730\u7ec4\u7ec7\u5728\u4e00\u8d77":20,"\u8f93\u51fa\u6570\u636e\u7ec4\u7ec7":[18,20],"\u8f93\u51fa\u7531":19,"\u8f93\u51fa\u7684\u5e8f\u5217\u4fe1\u606f":19,"\u8f93\u51fa\u7684\u68af\u5ea6":33,"\u8f93\u51fa\u7ed3\u679c\u53ef\u80fd\u4f1a\u968f\u7740\u5bb9\u5668\u7684\u6d88\u8017\u800c\u88ab\u5220\u9664":26,"\u8f93\u51fa\u88ab\u7ec4\u7ec7\u4e3a":19,"\u8f93\u51fa\u88ab\u7ec4\u7ec7\u4e3a\u4e00\u4e2a":19,"\u8f93\u51fa\u90fd\u4f1a\u5bf9\u5e94\u6709\u81ea\u5df1\u7684":[19,20],"\u8fc7\u4e86\u4e00\u4e2a\u5f88\u7b80\u5355\u7684recurrent_group":39,"\u8fc7\u5b8c\u6240\u6709\u8bad\u7ec3\u6570\u636e\u5373\u4e3a\u4e00\u4e2apass":11,"\u8fd0\u884c":20,"\u8fd0\u884c\u4e00\u4e2a":0,"\u8fd0\u884c\u5931\u8d25":35,"\u8fd0\u884c\u5b8c\u6210\u540e":23,"\u8fd0\u884c\u65e5\u5fd7":23,"\u8fd0\u884c\u65f6\u4f1a\u81ea\u52a8\u627e\u5230\u7cfb\u7edf\u4e2d\u5b89\u88c5\u7684cuda\u548ccudnn\u5e93\u8fdb\u884c\u7f16\u8bd1\u548c\u6267\u884c":0,"\u8fd0\u884c\u65f6c":20,"\u8fd0\u884c\u73af\u5883":34,"\u8fd0\u884c\u7684\u4e00\u4e9b\u53c2\u6570\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\u4f20\u9012\u5230\u5bb9\u5668\u5185":27,"\u8fd0\u884c\u9636\u6bb5":34,"\u8fd1":39,"\u8fd4\u56de\u7684\u662f":14,"\u8fd4\u56de\u7b2ci\u4e2a\u8f93\u5165\u77e9\u9635":6,"\u8fd8\u4f1a":39,"\u8fd8\u4f1a\u4e0b\u8f7dmkl":0,"\u8fd8\u4f1a\u8f93\u51fa\u4e00\u4e2a":4,"\u8fd8\u53ef\u4ee5\u901a\u8fc7\u51cf\u5c0f\u5b66\u4e60\u7387\u6216\u8005\u5bf9\u6570\u636e\u8fdb\u884c\u5f52\u4e00\u5316\u5904\u7406\u6765\u89e3\u51b3\u8fd9\u7c7b\u95ee\u9898":11,"\u8fd8\u662f":39,"\u8fd8\u662f\u865a\u62df\u673a":0,"\u8fd8\u6709":39,"\u8fd8\u9700\u8981\u5728\u8282\u70b9\u4e0a\u5b89\u88c5\u5bf9\u5e94\u7684gpu\u9a71\u52a8\u4ee5\u53cacuda":31,"\u8fd9":[11,39],"\u8fd98\u79cdlearning_rate_schedule\u53ca\u5176\u5bf9\u5e94\u5b66\u4e60\u7387\u8ba1\u7b97\u65b9\u5f0f\u5982\u4e0b":13,"\u8fd9\u4e00\u4e2a\u5e93":17,"\u8fd9\u4e00\u5757\u7684\u8017\u65f6\u6bd4\u4f8b\u771f\u7684\u592a\u9ad8":37,"\u8fd9\u4e00\u8282\u5bf9\u56fe1\u4e2d\u9884\u6d4b\u4ee3\u7801\u7f16\u5199\u76845\u4e2a\u6b65\u9aa4\u8fdb\u884c\u4ecb\u7ecd\u548c\u8bf4\u660e":20,"\u8fd9\u4e00\u8ba1\u7b97\u5355\u5143":12,"\u8fd9\u4e00\u8fc7\u7a0b\u5bf9\u7528\u6237\u662f\u5b8c\u5168\u900f\u660e\u7684":41,"\u8fd9\u4e2a":[3,39],"\u8fd9\u4e2a\u4efb\u52a1\u7684\u914d\u7f6e\u4e3a":11,"\u8fd9\u4e2a\u4efb\u52a1\u7684dataprovider\u4e3a":11,"\u8fd9\u4e2a\u51fd\u6570\u7684":42,"\u8fd9\u4e2a\u51fd\u6570\u8fdb\u884c\u53d8\u6362":39,"\u8fd9\u4e2a\u51fd\u6570\u9700\u8981\u8bbe\u7f6e":42,"\u8fd9\u4e2a\u5730\u5740\u6765\u8868\u793a\u6b64\u6b65\u9aa4\u6240\u6784\u5efa\u51fa\u7684\u955c\u50cf":27,"\u8fd9\u4e2a\u57fa\u7c7b":6,"\u8fd9\u4e2a\u5e8f\u5217\u7684\u6bcf\u4e2a\u5143\u7d20\u53c8\u662f\u4e00\u4e2a\u5e8f\u5217":41,"\u8fd9\u4e2a\u60c5\u51b5\u4e0b\u6240\u6709\u7684\u6587\u4ef6\u4f1a\u5b58\u5728\u6574\u7406\u8fc7\u7684\u7684\u6587\u4ef6\u76ee\u5f55":7,"\u8fd9\u4e2a\u6570\u636e\u4e5f\u88ab\u5355\u5c42rnn\u7f51\u7edc\u76f4\u63a5\u4f7f\u7528":39,"\u8fd9\u4e2a\u662f\u76ee\u524d\u63a8\u8350\u7684\u4f7f\u7528\u65b9\u6cd5":7,"\u8fd9\u4e2a\u793a\u4f8b":20,"\u8fd9\u4e2a\u795e\u7ecf\u7f51\u7edc\u5355\u5143\u5c31\u53ebmemori":39,"\u8fd9\u4e2a\u7c7b\u7684\u53c2\u6570\u5305\u62ec":6,"\u8fd9\u4e2a\u7c7b\u9700\u8981\u7ee7\u627f":6,"\u8fd9\u4e2a\u811a\u672c\u8c03\u7528":0,"\u8fd9\u4e2a\u8fc7\u7a0b\u5bf9\u7528\u6237\u4e5f\u662f\u900f\u660e\u7684":41,"\u8fd9\u4e2a\u8fc7\u7a0b\u9664\u4e86\u7f16\u8bd1paddlepaddle\u4e3a":4,"\u8fd9\u4e2a\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u751f\u6210\u4e00\u7cfb\u5217\u6743\u91cd":42,"\u8fd9\u4e2aissu":0,"\u8fd9\u4e2ajob\u624d\u7b97\u6210\u529f\u7ed3\u675f":27,"\u8fd9\u4e2alayer\u7684\u8f93\u51fa\u4f1a\u4f5c\u4e3a\u6574\u4e2a":41,"\u8fd9\u4e5f\u4f1a\u6781\u5927\u51cf\u5c11\u6570\u636e\u8bfb\u5165\u7684\u8017\u65f6":11,"\u8fd9\u4e9b\u53c2\u6570\u53ef\u4ee5\u901a\u8fc7":21,"\u8fd9\u4e9b\u53c2\u6570\u7684\u5177\u4f53\u63cf\u8ff0":27,"\u8fd9\u4e9b\u540d\u5b57\u5fc5\u987b\u8981\u5199\u5bf9":6,"\u8fd9\u4e9b\u6570\u636e\u4f1a\u88ab\u7528\u6765\u66f4\u65b0\u53c2\u6570":11,"\u8fd9\u4e9b\u6570\u636e\u4f7f\u7528\u7684\u5185\u5b58\u4e3b\u8981\u548c\u4e24\u4e2a\u53c2\u6570\u6709\u5173\u7cfb":11,"\u8fd9\u4e9b\u7279\u5f81\u6570\u636e\u4e4b\u95f4\u7684\u987a\u5e8f\u662f\u6709\u610f\u4e49\u7684":39,"\u8fd9\u4efd\u6559\u7a0b\u5c55\u793a\u4e86\u5982\u4f55\u5728paddlepaddle\u4e2d\u5b9e\u73b0\u4e00\u4e2a\u81ea\u5b9a\u4e49\u7684\u7f51\u7edc\u5c42":6,"\u8fd9\u4f1a\u63d0\u793a\u5f53\u524d\u76ee\u5f55\u7684\u4e00\u4e9b\u53d8\u5316":4,"\u8fd9\u4f1a\u7ed9\u8bc4\u5ba1\u4eba\u5e26\u6765\u5f88\u5927\u56f0\u6270":4,"\u8fd9\u4f1a\u81ea\u52a8\u8fdb\u884c\u7f51\u7edc\u914d\u7f6e\u4e2d\u58f0\u660e\u7684\u6fc0\u6d3b\u64cd\u4f5c":6,"\u8fd9\u4fbf\u662f\u4e00\u79cd\u53cc\u5c42rnn\u7684\u8f93\u5165\u6570\u636e":39,"\u8fd9\u51e0\u4e2a\u7f16\u8bd1\u9009\u9879\u7684\u8bbe\u7f6e":0,"\u8fd9\u53ef\u4ee5\u5e2e\u60a8\u7701\u6389\u82b1\u4e00\u5c0f\u65f6\u5b89\u88c5\u548c\u914d\u7f6e\u5404\u79cd\u5f00\u53d1\u5de5\u5177":0,"\u8fd9\u53ef\u4ee5\u8ba9\u5176\u4ed6\u4eba\u77e5\u9053\u8fd9\u6b21\u63d0\u4ea4\u505a\u4e86\u54ea\u4e9b\u6539\u53d8":4,"\u8fd9\u53ef\u4ee5\u901a\u8fc7":4,"\u8fd9\u548c\u5355\u5c42rnn\u7684\u914d\u7f6e\u662f\u7b49\u4ef7\u7684":39,"\u8fd9\u56db\u4e2a\u5e8f\u5217\u53c8\u5206\u522b\u542b\u67093":19,"\u8fd9\u56db\u6761\u6570\u636e\u540c\u65f6\u5904\u7406\u7684\u53e5\u5b50\u6570\u91cf\u4e3a":39,"\u8fd9\u5728\u6784\u9020\u975e\u5e38\u590d\u6742\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u65f6\u662f\u6709\u7528\u7684":42,"\u8fd9\u610f\u5473\u7740":42,"\u8fd9\u610f\u5473\u7740\u9664\u4e86\u6307\u5b9adevic":35,"\u8fd9\u65f6":[11,20],"\u8fd9\u65f6\u5728\u4f7f\u7528":13,"\u8fd9\u65f6\u7684":19,"\u8fd9\u65f6\u7684\u9700\u8981\u540c\u65f6\u63d0\u4f9b":19,"\u8fd9\u65f6\u884c\u504f\u79fb\u548c\u5217\u53f7\u6307\u5b9a\u7684\u5143\u7d20\u9ed8\u8ba4\u5176\u503c\u4e3a1":19,"\u8fd9\u65f6\u8fdb\u884c\u77e9\u9635\u4e58\u6cd5\u8fd0\u7b97\u5c31\u53ef\u80fd\u5bfc\u81f4\u6d6e\u70b9\u6570\u6ea2\u51fa":11,"\u8fd9\u65f6\u9700\u8981\u8c03\u7528\u521b\u5efa\u5e8f\u5217\u4fe1\u606f\u548c\u4e3a":19,"\u8fd9\u662f\u4e00\u79cd\u6309\u5df2\u8bad\u7ec3\u6837\u672c\u6570\u5206\u6bb5\u53d6\u503c\u7684\u5b66\u4e60\u7387\u9000\u706b\u65b9\u6cd5":13,"\u8fd9\u662f\u4e00\u79cd\u6309\u5df2\u8bad\u7ec3pass\u6570\u5206\u6bb5\u53d6\u503c\u7684\u5b66\u4e60\u7387\u9000\u706b\u65b9\u6cd5":13,"\u8fd9\u662f\u4e00\u79cd\u975e\u5e38\u7075\u6d3b\u7684\u6570\u636e\u7ec4\u7ec7\u65b9\u5f0f":38,"\u8fd9\u662f\u5f00\u6e90\u793e\u533a\u7684\u57fa\u672c\u793c\u8c8c":4,"\u8fd9\u662f\u666e\u901a\u7684\u5355\u5c42\u65f6\u95f4\u5e8f\u5217\u7684dataprovider\u4ee3\u7801":39,"\u8fd9\u662f\u6700\u4fbf\u6377\u7684\u5b89\u88c5\u65b9\u5f0f":2,"\u8fd9\u662f\u76ee\u524dcmake\u5bfb\u627epython\u7684\u903b\u8f91\u5b58\u5728\u7f3a\u9677":8,"\u8fd9\u6837":22,"\u8fd9\u6837\u4fdd\u5b58\u5728\u5206\u5e03\u5f0f\u5b58\u50a8\u4e2d\u7684\u6570\u636e\u53ef\u4ee5\u88ab\u96c6\u7fa4\u4e2d\u7684\u6bcf\u4e2a\u8282\u70b9\u8bfb\u53d6\u5230":21,"\u8fd9\u6837\u4fdd\u8bc1\u8fd0\u884c\u7ed3\u675f\u4e4b\u540e\u7684":0,"\u8fd9\u6837\u505a\u53ef\u4ee5\u6781\u5927\u7684\u51cf\u5c11\u5185\u5b58\u5360\u7528":11,"\u8fd9\u6837\u53ef\u4ee5\u514d\u53bb\u5355\u72ec\u5b89\u88c5\u7f16\u8bd1\u4f9d\u8d56\u7684\u6b65\u9aa4":0,"\u8fd9\u6837\u53ef\u4ee5\u51cf\u5c0fgpu\u5185\u5b58":35,"\u8fd9\u6837\u5982\u679c\u9047\u5230\u95ee\u9898":0,"\u8fd9\u6837\u5bb9\u5668\u7684":27,"\u8fd9\u6837\u5f53\u8be5pull":4,"\u8fd9\u6837\u6781\u5927\u5730\u63d0\u9ad8\u4e86\u8ba1\u7b97\u7684\u5e76\u884c\u6027":22,"\u8fd9\u6837\u7684\u88c5\u9970\u5668":6,"\u8fd9\u6837\u7684\u8bdd":26,"\u8fd9\u6837\u8bad\u7ec3\u6587\u4ef6\u7684\u4e2a\u6570\u4f1a\u6bd4\u8f83\u591a":21,"\u8fd9\u6b63\u662f\u5b83\u4eec\u901f\u5ea6\u5feb\u7684\u539f\u56e0":37,"\u8fd9\u7528\u4e8e\u5728\u591a\u7ebf\u7a0b\u548c\u591a\u673a\u4e0a\u66f4\u65b0\u53c2\u6570":6,"\u8fd9\u79cd\u521d\u59cb\u5316\u65b9\u5f0f\u5728\u4e00\u822c\u60c5\u51b5\u4e0b\u4e0d\u4f1a\u4ea7\u751f\u5f88\u5dee\u7684\u7ed3\u679c":13,"\u8fd9\u79cd\u5b89\u88c5\u65b9\u5f0f\u4f1a\u6d89\u53ca\u5230\u4e00\u4e9b\u7b2c\u4e09\u65b9\u5e93\u7684\u4e0b\u8f7d":2,"\u8fd9\u79cd\u60c5\u51b5\u4e0b\u4e0d\u9700\u8981\u91cd\u5199\u8be5\u51fd\u6570":6,"\u8fd9\u79cd\u60c5\u51b5\u591a\u51fa\u73b0\u5728\u4f7f\u7528\u591a\u7ebf\u7a0b\u9884\u6d4b\u65f6":20,"\u8fd9\u79cd\u60c5\u51b5\u5e38\u5e38\u53d1\u751f\u5728":11,"\u8fd9\u79cd\u65b9\u5f0f\u5bf9\u5185\u5b58\u6d88\u8017\u8f83\u5927":12,"\u8fd9\u79cd\u65b9\u5f0f\u5fc5\u987b\u4f7f\u7528paddle\u5b58\u50a8\u7684\u6a21\u578b\u8def\u5f84\u683c\u5f0f":35,"\u8fd9\u79cd\u65b9\u5f0f\u6700\u4e3a\u7b80\u4fbf":17,"\u8fd9\u79cd\u751f\u6210\u6280\u672f\u53ea\u7528\u4e8e\u7c7b\u4f3c\u89e3\u7801\u5668\u7684\u751f\u6210\u8fc7\u7a0b":42,"\u8fd9\u79cd\u7c7b\u578b\u7684\u8f93\u5165\u5fc5\u987b\u901a\u8fc7":41,"\u8fd9\u79cd\u94fe\u63a5\u65b9\u5f0f\u4e3b\u8981\u7528\u4e8e\u79fb\u52a8\u7aef\u9884\u6d4b":17,"\u8fd9\u79cd\u96c6\u7fa4\u8282\u70b9\u7ba1\u7406\u65b9\u5f0f\u4f1a\u5728\u5c06\u6765\u4f7f\u7528":27,"\u8fd9\u7bc7":1,"\u8fd9\u7bc7\u6587\u6863":4,"\u8fd9\u7bc7\u6587\u6863\u4e4b\u540e\u90e8\u5206\u4f1a\u4f7f\u7528":20,"\u8fd9\u7bc7\u6587\u6863\u4e4b\u540e\u90e8\u5206\u4f1a\u7edf\u4e00\u4f7f\u7528":19,"\u8fd9\u7bc7\u6587\u6863\u4e4b\u540e\u90e8\u5206\u5c06\u4f1a\u7edf\u4e00\u4f7f\u7528":19,"\u8fd9\u7bc7\u6587\u6863\u4ecb\u7ecd":20,"\u8fd9\u7bc7\u6587\u6863\u4ecb\u7ecd\u5728\u4f7f\u7528":19,"\u8fd9\u7bc7\u6587\u6863\u4ecb\u7ecd\u57fa\u4e8e":0,"\u8fd9\u7bc7\u6587\u6863\u7684\u4e4b\u540e\u90e8\u5206\u4f1a\u4f7f\u7528":20,"\u8fd9\u7bc7\u6587\u7ae0":0,"\u8fd9\u7ec4\u8bed\u4e49\u76f8\u540c\u7684\u793a\u4f8b\u914d\u7f6e\u5982\u4e0b":39,"\u8fd9\u901a\u8fc7\u83b7\u5f97\u53cd\u5411\u5faa\u73af\u7f51\u7edc\u7684\u7b2c\u4e00\u4e2a\u5b9e\u4f8b":42,"\u8fd9\u91cc":[0,4,13,27,42],"\u8fd9\u91cc\u4ecb\u7ecdc":20,"\u8fd9\u91cc\u4f7f\u7528\u4e86paddlepaddle\u9884\u5b9a\u4e49\u597d\u7684rnn\u5904\u7406\u51fd\u6570":39,"\u8fd9\u91cc\u4f7f\u7528\u7b80\u5355\u7684":11,"\u8fd9\u91cc\u5c06\u4ecb\u7ecdpaddlepaddle\u7684\u57fa\u672c\u4f7f\u7528\u6982\u5ff5":14,"\u8fd9\u91cc\u6211\u4eec\u5c55\u793a\u4e00\u4efd\u7b80\u5316\u8fc7\u7684\u4ee3\u7801":6,"\u8fd9\u91cc\u6211\u4eec\u901a\u8fc7\u5728kubernetes\u96c6\u7fa4\u4e0a\u542f\u52a8\u4e00\u4e2ajob\u6765\u4e0b\u8f7d\u5e76\u5207\u5272\u6570\u636e":27,"\u8fd9\u91cc\u6709\u4e24\u79cd\u6709\u6548\u7684\u89e3\u51b3\u65b9\u6cd5":11,"\u8fd9\u91cc\u68c0\u9a8c\u8fd0\u884c\u65f6\u95f4\u6a21\u578b\u7684\u6536\u655b":23,"\u8fdb\u4e3b\u4ed3\u5e93\u540e":4,"\u8fdb\u5165\u5bb9\u5668":26,"\u8fdb\u5165\u5bf9\u5e94\u7684\u76ee\u5f55":8,"\u8fdb\u7a0b\u542f\u52a8\u7684\u5fc5\u8981\u53c2\u6570":27,"\u8fdb\u7a0b\u7684":23,"\u8fdb\u7a0b\u7684\u542f\u52a8\u53c2\u6570":27,"\u8fdb\u7a0b\u7684\u8fd0\u884c\u73af\u5883":27,"\u8fdb\u7a0b\u9700\u8981\u7684":27,"\u8fdb\u884c\u4e86":39,"\u8fdb\u884c\u5206\u5e03\u5f0f\u8bad\u7ec3\u7684\u65b9\u6848":27,"\u8fdb\u884c\u5206\u5e03\u5f0f\u8bad\u7ec3\u7684\u65b9\u6cd5":27,"\u8fdb\u884c\u524d\u5411\u8ba1\u7b97":20,"\u8fdb\u884c\u56de\u590d":4,"\u8fdb\u884c\u5e8f\u5217\u5316":20,"\u8fdb\u884c\u5f00\u53d1":4,"\u8fdb\u884c\u62c6\u89e3":39,"\u8fdb\u884c\u6fc0\u6d3b\u64cd\u4f5c":6,"\u8fdb\u884c\u8bad\u7ec3":20,"\u8fdb\u884c\u90e8\u7f72":24,"\u8fdb\u884c\u94fe\u63a5":17,"\u8fdb\u884c\u9884\u6d4b\u4f9d\u8d56\u4e8e\u5c06":17,"\u8fdb\u884c\u9884\u6d4b\u65f6":20,"\u8fdb\u9636\u4f7f\u7528":43,"\u8fdb\u9636\u6307\u5357":14,"\u8fde\u63a5":41,"\u8fde\u63a5\u5230pserver\u7684\u7aef\u53e3":21,"\u8fde\u63a5\u5230pserver\u7684\u7aef\u53e3\u4e2a\u6570":21,"\u9000\u51fa\u5bb9\u5668":26,"\u9002\u4e2d":39,"\u9009":39,"\u9009\u62e9":39,"\u9009\u62e9\u4e0b\u8f7d\u4f7f\u7528\u4e0d\u540c\u7684blas\u5e93\u7684docker\u955c\u50cf":1,"\u9009\u62e9\u76ee\u6807\u5206\u652f":4,"\u9009\u62e9\u8def\u5f84\u6765\u52a8\u6001\u52a0\u8f7dnvidia":33,"\u9009\u9879":0,"\u9012\u5f52\u795e\u7ecf\u7f51\u7edc":32,"\u901a\u5e38\u4f1a\u4f7f\u7528\u73af\u5883\u53d8\u91cf\u914d\u7f6ejob\u7684\u914d\u7f6e\u4fe1\u606f":27,"\u901a\u5e38\u4f1a\u4f7f\u7528mapreduce\u4efb\u52a1\u7684\u8f93\u51fa\u7ed3\u679c\u4f5c\u4e3a\u8bad\u7ec3\u7ed3\u679c":21,"\u901a\u5e38\u4f7f\u7528\u7a00\u758f\u8bad\u7ec3\u6765\u52a0\u901f\u8ba1\u7b97\u8fc7\u7a0b":35,"\u901a\u5e38\u4f7f\u7528cento":3,"\u901a\u5e38\u505a\u6cd5\u662f\u4ece\u4e00\u4e2a\u6bd4\u8f83\u5927\u7684learning_rate\u5f00\u59cb\u8bd5":13,"\u901a\u5e38\u540d\u5b57\u662f":4,"\u901a\u5e38\u60c5\u51b5\u4e0b":37,"\u901a\u5e38\u6211\u4eec\u4f1a\u5b89\u88c5ceph\u7b49\u5206\u5e03\u5f0f\u6587\u4ef6\u7cfb\u7edf\u6765\u5b58\u50a8\u8bad\u7ec3\u6570\u636e":26,"\u901a\u5e38\u7528\u4e8e\u8868\u793a\u79bb\u6563\u7684\u7c7b\u522b\u6807\u7b7e":19,"\u901a\u5e38\u7684\u505a\u6cd5\u662f\u4f7f\u7528":42,"\u901a\u5e38\u7684\u505a\u6cd5\u662f\u5c06\u914d\u7f6e\u5b58\u4e8e":6,"\u901a\u5e38\u8981\u6c42\u65f6\u95f4\u6b65\u4e4b\u95f4\u5177\u6709\u4e00\u4e9b\u4f9d\u8d56\u6027":39,"\u901a\u5e38\u90fd\u4f1a\u4f7f\u7528\u4e0b\u9762\u8fd9\u4e9b\u547d\u4ee4\u884c\u53c2\u6570":35,"\u901a\u5e38\u9700\u8981\u53bb\u6389\u7f51\u7edc\u4e2d\u7684":20,"\u901a\u7528":32,"\u901a\u77e5":39,"\u901a\u8fc7":[4,6,11,19,39],"\u901a\u8fc7\u4e24\u4e2a\u5d4c\u5957\u7684":41,"\u901a\u8fc7\u4f7f\u7528":0,"\u901a\u8fc7\u51fd\u6570":27,"\u901a\u8fc7\u547d\u4ee4\u884c\u53c2\u6570":11,"\u901a\u8fc7\u591a\u4e2a\u7ebf\u7a0b\u5171\u4eab\u540c\u4e00\u4e2a\u6a21\u578b\u6765\u51cf\u5c11\u5185\u5b58\u5f00\u9500":20,"\u901a\u8fc7\u5f15\u7528memory\u5f97\u5230\u8fd9\u4e2alayer\u4e0a\u4e00\u4e2a\u65f6\u523b\u7684\u8f93\u51fa":41,"\u901a\u8fc7\u5f15\u7528memory\u5f97\u5230\u8fd9\u4e2alayer\u4e0a\u4e00\u4e2a\u65f6\u523b\u8f93\u51fa":41,"\u901a\u8fc7\u6240\u6709\u5355\u5143\u6d4b\u8bd5":4,"\u901a\u8fc7\u7075\u6d3b\u4f7f\u7528\u4ee5\u4e0a\u4e24\u4e2a\u63a5\u53e3":20,"\u901a\u8fc7\u7ec4\u5408\u4e0d\u540c\u7684layer":14,"\u901a\u8fc7\u7f51\u7edc\u5c42\u7684\u6807\u8bc6\u7b26\u6765\u6307\u5b9a":6,"\u901a\u8fc7\u8ba1\u7b97\u8282\u70b9\u548c\u53c2\u6570\u670d\u52a1\u5668\u7684\u5206\u5e03\u5f0f\u534f\u4f5c":22,"\u901a\u8fc7\u8c03\u7528":[19,20],"\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u63a5\u53e3\u521b\u5efa\u7a00\u758f\u77e9\u9635":19,"\u901a\u8fc7data":41,"\u903b\u8f91\u4e0a\u9ad8\u4e8e\u4e8c\u7ef4\u7684\u6570\u636e":19,"\u9047\u5230\u8be5\u9519\u8bef\u65f6":12,"\u9053\u6b49":39,"\u9069":39,"\u9075\u5b88\u4ee5\u4e0b\u7ea6\u5b9a":4,"\u90a3\u4e48":[6,41],"\u90a3\u4e480\u5c42\u5e8f\u5217\u5373\u4e3a\u4e00\u4e2a\u8bcd\u8bed":41,"\u90a3\u4e48\u4f1a\u643a\u5e26\u6709":19,"\u90a3\u4e48\u53ef\u4ee5\u8ba4\u4e3a\u8bad\u7ec3\u4e0d\u6536\u655b":13,"\u90a3\u4e48\u5982\u4f55\u5224\u65ad\u8bad\u7ec3\u4e0d\u6536\u655b\u5462":13,"\u90a3\u4e48\u5e38\u6570\u8f93\u51fa\u6240\u80fd\u8fbe\u5230\u7684\u6700\u5c0fcost\u662f":13,"\u90a3\u4e48\u6211\u4eec\u53ef\u4ee5\u5224\u65ad\u4e3a\u8bad\u7ec3\u4e0d\u6536\u655b":13,"\u90a3\u4e48\u63a8\u8350\u4f7f\u7528":42,"\u90a3\u4e48\u63a8\u8350\u4f7f\u7528\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u65b9\u6cd5":42,"\u90a3\u4e48\u6536\u655b\u53ef\u80fd\u5f88\u6162":13,"\u90a3\u4e48\u6700\u597d\u5c06\u6570\u636e\u6587\u4ef6\u5728\u6bcf\u6b21\u8bfb\u53d6\u4e4b\u524d\u505a\u4e00\u6b21shuffl":11,"\u90a3\u4e48\u7528\u6237\u9700\u8981\u62c9\u53d6\u6240\u6709\u7684\u8fdc\u7a0b\u5206\u652f\u5230\u672c\u673a":8,"\u90a3\u4e48\u8bad\u7ec3\u6709\u53ef\u80fd\u4e0d\u6536\u655b":13,"\u90a3\u4e48\u8be5\u4f18\u5316\u7b97\u6cd5\u81f3\u5c11\u9700\u8981":11,"\u90a3\u4e48fc1\u548cfc2\u5c42\u5c06\u4f1a\u4f7f\u7528\u7b2c1\u4e2agpu\u6765\u8ba1\u7b97":35,"\u90a3\u4e5f\u5c31\u4e0d\u9700\u8981\u6025\u7740\u4f18\u5316\u6027\u80fd\u5566":37,"\u90a3\u4f30\u8ba1\u8fd9\u91cc\u7684\u6f5c\u529b\u5c31\u6ca1\u5565\u597d\u6316\u7684\u4e86":37,"\u90a3\u51cf\u5c11\u5b66\u4e60\u738710\u500d\u7ee7\u7eed\u8bd5\u9a8c":13,"\u90a3\u6211\u4f1a\u671f\u671b\u5206\u6790\u5de5\u5177\u7edf\u8ba1\u5230\u901f\u5ea6\u662f100gb":37,"\u90a3\u7a0b\u5e8f\u5206\u6790\u5de5\u5177\u662f\u5fc5\u4e0d\u53ef\u5c11\u7684\u5229\u5668":37,"\u90fd":39,"\u90fd\u4e0d\u9700\u8981":0,"\u90fd\u4f1a\u4ea7\u751f\u5f53\u524d\u5c42\u72b6\u6001\u7684\u6240\u6709\u7ee7\u627f\u7ed3\u679c":33,"\u90fd\u4f1a\u7ba1\u7406\u7ef4\u62a4\u4e00\u4efd\u8bad\u7ec3\u597d\u7684\u6a21\u578b":20,"\u90fd\u4f1a\u9020\u6210\u8bad\u7ec3\u4e2d\u7684\u6570\u636e\u4ecec":11,"\u90fd\u4f7f\u7528":19,"\u90fd\u53ea\u662f\u4ecb\u7ecd\u53cc\u5c42rnn\u7684api\u63a5\u53e3":39,"\u90fd\u53ef\u4ee5\u8fd0\u884c":0,"\u90fd\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4e0b\u9762\u7684\u63a5\u53e3\u4e3a\u539f\u6709\u7684\u6570\u636e\u8f93\u5165\u9644\u52a0\u4e0a\u5e8f\u5217\u4fe1\u606f":19,"\u90fd\u5e94\u4f7f\u7528c":19,"\u90fd\u662f\u5bf9layer1\u5143\u7d20\u7684\u62f7\u8d1d":38,"\u90fd\u662f\u5c06\u6bcf\u4e00\u53e5\u5206\u597d\u8bcd\u540e\u7684\u53e5\u5b50":39,"\u90fd\u7528":4,"\u90fd\u9700\u8981\u5199\u63d0\u4ea4\u8bf4\u660e":4,"\u90fd\u9700\u8981\u8c03\u7528\u4e00\u6b21":6,"\u914d\u5236\u7f16\u8bd1\u9009\u9879":17,"\u914d\u7f6e\u6253\u5f00":37,"\u914d\u7f6e\u6587\u4ef6\u63a5\u53e3\u662ffc_layer":6,"\u914d\u7f6e\u6587\u4ef6\u91cc\u52a0\u4e24\u884c":0,"\u914d\u7f6e\u7b80\u5355\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u7684\u4f8b\u5b50":42,"\u914d\u7f6e\u7f51\u7edc\u5c42\u7684\u8f93\u5165":6,"\u914d\u7f6eapi":38,"\u9152\u5e97":39,"\u91c7\u7528\u5747\u5300\u5206\u5e03\u6216\u8005\u9ad8\u65af\u5206\u5e03\u521d\u59cb\u5316":33,"\u91c7\u7528multi":13,"\u91cc\u53ef\u4ee5\u6807\u51c6\u5316\u7f16\u8bd1\u73af\u5883":0,"\u91cc\u7684":0,"\u91cc\u7684\u65e5\u5fd7":23,"\u91cc\u8fd0\u884c\u7684\u7f16\u8bd1\u5de5\u5177\u5b9e\u9645\u4e0a\u90fd\u662f\u5728\u672c\u673a\u7684":0,"\u91ccstep\u7684\u5185\u5bb9":11,"\u91cd\u65b0\u7f16\u8bd1paddlepaddl":37,"\u9488\u5bf9\u4efb\u52a1\u8fd0\u884c\u5b8c\u6210\u540e\u5bb9\u5668\u81ea\u52a8\u9000\u51fa\u7684\u573a\u666f":26,"\u9488\u5bf9\u5185\u5b58\u548c\u663e\u5b58":11,"\u94fe\u63a5":17,"\u94fe\u63a5\u4e2d\u627e\u5230":3,"\u94fe\u63a5\u4f55\u79cdblas\u5e93\u7b49":0,"\u94fe\u63a5\u76f8\u5bf9\u5bb9\u6613":17,"\u94fe\u63a5\u9009\u9879":17,"\u94fe\u63a5\u9759\u6001\u5e93":17,"\u9519\u8bef":8,"\u9519\u8bef\u7684define_py_data_sources2\u7c7b\u4f3c":13,"\u952e\u6765\u542f\u52a8\u7f16\u8bd1\u4e86":0,"\u955c\u50cf\u91cc":0,"\u955c\u50cf\u91cc\u6709paddlepaddle\u7684\u6e90\u7801\u4e0edemo":26,"\u957f\u5ea6":11,"\u95e8\u63a7\u5faa\u73af\u5355\u5143\u5355\u6b65\u51fd\u6570\u548c\u8f93\u51fa\u51fd\u6570":42,"\u95e8\u63a7\u5faa\u73af\u5355\u5143\u7684\u8f93\u51fa\u88ab\u7528\u4f5c\u8f93\u51famemori":42,"\u9644\u52a0\u4e0a\u5e8f\u5217\u4fe1\u606f":19,"\u9650\u5236\u5957\u63a5\u5b57\u53d1\u9001\u7f13\u51b2\u533a\u7684\u5927\u5c0f":33,"\u9650\u5236\u5957\u63a5\u5b57\u63a5\u6536\u7f13\u51b2\u533a\u7684\u5927\u5c0f":33,"\u9664\u4e86\u53ef\u4ee5\u81ea\u52a8\u7f16\u8bd1\u6587\u6863":7,"\u9664\u4e86boot_lay":39,"\u9664\u6b64\u4e4b\u5916":11,"\u9664\u96f6\u7b49\u95ee\u9898":11,"\u968f\u540e\u53ef\u4ee5\u7528\u8fd9\u4e2a\u5f00\u53d1\u955c\u50cf\u5f00\u59cbbuild":4,"\u968f\u673a\u6570\u7684\u79cd\u5b50":33,"\u968f\u673a\u6570seed":32,"\u9694\u5f00":21,"\u96c6\u675f\u641c\u7d22\u4f7f\u7528\u5e7f\u5ea6\u4f18\u5148\u641c\u7d22\u7684\u65b9\u5f0f\u6784\u5efa\u67e5\u627e\u6811":33,"\u96c6\u7fa4\u4e0a\u542f\u52a8\u4e00\u4e2a\u5355\u673a\u4f7f\u7528cpu\u7684paddlepaddle\u8bad\u7ec3\u4f5c\u4e1a":26,"\u96c6\u7fa4\u4e2d\u7684\u6bcf\u53f0\u8ba1\u7b97\u673a\u901a\u5e38\u88ab\u6210\u4e3a\u4e00\u4e2a":31,"\u96c6\u7fa4\u4efb\u52a1":23,"\u96c6\u7fa4\u4f5c\u4e1a\u5c06\u4f1a\u5728\u51e0\u79d2\u540e\u542f\u52a8":23,"\u96c6\u7fa4\u6d4b\u8bd5":32,"\u96c6\u7fa4\u8bad\u7ec3":32,"\u96c6\u7fa4\u8bad\u7ec3\u4e0e\u9884\u6d4b":10,"\u96c6\u7fa4\u8fdb\u7a0b":23,"\u9700\u5728nvvp\u754c\u9762\u4e2d\u9009\u4e0a\u624d\u80fd\u5f00\u542f":37,"\u9700\u6307\u5b9a":17,"\u9700\u63d0\u4f9b\u975e\u96f6\u5143\u7684\u503c":19,"\u9700\u6ce8\u610f":17,"\u9700\u8981":[0,20],"\u9700\u8981\u4f7f\u7528":11,"\u9700\u8981\u4f7f\u7528\u5176\u5236\u5b9a\u7684\u65b9\u5f0f\u6302\u8f7d\u540e\u5e76\u5bfc\u5165\u6570\u636e":27,"\u9700\u8981\u4f7f\u7528\u6700\u65b0\u7684pip":3,"\u9700\u8981\u4f7f\u7528\u8005\u81ea\u5df1\u4e86\u89e3\u5e76\u5b8c\u6210\u8f6c\u5316":19,"\u9700\u8981\u4fdd\u6301\u5f53\u524d\u5206\u652f\u76ee\u5f55":4,"\u9700\u8981\u521b\u5efa\u5e76\u586b\u5199":19,"\u9700\u8981\u5347\u7ea7pip\u7248\u672c\u5230\u6700\u65b0":[3,8],"\u9700\u8981\u5355\u72ec":1,"\u9700\u8981\u540c\u65f6\u63d0\u4f9b\u6bcf\u4e00\u4e2a\u5185\u5c42\u5e8f\u5217\u5728\u6574\u4e2a":19,"\u9700\u8981\u540c\u6b65\u539f\u4ed3\u5e93":4,"\u9700\u8981\u542f\u52a8\u7684\u8282\u70b9\u4e2a\u6570\u4ee5\u53ca":27,"\u9700\u8981\u54ea\u4e9b\u5c42\u7684\u8ba1\u7b97\u7ed3\u679c\u4f5c\u4e3a\u8f93\u51fa":20,"\u9700\u8981\u5728\u521b\u5efa\u5bb9\u5668\u524d\u6302\u8f7d\u5377\u4ee5\u4fbf\u6211\u4eec\u4fdd\u5b58\u8bad\u7ec3\u7ed3\u679c":26,"\u9700\u8981\u5728\u7cfb\u7edf\u91cc\u5148\u5b89\u88c5\u597ddocker\u5de5\u5177\u5305":7,"\u9700\u8981\u5c06\u5176parameter\u8bbe\u7f6e\u6210":11,"\u9700\u8981\u5c06\u7f51\u7edc\u7ed3\u6784\u4f7f\u7528":20,"\u9700\u8981\u5c06cuda\u76f8\u5173\u7684\u5e93\u8bbe\u7f6e\u5230":17,"\u9700\u8981\u5c06paddl":17,"\u9700\u8981\u5f3a\u8c03\u7684\u662f":0,"\u9700\u8981\u601d\u8003\u5b8c\u6210\u4ee5\u4e0b\u5de5\u4f5c":[19,20],"\u9700\u8981\u624b\u52a8\u8fdb\u884c\u89e3\u538b":20,"\u9700\u8981\u6267\u884c":[0,3,16],"\u9700\u8981\u6307\u5b9a":17,"\u9700\u8981\u6307\u5b9a\u4e0e\u67d0\u4e00\u4e2a\u8f93\u5165\u7684\u5e8f\u5217\u4fe1\u606f\u662f\u4e00\u81f4\u7684":39,"\u9700\u8981\u6307\u5b9alayer\u7684\u8f93\u5165\u6765\u6e90":14,"\u9700\u8981\u63d0\u9192\u7684\u662f":2,"\u9700\u8981\u660e\u786e\u6307\u5b9a":33,"\u9700\u8981\u663e\u5f0f\u5730\u94fe\u63a5":17,"\u9700\u8981\u663e\u793a\u5730\u94fe\u63a5":17,"\u9700\u8981\u663e\u793a\u5730\u94fe\u63a5mkl\u7684\u52a8\u6001\u5e93":17,"\u9700\u8981\u6839\u636e\u4e0d\u540c\u7684\u5206\u5e03\u5f0f\u5b58\u50a8\u6765\u7ed1\u5b9a\u4e00\u4e2a":27,"\u9700\u8981\u6ce8\u610f\u7684\u662f":[11,33],"\u9700\u8981\u6ce8\u610f\u7684\u662f\u68af\u5ea6\u68c0\u67e5\u4ec5\u4ec5\u9a8c\u8bc1\u4e86\u68af\u5ea6\u7684\u8ba1\u7b97":6,"\u9700\u8981\u6ce8\u610f\u7684\u662fpaddlepaddle\u76ee\u524d\u53ea\u652f\u6301\u5b50\u5e8f\u5217\u6570\u76ee\u4e00\u6837\u7684\u591a\u8f93\u5165\u53cc\u5c42rnn":39,"\u9700\u8981\u7528\u6237\u663e\u5f0f\u8bbe\u5b9a":12,"\u9700\u8981\u81ea\u5df1\u94fe\u63a5mkl\u94fe\u63a5\u5e93":17,"\u9700\u8981\u8bf7\u7ba1\u7406\u5458\u5b89\u88c5\u548c\u914d\u7f6e\u597d":0,"\u9700\u8981\u9075\u5faa\u4ee5\u4e0b\u7ea6\u5b9a":41,"\u9700\u9644\u52a0\u53cc\u5c42\u5e8f\u5217\u4fe1\u606f":19,"\u9700\u9644\u52a0\u5e8f\u5217\u4fe1\u606f":19,"\u975e\u5e38\u6570":6,"\u975e\u5e8f\u5217\u8f93\u5165\u4e0d\u643a\u5e26":19,"\u975e\u5e8f\u5217\u8f93\u5165\u65e0\u9700\u6784\u9020":19,"\u975e\u96f6\u5143\u4e2a\u6570":19,"\u975e\u96f6\u5143\u7d20\u7684\u503c":19,"\u975e\u96f6\u5143\u7d20\u7684\u5217\u53f7":19,"\u975e\u96f6\u6570\u5b57\u7684\u4e2a\u6570":6,"\u9879\u76ee\u5728\u52aa\u529b\u5f00\u59cb\u652f\u6301\u5176\u4ed6\u4e0d\u9700\u8981":0,"\u987a\u5e8f":39,"\u9884\u63d0\u4ea4\u94a9\u5b50":4,"\u9884\u6d4b\u4e0d\u9700\u8981\u6807\u7b7e":18,"\u9884\u6d4b\u4e0d\u9700\u8981\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u53cd\u5411\u4f20\u64ad\u548c\u53c2\u6570\u66f4\u65b0\u7684\u90e8\u5206":18,"\u9884\u6d4b\u4ee3\u7801\u66f4\u591a\u8be6\u7ec6\u793a\u4f8b\u4ee3\u7801\u8bf7\u53c2\u8003":20,"\u9884\u6d4b\u4f7f\u7528\u7684\u7f51\u7edc\u7ed3\u6784\u5f80\u5f80\u4e0d\u540c\u4e8e\u8bad\u7ec3":20,"\u9884\u6d4b\u5c31\u662f\u51c6\u5907\u8f93\u5165\u6570\u636e":18,"\u9884\u6d4b\u5f88\u591a\u65f6\u5019\u9700\u8981\u548c\u7528\u6237\u7cfb\u7edf\u6574\u5408\u5728\u4e00\u8d77":18,"\u9884\u6d4b\u65f6":20,"\u9884\u6d4b\u65f6\u53ea\u9700\u52a0\u8f7d\u4e00\u4e2a\u6587\u4ef6\u4fbf\u4e8e\u53d1\u5e03":20,"\u9884\u6d4b\u6709\u5982\u4e0b\u7279\u70b9":18,"\u9884\u6d4b\u7a0b\u5e8f\u5f00\u53d1\u4e24\u5927\u90e8\u5206":20,"\u9884\u6d4bsdk\u4e0d\u5305\u542b\u53cd\u5411\u4f20\u64ad\u548c\u53c2\u6570\u66f4\u65b0\u90e8\u5206":18,"\u9884\u6d4bsdk\u9700\u8981\u63d0\u4f9b\u4e00\u4e2a\u7b80\u6d01\u7684\u7528\u6237\u63a5\u53e3":18,"\u9996\u5148":[6,39,42],"\u9996\u5148\u4ee5\u51e0\u4e2a\u5b9e\u9645\u573a\u666f\u4e3a\u4f8b":34,"\u9996\u5148\u5728\u7cfb\u7edf\u8def\u5f84":0,"\u9996\u5148\u5b89\u88c5\u5e76\u5728\u5f53\u524d\u76ee\u5f55\u8fd0\u884c\u5b83":4,"\u9996\u5148\u5bf9\u8f93\u5165\u505a\u4e00\u4e2a\u5c0f\u7684\u6270\u52a8":6,"\u9996\u5148\u6211\u4eec\u9700\u8981\u63a8\u5bfc\u8be5\u7f51\u7edc\u5c42\u7684":6,"\u9996\u5148\u6784\u9020\u5934\u4fe1\u606f":13,"\u9996\u5148\u901a\u8fc7":4,"\u9996\u5148\u9700\u8981\u52a0\u8f7d\u76f8\u5e94\u7684python\u5e93":14,"\u9a71\u52a8":7,"\u9ad8\u4eae\u90e8\u5206":39,"\u9ad8\u5ea6":19,"\u9ad8\u5ea6\u652f\u6301\u7075\u6d3b\u548c\u9ad8\u6548\u7684\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u914d\u7f6e":42,"\u9ad8\u65af\u5206\u5e03":13,"\u9ed8\u8ba4":33,"\u9ed8\u8ba40":21,"\u9ed8\u8ba41":21,"\u9ed8\u8ba4127":21,"\u9ed8\u8ba47164":21,"\u9ed8\u8ba4\u4e0d\u663e\u793a":33,"\u9ed8\u8ba4\u4e0d\u8bbe\u7f6e":41,"\u9ed8\u8ba4\u4e3a0":[33,35],"\u9ed8\u8ba4\u4e3a1":[19,35],"\u9ed8\u8ba4\u4e3a100":35,"\u9ed8\u8ba4\u4e3a4096mb":33,"\u9ed8\u8ba4\u4e3a\u7b2c\u4e00\u4e2a\u8f93\u5165":41,"\u9ed8\u8ba4\u4e3anull":33,"\u9ed8\u8ba4\u4f1a\u5c06a\u548cb":11,"\u9ed8\u8ba4\u4f7f\u7528concurrentremoteparameterupdat":33,"\u9ed8\u8ba4\u4f7f\u7528mkl":0,"\u9ed8\u8ba4\u503c":[0,35,38],"\u9ed8\u8ba4\u521d\u59cb\u72b6\u4e3a0":41,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b":[13,23],"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u6309\u7167float\u7cbe\u5ea6\u8ba1\u7b97":13,"\u9ed8\u8ba4\u6307\u5b9a\u7b2c\u4e00\u4e2a\u8f93\u5165":39,"\u9ed8\u8ba4\u662f\u4f7f\u7528mkl\u7684\u955c\u50cf":1,"\u9ed8\u8ba4\u6ca1\u6709\u5b89\u88c5vim":1,"\u9ed8\u8ba4\u7684paddlepaddle\u751f\u4ea7\u73af\u5883\u955c\u50cf":26,"\u9ed8\u8ba4\u8bbe\u7f6e\u4e3a\u771f":35,"\u9ed8\u8ba4\u8c03\u7528":0,"\u9ed8\u8ba4fals":21,"api\u4e0d\u4f1a\u76f4\u63a5\u52a0\u8f7d":20,"api\u4e2d":19,"api\u4e2d\u7684\u4e00\u7ef4\u6570\u7ec4":19,"api\u4e2d\u7684\u77e9\u9635\u6765\u8868\u793a":19,"api\u4e2d\u795e\u7ecf\u7f51\u7edc\u7684\u4e00\u4e2a\u8f93\u5165":20,"api\u4f7f\u7528\u4e2d\u7684\u4e00\u4e2a\u91cd\u8981\u6982\u5ff5":20,"api\u4f7f\u7528\u6d41\u7a0b":18,"api\u4f7f\u7528\u6d41\u7a0b\u793a\u610f\u56fe":20,"api\u4f7f\u7528\u793a\u4f8b":20,"api\u521b\u5efa\u7684gradientmachine\u7c7b\u7684\u5bf9\u8c61":20,"api\u53ef\u4ee5\u901a\u8fc7\u5206\u522b\u6307\u5b9a\u5e8f\u5217\u5316\u540e\u7684\u7f51\u7edc\u7ed3\u6784\u6587\u4ef6\u548c\u53c2\u6570\u76ee\u5f55\u6765\u52a0\u8f7d\u8bad\u7ec3\u597d\u7684\u6a21\u578b":20,"api\u53ef\u4ee5\u901a\u8fc7\u6307\u5b9a":20,"api\u5b8c\u6210\u5206\u5e03\u5f0f\u8bad\u7ec3":21,"api\u5bf9\u6bd4\u4ecb\u7ecd":40,"api\u5f00\u53d1\u5305\u5e76\u5b89\u88c5":3,"api\u5f00\u53d1\u9884\u6d4b\u7a0b\u5e8f\u65f6":17,"api\u5f00\u53d1\u9884\u6d4b\u7a0b\u5e8f\u9700\u8981\u4e00\u4e2a\u8bad\u7ec3\u597d\u7684\u6a21\u578b":20,"api\u6240\u9700\u7684\u4f9d\u8d56":17,"api\u63d0\u4f9b\u7684":20,"api\u652f\u6301\u7684\u6240\u6709\u8f93\u5165\u6570\u636e\u7c7b\u578b\u548c\u4ed6\u4eec\u7684\u7ec4\u7ec7\u65b9\u5f0f":20,"api\u65f6\u4e3a\u8f93\u51fa":20,"api\u7684\u4f7f\u7528":18,"api\u76f8\u5173\u63a5\u53e3":19,"api\u8bad\u7ec3":20,"api\u9700\u8981\u521b\u5efa\u7684\u6570\u636e\u7c7b\u578b":19,"api\u9884\u6d4b\u5e93":36,"api\u9884\u6d4b\u65f6":20,"async_sgd\u8fdb\u884c\u8bad\u7ec3\u65f6":13,"avx\u662f\u4e00\u79cdcpu\u6307\u4ee4\u96c6":1,"avx\u7248\u672c":1,"avx\u7684\u955c\u50cf":1,"batch\u4e2d\u5305\u542b":11,"batch\u7684\u6743\u91cd":11,"batches\u4e2a\u6279\u6b21\u4fdd\u5b58\u4e00\u6b21\u53c2\u6570":33,"batches\u6b21":33,"book\u4e00\u5b9a\u662f\u60a8\u6700\u597d\u7684\u9009\u62e9":1,"book\u662f\u4e3a\u7528\u6237\u548c\u5f00\u53d1\u8005\u5236\u4f5c\u7684\u4e00\u4e2a\u4ea4\u4e92\u5f0f\u7684jupyt":1,"book\u7684":14,"book\u7684docker\u955c\u50cf":1,"byte":13,"case":[25,37],"cells\u7b49":12,"class":[6,13],"cmake\u4e2d\u5c06":37,"cmake\u627e\u5230\u7684python\u5e93\u548cpython\u89e3\u91ca\u5668\u7248\u672c\u53ef\u80fd\u6709\u4e0d\u4e00\u81f4\u73b0\u8c61":8,"cmake\u7f16\u8bd1\u65f6":0,"cmake\u914d\u7f6e\u4e2d\u5c06":37,"const":6,"container\u4e2d":26,"cost\u63a5\u6536y_predict\u4e0ey\u4f5c\u4e3a\u8f93\u5165":14,"cost\u8fd8\u5927\u4e8e\u8fd9\u4e2a\u6570":13,"count\u4e2agpu\u4e0a\u4f7f\u7528\u6570\u636e\u5e76\u884c\u6765\u8ba1\u7b97\u67d0\u4e00\u5c42":35,"count\u548cgpu":35,"csr\u5b58\u50a8\u683c\u5f0f\u901a\u8fc7":19,"cuda\u5e93":33,"cuda\u76f8\u5173\u5e93\u4f1a\u5728\u9884\u6d4b\u7a0b\u5e8f\u8fd0\u884c\u65f6\u52a8\u6001\u88c5\u8f7d":17,"cudnn\u5e93":[0,33],"data\u76ee\u5f55\u4e2d\u5b58\u653e\u5207\u5206\u597d\u7684\u6570\u636e":27,"dataprovider\u5171\u8fd4\u56de\u4e24\u4e2a\u6570\u636e":39,"dataprovider\u5171\u8fd4\u56de\u4e24\u7ec4\u6570\u636e":39,"dataprovider\u7f13\u51b2\u6c60\u5185\u5b58":11,"decoder\u5faa\u73af\u5c55\u5f00\u7684\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65\u4f1a\u5f15\u7528\u5168\u90e8\u7ed3\u679c":41,"decoder\u63a5\u53d7\u4e24\u4e2a\u8f93\u5165":41,"decoder\u6bcf\u6b21\u9884\u6d4b\u4ea7\u751f\u4e0b\u4e00\u4e2a\u6700\u53ef\u80fd\u7684\u8bcd\u8bed":41,"decoer\u67b6\u6784":41,"default":[25,26,27,35],"dist\u76ee\u5f55\u4e0b\u751f\u6210\u8f93\u51fa\u7684whl\u5305":0,"dnn\u6570\u5b66\u5e93":0,"docker\u5b89\u88c5\u65b9\u5f0f\u53ef\u4ee5\u8fdb\u5165docker\u5bb9\u5668\u6267\u884c":31,"docker\u5b89\u88c5\u8bf7\u53c2\u8003":7,"docker\u5b89\u88c5\u8bf7\u53c2\u8003docker\u7684\u5b98\u7f51":7,"docker\u5b98\u7f51":1,"docker\u7684\u5b98\u7f51":7,"docker\u955c\u50cf":1,"docker\u955c\u50cf\u4e3a\u4e86\u51cf\u5c0f\u4f53\u79ef":1,"docker\u955c\u50cf\u9ed8\u8ba4":1,"dockerhub\u7f51\u7ad9":1,"double\u7c7b\u578b\u65f6\u4e3a8":13,"dropout\u7684\u6bd4\u4f8b":6,"encode\u6210\u7684\u6700\u540e\u4e00\u4e2a\u5411\u91cf":39,"encoder\u548cdecoder\u53ef\u4ee5\u662f\u80fd\u591f\u5904\u7406\u5e8f\u5217\u7684\u4efb\u610f\u795e\u7ecf\u7f51\u7edc\u5355\u5143":41,"encoder\u8f93\u51fa":41,"entropy\u4f5c\u4e3acost":13,"export":[1,7,8,21],"f\u4ee3\u8868\u4e00\u4e2a\u6d6e\u70b9\u6570":14,"fc1\u548cfc2\u5c42\u5728gpu\u4e0a\u8ba1\u7b97":35,"fc3\u5c42\u4f7f\u7528cpu\u8ba1\u7b97":35,"float":[19,37],"float\u7b49":35,"forward\u7684output\u7684\u503c":11,"full\u53c2\u6570\u63d0\u4ea4":9,"function":42,"function\u4f7f\u7528":12,"git\u6d41\u5206\u652f\u6a21\u578b":4,"github\u9996\u9875":4,"glibc\u81f3\u5c11\u5305\u542bglibc_2":3,"gpu\u4e8c\u8fdb\u5236\u6587\u4ef6":0,"gpu\u5219\u8fd8\u9700\u8981\u9ad8\u5e76\u884c\u6027":37,"gpu\u6027\u80fd\u8c03\u4f18":36,"gpu\u6838\u5728\u8bad\u7ec3\u914d\u7f6e\u4e2d\u6307\u5b9a":33,"gpu\u7684docker\u955c\u50cf\u7684\u65f6\u5019":8,"group\u6559\u7a0b":40,"group\u7684\u5b9e\u73b0\u65b9\u5f0f":12,"gru\u6216lstm":42,"html\u5373\u53ef\u8bbf\u95ee\u672c\u5730\u6587\u6863":7,"i\u4ee3\u8868\u4e00\u4e2a\u6574\u6570":14,"id\u6307\u5b9a\u4f7f\u7528\u54ea\u4e2agpu\u6838":33,"id\u6307\u5b9a\u7684gpu":35,"id\u65e0\u6548":33,"image\u91cc":26,"imikolov\u6570\u636e\u96c6":21,"import":[3,14,16,20,21,25],"infer\u63a5\u53e3\u7684\u8fd4\u56de\u503c\u662f\u4e00\u4e2apython":11,"int":[6,19,21,35,39],"issue\u7f16\u53f7":4,"job\u662f\u672c\u6b21\u8bad\u7ec3\u5bf9\u5e94\u7684job":27,"job\u7684\u540d\u5b57":27,"kubernetes\u4e3a\u8fd9\u6b21\u8bad\u7ec3\u521b\u5efa\u4e863\u4e2apod\u5e76\u4e14\u8c03\u5ea6\u5230\u4e863\u4e2anode\u4e0a\u8fd0\u884c":27,"kubernetes\u5206\u5e03\u5f0f\u8bad\u7ec3":24,"kubernetes\u5355\u673a\u8bad\u7ec3":24,"kubernetes\u53ef\u4ee5\u901a\u8fc7yaml\u6587\u4ef6\u6765\u521b\u5efa\u76f8\u5173\u5bf9\u8c61":27,"kubernetes\u5c31\u4f1a\u521b\u5efa3\u4e2apod\u4f5c\u4e3apaddlepaddle\u8282\u70b9\u7136\u540e\u62c9\u53d6\u955c\u50cf":27,"kubernetes\u6709job\u7c7b\u578b\u7684\u8d44\u6e90\u6765\u652f\u6301":26,"label\u662f\u539f\u59cb\u6570\u636e\u4e2d\u5bf9\u4e8e\u6bcf\u4e00\u53e5\u8bdd\u7684\u5206\u7c7b\u6807\u7b7e":39,"labels\u662f\u6bcf\u7ec4\u5185\u6bcf\u4e2a\u53e5\u5b50\u7684\u6807\u7b7e":39,"layer1\u5fc5\u987b\u662f\u4e00\u4e2a0\u5c42\u5e8f\u5217":38,"layer1\u5fc5\u987b\u662f\u4e00\u4e2a\u5355\u5c42\u5e8f\u5217":38,"layer\u4f5c\u4e3a\u4e00\u4e2a\u6574\u4f53\u6765\u5b9e\u73b0":12,"layer\u62ff\u5230\u7684\u7528\u6237\u8f93\u5165":41,"layer\u65f6":12,"layer\u662f\u6211\u4eec\u7684\u79ef\u6728":14,"layer\u7c7b\u53ef\u4ee5\u81ea\u52a8\u8ba1\u7b97\u4e0a\u9762\u7684\u5bfc\u6570":6,"layer\u8ba1\u7b97\u7684\u8f93\u51fa":12,"linux\u4e2d":1,"list\u4e2d":20,"list\u5982\u4e0b\u6240\u793a":35,"list\u6307\u5b9a\u6d4b\u8bd5\u7684\u6a21\u578b\u5217\u8868":35,"memory\u4e0d\u80fd\u72ec\u7acb\u5b58\u5728":41,"memory\u4e5f\u53ef\u4ee5\u5177\u6709":42,"memory\u4e5f\u53ef\u4ee5\u662f\u5e8f\u5217":42,"memory\u53ea\u80fd\u5728":41,"memory\u53ef\u4ee5\u7f13\u5b58\u4e0a\u4e00\u4e2a\u65f6\u523b\u67d0\u4e00\u4e2a\u795e\u7ecf\u5143\u7684\u8f93\u51fa":39,"memory\u6307\u5411\u4e00\u4e2alay":41,"memory\u662f\u5728\u5355\u6b65\u51fd\u6570\u4e2d\u5faa\u73af\u4f7f\u7528\u7684\u72b6\u6001":42,"memory\u662fpaddlepaddle\u5b9e\u73b0rnn\u65f6\u5019\u4f7f\u7528\u7684\u4e00\u4e2a\u6982\u5ff5":39,"memory\u7684":42,"memory\u7684\u521d\u59cb\u72b6\u6001":41,"memory\u7684\u65f6\u95f4\u5e8f\u5217\u957f\u5ea6\u4e00\u81f4\u7684\u60c5\u51b5":39,"memory\u7684\u66f4\u591a\u8ba8\u8bba\u8bf7\u53c2\u8003\u8bba\u6587":41,"memory\u7684\u8f93\u51fa\u5b9a\u4e49\u5728":42,"memory\u7684i":41,"memory\u9ed8\u8ba4\u521d\u59cb\u5316\u4e3a0":41,"mnist\u624b\u5199\u6570\u5b57\u8bc6\u522b\u76ee\u5f55":20,"name\u7ec4\u5408\u53ef\u4ee5\u627e\u5230\u672c\u6b21\u8bad\u7ec3\u9700\u8981\u7684\u6587\u4ef6\u8def\u5f84":27,"new":[4,6,25],"null":[6,19,33],"num\u51b3\u5b9a\u603b\u7aef\u53e3\u4e2a\u6570":21,"num_gradient_servers\u53c2\u6570":27,"num_samples_processed\u4e3a\u5df2\u8bad\u7ec3\u6837\u672c\u6570":13,"only\u7684\u4e8c\u8fdb\u5236":0,"org\u5de5\u5177\u7684\u8be6\u7ec6\u4fe1\u606f":7,"outer_mem\u662f\u4e00\u4e2a\u5b50\u53e5\u7684\u6700\u540e\u4e00\u4e2a\u5411\u91cf":39,"output\u6587\u4ef6\u5939\u5b58\u653e\u8bad\u7ec3\u7ed3\u679c\u4e0e\u65e5\u5fd7":27,"packages\u91cc\u9762":8,"packages\u91cc\u9762\u7684python\u5305":8,"paddepaddle\u901a\u8fc7\u7f16\u8bd1\u65f6\u6307\u5b9a\u8def\u5f84\u6765\u5b9e\u73b0\u5f15\u7528\u5404\u79cdbla":0,"paddle\u4e2d\u7ecf\u5e38\u4f1a\u5c06\u65f6\u95f4\u5e8f\u5217\u6210\u4e3a":39,"paddle\u4e8c\u8fdb\u5236\u5728\u8fd0\u884c\u65f6\u6355\u83b7\u4e86\u6d6e\u70b9\u6570\u5f02\u5e38":11,"paddlepaddle\u4e2d":[38,41],"paddlepaddle\u4e2d\u4e00\u4e2a\u8ba1\u7b97\u5c42\u7684\u8f93\u51fa\u6570\u636e\u7ec4\u7ec7\u65b9\u5f0f\u548c\u8f93\u5165\u6570\u636e\u7ec4\u7ec7\u65b9\u5f0f\u5b8c\u5168\u76f8\u540c":19,"paddlepaddle\u4e2d\u7684\u8bb8\u591alayer\u5e76\u4e0d\u5728\u610f\u8f93\u5165\u662f\u5426\u662f\u65f6\u95f4\u5e8f\u5217":39,"paddlepaddle\u4e2d\u795e\u7ecf\u7f51\u7edc\u8ba1\u7b97\u5c42\u8f93\u5165":19,"paddlepaddle\u4e2d\u8fd8\u5305\u542b":12,"paddlepaddle\u4e2d\u901a\u8fc7reader\u6765\u52a0\u8f7d\u6570\u636e":14,"paddlepaddle\u4e3a\u6df1\u5ea6\u5b66\u4e60\u7814\u7a76\u4eba\u5458\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684api":14,"paddlepaddle\u4e3ano":1,"paddlepaddle\u4f1a\u81ea\u52a8\u8bbe\u5b9a":12,"paddlepaddle\u4f7f\u7528\u540c\u6b65\u5c4f\u969c":22,"paddlepaddle\u4f7f\u7528\u5747\u503c0":13,"paddlepaddle\u4f7f\u7528avx":8,"paddlepaddle\u4fdd\u5b58\u7684\u6a21\u578b\u53c2\u6570\u6587\u4ef6\u5185\u5bb9\u753116\u5b57\u8282\u5934\u4fe1\u606f\u548c\u7f51\u7edc\u53c2\u6570\u4e24\u90e8\u5206\u7ec4\u6210":13,"paddlepaddle\u4fdd\u5b58\u7684\u6a21\u578b\u53c2\u6570\u6587\u4ef6\u524d16\u5b57\u8282\u4e3a\u5934\u4fe1\u606f":13,"paddlepaddle\u53d1\u5e03\u7684\u5b89\u88c5\u5305\u4f1a\u5c3d\u91cf\u5bf9\u9f50":3,"paddlepaddle\u53ef\u4ee5\u4f7f\u7528\u5e38\u7528\u7684python\u5305\u7ba1\u7406\u5de5\u5177":3,"paddlepaddle\u53ef\u4ee5\u4f7f\u7528cudnn":0,"paddlepaddle\u53ef\u4ee5\u540c\u65f6\u652f\u6301\u540c\u6b65\u968f\u673a\u68af\u5ea6\u4e0b\u964d":22,"paddlepaddle\u53ef\u4ee5\u6bd4\u8f83\u7b80\u5355\u7684\u5224\u65ad\u54ea\u4e9b\u8f93\u51fa\u662f\u5e94\u8be5\u8de8\u8d8a\u65f6\u95f4\u6b65\u7684":39,"paddlepaddle\u53ef\u4ee5\u901a\u8fc7\u8be5\u673a\u5236\u5224\u65ad\u662f\u5426\u5df2\u7ecf\u6536\u96c6\u9f50\u6240\u6709\u7684\u68af\u5ea6":6,"paddlepaddle\u5728\u5b9e\u73b0rnn\u7684\u65f6\u5019":39,"paddlepaddle\u5728\u6fc0\u6d3b\u51fd\u6570\u91cc\u5b9e\u73b0dropout":12,"paddlepaddle\u5728\u7f16\u8bd1\u65f6":0,"paddlepaddle\u5b58\u7684\u662f\u6709\u503c\u4f4d\u7f6e\u7684\u7d22\u5f15":14,"paddlepaddle\u5b89\u88c5\u5305\u7531\u4e8e\u4e0d\u4ec5\u4ec5\u5305\u542b":3,"paddlepaddle\u63d0\u4f9b\u4e86\u57fa\u4e8edocker\u7684\u5b89\u88c5\u65b9\u5f0f":2,"paddlepaddle\u63d0\u4f9b\u4e86\u591a\u79cdpython":2,"paddlepaddle\u63d0\u4f9b\u4e86c":18,"paddlepaddle\u63d0\u4f9b\u7684":12,"paddlepaddle\u652f\u6301":0,"paddlepaddle\u652f\u6301\u4e0d\u540c\u7c7b\u578b\u7684\u8f93\u5165\u6570\u636e":14,"paddlepaddle\u652f\u6301\u4f7f\u7528pip\u5feb\u901f\u5b89\u88c5":16,"paddlepaddle\u652f\u6301\u7528\u6237\u7075\u6d3b\u5730\u8bbe\u7f6e\u5404\u79cd\u547d\u4ee4\u884c\u53c2\u6570":34,"paddlepaddle\u652f\u6301\u975e\u5e38\u591a\u7684\u4f18\u5316\u7b97\u6cd5":11,"paddlepaddle\u652f\u6301sparse\u7684\u8bad\u7ec3":11,"paddlepaddle\u6587\u6863\u4f7f\u7528":7,"paddlepaddle\u662f\u6e90\u4e8e\u767e\u5ea6\u7684\u4e00\u4e2a\u6df1\u5ea6\u5b66\u4e60\u5e73\u53f0":14,"paddlepaddle\u7684":26,"paddlepaddle\u7684\u5185\u5b58\u5360\u7528\u4e3b\u8981\u5206\u4e3a\u5982\u4e0b\u51e0\u4e2a\u65b9\u9762":11,"paddlepaddle\u7684\u53c2\u6570\u4f7f\u7528\u540d\u5b57":13,"paddlepaddle\u7684\u5404\u7248\u672c\u955c\u50cf\u53ef\u4ee5\u53c2\u8003":26,"paddlepaddle\u7684\u5b89\u88c5\u53ef\u4ee5\u53c2\u8003":31,"paddlepaddle\u7684\u6240\u6709layer\u90fd\u6709\u552f\u4e00\u7684nam":12,"paddlepaddle\u7684\u6587\u6863\u5305\u62ec\u82f1\u6587\u6587\u6863":7,"paddlepaddle\u7684\u6587\u6863\u6784\u5efa\u6709\u4e09\u79cd\u65b9\u5f0f":7,"paddlepaddle\u7684\u6e90\u7801":4,"paddlepaddle\u7684\u7f16\u8bd1\u9009\u9879":0,"paddlepaddle\u7684bas":6,"paddlepaddle\u7684dock":26,"paddlepaddle\u7684softmax\u4e0d\u80fd\u6307\u5b9a\u8ba1\u7b97\u7ef4\u5ea6":12,"paddlepaddle\u76ee\u524d\u53ea\u652f\u6301\u5728\u6bcf\u4e2a\u65f6\u95f4\u6b65\u4e2d":39,"paddlepaddle\u76ee\u524d\u63d0\u4f9b\u4e24\u79cd\u53c2\u6570\u521d\u59cb\u5316\u7684\u65b9\u5f0f":13,"paddlepaddle\u76ee\u524d\u652f\u63018\u79cdlearning_rate_schedul":13,"paddlepaddle\u793e\u533a":10,"paddlepaddle\u7f16\u8bd1\u9700\u8981\u4f7f\u7528\u5230\u4e0b\u9762\u7684\u4f9d\u8d56":0,"paddlepaddle\u8d1f\u8d23\u5b8c\u6210\u4fe1\u606f\u548c\u68af\u5ea6\u5728\u65f6\u95f4\u5e8f\u5217\u4e0a\u7684\u4f20\u64ad":41,"paddlepaddle\u8d1f\u8d23\u5b8c\u6210\u4fe1\u606f\u548c\u8bef\u5dee\u5728\u65f6\u95f4\u5e8f\u5217\u4e0a\u7684\u4f20\u64ad":41,"paddlepaddle\u9488\u5bf9\u4e0d\u540c\u7684\u7528\u6237\u7fa4\u4f53\u63d0\u4f9b\u4e86\u591a\u79cd\u5b89\u88c5\u65b9\u5f0f":2,"paddlepaddle\u955c\u50cf\u9700\u8981\u63d0\u4f9b":27,"paddlepaddle\u9700\u8981\u4f7f\u7528docker\u73af\u5883\u5b8c\u6210\u7f16\u8bd1":0,"pass\u4e2a\u6a21\u578b\u5230\u7b2c":33,"pass\u5c06\u4e0d\u8d77\u4f5c\u7528":33,"pass\u8f6e\u5f00\u59cb\u8bad\u7ec3":33,"pass\u8f6e\u7684\u6a21\u578b\u7528\u4e8e\u6d4b\u8bd5":33,"passes\u8f6e":33,"path\u6307\u5b9a\u6d4b\u8bd5\u7684\u6a21\u578b":35,"period\u4e2a\u6279\u6b21\u5bf9\u6240\u6709\u6d4b\u8bd5\u6570\u636e\u8fdb\u884c\u6d4b\u8bd5":33,"period\u4e2a\u6279\u6b21\u6253\u5370\u65e5\u5fd7\u8fdb\u5ea6":33,"period\u4e2a\u6279\u6b21\u8f93\u51fa\u53c2\u6570\u7edf\u8ba1":33,"period\u4e2a\u6279\u6b21\u8f93\u51fa\u7b26\u53f7":33,"period\u6574\u9664":33,"period\u8f6e\u4fdd\u5b58\u8bad\u7ec3\u53c2\u6570":33,"pserver\u5730\u5740\u7b49\u53c2\u6570\u4f7ftrainer\u53ef\u4ee5\u6b63\u786e\u8fde\u63a5\u5230pserv":21,"pserver\u76d1\u542c\u7684\u8d77\u59cb\u7aef\u53e3":21,"public":[6,25,26],"pwd\u53d8\u91cf\u4f1a\u5c55\u5f00\u4e3a\u5f53\u524d\u8def\u5f84\u7684\u7edd\u5bf9\u8def\u5f84":1,"py\u7a0b\u5e8f":3,"pydataprovider\u4f7f\u7528\u7684\u662f\u5f02\u6b65\u52a0\u8f7d":11,"pypi\u5b89\u88c5\u5305\u53ef\u4ee5\u5728":3,"python\u5b89\u88c5\u5305\u652f\u6301linux":8,"python\u5c01\u88c5\u7684\u5b9e\u73b0\u4f7f\u5f97\u6211\u4eec\u53ef\u4ee5\u5728\u914d\u7f6e\u6587\u4ef6\u4e2d\u4f7f\u7528\u65b0\u5b9e\u73b0\u7684\u7f51\u7edc\u5c42":6,"recommendation\u6587\u4ef6\u5939\u5185\u5b58\u653e\u8bad\u7ec3\u6587\u4ef6":27,"request\u524d":4,"request\u7684":4,"request\u88ab\u5408\u5e76\u540e":4,"return":[6,11,13,14,25,27,39,42],"rnn\u5373\u65f6\u95f4\u9012\u5f52\u795e\u7ecf\u7f51\u7edc":39,"rnn\u5bf9\u4e8e\u6bcf\u4e00\u4e2a\u65f6\u95f4\u6b65\u901a\u8fc7\u4e86\u4e00\u4e2alstm\u7f51\u7edc":39,"rnn\u603b\u662f\u5f15\u7528\u4e0a\u4e00\u65f6\u523b\u9884\u6d4b\u51fa\u7684\u8bcd\u7684\u8bcd\u5411\u91cf":41,"rnn\u6a21\u578b":36,"rnn\u914d\u7f6e":40,"root\u66ff\u6362\u4e3apaddlepaddle\u9884\u6d4b\u5e93\u7684\u5b89\u88c5\u8def\u5f84":17,"sdk\u7684\u63a5\u53e3\u9700\u8981\u662f\u6ee1\u8db3c\u6807\u51c6\u7684\u63a5\u53e3":18,"search\u7684\u65b9\u6cd5":33,"sentences\u662f\u53cc\u5c42\u65f6\u95f4\u5e8f\u5217\u7684\u6570\u636e":39,"seq\u53c2\u6570\u5fc5\u987b\u4e3afals":41,"server\u4e2a\u6279\u6b21\u6253\u5370\u65e5\u5fd7\u8fdb\u5ea6":33,"simd\u6307\u4ee4\u63d0\u9ad8cpu\u6267\u884c\u6548\u7387":8,"size\u4e3a512":33,"size\u53ef\u80fd\u4f1a\u5bf9\u8bad\u7ec3\u7ed3\u679c\u4ea7\u751f\u5f71\u54cd":11,"size\u672c\u8eab\u662f\u795e\u7ecf\u7f51\u7edc\u7684\u8d85\u53c2\u6570":11,"softmax\u6fc0\u6d3b\u7684\u8f93\u51fa\u7684\u548c\u603b\u662f1":6,"sparse\u8bad\u7ec3\u9700\u8981\u8bad\u7ec3\u7279\u5f81\u662f":11,"static":25,"step\u51fd\u6570\u4e2d\u7684memori":41,"step\u51fd\u6570\u5185\u90e8\u53ef\u4ee5\u81ea\u7531\u7ec4\u5408paddlepaddle\u652f\u6301\u7684\u5404\u79cdlay":41,"subseq\u7684\u6bcf\u4e2a\u5143\u7d20\u662f\u4e00\u4e2a0\u5c42\u5e8f\u5217":38,"super":6,"switch":25,"tests\u7684paddlepaddl":4,"tflops\u4e86":37,"throw":25,"trainer\u542f\u52a8\u9700\u8981\u4f20\u5165\u7aef\u53e3":21,"trainer\u63a5\u6536\u4e09\u4e2a\u53c2\u6570":14,"trainer\u8282\u70b9\u4e2a\u6570":21,"trainer\u9700\u8981\u548cpserver\u4fdd\u6301\u7f51\u7edc\u8054\u901a\u4ee5\u5b8c\u6210\u8bad\u7ec3":21,"true":[6,11,13,19,20,21,25,27,35,39,42],"true\u8868\u793a\u53cd\u5411\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":42,"try":8,"unit\u5728\u4e00\u4e2a\u65f6\u95f4\u6b65\u5185\u8ba1\u7b97\u5f97\u5230\u7684\u4e2d\u95f4\u503c":12,"update\u53c2\u6570\u65f6\u624d\u6709\u6548":33,"v1\u7248\u672c":8,"var":7,"void":6,"wheel\u5305":2,"while":27,"wmt14\u6570\u636e\u7684\u63d0\u4f9b\u6587\u4ef6\u5728":42,"words\u5373\u4e3a\u8fd9\u4e2a\u6570\u636e\u4e2d\u7684\u5355\u5c42\u65f6\u95f4\u5e8f\u5217":39,"words\u662f\u539f\u59cb\u6570\u636e\u4e2d\u7684\u6bcf\u4e00\u53e5\u8bdd":39,"x86_64\u548cmaco":8,"x\u4e0ey\u4e3a\u4e4b\u524d\u63cf\u8ff0\u7684\u8f93\u5165\u5c42":14,"y\u8868\u793a\u8f93\u5165\u6570\u636e\u662f\u4e00\u4e2a\u7ef4\u5ea6\u4e3a1\u7684\u7a20\u5bc6\u5411\u91cf":14,"yaml\u6587\u4ef6\u4e2d\u5404\u4e2a\u5b57\u6bb5\u7684\u5177\u4f53\u542b\u4e49":27,"yaml\u6587\u4ef6\u63cf\u8ff0\u4e86\u8fd9\u6b21\u8bad\u7ec3\u4f7f\u7528\u7684docker\u955c\u50cf":27,"zero\u4e09\u79cd\u64cd\u4f5c":33,AGE:[25,26],AWS:[24,29,30],And:25,But:8,For:37,IDE:0,Into:25,Its:25,QoS:26,TLS:25,The:[6,19,25,27],Then:25,There:25,Use:25,VPS:25,Will:14,Yes:1,___embedding_0__:27,___embedding_1__:27,___fc_layer_0__:25,__init__:6,__rnn_step__:42,__square_error_cost_0__:27,_recurrent_group:42,_source_language_embed:42,_target_language_embed:42,aaaaaaaaaaaaa:25,about:25,abov:[25,37],abs:11,absolut:11,accessmod:25,act:[11,14,16,39,42],action:25,activ:[11,14,16,42],adadelta:11,adagrad:21,adam:13,add:[4,8],add_input:6,add_test:6,add_to:12,add_unittest_without_exec:6,addbia:6,added:4,address:19,addrow:6,after:[4,25],against:25,age:27,agg_level:[38,39],aggreg:25,aggregatelevel:[38,39],agre:[11,14],alexnet_pass1:35,alexnet_pass2:35,algo_hrnn_demo:39,all:[8,11,14,25,27,41],allow:25,allow_only_one_model_on_one_gpu:[32,33,35],alreadi:[8,25],also:37,alwai:[25,27],amazon:[25,26],amazonaw:25,amazonec2fullaccess:25,amazonelasticfilesystemfullaccess:25,amazonroute53domainsfullaccess:25,amazonroute53fullaccess:25,amazons3fullaccess:25,amazonvpcfullaccess:25,amd64:25,amend:4,among:25,andd:25,ani:[11,14,25],anoth:25,ans:25,answer:25,anyth:25,apach:[11,14],api:[3,17,18,19,20,21,25,27,37],api_pydataprovider2:11,api_trainer_config_helpers_lay:42,api_v2:38,apiserv:25,apivers:[25,26,27],append:[21,27,39,42],appleyard:37,applic:[11,14,25,26,37],apt:1,archiv:17,arg:[13,27],argpars:27,args_ext:27,argument:[17,19,20,27],argumentpars:27,arn:25,around:25,arrai:[11,13,14,19],arrari:19,articl:4,artifact:25,assign:[19,25],async:32,async_count:[32,33],async_lagged_grad_discard_ratio:[21,33],async_lagged_ratio_default:[32,33],async_lagged_ratio_min:[32,33],attr:[11,12,13,42],auc:32,authent:25,author:[11,14,25],auto:[0,6,37],autom:25,automat:25,avail:25,averag:11,average_test_period:[32,33],avg:[37,38],avoid:37,avx:1,await:26,awar:25,awk:28,aws_account_id:25,awsaccountid:25,awskeymanagementservicepowerus:25,axi:11,b363:26,b8561f5c79193550d64fa47418a9e67ebdd71546186e840f88de5026b8097465:26,ba5f:25,backward:6,backward_first:42,backwardactiv:6,baidu:26,balanc:25,bare:26,barrier:22,barrierstatset:37,base:25,basematrix:6,bash:[0,1,4,25,26,27,31],basi:[11,14],batch:[11,14,19,25,26,27],batch_id:[11,14],batch_siz:[11,14],batchsiz:6,beam:42,beam_gen:42,beam_search:[41,42],beam_siz:[32,33,35,42],becaus:[25,39],befor:[8,11,25],beginn:42,below:25,besteffort:26,better:25,between:25,bia:6,bias_attr:[11,13,39,42],biases_:6,biasparameter_:6,biassiz:6,bidi:26,bidirectional_lstm:12,bilinearfwdbwd:37,bin:[0,1,20,21,25,26,27,31],binari:[20,25],blank:25,blob:0,book:[1,7,42],bool:[6,19,33,35],boot:[41,42],boot_lay:[39,42],bos_id:42,both:25,branch:4,broken:4,browser:25,bucket_nam:25,bug:[4,25],build:[0,4,7,8,17,25,27,29,30,31],build_doc:7,built:37,button:25,c703c041:4,c99e:25,cach:11,cache_pass_in_mem:11,cachetyp:11,caffe_poli:13,call:[25,27,37],callback:6,caller:25,calrnn:39,can:[25,37],cannot:8,capac:25,capi:17,capi_priv:17,cat:[1,27,28],categoryfil:26,caution:25,cbla:17,cento:3,certif:[8,25],cfg:26,chang:[4,25],channel:37,check:[4,6,8,13,19,25,33],check_eq:6,check_l:6,check_sparse_distribution_batch:[32,33],check_sparse_distribution_in_pserv:[32,33],check_sparse_distribution_ratio:[32,33],check_sparse_distribution_unbalance_degre:[32,33],checkgrad:33,checkgrad_ep:33,checkout:4,chmod:25,claim:25,claimnam:[25,27],clang:4,classification_cost:[11,39],claster:25,clean:[4,8],cli:25,click:25,clip:33,clone:[0,7,17],close:4,cludform:25,cluster:[21,23,27],cluster_test_fil:21,cluster_train:[11,23],cluster_train_fil:21,cluster_train_v2:[23,24,28],cm469:25,cmake:[0,4,7,8,17,37],cmakefil:8,cmakelist:6,cname:25,cnn:26,code:[6,25,26],coded_stream:13,codedinputstream:13,colindic:19,collectbia:6,colum:19,column:19,com:[0,1,4,7,8,17,25,26],command:[0,6,25,26,27,29,30,35],commandlin:[27,37],comment:[27,39],commit:26,commun:25,compil:[0,31],complet:[25,26,27],complianc:[11,14],compress:19,comput:25,concat:42,concaten:11,condit:[11,14,26],conf:[13,23,27,39],conf_paddle_gradient_num:[25,27],conf_paddle_n:[25,27],conf_paddle_port:[25,27],conf_paddle_ports_num:[25,27],conf_paddle_ports_num_spars:[25,27],config:[6,14,17,25,26,27,32,33,35],config_:33,config_arg:[32,33,35],config_lay:6,config_pars:6,configprotostr:13,configur:[6,16],conflict:4,connect:[9,25,26],consol:25,constant:13,contain:[0,25,26,27],containerport:25,content:7,content_dir:7,context:[11,42],contin:25,control:[25,26],cool:4,copi:[11,14,25],copyright:[11,14],coreo:25,correct:25,correspond:13,cost:[11,14],could:25,count:[21,26,33,35,37],cp27:3,cp27m:3,cp27mu:3,cpp:[6,13,27,37,39],cpu:[0,26,35,37],cpu_avx_mkl:3,cpu_avx_openbla:3,cpu_noavx_openbla:3,cpuinfo:1,crash:37,creat:[4,6,7,11,13,14,19,26,27,28],create_bias_paramet:6,create_input_paramet:6,createstack:25,creation:25,creationd:25,crlf:4,cross:13,csc:6,csr:[6,19],csv:13,ctest:[0,4],ctrl:[0,23],cuda7:[3,16],cuda8:[0,1,3],cuda:[33,37],cuda_dir:[32,33],cuda_so:[1,8],cuda_visible_devic:11,cudaconfigurecal:37,cudadevicegetattribut:37,cudaeventcr:37,cudaeventcreatewithflag:37,cudafre:37,cudagetdevic:37,cudagetdevicecount:37,cudagetdeviceproperti:37,cudagetlasterror:37,cudahostalloc:37,cudalaunch:37,cudamalloc:37,cudamemcpi:37,cudaprofilerstart:37,cudaprofilerstop:37,cudaprofilestop:37,cudaruntimegetvers:37,cudasetdevic:37,cudasetupargu:37,cudastreamcr:37,cudastreamcreatewithflag:37,cudastreamsynchron:37,cudeviceget:37,cudevicegetattribut:37,cudevicegetcount:37,cudevicegetnam:37,cudevicetotalmem:37,cudnn_conv_workspace_limit_in_mb:[32,33],cudnn_dir:[32,33],cudnnv5:0,cudrivergetvers:37,cuinit:37,curl:25,current:[7,25],current_word:[11,42],custom:25,cxxabi_1:3,d3e0:25,darwin:25,data:[11,14,16,19,22,26,27,29,32,39,42],data_batch:11,data_lay:[11,39],data_typ:[12,14,16,19,42],dataprovid:[11,13,27],dataset:[14,16,21,42],dcmake_build_typ:[7,17],dcmake_install_prefix:17,dcuda_arch_nam:0,dcudnn_root:0,deb:4,debug:7,decod:[41,42],decoder_boot:42,decoder_group_nam:42,decoder_input:[11,42],decoder_mem:42,decoder_s:[11,42],decoder_st:42,decrypt:25,deep:37,def:[6,11,13,14,27,39,42],default_decor:27,default_devic:35,default_valu:35,defin:[11,14],define_py_data_sources2:13,delet:4,deletestack:25,delimit:13,demo:[26,29],dens:25,dense_arrai:12,dense_vector:[14,16,19],dense_vector_sequ:19,dense_vector_sub_sequ:19,deploy:25,describ:[25,26],describestack:25,describestackev:25,describestackresourc:25,descript:[25,27],desir:[25,26],detail:25,detect:4,dev:[0,1,4,8],develop:[0,4],devic:[1,8,35],deviceid:35,dict:[13,27,39],dict_dim:[11,39],dict_fil:39,dictionari:11,diff:[4,11],differ:25,dig:25,dim:6,dimens:11,dimension:19,dir:[8,27],directori:[4,7,26,37],disabl:13,discard:[4,33],discexp:13,discoveri:25,dist:[0,8],distribut:[11,14,29,30,33],distribute_test:[32,33],diy_beam_search_prob_so:[32,33],dnn:8,dns:25,doc:[7,21,23,27],doc_cn:7,docker:[0,1,4,7,8,25,26,27,29,30,31],docker_clust:[23,28],dockerfil:[0,4,27],domain:25,don:25,done:[4,25,27,37],dot_period:[27,33,35],doubl:33,down:37,download:[8,26],doxygen:4,dpython_execut:8,dpython_include_dir:8,dpython_librari:8,drop_fc:12,drop_rat:12,dropout:12,dropout_r:12,drwxr:26,dtoh:37,dtype:13,dump:20,dump_config:20,dump_v2_config:20,dure:25,dwith_c_api:17,dwith_doc:7,dwith_golang:17,dwith_gpu:[0,7,17],dwith_mkl:[7,17],dwith_profil:37,dwith_python:17,dwith_swig_pi:17,dwith_test:0,dwith_tim:37,dynamic_cast:6,each:25,echo:[1,8],edit:25,edu:[25,26],eeoi3ezpr86c:25,effect:25,efs:25,efs_dns_nam:25,efsvol:25,either:[11,14],elb:25,elbapis:25,electron:26,els:[1,6,39],emac:0,emb1:39,emb2:39,emb:[11,13,26,39],emb_group:39,emb_para:13,emb_param_fil:13,emb_sum:11,embed:[13,42],embedding_lay:[11,39],embedding_nam:42,embedding_s:42,emplace_back:6,enabl:[25,37],enable_grad_shar:[32,33],enable_parallel_vector:33,enc_proj:42,enc_vec:42,encod:39,encoded_proj:42,encoded_sequ:42,encoded_vector:42,encoder1:39,encoder1_expand:39,encoder1_last:39,encoder1_rep:39,encoder2:39,encoder2_rep:39,encoder_s:42,encrypt:25,encrypt_decrypt:25,end:[4,42],endforwardbackward:11,enditer:[11,14],endpass:14,endpoint:25,entri:25,enumer:13,env:[7,11,25,27],environ:[8,25,26,37],environmenterror:21,eol:4,eos_id:42,equal:39,error:[8,13,17,25,33],error_clipping_threshold:11,eta:26,etc:25,eth0:[25,27],evalu:[20,37],evenli:25,event:[11,14,26],event_handl:[11,14],everi:14,exactli:[11,25],exampl:25,exc_path:8,except:14,execut:25,exist:25,exit:26,exp:13,expand:39,expand_a:[38,39],expand_lay:39,expand_level:38,expandlevel:38,explicit:6,expos:25,express:[11,14,25],extern_mklml:8,extraattr:35,extract:25,extralayerattribut:[11,12],f1205:13,f120da72:26,f7e3:25,fa0wx:26,fabric:[23,24],fail:[8,13,26,33],fals:[6,11,14,16,19,21,26,35,39,42],faq:43,fast:37,fbd1f2bb71f4:26,fc1:[6,35],fc2:35,fc3:35,fc4:35,fc8a365:25,fc8a:25,fc_layer:[11,13,35,39],fclayer:6,fdata:39,featur:4,feed:14,fetch:[4,8],field:[11,25],file:[4,11,14],file_nam:[13,39],filenam:11,filesystem:25,fill:[19,25],fingerprint:25,finish:[25,26],first:[19,25],first_seq:42,firstseen:26,fix:[4,19],flatten_result:11,flist:21,float32:13,floor:13,fmt:13,fname:13,fnt03:25,folder:25,follow:[25,29,30],format:[4,6,16,19,25],forward:6,forwardactiv:6,fparam:13,from:[8,20,25,26,37,41],from_no_sequ:38,from_sequ:38,from_tar:14,fromfil:13,fromstr:13,fulfil:37,full_matrix_project:[39,42],fullyconnectedlay:6,gate_act:39,gcc:0,gcc_3:3,gen_proto_pi:7,gen_rand_param:13,gender:27,gener:[14,19,25,27,35,37],generatedinput:[41,42],genr:27,get:[1,6,11,19,23,25,26,28],get_config_arg:35,get_data:26,get_grad:11,get_input_lay:6,get_sample_from_lin:11,get_support:[3,8],getbatchs:6,getenv:[21,27],gethostbynam:27,gethostnam:27,getidmap:27,getinput:6,getinputgrad:6,getinputvalu:6,getlayeroutput:11,getoutputgrad:6,getoutputvalu:6,getparameterptr:6,getpodlist:27,getsiz:6,gettempl:25,gettranspos:6,getw:6,getweight:6,getwgrad:6,gflag:17,gflags_complet:17,gflags_declar:17,git:[0,4,7,8,17],github:[0,4,7,8,17],give:25,glibc_2:3,glibcxx_3:3,global:[0,25,37],globalstat:37,globalstatinfo:37,glog:17,googl:[13,17],googleapi:25,govern:[11,14],gpg2:25,gpg:25,gpu:[1,3,8,16,19,21,35,37],gpu_id:[11,33,35],gpugpu_id:32,grad:[11,33],grad_share_block_num:[32,33],gradient:[20,21,22,27,33],gradient_clipping_threshold:11,gradient_machin:17,gradientmachin:27,grant:25,greater:19,grep:[1,28],groudtruth:42,group_input1:42,group_input2:42,group_input:[39,42],gru_decod:42,gru_decoder_with_attent:42,gru_step:42,grumemori:[12,42],gserver:6,gsizex:37,guest:3,guid:[25,26],gzip:26,half:25,hard:25,has:[19,25,37],hassubseq:39,have:25,head:28,header:13,headip:28,height:[6,13,19],help:4,here:[19,25],hidden:[12,13,25],hidden_a:13,hidden_b:13,hidden_dim:39,hierach:41,hl_get_sync_flag:6,hold:25,home:[1,25,26,27,28],hook2:39,hook:39,host:[25,26],hostfil:28,hostnam:25,hostnetwork:27,hostpath:[26,27],hostport:25,hous:16,how:25,howardjohnson:39,howev:25,howto:[21,23,27],htod:37,http:[0,1,4,7,8,11,14,17,25,26],i1116:27,i1117:37,iamfullaccess:25,iamusersshkei:25,id_rsa:28,ident:25,idmap:27,ids:[11,19],ids_arrai:19,idx:6,iil:13,imag:[0,4,25,26,27,29,30],imagepullpolici:[25,27],imgsiz:37,imgsizei:37,imgsizex:37,immedi:25,impli:[11,14],improv:25,in_arg:19,inbound:25,inc_path:8,includ:[4,17,25,37],increas:13,incupd:6,index:[25,39],indic:[19,25],individu:25,infer:[14,16],info:[6,11,14,23,27,39],inform:25,infrastructur:25,init:[6,14,16,21,25,27],init_hook:39,init_model_path:[32,33,35],initi:[16,33],initial_max:13,initial_mean:13,initial_min:13,initial_std:13,inlin:25,inner:[11,19,39],inner_:39,inner_mem:39,inner_pos_arrai:19,inner_rnn_output:39,inner_rnn_st:39,inner_rnn_state_:39,inner_seq_pos_arrai:19,inner_step:39,inner_step_impl:39,input:[6,11,12,13,14,16,19,27,35,38,39,41,42],input_data:6,input_data_target:6,input_hassub_sequence_data:6,input_index:6,input_label:6,input_lay:6,input_sequence_data:6,input_sequence_label:6,input_sparse_float_value_data:6,input_sparse_non_value_data:6,input_t:6,input_typ:[11,39],inputdef:6,inputlayers_:6,insert:4,insid:25,instal:[0,1,3,4,7,8,16,17,26,31],install_step:16,instance_ip:25,int32:33,integ:14,integer_sequ:11,integer_valu:[11,14,19,39],integer_value_sequ:[19,39,42],integer_value_sub_sequ:[19,39],interact:25,interfac:25,intern:25,invok:[25,37],ip_str:27,ips:[25,27],ipt:[13,39,42],is_async:21,is_inf:20,is_seq:42,is_stat:13,isbinari:19,isinst:[11,14],ispodallrun:27,isspars:6,issu:[0,10],issue_numb:4,item:[16,27],its:[25,37],ivector:[19,20],jeremi:37,job:[27,32,33,35],job_dispatch_packag:23,job_nam:[25,27],job_namespac:[25,27],job_path:[25,27],job_path_output:27,job_workspac:23,jobnam:27,jobpath:[25,27],jobport0:25,jobport1:25,jobport2:25,jobport3:25,jobselector:27,join:39,json:[25,26],just:25,jx4xr:25,k8s:27,k8s_data:[25,27],k8s_train:[25,27],kebilinearinterpbw:37,kebilinearinterpfw:37,kei:[0,4,11,27,37],key1:33,key2:33,key_pair_nam:25,keyid:25,keymetadata:25,keypair:25,keyserv:25,keystat:25,keyusag:25,keyword:27,kill:25,kind:[11,14,25,26,27],kms:25,know:25,kubeconfig:25,kubectl:[23,26,27,28],kuberent:25,kubernet:[24,27,29,30],kwarg:39,l2regular:[11,21],label:[11,14,18,26,39],label_dim:39,labelselector:27,lag:33,lan:31,languag:[11,14],larg:4,last:[38,39],last_seq:39,lastseen:26,latenc:25,later:25,latest:[1,4,7,8,26,27],launch:25,law:[11,14],layer1:[11,38],layer2:[11,38],layer:[6,11,13,14,16,19,20,38,41,42],layer_0:6,layer_att:12,layer_attr:[11,12,35,42],layer_expand:38,layer_first_seq:38,layer_last_seq:38,layer_nam:11,layer_num:35,layer_pool:38,layer_s:19,layerbas:6,layerconfig:6,layergradutil:6,layermap:6,layers_test:8,ld_library_path:17,learn:[1,37],learning_r:[11,13,21],learning_rate_arg:13,learning_rate_decay_a:13,learning_rate_decay_b:13,learning_rate_schedul:13,leav:25,left_scor:11,len:[6,16,27,39],length:26,let02:26,let:25,level:[19,41],lib64:[1,8,33],lib:[0,17],lib_path:8,libc:3,libcuda:[1,8],libgcc_:3,libgflag:17,libglog:17,libnvidia:[1,8],libopenbla:17,libpaddl:4,libpaddle_capi_engin:17,libpaddle_capi_lay:17,libpaddle_capi_shar:17,libpaddle_capi_whol:17,libprotobuf:[13,17],librari:33,libstdc:3,libz:17,licens:[11,14],like:25,limit:[11,13,14,37],line:[4,11,13,25,35,39],line_count:13,linear:[11,13,14,16],link:[25,41],linux:[0,3,25],linux_x86_64:[3,8],list:[11,25,35],listdir:21,lite:17,load:[14,25,27],load_missing_parameter_strategi:[32,33,35],load_paramet:13,loadsave_parameters_in_pserv:[32,33],local:[0,27,32,33],localhost:[1,7],localip:27,log:[3,6,9,13,21,23,25,26,27,28,33],log_barrier_abstract:[32,33],log_barrier_lowest_nod:[32,33],log_barrier_show_log:[32,33],log_clip:[32,33],log_error_clip:[32,33],log_period:[26,27,33,35],log_period_serv:[32,33],logger:[11,39],look:25,lpaddle_capi_engin:17,lpaddle_capi_lay:17,lstm:[26,39,42],lstm_group:39,lstm_group_input:39,lstm_input:39,lstm_last:39,lstm_nest_group:39,lstm_output:39,lstmemori:[12,39,42],lstmemory_group:[12,39],lstmemory_unit:12,machin:[11,20,25,28,41],machine_transl:42,maco:[0,3],mai:[11,14,25],main:[17,25],maintain:25,make:[0,4,6,7,8,17,25,37],manag:7,manual:13,manylinux1:3,manylinux1_x86_64:[3,8],map:[14,17],mat:19,match:11,math:[6,37],matrix:[6,17,19,20],matrixptr:6,max:[13,35,37,38],max_length:42,mean:[11,25,33],mechan:25,mem:39,memcpi:37,memori:[26,37,42],memory_nam:12,memory_threshold_on_load_data:[32,33],merg:[4,20],merge_model:20,merge_v2_model:20,merge_v2_modelss:20,messag:[4,8,26],metadata:[25,26,27],mfs:27,might:25,min:[25,35,37],min_pool_s:11,mini:11,minut:25,mit:25,mix:42,mixed_lay:39,mkdir:[7,17,25,28],mkl:[0,8,17],mklml:8,mklml_lnx_2018:8,mnist:20,mnist_v2:20,mnt:27,mobil:7,mode:[4,27],model:[7,14,16,20,25,35],model_list:[33,35],model_path:35,modifi:[4,25],modul:13,momentum:[11,14],mon:26,more:[13,37],mount:25,mountpath:[25,26,27],move:25,movie_id:27,mpi:28,mpirun:28,mul:6,multipl:[14,25],must:[6,11,21,25],my_cluster_nam:25,my_cost:13,my_external_dns_nam:25,my_lib:21,mypaddl:[26,27],name:[6,13,14,16,26,27,29,30,35,37,39,42],namespac:[6,26,27],ndarrai:11,need:[8,25,27,37],need_tran:13,nest:19,net:[0,20],network:[12,14,16,19,20,27,35,39],network_config:35,networkadministr:25,neural:[16,39,41],never:[25,26,27],next:25,nfs4:25,nfs:[25,27],nfsdir:27,nfsver:25,nic:[27,32,33],nmt_without_attent:11,nnz:[6,19],no_sequ:14,node0:27,node1ip:28,node2ip:28,node3ip:28,node:[25,26,27,28],node_0:[25,27],node_1:[25,27],node_2:[25,27],node_id:21,nodefil:23,nohup:21,non:25,none:42,normal:[26,27],note:25,notebook:1,noth:4,now:[25,41],nproc:0,nullptr:6,num:[21,27,33],num_gradient_serv:[21,32,33],num_pass:[14,26,27,32,33,35],num_samples_process:13,number:25,numdevices_:35,numlogicaldevices_:35,numpi:[0,11,13,14],numsampl:37,nvidia:[1,8],obj:13,object:37,obtain:[11,14],occup:27,oct:26,off:[0,4,7,17,31],offici:25,offset:19,ograd:6,omit:11,ompi_comm_world_rank:21,onc:25,one:[19,25],onli:[19,25,39,41],onto:25,open:[11,13,14,25,39],openbla:[0,1,17],openmpi:[24,28],oper:25,opt:[0,27],optim:[11,13,14,21],optimzi:11,order:[25,27],oregon:25,org:[11,14],origin:4,other:25,our:25,out:[11,25,39,41,42],out_dir:[25,27],out_mem:42,outer:39,outer_mem:39,outer_rnn_st:39,outer_rnn_state_:39,outer_step:39,output:[11,14,20,23,26,27,35,39,42],output_fil:20,output_lay:[11,14,16],output_mem:42,outter:19,outter_pos_arrai:19,outter_seq_pos_arrai:19,outv:6,own:25,pack:13,packag:[8,25],paddl:[0,1,3,4,6,7,11,13,14,16,17,19,20,21,23,25,26,27,28,31,35,37,42],paddle_arguments_get_sequence_start_po:19,paddle_arguments_set_id:19,paddle_arguments_set_sequence_start_po:19,paddle_arguments_set_valu:19,paddle_capi:17,paddle_doc:7,paddle_docs_cn:7,paddle_gradient_machine_create_shared_param:20,paddle_gradient_machine_forward:20,paddle_gradient_machine_load_parameter_from_disk:20,paddle_init:20,paddle_init_num_gradient_serv:21,paddle_init_port:21,paddle_init_ports_num:21,paddle_init_ports_num_for_spars:21,paddle_init_pserv:21,paddle_init_trainer_count:21,paddle_init_trainer_id:21,paddle_init_use_gpu:21,paddle_ivector:19,paddle_ivector_cr:19,paddle_manylinux_devel:0,paddle_matrix:[19,20],paddle_matrix_cr:19,paddle_matrix_create_spars:19,paddle_matrix_get_row:19,paddle_matrix_sparse_copy_from:19,paddle_n:27,paddle_output:26,paddle_port:27,paddle_ports_num:27,paddle_ports_num_spars:27,paddle_process_by_paddl:27,paddle_pserver2:23,paddle_r:19,paddle_root:17,paddle_server_num:27,paddle_train:[23,27],paddlepaddl:[0,1,3,4,11,14,16,17,19,20,23,26,27,29,30,31,37,42],paddlepaddle_gpu:3,paddlepaddlebook:1,paddlepaddlehub:1,page:25,parallel:[25,26,27,35,37],parallel_nn:[32,33],param:[11,13],param_attr:[11,13,42],param_fil:[13,20],paramattr:[11,13,42],paramet:[11,13,14,16,19,22,23,27,33],parameter_block_s:[32,33],parameter_block_size_for_spars:[32,33],parameterclient2:27,parametermap:6,parameters_:6,params_pass_4:20,params_pass_90:14,params_pass_:14,paramt:25,paraspars:6,pars:[0,25],parse_known_arg:27,parsefromstr:13,parser:27,partit:25,paserv:27,pass:[4,11,14,25,26,27,33,35,37],pass_id:[11,14],pass_manu:13,passtyp:6,past:25,path:[17,25,26,27,33],path_to_paddlepaddle_working_directori:7,pattern:25,pd_api:19,peer:9,pem:25,pep425tag:[3,8],perform:[32,37],period:33,permiss:[11,14,25],persist:25,persistentvolum:25,persistentvolumeclaim:[25,27],pgp:25,pick:25,pickl:[21,28],pip:[0,3,4,7,8,16],platform:[3,25],pleas:[7,8,25,27],pnpairvalid:32,pod:[25,26,27],pod_nam:25,podip:27,podlist:27,point:[19,37],pointer:19,poli:13,polici:25,pool3:6,pooling_lay:11,pooling_typ:[11,38],port:[21,25,26,27,32,33],port_num:32,portal:7,ports_num:[21,27,33],ports_num_for_spars:[21,27,32,33,35],posit:19,post:0,potenti:37,pow:13,ppo_workspac:7,pre:25,predict:[11,16,20],predict_fil:[32,33],predict_output_dir:[32,33],prefetch:6,prefix:25,pregrad:6,prepar:[21,28,29],present:4,prev_batch_st:[32,33],previou:25,price:16,print:[3,8,14,16,28],printallstatu:37,printstatu:37,privat:4,privileg:25,prob:16,proc:1,proce:25,process2:39,process:[11,13,25,27,39],processor:37,prod:4,product:[14,25],productgraph:26,profil:37,proflier:37,prog:27,program:[27,37],protect:6,protobuf:[13,17,20],provi:21,provid:[11,16,25,32,39],provis:25,pserver:[21,23,25,27,32,33],pserver_num_thread:[32,33],psize:6,pub:28,pull:1,purpos:37,push:27,push_back:6,pvc:25,pwd:[0,1,4,7],py_paddl:8,pydataprovid:11,pydataprovider2:27,python:[0,3,4,6,7,8,11,16,20,21,28,42],pythonpath:8,queri:25,question:25,quick_start:[25,26,27,29],quick_start_data:26,quickstart:26,rais:21,ran:37,rand:[13,19,33,35,37],rand_max:19,random:13,randomli:19,rang:27,rank:25,rate:[11,27],rather:25,ratio:33,rdma_tcp:[32,33],read:[13,25],read_next_from_fil:11,read_paramet:13,reader:[14,21],readi:[25,26],readm:4,readwritemani:25,reason:26,recommend:27,record:25,recurr:[39,40],recurrent_group:[11,12,39,41,42],recv:25,refine_unknown_arg:27,register_gpu_profil:37,register_lay:6,register_timer_info:37,registri:26,regular:[11,21,25],releas:[8,17,25],remot:[4,25,33,35],remov:4,removing_docker_contain:0,repositori:7,repres:25,request:[25,26],requir:[7,11,14,25],reserv:[11,14],reserveoutput:6,reset:9,reshap:13,resolv:[4,26],resourc:25,respons:[25,26],restart:[25,26],restartpolici:[25,26,27],result:[14,25,37],retran:25,rev:0,revers:[41,42],review:[4,26],reviews_electronics_5:26,right:[11,14],right_scor:11,rkt:0,rmsprop:11,rnn:[32,41,42],rnn_bias_attr:42,rnn_layer_attr:42,rnn_out:42,rnn_state:39,rnn_state_:39,rnn_use_batch:[32,33],role:25,root:[25,26,27],row:19,row_offset:19,rowoffset:19,rsize:25,rstrip:27,rule:25,run:[0,1,4,7,8,23,25,26,27,29,30,31,37],run_test:0,runinitfunct:[27,37],runserv:7,runtim:8,same:[25,39],sampl:19,satisfi:25,save:[25,26],save_dir:[26,27,33,35],save_only_on:[32,33],save_parameter_to_tar:14,savetxt:13,saving_period:[27,32,33],saving_period_by_batch:[32,33,35],schdule:25,schedul:25,score:11,score_diff:11,scp:28,script:[0,7,23,25,28],search:42,secret:25,section:25,see:[11,13,14,25],seed:[13,33,37],select:25,selector:26,self:6,send:25,sent:26,sentanc:11,sentenc:[39,42],sentence_last_state1:39,sentence_last_state2:39,seq:39,seq_po:19,seq_pool:38,seq_pos_arrai:19,seqlastin:39,sequenc:[11,14,19,39,41],sequence_layer_group:39,sequence_nest_layer_group:39,sequence_recurr:13,sequence_start_posit:19,sequencegen:39,sequencetyp:14,seri:39,serv:25,server:[0,9,21,22,23,27,33],set:[0,7,11,13,14,19,25,26,37,39],set_active_typ:6,set_drop_r:6,set_siz:6,set_typ:6,setp:25,setq:0,settotalbyteslimit:13,setup:6,sever:25,sgd:[14,22,32],shape:14,shard:[22,25],shell:25,should:[7,25,41],should_shuffl:39,show:[0,25],show_check_sparse_distribution_log:[32,33],show_layer_stat:[32,33],show_parameter_stats_period:[26,32,33,35],shown:25,shuf:11,shuffl:11,sid:25,sig:25,sigint:23,sigmoidactiv:39,sign:25,signatur:25,similar:25,simpl:27,simple_attent:42,simple_gru:42,simple_lstm:12,simple_rnn:42,simplest:25,simultan:25,sinc:25,site:25,size:[6,11,13,14,16,19,39,42],size_t:6,sizeof:19,skip:[4,13,25],sleep:27,small_messag:[32,33],snap:26,snapshot:25,snippet:25,sock_recv_buf_s:[32,33],sock_send_buf_s:[32,33],socket:27,softmax:[6,11,42],softmax_param:13,softmaxactiv:39,softwar:[11,14],some:25,sort:[25,27],sourc:25,source_dict_dim:42,source_language_word:42,spars:[6,11,19,21,25,27,33,35],sparse_binary_vector:[11,14,19],sparse_binary_vector_sequ:19,sparse_binary_vector_sub_sequ:19,sparse_float_vector:14,sparse_upd:11,sparse_vector:[11,19],sparse_vector_sequ:19,sparse_vector_sub_sequ:19,sparseparam:6,sparseprefetchrowcpumatrix:6,spec:[25,26,27],specif:[11,14],specifi:[7,25],sphinx:7,split:[21,25,39],split_count:[21,25,27],square_error_cost:14,squash:4,srand:[19,33],src:[8,21,23,27],src_backward:42,src_dict:13,src_dict_path:13,src_embed:42,src_forward:42,src_word_id:42,ssh:[25,28],ssh_server:23,stabl:25,stack:25,stage:4,stamp:8,stanford:26,start:[4,8,19,26,27,33],start_mpi_train:28,start_paddl:27,start_pass:[32,33],start_pserv:[32,33],startpaddl:27,startup:25,stat:[33,37],state:[12,26,41],state_act:39,statement:25,statfulset:27,staticinput:[41,42],statset:37,statu:[4,25,26,27,37],status:26,std:[6,33],stdbuf:21,stderr:23,stdout:23,step:[25,39,41,42],stepout:39,stmt1482205552000:25,stmt1482205746000:25,storag:25,store:25,str:[27,35],strategi:33,string:[6,25,33],strip:[13,39],struct:13,structur:25,sts:25,stuff:4,sub_sequ:14,submit:25,subnet0:25,subnet:25,subobjectpath:26,subseq:[38,41],subsequenceinput:39,succeed:26,success:[25,26],successfulcr:26,sudo:[0,25],suffix:21,sumpool:11,support:[3,25,39],suppos:19,sure:25,swig:0,switch_ord:12,symlink:4,syncflag:6,synchron:25,system:11,tag:[1,4,8,31],tainer_id:27,take:25,tanh:[6,42],tanhactiv:39,tar:[8,14,20,25],tarbal:25,target_dict_dim:42,target_language_word:42,targetinlink:39,task:20,tbd:39,tcp:[25,33],tear:37,tee:26,templat:[26,27],termin:26,test:[4,6,16,19,21,28,33,35,37],test_all_data_in_one_period:26,test_compar:8,test_comparespars:8,test_comparetwonet:8,test_comparetwoopt:8,test_config_pars:8,test_data_dir:21,test_fcgrad:6,test_gpuprofil:37,test_layergrad:6,test_list:13,test_networkcompar:8,test_pass:[32,33,35],test_period:[32,33,35],test_predict:8,test_pydataprovid:8,test_pydataprovider2:8,test_pydataproviderwrapp:8,test_recurrent_machine_gener:8,test_recurrentgradientmachin:[8,39],test_sum_op:0,test_swig_api:8,test_train:8,test_traineronepass:8,test_wait:[32,33],testbilinearfwdbwd:37,testconfig:6,testfcgrad:6,testfclay:6,testlayergrad:6,testutil:6,text:25,tflop:37,tgz:[3,8],than:[13,19,25],thei:[25,37],them:[25,37],thi:[3,11,14,19,25,37],third:19,third_parti:[8,17],thread:37,thread_local_rand_use_global_se:[32,33],threadid:35,threadloc:37,threshold:33,through:7,throughput:37,thu:25,tier:26,time:[19,26,27,33,37,39],timeo:25,timer:37,titl:27,to_no_sequ:38,to_sequ:[38,39],to_your_paddle_clone_path:7,token:42,tool:[7,25,27],toplevel:0,tostr:13,total:[26,37],touch:8,track:4,train:[1,9,11,14,21,23,26,27,28,29,30,33,35,42],train_arg:27,train_args_dict:27,train_args_list:27,train_config_dir:[25,27],train_data:21,train_data_dir:21,train_i:14,train_id:25,train_list:[13,21],train_read:14,train_x:14,trainer:[6,14,21,22,27,33,35],trainer_config:[20,25,26,27],trainer_config_help:6,trainer_count:[11,16,21,25,26,27,32,33,35],trainer_id:[21,25,27,33],trainerconfighelp:13,trainerid:27,tran:6,translat:11,travi:4,tree:27,trg_embed:42,tune:32,turn:41,tutori:[25,27,28,29,30],two:[25,37],txt:[6,7,21,25,28],type:[6,14,16,19,25,26,35,39,42],ubuntu:[3,16],uci_h:16,uid:26,uint64_t:19,under:[11,14,25],understand_senti:42,undeterminist:37,uninstal:[0,8],uniqu:25,unique_ptr:6,unittest:8,unless:[11,14],until:[25,27],untrack:4,updat:[4,35],update_equ:14,updatecallback:6,updatestack:25,upgrad:[3,8],upstream:[4,8],uri:25,usag:[23,27],use:[4,11,14,19,21,25,27,37],use_gpu:[11,14,16,21,26,27,32,33,35],use_old_updat:[32,33],used:[25,37],usegpu:[6,19],user:25,user_id:27,usernam:4,uses:25,using:[16,25],usr:[0,1,8,21,25,27,33],usual:[25,37],util:[20,27,37],valid:25,valu:[6,11,19,25,27,35],value1:33,value2:33,valueerror:11,vanilla:42,vari:25,variabl:[25,26],vec:13,vector:[17,19],version:[4,11,14,25,31,32,33,37],via:[4,25],vim:1,virtualenv:0,volum:[7,26,27],volumemount:[25,26,27],volumn:25,wait:27,warn:[8,13,27],warranti:[11,14],wbia:25,weight:6,weightlist:6,weights_:6,weights_t:6,well:25,west:25,wget:8,what:4,wheel:3,when:[25,37],whether:19,which:[14,25],whl:[0,3],whole:[17,25],why:37,wide:[23,28],width:[6,13,19],window:0,with_avx:[0,4,31],with_c_api:[0,17],with_doc:0,with_doubl:[0,6,31],with_dso:0,with_golang:[0,17],with_gpu:[0,4,17,31],with_mkl:[0,17],with_profil:37,with_python:[0,17,31],with_rdma:31,with_style_check:[0,4],with_swig_pi:[0,17],with_test:[0,4],with_tim:[31,37],without:[11,14],wmt14:42,won:39,word2vec:[11,21,23],word:[11,39,41],word_dict:[21,28,39],word_dim:[13,39],word_id:11,word_vector_dim:42,work:[1,4,7,25,26,27,39],worker:25,workercount:25,workflow:25,workspac:[21,23],would:25,wrapper:37,write:[11,13,14,25],wsize:25,www:[11,14],xarg:[1,6,8,28],xgbe0:33,xgbe1:33,xrang:[6,14,16],xxxxxxxxx:25,xxxxxxxxxx:25,xxxxxxxxxxxxx:25,xxxxxxxxxxxxxxxxxxx:25,y_predict:[14,16],yaml:[23,25,26,27,28],yapf:4,yield:[11,14,39],you:[11,14,25],your:[8,25],your_access_key_id:25,your_param_nam:13,your_repo:27,your_secrete_access_kei:25,zaist:0,zero:[25,33],zhihu:0,zhuanlan:0,zip:27,zlib:17,zone:25,zxf:8,zxvf:25},titles:["\u4ece\u6e90\u7801\u7f16\u8bd1","\u4f7f\u7528Docker\u5b89\u88c5\u8fd0\u884c","\u5b89\u88c5\u4e0e\u7f16\u8bd1","\u4f7f\u7528pip\u5b89\u88c5","\u5982\u4f55\u8d21\u732e\u4ee3\u7801","\u5f00\u53d1\u6807\u51c6","\u5982\u4f55\u5b9e\u73b0\u65b0\u7684\u7f51\u7edc\u5c42","\u5982\u4f55\u8d21\u732e\u6587\u6863","\u7f16\u8bd1\u5b89\u88c5\u4e0e\u5355\u5143\u6d4b\u8bd5","\u96c6\u7fa4\u8bad\u7ec3\u4e0e\u9884\u6d4b","FAQ","\u672c\u5730\u8bad\u7ec3\u4e0e\u9884\u6d4b","\u6a21\u578b\u914d\u7f6e","\u53c2\u6570\u8bbe\u7f6e","\u57fa\u672c\u4f7f\u7528\u6982\u5ff5","\u65b0\u624b\u5165\u95e8","\u5feb\u901f\u5f00\u59cb","\u5b89\u88c5\u4e0e\u7f16\u8bd1C-API\u9884\u6d4b\u5e93","C-API\u9884\u6d4b\u5e93","\u8f93\u5165/\u8f93\u51fa\u6570\u636e\u7ec4\u7ec7","C-API\u4f7f\u7528\u6d41\u7a0b","\u542f\u52a8\u53c2\u6570\u8bf4\u660e","\u5206\u5e03\u5f0f\u8bad\u7ec3","\u4f7f\u7528fabric\u542f\u52a8\u96c6\u7fa4\u8bad\u7ec3","\u5728\u4e0d\u540c\u96c6\u7fa4\u4e2d\u8fd0\u884c","Kubernetes on AWS","Kubernetes\u5355\u673a\u8bad\u7ec3","Kubernetes\u5206\u5e03\u5f0f\u8bad\u7ec3","\u5728OpenMPI\u96c6\u7fa4\u4e2d\u542f\u52a8\u8bad\u7ec3","<no title>","<no title>","\u73af\u5883\u51c6\u5907","\u53c2\u6570\u6982\u8ff0","\u7ec6\u8282\u63cf\u8ff0","\u547d\u4ee4\u884c\u53c2\u6570\u8bbe\u7f6e","\u4f7f\u7528\u6848\u4f8b","\u8fdb\u9636\u4f7f\u7528","GPU\u6027\u80fd\u8c03\u4f18","\u652f\u6301\u53cc\u5c42\u5e8f\u5217\u4f5c\u4e3a\u8f93\u5165\u7684Layer","\u5355\u53cc\u5c42RNN API\u5bf9\u6bd4\u4ecb\u7ecd","RNN\u6a21\u578b","Recurrent Group\u6559\u7a0b","RNN\u914d\u7f6e","PaddlePaddle \u6587\u6863"],titleterms:{"\u4e00\u4e9b\u7ec6\u8282\u7684\u8865\u5145":27,"\u4e0b\u8f7d\u6570\u636e":26,"\u4e0b\u8f7dmklml\u5e93\u5931\u8d25":8,"\u4e0d\u540c\u7684":12,"\u4e13\u6ce8\u6df1\u5ea6\u5b66\u4e60\u6a21\u578b\u5f00\u53d1":2,"\u4e24\u79cd\u4f7f\u7528":12,"\u4e3a\u4ec0\u4e48\u9700\u8981\u6027\u80fd\u5206\u6790":37,"\u4ec0\u4e48\u662f\u6027\u80fd\u5206\u6790":37,"\u4ece\u6e90\u7801\u7f16\u8bd1":0,"\u4ee3\u7801\u8981\u6c42":4,"\u4f7f\u7528":[4,26],"\u4f7f\u7528\u6848\u4f8b":35,"\u4f7f\u7528\u6a21\u578b\u521d\u59cb\u5316\u7f51\u7edc":35,"\u4f7f\u7528\u6d41\u7a0b":20,"\u4f7f\u7528\u73af\u5883\u53d8\u91cf":27,"\u4f7f\u7528docker\u542f\u52a8paddlepaddl":1,"\u4f7f\u7528docker\u5b89\u88c5\u8fd0\u884c":1,"\u4f7f\u7528docker\u6267\u884cgpu\u8bad\u7ec3":1,"\u4f7f\u7528docker\u6784\u5efa":7,"\u4f7f\u7528fabric\u542f\u52a8\u96c6\u7fa4\u8bad\u7ec3":23,"\u4f7f\u7528paddlepaddl":7,"\u4f7f\u7528pip\u5b89\u88c5":3,"\u4fdd\u6301\u672c\u5730\u4ed3\u5e93\u6700\u65b0":4,"\u4fee\u6539\u542f\u52a8\u811a\u672c":26,"\u514b\u9686":4,"\u5173\u6ce8\u5e95\u5c42\u6846\u67b6":2,"\u5185\u7f6e\u5b9a\u65f6\u5668":37,"\u5199\u68af\u5ea6\u68c0\u67e5\u5355\u5143\u6d4b\u8bd5":6,"\u51c6\u5907\u4e00\u4e2alinux\u96c6\u7fa4":23,"\u51c6\u5907\u6570\u636e\u96c6":21,"\u51c6\u5907\u8bad\u7ec3\u6570\u636e":27,"\u51c6\u5907\u8bad\u7ec3\u7a0b\u5e8f":21,"\u51c6\u5907\u9884\u6d4b\u6a21\u578b":20,"\u51c6\u5907openmpi\u96c6\u7fa4":28,"\u51cf\u5c11\u6570\u636e\u8f7d\u5165\u7684\u8017\u65f6":11,"\u51cf\u5c11dataprovider\u7f13\u51b2\u6c60\u5185\u5b58":11,"\u51fa\u73b0":12,"\u5206\u5e03\u5f0f\u8bad\u7ec3":22,"\u521b\u5efa\u672c\u5730\u5206\u652f":4,"\u521b\u5efa\u795e\u7ecf\u7f51\u7edc\u8f93\u5165":20,"\u521b\u5efajob":27,"\u521b\u5efapaddlepaddl":26,"\u521d\u59cb\u5316paddlepaddle\u8fd0\u884c\u73af\u5883":20,"\u5220\u9664\u672c\u5730\u5206\u652f":4,"\u5220\u9664\u8fdc\u7a0b\u5206\u652f":4,"\u5229\u7528\u66f4\u591a\u7684\u8ba1\u7b97\u8d44\u6e90":11,"\u5230\u8fdc\u7a0b\u4ed3\u5e93":4,"\u5236\u4f5c\u955c\u50cf":27,"\u5236\u4f5cdocker\u955c\u50cf":26,"\u524d\u5411\u8ba1\u7b97":20,"\u52a0\u8f7d\u6a21\u578b":20,"\u52a0\u8f7dpaddlepaddl":14,"\u52a0\u901f\u8bad\u7ec3\u901f\u5ea6":11,"\u5355\u5143\u6d4b\u8bd5":33,"\u5355\u53cc\u5c42rnn":39,"\u53c2\u6570\u5185\u5b58":11,"\u53c2\u6570\u670d\u52a1\u5668\u548c\u5206\u5e03\u5f0f\u901a\u4fe1":33,"\u53c2\u6570\u6982\u8ff0":32,"\u53c2\u6570\u8bbe\u7f6e":13,"\u53c2\u8003\u8d44\u6599":37,"\u53cc\u5c42rnn":39,"\u53cc\u5c42rnn\u4ecb\u7ecd":41,"\u53cc\u5c42rnn\u7684\u4f7f\u7528":41,"\u5404\u4e2a\u7248\u672c\u6700\u65b0\u7684whl\u5305":3,"\u5411\u91cf":33,"\u542f\u52a8\u4efb\u52a1":27,"\u542f\u52a8\u53c2\u6570\u670d\u52a1\u5668":21,"\u542f\u52a8\u53c2\u6570\u8bf4\u660e":21,"\u542f\u52a8\u8ba1\u7b97\u8282\u70b9":21,"\u542f\u52a8\u96c6\u7fa4\u4f5c\u4e1a":[23,28],"\u547d\u4ee4\u884c\u53c2\u6570\u8bbe\u7f6e":34,"\u548c":38,"\u5728\u4e0d\u540c\u8bbe\u5907\u4e0a\u6307\u5b9a\u5c42":35,"\u5728\u4e0d\u540c\u96c6\u7fa4\u4e2d\u8fd0\u884c":24,"\u5728docker\u4e2d\u6267\u884cpaddlepaddle\u8bad\u7ec3\u7a0b\u5e8f":1,"\u5728openmpi\u96c6\u7fa4\u4e2d\u542f\u52a8\u8bad\u7ec3":28,"\u57fa\u672c\u4f7f\u7528\u6982\u5ff5":[14,19],"\u57fa\u672c\u539f\u7406":41,"\u5982\u4f55\u4e66\u5199\u6587\u6863":7,"\u5982\u4f55\u4f7f\u7528":12,"\u5982\u4f55\u5171\u4eab\u53c2\u6570":13,"\u5982\u4f55\u51cf\u5c11\u5185\u5b58\u5360\u7528":11,"\u5982\u4f55\u521d\u59cb\u5316\u53c2\u6570":13,"\u5982\u4f55\u52a0\u8f7d\u9884\u8bad\u7ec3\u53c2\u6570":13,"\u5982\u4f55\u52a0\u901f\u8bad\u7ec3\u901f\u5ea6":11,"\u5982\u4f55\u548c\u660e\u6587\u8fdb\u884c\u76f8\u4e92\u8f6c\u5316":13,"\u5982\u4f55\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u83b7\u5f97\u53c2\u6570\u7684\u6743\u91cd\u548c\u68af\u5ea6":11,"\u5982\u4f55\u5728\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u83b7\u5f97\u67d0\u4e00\u4e2alayer\u7684output":11,"\u5982\u4f55\u5b9e\u73b0\u65b0\u7684\u7f51\u7edc\u5c42":6,"\u5982\u4f55\u6307\u5b9agpu\u8bbe\u5907":11,"\u5982\u4f55\u66f4\u65b0www":7,"\u5982\u4f55\u6784\u5efa\u6587\u6863":7,"\u5982\u4f55\u8bbe\u7f6e\u5b66\u4e60\u7387\u9000\u706b":13,"\u5982\u4f55\u8c03\u7528":11,"\u5982\u4f55\u8d21\u732e\u4ee3\u7801":4,"\u5982\u4f55\u8d21\u732e\u6587\u6863":7,"\u5982\u4f55\u8fdb\u884c\u6027\u80fd\u5206\u6790":37,"\u5982\u4f55\u9009\u62e9sgd\u7b97\u6cd5\u7684\u5b66\u4e60\u7387":13,"\u5b50\u5e8f\u5217\u95f4\u65e0memori":39,"\u5b50\u5e8f\u5217\u95f4\u6709memori":39,"\u5b58\u50a8\u7684\u53c2\u6570\u683c\u5f0f\u662f\u4ec0\u4e48":13,"\u5b89\u88c5":3,"\u5b89\u88c5\u4e0e\u7f16\u8bd1":2,"\u5b89\u88c5\u4e0e\u7f16\u8bd1c":17,"\u5b9e\u73b0c":6,"\u5b9e\u73b0python\u5c01\u88c5":6,"\u5c06\u547d\u4ee4\u53c2\u6570\u4f20\u7ed9\u7f51\u7edc\u914d\u7f6e":35,"\u5de5\u5177":37,"\u5e38\u89c1\u95ee\u9898":0,"\u5e38\u89c1\u95ee\u9898\u548c\u89e3\u51b3\u65b9\u6cd5":3,"\u5e38\u89c1\u95ee\u9898\u6c47\u603b":2,"\u5e76\u5b8c\u6210":4,"\u5efa\u7acb":4,"\u5f00\u53d1\u6807\u51c6":5,"\u5f00\u59cb\u5f00\u53d1":4,"\u5f02\u6b65":21,"\u5f02\u6b65\u968f\u673a\u68af\u5ea6\u4e0b\u964d":33,"\u5feb\u901f\u4f7f\u7528":16,"\u5feb\u901f\u5b89\u88c5":16,"\u5feb\u901f\u5f00\u59cb":16,"\u6027\u80fd\u5206\u6790\u5c0f\u6280\u5de7":37,"\u6027\u80fd\u5206\u6790\u5de5\u5177\u4ecb\u7ecd":37,"\u6027\u80fd\u8c03\u4f18":33,"\u603b\u7ed3":19,"\u6216\u8005\u662f":8,"\u6267\u884c\u5355\u5143\u6d4b\u8bd5":0,"\u627e\u5230\u7684pythonlibs\u548cpythoninterp\u7248\u672c\u4e0d\u4e00\u81f4":8,"\u62a5importerror":8,"\u63a5\u53e3\u8f93\u51fa\u591a\u4e2alayer\u7684\u9884\u6d4b\u7ed3\u679c":11,"\u63a8\u5bfc\u65b9\u7a0b":6,"\u63d0\u4ea4":4,"\u63d0\u4ea4\u4ee3\u7801\u7684\u4e00\u4e9b\u7ea6\u5b9a":4,"\u63d0\u4ea4\u955c\u50cf":26,"\u642d\u5efa\u795e\u7ecf\u7f51\u7edc":14,"\u652f\u6301\u53cc\u5c42\u5e8f\u5217\u4f5c\u4e3a\u8f93\u5165\u7684layer":38,"\u6570\u636e\u652f\u6301":33,"\u6574\u4f53\u65b9\u6848":27,"\u6587\u6863":43,"\u65b0\u624b\u5165\u95e8":15,"\u65e5\u5fd7\u4e2d\u4fdd\u5b58\u5747\u4e3a\u7f51\u7edc\u901a\u4fe1\u7c7b\u9519\u8bef":9,"\u65f6\u95f4\u5e8f\u5217":39,"\u65f6\u95f4\u6b65":39,"\u66f4\u65b0":21,"\u672c\u5730\u6d4b\u8bd5":35,"\u672c\u5730\u8bad\u7ec3":35,"\u672c\u5730\u8bad\u7ec3\u4e0e\u9884\u6d4b":11,"\u6784\u5efa\u548c\u6d4b\u8bd5":4,"\u67e5\u770b\u8bad\u7ec3\u7ed3\u679c":26,"\u67e5\u770b\u8f93\u51fa":27,"\u6848\u4f8b\u4e00":35,"\u6848\u4f8b\u4e8c":35,"\u68c0\u67e5\u6a21\u578b\u8f93\u51fa":23,"\u68c0\u67e5\u96c6\u7fa4\u8bad\u7ec3\u7ed3\u679c":23,"\u6982\u8ff0":[17,38,41],"\u6a21\u578b\u914d\u7f6e":[12,39],"\u6a21\u578b\u914d\u7f6e\u7684\u6a21\u578b\u914d\u7f6e":39,"\u6ce8\u610f\u4e8b\u9879":20,"\u6d4b\u8bd5":33,"\u6e05\u7406":20,"\u73af\u5883\u51c6\u5907":31,"\u751f\u6210\u5e8f\u5217":42,"\u751f\u6210\u6d41\u7a0b\u7684\u4f7f\u7528\u65b9\u6cd5":41,"\u7684\u533a\u522b":12,"\u7684\u53c2\u6570":12,"\u7684\u65b9\u6cd5\u6709\u4f55\u533a\u522b":12,"\u76f4\u63a5\u6784\u5efa":7,"\u76f8\u5173\u6982\u5ff5":41,"\u77e9\u9635":33,"\u793a\u4f8b1":39,"\u793a\u4f8b2":39,"\u793a\u4f8b3":39,"\u793a\u4f8b4":39,"\u795e\u7ecf\u5143\u6fc0\u6d3b\u5185\u5b58":11,"\u7a00\u758f\u8bad\u7ec3":35,"\u7aef\u6570\u636e\u7c7b\u578b\u8bf4\u660e":19,"\u7b80\u5355\u95e8\u63a7\u5faa\u73af\u795e\u7ecf\u7f51\u7edc":42,"\u7c7b":6,"\u7ebf\u6027\u56de\u5f52\u5b8c\u6574\u793a\u4f8b":14,"\u7ec4\u7ec7\u5e8f\u5217\u4fe1\u606f":19,"\u7ec4\u7ec7\u8f93\u5165\u6570\u636e":[19,20],"\u7ec6\u8282\u63cf\u8ff0":33,"\u7ec8\u6b62\u96c6\u7fa4\u4f5c\u4e1a":23,"\u7f16\u5199\u9884\u6d4b\u4ee3\u7801":20,"\u7f16\u5199yaml\u6587\u4ef6":26,"\u7f16\u8bd1\u4f9d\u8d56":0,"\u7f16\u8bd1\u5b89\u88c5\u4e0e\u5355\u5143\u6d4b\u8bd5":8,"\u7f16\u8bd1\u5b89\u88c5\u540e\u6267\u884c":8,"\u7f16\u8bd1\u65b9\u6cd5":0,"\u7f16\u8bd1\u9009\u9879":0,"\u7f16\u8bd1\u9009\u9879\u7684\u8bbe\u7f6e":0,"\u7f16\u8bd1\u9009\u9879\u8bf4\u660e":0,"\u81ea\u7136\u8bed\u8a00\u5904\u7406":33,"\u83b7\u53d6paddlepaddle\u7684docker\u955c\u50cf":1,"\u8bad\u7ec3":33,"\u8bad\u7ec3\u56e0\u6b64\u9000\u51fa\u600e\u4e48\u529e":11,"\u8bad\u7ec3\u6a21\u578b":14,"\u8bad\u7ec3\u6d41\u7a0b\u7684\u4f7f\u7528\u65b9\u6cd5":41,"\u8bad\u7ec3\u8fc7\u7a0b\u4e2d\u51fa\u73b0":11,"\u8bcd\u6c47\u8868":39,"\u8be6\u7ec6\u6559\u7a0b":37,"\u8bfb\u53d6\u53cc\u5c42\u5e8f\u5217\u6570\u636e":39,"\u8f93\u5165":[19,41],"\u8f93\u5165\u4e0d\u7b49\u957f":39,"\u8f93\u5165\u793a\u4f8b":41,"\u8f93\u51fa":41,"\u8f93\u51fa\u6570\u636e":19,"\u8f93\u51fa\u6570\u636e\u7c7b\u578b":19,"\u8f93\u51fa\u6570\u636e\u7ec4\u7ec7":19,"\u8fd0\u884c\u5bb9\u5668":26,"\u8fd0\u884c\u73af\u5883\u4f9d\u8d56":3,"\u8fd0\u884cdocker":8,"\u8fdb\u884c\u8bad\u7ec3":26,"\u8fdb\u9636\u4f7f\u7528":36,"\u901a\u7528":33,"\u9047\u5230":8,"\u914d\u7f6e\u5faa\u73af\u795e\u7ecf\u7f51\u7edc\u67b6\u6784":42,"\u914d\u7f6e\u7f51\u7edc":14,"\u94a9\u5b50":4,"\u94fe\u63a5\u8bf4\u660e":17,"\u9519\u8bef\u600e\u4e48\u529e":12,"\u9644\u5f55":0,"\u968f\u673a\u6570":33,"\u96c6\u7fa4\u591a\u8282\u70b9\u8bad\u7ec3":9,"\u96c6\u7fa4\u8bad\u7ec3":35,"\u96c6\u7fa4\u8bad\u7ec3\u4e0e\u9884\u6d4b":9,"\u9700\u8981\u7684\u8f6f\u786c\u4ef6":0,"\u975e\u6cd5\u6307\u4ee4":8,"api\u4f7f\u7528\u6d41\u7a0b":20,"api\u5bf9\u6bd4\u4ecb\u7ecd":39,"api\u9884\u6d4b\u5e93":[17,18],"beam_search\u7684\u751f\u6210":39,"book\u6559\u7a0b":1,"cmake\u6e90\u7801\u7f16\u8bd1":8,"float":11,"gpu\u548ccpu\u6df7\u5408\u4f7f\u7528":35,"gpu\u6027\u80fd\u8c03\u4f18":37,"gpu\u955c\u50cf\u51fa\u73b0":8,"group\u6559\u7a0b":41,"import":8,"kubernetes\u5206\u5e03\u5f0f\u8bad\u7ec3":27,"kubernetes\u5355\u673a\u8bad\u7ec3":26,"org\u5de5\u5177":7,"paddle\u7248\u672c\u53f7\u4e3a0":8,"paddlepaddle\u662f\u5426\u652f\u6301\u7ef4\u6570\u53ef\u53d8\u7684\u6570\u636e\u8f93\u5165":12,"paddlepaddle\u73af\u5883\u4f9d\u8d56":3,"paddlepaddle\u7684softmax\u80fd\u5426\u6307\u5b9a\u8ba1\u7b97\u7684\u7ef4\u5ea6":12,"paddlepaddle\u7f16\u8bd1\u4f9d\u8d56":0,"pod\u95f4\u901a\u4fe1":27,"python\u76f8\u5173\u7684\u5355\u5143\u6d4b\u8bd5\u90fd\u8fc7\u4e0d\u4e86":8,"rnn\u6a21\u578b":40,"rnn\u914d\u7f6e":42,AWS:25,DNS:25,EFS:25,KMS:25,access:25,account:25,add:25,address:25,anneal:13,asset:25,associ:25,async:33,attent:42,aws:25,becaus:13,big:13,bla:0,bucket:25,choos:25,clone:4,cloudform:25,cluster:25,commit:4,concept:25,configur:25,content:[8,9,11,12,13,25,37,38],core:25,creat:25,credenti:25,cuda:[0,8],cudnn:0,data:25,dataprovid:33,defin:25,delet:25,demo:25,destroi:25,directori:25,distribut:25,down:25,download:25,driver:8,drop_out:12,duplic:12,ec2:25,elast:25,except:11,expand:38,extern:25,faq:10,file:25,find:25,first_seq:38,fork:4,gate:42,gpu:33,group:25,gru:33,iam:25,illeg:8,infer:11,initi:25,inspect:25,instal:25,instanc:25,instruct:8,insuffici:8,integr:25,issu:4,job:[25,26],kei:25,kube:25,kubectl:25,kubernet:[25,26],last_seq:38,layer:12,learn:13,local:25,lstm:33,memori:[12,39,41],messag:13,model:42,modul:8,name:[8,12,25],network:42,neural:42,nlp:33,nvprof:37,nvvp:37,org:7,output:25,paddl:[8,12],paddlepaddl:[7,8,25,43],pair:25,parallel_nn:35,paramet:25,perform:33,platform:8,point:[11,25],pool:38,pre:4,prepar:25,privat:25,protocol:13,pull:4,push:4,python:19,rate:13,recurr:[12,41,42],region:25,reject:13,render:25,request:4,rnn:[33,39],route53:25,secur:25,sequenc:42,server:25,servic:25,setup:25,sgd:[21,33],start:25,step2:20,step:20,support:8,system:25,tear:25,templat:25,thi:8,too:13,train:25,trainer:25,tune:33,updat:25,verifi:25,version:8,volum:25,vpc:25,wheel:8,whl:8}}) \ No newline at end of file diff --git a/develop/doc_cn/survey/cluster_bootstrapping_tools.html b/develop/doc_cn/survey/cluster_bootstrapping_tools.html deleted file mode 100644 index c3356f9b53b..00000000000 --- a/develop/doc_cn/survey/cluster_bootstrapping_tools.html +++ /dev/null @@ -1,365 +0,0 @@ - - - - - - - - - - - - - Cluster bootstrapping tool survey — PaddlePaddle 文档 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                                  - - - - -
                                                                  - - - - - - -
                                                                  -
                                                                  - - - - - - -
                                                                  - -
                                                                  -
                                                                  -
                                                                  -
                                                                  - -
                                                                  -

                                                                  Cluster bootstrapping tool survey

                                                                  -
                                                                  -

                                                                  Abstract

                                                                  -

                                                                  In order to bring up a cluster from bare metal machine to a fully functional kubernetes cluster for Paddlepaddle to run, we need to utilize some tools. Here we are going to compare Sextant and Tectonic installer

                                                                  -
                                                                  -
                                                                  -

                                                                  Basic assumptions

                                                                  -

                                                                  Here are some basic assumptions before we move on to details

                                                                  -
                                                                    -
                                                                  1. You are an administrator of a bare metal machine cluster, which means:
                                                                  2. -
                                                                  -
                                                                    -
                                                                  • you have full control to each of the machines.
                                                                  • -
                                                                  • you have full control to the network which machines are connected to.
                                                                  • -
                                                                  -
                                                                    -
                                                                  1. Machines can be booted from network with PEX or iPXE
                                                                  2. -
                                                                  3. You understand the general procedure to bring up a cluster
                                                                  4. -
                                                                  -

                                                                  if your cluster is able to mark above items with checkmarks, then keep reading.

                                                                  -
                                                                  -
                                                                  -

                                                                  Comparing Sextant and Tectonic installer

                                                                  -
                                                                  -

                                                                  Sextant

                                                                  -

                                                                  Sextant is an end2end solution to bring up a bare metal cluster to a fully functional k8s cluster, it integrates DHCP, name service, PEX, cloud-config-service, docker registry services altogether.

                                                                  -
                                                                  -

                                                                  Pros

                                                                  -
                                                                    -
                                                                  1. End2End: basically all admin need to do is to config the cluster.yaml and power on the cluster.
                                                                  2. -
                                                                  3. Offline cluster configuration: Sextant has 2 phases during working with it, config time and deploy time. when admin is configuring, it requires admin’s machine has internet connectivity, which will download some images, etc. But in deploy time, it’s completely OK to go offline since all dependencies are ready during config time.
                                                                  4. -
                                                                  5. docker registry integrated.
                                                                  6. -
                                                                  7. GPU machine took care of.
                                                                  8. -
                                                                  -
                                                                  -
                                                                  -
                                                                  -

                                                                  Cons

                                                                  -
                                                                    -
                                                                  1. k8s API server is not deployed with high availability in considering by default.
                                                                  2. -
                                                                  3. No grouping support.
                                                                  4. -
                                                                  5. No API interface, a one-off service.
                                                                  6. -
                                                                  -
                                                                  -
                                                                  -

                                                                  Tectonic installer

                                                                  -

                                                                  First of all, Tectonic is not free, it requires coreos.com account as a step of installation, and free user can only create less than 10 nodes.

                                                                  -

                                                                  Tectonic is a suite of software which wraps around k8s and providing more utility regarding dev ops, ie, -Tectonic installer as it’s named, it installs Tectonic to a bare metal cluster which means it’s not totally an equivalent of Sextant. At the “booting a cluster” part, it mostly utilizes Matchbox, which is a general cluster bootstrapper.

                                                                  -

                                                                  Matchbox’s Approach is similar to Sexstant.

                                                                  -
                                                                  -
                                                                  -

                                                                  Pros

                                                                  -
                                                                    -
                                                                  1. supports grouping machines.
                                                                  2. -
                                                                  3. supports running provisioning service in rtk. (not a big deal though).
                                                                  4. -
                                                                  5. supports http/gRPC API interface.
                                                                  6. -
                                                                  7. supports multi-template.
                                                                  8. -
                                                                  -
                                                                  -
                                                                  -

                                                                  Cons

                                                                  -
                                                                    -
                                                                  1. Not an e2e solution to bring up a cluster, need a lot of extra work and other software.
                                                                  2. -
                                                                  3. Not fully supporting centOS deployment yet.
                                                                  4. -
                                                                  -
                                                                  -
                                                                  -
                                                                  -

                                                                  Conclusion

                                                                  -

                                                                  Sextant is a better solution overall for paddle cloud deploying to a bare metal cluster. It would be great if Sextant can also 1) deploy k8s api server with high availability by default; 2) not designed as a one-off service.

                                                                  -
                                                                  -
                                                                  -

                                                                  Appendix: General procedure to bring up a cluster

                                                                  -

                                                                  It’s physically impossible for a cluster admin to manually install OS and applications into cluster nodes one by one, here is what an admin would do in cloud industry:

                                                                  -
                                                                    -
                                                                  1. setup a bootstrap machine with static IP in the cluster, which has following services:
                                                                  2. -
                                                                  -
                                                                    -
                                                                  • DHCP: assigns ip address for rest of the nodes.
                                                                  • -
                                                                  • name service: to map node name to a IP
                                                                  • -
                                                                  • PXE related services: the booting related info will be delivered to newly booted machines as their IP is assigned via DHCP service, PXE service will provide further booting and installing info and image with TFTP and http protocol.
                                                                  • -
                                                                  • cluster config service: this is for providing cluster node with OS config via http
                                                                  • -
                                                                  • optional docker registry: a built-in docker registry makes the whole cluster independent from connecting internet, and speeds up software distribution.
                                                                  • -
                                                                  -
                                                                    -
                                                                  1. New node powers on, it will
                                                                  2. -
                                                                  -
                                                                    -
                                                                  • broadcast the request for an IP address
                                                                  • -
                                                                  • DHCP server assigns the IP address, and deliver the PXE booting related info to the node.
                                                                  • -
                                                                  • cluster node will request config files with booting info delivered with DHCP via the TFTP service, and in most of the cases, the config file will point to a http service for the booting image.
                                                                  • -
                                                                  • Since PXE is configured with initrd, it will utilize the cloud config service and do further installations like coreOS or K8s installations.
                                                                  • -
                                                                  • then restart the node.
                                                                  • -
                                                                  -

                                                                  For further understanding, following 2 links from Matchbox are some good readings:

                                                                  - -
                                                                  -
                                                                  - - -
                                                                  -
                                                                  -
                                                                  - - -
                                                                  - -
                                                                  -

                                                                  - © Copyright 2016, PaddlePaddle developers. - -

                                                                  -
                                                                  - Built with Sphinx using a theme provided by Read the Docs. - -
                                                                  - -
                                                                  -
                                                                  - -
                                                                  - -
                                                                  - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file -- GitLab