-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6790 from jacquesqiao/kernel-hint-design
Kernel hint design
- Loading branch information
Showing
1 changed file
with
57 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
## 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<bool>(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}) | ||
``` |