“a87f4963edf35dcf4b203fb6e2541f04b424dc02”上不存在“paddle/fluid/operators/conditional_block_op.cc”
kernel_hint_design.md 2.4 KB
Newer Older
Q
qiaolongfei 已提交
1
## Problem
Q
qiaolongfei 已提交
2
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.
Q
qiaolongfei 已提交
3

Q
qiaolongfei 已提交
4
In the current design, we use KernelType to describe one kernel.
Q
qiaolongfei 已提交
5 6 7 8 9 10 11 12

```cpp
struct KernelType {
  Place place_;
  DataType data_type_;
  LayoutType layout_;
};
```
Q
qiaolongfei 已提交
13
 `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.
Q
qiaolongfei 已提交
14

Q
qiaolongfei 已提交
15
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.
Q
qiaolongfei 已提交
16

Q
qiaolongfei 已提交
17
So we should send the information user defined in proto to `GetExpectedKernelType` for choosing a kernel.
Q
qiaolongfei 已提交
18 19 20 21

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

## Solution
Q
qiaolongfei 已提交
22

Q
qiaolongfei 已提交
23 24
### 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.
Q
qiaolongfei 已提交
25

Q
qiaolongfei 已提交
26
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.
Q
qiaolongfei 已提交
27

Q
qiaolongfei 已提交
28 29 30 31
### 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++
Q
qiaolongfei 已提交
32 33 34 35 36 37

```cpp
const std::string kForceCPU = "force_cpu";
const std::string kUseCUDNN = "use_cudnn";
const std::string kUseMKLDNN = "use_mkldnn";

Q
qiaolongfei 已提交
38
KernelType GetExpectedKernelType() {
Q
qiaolongfei 已提交
39 40 41 42 43
  if (Attr<bool>(kForceCPU)) {
    return KernelType(CPUPlace, ...)
  } else {
    ...
  }
Q
qiaolongfei 已提交
44 45 46 47 48 49
}
```

In Python code

```python
Q
qiaolongfei 已提交
50 51 52
FORCE_CPU = core.kForceCPU()

def xx_layer(..., force_cpu=false):
Q
qiaolongfei 已提交
53 54 55 56
  layer_helper = LayerHelper(...)
  layer_helper.append_op(
    type="xx",
    attr={FORCE_CPU: force_cpu})
Q
qiaolongfei 已提交
57
```