kernel_hint_design.md 2.4 KB
Newer Older
Q
qiaolongfei 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
## 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 use a CPU kernel, `use_cudnn` to choose a CUDNN kernel, we need to provide a way for a user 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 come from the input tensor of the operator, `GetActualKernelType(inputs)` use inputs to infer the proper kernel key that fit the incoming data, user can not config it.

The design also provides a virtual method `GetExpectedKernelType` that user can overload and 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
Q
qiaolongfei 已提交
22 23

### potential choice
Q
qiaolongfei 已提交
24 25 26 27
1, Do nothing, let the user add the information they want to operator‘s attribute and get them inside `GetExpectedKernelType`, this can work right. 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` for CPU kernel, and `use_cudnn`, `force_cudnn`, `cudnn_kernel` for use of 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.

Q
qiaolongfei 已提交
28
### final choice
Q
qiaolongfei 已提交
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
To provide enough flexibility while avoiding confusion definition, we can predefine some options, such as `force_cpu`, `use_cudnn`, `use_mkldnn` for a user to choose.

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

KernelType GetExpectedKernelTyp() {
    // "kernel_hint" is a user defined attribute name
	if (Attr<std::string>("kernel_hint") == kForceCPU) {
		return KernelType(CPUPlace, ...)
	} else {
		...
	}
}
```

In Python code

```python
def xx_layer(..., kernel_hint=None):
	layer_helper = ...
	layer_helper .append_op(
		type="xx",
		# "kernel_hint" should be the same with the attr name in CPP
		attr={"kernel_hint": kernel_hint or ""})
```