-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ExecutionPlan design. #6078
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
|
||
## 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 PaddlePaddle program consists of three parts -- the first generates a `ProgramDesc` protobuf message that describes the program, the second plans this message using a C++ class `Planner` and generates an `ExecutionPlan` protobuf messages, and the third run the message using a C++ class `Executor`. | ||
|
||
A simple example PaddlePaddle program can be found in [graph.md](./graph.md): | ||
|
||
|
@@ -15,7 +15,64 @@ 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. | ||
The first five lines of the following PaddlePaddle program generates, | ||
or, compiles, the `ProgramDesc` message. The last line runs it by | ||
generating the `ExecutionPlan` and sending to `Executor` for | ||
execution. | ||
|
||
|
||
### ProgramDesc | ||
|
||
The `ProgramDesc` describes the computation specified by the user, it | ||
will be the same regardless which devices the program runs on | ||
(CPU/single GPU/multiple GPU/multiple nodes), with the following | ||
requirements: | ||
|
||
1. It should be programming language agnostic. Currently, we have a | ||
Python API that generates the `ProgramDesc`, but we could add the | ||
support for other languages later. | ||
|
||
1. It should **not** describe anything that is not specified by the | ||
user. For example: | ||
1. The OPs for the backward pass added by PaddlePaddle | ||
1. Any optimizations to the program. | ||
1. OP placement information that is not specified by the user. | ||
|
||
|
||
### ExecutionPlan | ||
|
||
The `ExecutionPlan` contains all the details of running the program, | ||
including which device each OP is placed on. One `Executor` could have | ||
multiple devices (e.g, CPU, GPUs), but it runs only one | ||
`ExecutionPlan`. In distributed training there will be `n` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. available devices for distributed training are dynamic, should this plan be generated every time when available devices change (device added/removed/updated)? how are we going to efficiently deploy it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes this should be generated every time when available devices change. Currently in distributed training we can have a constant number of trainers/pservers, I think it's a good starting point. |
||
`ExecutionPlan` for `n` `Executor`, jointly completes the | ||
`ProgramDesc` specified by the user. | ||
|
||
|
||
### Planner | ||
|
||
The planner takes `ProgramDesc` as the input and outputs the | ||
`ExcutionPlan`, the steps are: | ||
|
||
1. Add necessary OPs that are not specified by the user to the | ||
`ProgramDesc`. E.g., add the backward pass. | ||
|
||
1. Prune the unnecessary computations from the `ProgramDesc`. | ||
|
||
1. Transforms the `ProgramDesc` given the available devices. E.g., add | ||
data parallelism by splitting the input mini-batches and | ||
replicating the OPs onto different GPUs. | ||
|
||
1. Generate `ExecutionPlan` by placing each OP onto available devices, | ||
the placement information is written in the `ExecutionPlan`. | ||
|
||
1. In distributed training, split the `ExecutionPlan` into multiple | ||
`ExecutionPlans` and add send/recv OP between them. For local | ||
training, this step is not necessary since there is only one | ||
executor. | ||
|
||
1. Send the `ExecutionPlan` to the executor for execution. | ||
|
||
|
||
## Programs and Blocks | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -143,3 +143,13 @@ message BlockDesc { | |
// https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/program.md | ||
// for more details. | ||
message ProgramDesc { repeated BlockDesc blocks = 1; } | ||
|
||
message OpPlacement { | ||
optional string name = 1; | ||
optional string device = 2; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am also wondering if device info for Operator is enough. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
So, this a only one case which we should set device for variable. For other cases, the variable device can be decided by operator's device info. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @QiJune thanks, great question, I guess we need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Isn't the data initially CPU, and copied to GPU implicitly when needed, since we don't do explicit copies, maybe we don't need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not put There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we also need to allow users the specify the device information by two approaches:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The In the future when we have that API we can add it to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's fine to add it to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @typhoonzero I think Since there are two entities: In the future when we want enable the user to configure which device an OP runs, we can put the field indicating device in Maybe I need to change message ExecutionPlan {
repeated BlockDesc blocks = 1;
repeated OpPlacement op_placement = 2;
} What do you think? |
||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can add a detail example in comment. message OpPlacement {
// pserver:gpu0
optional string name = 1;
optional string device = 2;
}
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the "pserver" in "pserver:gpu0" is not necessary, the executor does not need to know what role (e.g., pserver) it takes. Maybe only "gpu0" is sufficient. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. bit confused how would There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
message ExecutionPlan { | ||
repeated BlockDesc blocks = 1; | ||
repeated OpPlacement op_placement = 2; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should there be a way of exporting ProgramDesc? so that user can share it, like
export(cost, SAVE_TO_PATH)
? how we are going to differentiate saving algorithm(ProgramDesc) from saving model?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a model should be saved separately:
ProgramDesc
and the weights. So that the weights can be re-used for differentProgramDescs
.Maybe saving model is not strictly related to this PR, we can discuss more in a separate issue if we wish :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree, thanks:)