Skip to content

Commit 7bef85e

Browse files
pytorchbotlucylq
andauthored
Update kernels readme (#4274) (#4280)
Summary: Pull Request resolved: #4274 Update kernels readme with Cmake instructions. Major changes are: 1. Instructions to generate the operator function signature with cmake instead of buck. 2. Instructions to build and test the operator with cmake. 3. Update links from buck to cmake, internal to oss Move existing buck instructions to fb/ directory. Reviewed By: larryliu0820, kirklandsign Differential Revision: D59784834 fbshipit-source-id: 4a73c43b57ce3d87fa8e162b2e5417ba068f0c45 (cherry picked from commit 7d6c8fc) Co-authored-by: Lucy Qiu <[email protected]>
1 parent 3340b15 commit 7bef85e

File tree

1 file changed

+95
-116
lines changed

1 file changed

+95
-116
lines changed

kernels/README.md

Lines changed: 95 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
This subtree contains operator implementations that ExecuTorch clients can
2-
use and contribute to.
1+
This subtree contains operator implementations that ExecuTorch clients can use and
2+
contribute to. For internal users, please see `executorch/kernels/fb/README.md`.
33

44
## Layout
55

@@ -51,16 +51,6 @@ built against ATen/c10. But, there are features of `at::Tensor` and other
5151
ATen/c10 types that may not be present. In many cases this is intentional, but
5252
in other cases we can consider adding the missing features.
5353

54-
### Do your initial work in fbcode (skip this if in OSS)
55-
56-
Although ExecuTorch is mapped into both `xplat` and `fbcode`, we recommend
57-
setting up the initial targets while working from `fbcode`. Once everything's in
58-
place, you should be able to build from either spot.
59-
60-
The most important thing is to consistently work out of one root or the other.
61-
And, if you're getting weird build failures, `hg commit` your edited files
62-
locally to make sure that both `xplat` and `fbcode` are in sync with each other.
63-
6454
### Declare the operator in a YAML file
6555

6656
We use yaml files to declare the ATen operators or custom operators being implemented by this kernel library.
@@ -189,68 +179,50 @@ When using macros that require a `NAME` argument, eg. `#define ET_SWITCH_REAL_TY
189179

190180
### Overview of files and targets
191181

192-
For the operator base name `<name>`, you should work with these files and Buck
193-
targets. Sections below give more details about what they should contain.
182+
For the operator base name `<name>`, you should work with these files. Sections below give more details about what they should contain.
194183

195184
- `./kernels/portable/cpu/op_<name>.cpp`: The implementations of operator overloads
196185
with base name `<name>`. This is the file that clients will link into their
197186
runtimes.
198-
- `//executorch/kernels/portable/cpu:op_<name>`: The build target for
199-
`op_<name>.cpp`, defined in `targets.bzl` in the same directory.
187+
- `./kernels/portable/CMakeLists.txt`: The CMake build file for all the
188+
`op_<name>.cpp` files in the same directory.
200189
- `./kernels/test/op_<name>_test.cpp`: Unit tests for the operator overloads
201190
with base name `<name>`.
202191
- Note that tests under this directory are for portable kernel specific. To
203192
share tests between multiple kernels, we can put tests in ../test.
204193
- Note that the tests do not live under `cpu`; tests should be
205194
implementation-agnostic. This will let us run the same tests against all
206195
implementations of a given operator, which should behave identically.
207-
- `//executorch/kernels/portable/test:op_<name>_test`: The test target for
208-
`op_<name>_test.cpp`, defined in `targets.bzl` in the same directory.
196+
- `./kernels/test/CMakeLists.txt`: The CMake build file for all the
197+
`op_<name>_test.cpp` files in the same directory.
209198

210199
For an example, see the `add` operator (note that these are slightly different
211200
from the `add` examples in this doc):
212-
- [`//executorch/kernels/portable/cpu/op_add.cpp`](https://www.internalfb.com/code/fbsource/fbcode/executorch/kernels/portable/cpu/op_add.cpp):
201+
- [`executorch/kernels/portable/cpu/op_add.cpp`](https://github.com/pytorch/executorch/blob/main/kernels/portable/cpu/op_add.cpp):
213202
Implementations.
214-
- [`//executorch/kernels/portable/cpu/targets.bzl`](https://www.internalfb.com/code/fbsource/fbcode/executorch/kernels/portable/cpu/targets.bzl):
215-
Definition of the `:op_add` target.
216-
- [`//executorch/kernels/portable/test/op_add_test.cpp`](https://www.internalfb.com/code/fbsource/fbcode/executorch/kernels/portable/test/op_add_test.cpp):
203+
- [`./kernels/portable/CMakeLists.txt`](https://github.com/pytorch/executorch/blob/main/kernels/portable/CMakeLists.txt):
204+
Build portable ops.
205+
- [`executorch/kernels/portable/test/op_add_test.cpp`](https://github.com/pytorch/executorch/blob/main/kernels/test/op_add_test.cpp):
217206
Unit tests.
218-
- [`//executorch/kernels/portable/test/targets.bzl`](https://www.internalfb.com/code/fbsource/fbcode/executorch/kernels/portable/test/targets.bzl):
219-
Definition of the `:op_add_test` target.
220-
221-
### Define the build target for the operator implementation
222-
223-
Define a build target by adding an entry to
224-
`//executorch/kernels/portable/cpu/targets.bzl`, inside
225-
`define_common_targets()`, in sorted order with other `_op_target` entries:
226-
```
227-
_op_target(name = "op_<name>")
228-
```
207+
- [`./kernels/test/CMakeLists.txt`](https://github.com/pytorch/executorch/blob/main/kernels/test/CMakeLists.txt):
208+
Build kernel tests.
229209

230-
If your operator overload group is ATen-compatible, its `_op_target` entry
231-
belongs in the `_ATEN_OPS` list, otherwise it belongs in the `_CUSTOM_OPS` list.
232-
Note that this means that a given `op_<name>` cannot implement both
233-
ATen-compatible and non-ATen-compatible (i.e., custom) operators. We suggest
234-
adding the suffix `_custom` if necessary: e.g., `op_add` for ATen-compatible
235-
overloads of the `add` operator, and `op_add_custom` for non-ATen-compatible
236-
overloads.
210+
### Add the operator implementation to CMakeLists.txt
237211

238-
By default, this target will depend on the core ExecuTorch types, but you can
239-
add additional deps if you want to.
212+
The portable operator files are collected by [`./kernels/portable/CMakeLists.txt`](https://github.com/pytorch/executorch/blob/main/kernels/portable/CMakeLists.txt) with a glob on `./kernels/portable/cpu/*.cpp`. Ensure your operator file is in that directory.
240213

241-
NOTE: An `op_<name>` target may not depend on another `op_<name>` target. If two
242-
`op_` targets need to share code, define a separate `runtime.cxx_library` target
243-
under `//executorch/kernels/portable/cpu/lib` that they both depend on. This
244-
keeps the dependencies more managable, especially for selective builds where
245-
only a subset of operators are used.
214+
NOTE: a given `op_<name>` cannot implement both ATen-compatible and
215+
non-ATen-compatible (i.e., custom) operators. We suggest adding the suffix
216+
`_custom` if necessary: e.g., `op_add` for ATen-compatible overloads of
217+
the `add` operator, and `op_add_custom` for non-ATen-compatible overloads.
246218

247-
NOTE: An `op_<name>` target may not depend on targets outside of `//executorch`.
219+
NOTE: An `op_<name>` may not have dependencies outside of `//executorch`.
248220
This library is intended to be portable, open-sourceable, and self-contained.
249221

250222
### Create a skeleton .cpp file for the operator implementation
251223

252224
If not already present, create the file
253-
`//executorch/kernels/portable/cpu/op_<name>.cpp`, which should follow the
225+
`executorch/kernels/portable/cpu/op_<name>.cpp`, which should follow the
254226
pattern:
255227
```
256228
// Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -271,39 +243,30 @@ namespace {
271243
} // namespace torch
272244
```
273245

274-
With the target and cpp file in place, you should be able to build it:
275-
```
276-
cd ${HOME}/fbsource/fbcode/executorch
277-
buck build fbcode//executorch/kernels/portable/cpu:op_<name>
278-
```
279-
280246
### Find the function signature for the operator overload
281247

282248
When you add an entry to the YAML file, the codegen tools will generate an
283249
expected function signature for you to implement in a file called
284-
`NativeFunctions.h`.
250+
`NativeFunctions.h`. To build and find that generated header:
285251

286-
To build and find that generated header, run the script
287-
`fbsource/fbcode/executorch/kernels/portable/find_op_header.sh`. It will print
288-
output like:
252+
1. Build executorch
289253
```
290-
===== Generating header files =====
291-
File changed: fbcode//executorch/kernels/portable/functions.yaml
292-
Buck UI: https://www.internalfb.com/buck2/e5a6f22a-5b6e-4931-9a7f-df18bdf97ab6
293-
RE Session: reSessionID-4b735cfa-e66f-43d8-a73b-94f22d5936c5
294-
Jobs completed: 3. Time elapsed: 0.2s. Cache hits: 100%. Commands: 1 (cached: 1, remote: 0, local: 0)
295-
BUILD SUCCEEDED
296-
297-
Header file: /data/users/USER/fbsource/buck-out/v2/gen/fbcode/d839c731f5505c62/executorch/codegen/__generated_lib_generate__/out/NativeFunctions.h
254+
cmake -DCMAKE_INSTALL_PREFIX=cmake-out \
255+
-DCMAKE_BUILD_TYPE=Release \
256+
-DPYTHON_EXECUTABLE=python \
257+
-Bcmake-out .
258+
cmake --build cmake-out -j9 --target install --config Release
298259
```
299-
The path will be different in your environment, so be sure to use the output
300-
from the script instead of copy-pasting this path. And, since this header is
301-
generated from the YAML files, re-run the script if you have modified your
260+
2. The generated `NativeFunctions.h` file is located in
261+
```
262+
cmake-out/kernels/portable/portable_ops_lib/NativeFunctions.h
263+
```
264+
265+
Since this header is generated from the YAML files, re-run the script if you have modified your
302266
operator's entry in those files.
303267

304-
Open that file and look for the function with the same name that you earlier
305-
added under `CPU: dispatch:` in the YAML file. For `add_out`, this might look
306-
like
268+
Open the file and look for the function with the same name that you earlier
269+
added in the YAML file. For `add_out`, this might look like
307270
```
308271
TORCH_API torch::executor::Tensor & add_out(const at::Tensor & self, const at::Tensor & other, at::Tensor & out);
309272
```
@@ -325,31 +288,10 @@ Tensor& add_out(
325288

326289
Note that you should drop the `TORCH_API` attribute, and should drop `at::`.
327290

328-
Try building again with
329-
```
330-
cd ${HOME}/fbsource/fbcode/executorch
331-
buck build fbcode//executorch/kernels/portable/cpu:op_<name>
332-
```
333-
334-
### Create a test build target
335-
336-
Define a test build target by adding an entry to
337-
`//executorch/kernels/portable/test/targets.bzl`, inside
338-
`define_common_targets()`, in sorted order with other `_op_test` entries:
339-
```
340-
_op_target(name = "op_<name>_test")
341-
```
342-
343-
By default, this target will depend on
344-
`//executorch/kernels/portable/cpu:op_<name>`, the core Executor types, and
345-
some helper test utilities ([see
346-
headers](https://www.internalfb.com/code/fbsource/fbcode/executorch/runtime/core/exec_aten/testing_util/)),
347-
but you can add additional deps if you want to.
348-
349291
### Create a skeleton test .cpp file
350292

351293
If not already present, create the file
352-
`//executorch/kernels/portable/test/op_<name>_test.cpp`. Here's a suggested
294+
`executorch/kernels/portable/test/op_<name>_test.cpp`. Here's a suggested
353295
starting point:
354296
```
355297
// Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -383,23 +325,70 @@ TEST(Op<Name>Test, SmokeTest) {
383325
}
384326
```
385327

386-
Try running the test:
387-
```
388-
cd ${HOME}/fbsource/fbcode/executorch
389-
buck test fbcode//executorch/kernels/test:op_<name>_test
390-
```
328+
### Add operator test to CMakeLists.txt
329+
330+
Now, we have to add this to [executorch/kernels/tests/CMakeLists.txt](https://github.com/pytorch/executorch/blob/main/kernels/test/CMakeLists.txt). Note that this builds all the kernel tests.
331+
332+
For portable kernels, add your test file to [`all_test_sources`](https://github.com/pytorch/executorch/blob/main/kernels/test/CMakeLists.txt#L69).
333+
334+
For optimized kernels, add your test file to [`_optimized_kernels_test_sources](https://github.com/pytorch/executorch/blob/main/kernels/test/CMakeLists.txt#L230).
391335

392336
### Implement and test the operator
393337

394338
You should now be able to implement and test your operator. It's helpful to see
395339
how other operators do it, so take a look at `op_add`:
396-
- [`//executorch/kernels/portable/cpu/op_add.cpp`](https://www.internalfb.com/code/fbsource/fbcode/executorch/kernels/portable/cpu/op_add.cpp)
397-
- [`//executorch/kernels/portable/test/op_add_test.cpp`](https://www.internalfb.com/code/fbsource/fbcode/executorch/kernels/portable/test/op_add_test.cpp)
340+
- [`executorch/kernels/portable/cpu/op_add.cpp`](https://github.com/pytorch/executorch/blob/main/kernels/portable/cpu/op_add.cpp)
341+
- [`executorch/kernels/portable/test/op_add_test.cpp`](https://github.com/pytorch/executorch/blob/main/kernels/test/op_add_test.cpp):
398342

399343
Check out how it uses helper macros like `ET_CHECK_SAME_SHAPE_AND_DTYPE` and
400344
`ET_FORALL_REAL_TYPES` when implementing the operator, and test helpers like
401345
`TensorFactory` and `IsCloseTo()` when testing.
402346

347+
Once you have your operator and corresponding tests in place, we can try it out.
348+
349+
1. Build ExecuTorch.
350+
```
351+
cmake . \
352+
-DCMAKE_INSTALL_PREFIX=cmake-out \
353+
-DEXECUTORCH_USE_CPP_CODE_COVERAGE=ON \
354+
-DEXECUTORCH_BUILD_KERNELS_OPTIMIZED=ON \
355+
-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \
356+
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
357+
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
358+
-DEXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL=ON \
359+
-DEXECUTORCH_BUILD_SDK=ON \
360+
-DEXECUTORCH_BUILD_VULKAN=OFF \
361+
-DEXECUTORCH_BUILD_XNNPACK=ON \
362+
-Bcmake-out
363+
364+
cmake --build cmake-out -j9 --target install
365+
```
366+
2. Build gtest.
367+
```
368+
mkdir -p third-party/googletest/build
369+
cd third-party/googletest/build
370+
cmake .. -DCMAKE_INSTALL_PREFIX=.
371+
make -j4
372+
make install
373+
cd ../../../
374+
```
375+
376+
3. Build kernel tests.
377+
```
378+
cmake kernels/test \
379+
-DCMAKE_BUILD_TYPE=Debug \
380+
-DCMAKE_INSTALL_PREFIX=cmake-out \
381+
-DEXECUTORCH_USE_CPP_CODE_COVERAGE=ON \
382+
-DCMAKE_PREFIX_PATH="$(pwd)/third-party/googletest/build" \
383+
-Bcmake-out/kernels/test
384+
cmake --build cmake-out/kernels/test -j9
385+
```
386+
4. Run tests. You should see your test here.
387+
```
388+
./cmake-out/kernels/test/portable_kernels_test
389+
./cmake-out/kernels/test/optimized_kernels_test
390+
```
391+
403392
#### Implementation restrictions
404393

405394
To reduce dependencies and size, to ensure portability, and to conform to the
@@ -437,22 +426,12 @@ target-specific APIs to do so. But, since this library is only for portable
437426
operator implementations, the operators it contains can't depend on
438427
target-specific APIs like that.
439428

440-
### Shared kernel tests (//executorch/kernels/test)
441-
The portable kernel impelemntation and its corresponding tests can be used as a
429+
### Shared kernel tests (executorch/kernels/test)
430+
The portable kernel implementation and its corresponding tests can be used as a
442431
reference for other kernels. We can also share the test cases in
443432
`//executorch/kernels/test`, which contains common resources for kernel testing.
444433

445-
*util.bzl* contains common BUCK targets for other test libs to include:
446-
- op_test(): Defines a cxx_test() for an "op_*_test.cpp" file
447-
- define_supported_features_lib(): Defines the corresponding supported features library
448-
449-
*targets.bzl* has targets shared by other kernels tests:
450-
- supported_features_header: header file for SupportedFeatures
451-
- supported_features_header_aten: ATen implementation of SupportedFeatures
452-
- _codegen_function_header_wrapper: a wrapper to include the right Functions.h header
453-
- _common_op_test: generates <kernel>_<op_test>
454-
455-
*_codegen_function_header_wrapper* generates a header FunctionHeaderWrapper.h, which simply
434+
*generate_wrapper* generates a header FunctionHeaderWrapper.h, which simply
456435
includes the corresponding Functions.h file for the specified kernel:
457436
`#include <executorch/kernels/{}/Functions.h>`. With that, the test sources don't need to know
458437
about which kernel we are testing and which Functions.h we should use.
@@ -463,7 +442,7 @@ it can be used to test multiple kernels.
463442

464443
In <kernel>/test/ we can put kernel-specific test cases.
465444

466-
*SupportedFeatures* is used to distinguish between different kernel features. For example,
445+
*supported_features* is used to distinguish between different kernel features. For example,
467446
ATen supports mixing input and output dtype while portable doesn't. When we expect death in
468447
portable testing in such case, we can check the supported features by the running kernel and
469448
bypass if it's supported.

0 commit comments

Comments
 (0)