Skip to content

Commit 93a1b85

Browse files
authored
Generate 1 kernel libary with dtype selective build and used it in multiple executorch_generated_lib
Differential Revision: D75029407 Pull Request resolved: #11378
1 parent 6467251 commit 93a1b85

File tree

2 files changed

+116
-28
lines changed

2 files changed

+116
-28
lines changed

kernels/portable/cpu/util/targets.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def define_common_targets():
132132
"//executorch/runtime/core/exec_aten/util:tensor_shape_to_c_string",
133133
"//executorch/runtime/kernel:kernel_includes",
134134
],
135-
visibility = ["//executorch/kernels/portable/cpu/...", "//executorch/kernels/optimized/cpu/..."],
135+
visibility = ["//executorch/kernels/portable/cpu/...", "//executorch/kernels/optimized/cpu/...", "@EXECUTORCH_CLIENTS"],
136136
)
137137

138138
runtime.cxx_library(

shim_et/xplat/executorch/codegen/codegen.bzl

Lines changed: 115 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -444,10 +444,53 @@ def build_portable_header_lib(name, oplist_header_name, feature = None):
444444
feature = feature,
445445
)
446446

447-
def build_portable_lib(name, oplist_header_name, portable_header_lib, feature = None, expose_operator_symbols = False):
448-
"""Build portable lib from source. We build from source so that the generated header file,
449-
selected_op_variants.h, can be used to selectively build the lib for different dtypes.
447+
def build_portable_lib(
448+
name,
449+
et_operator_lib_deps = [],
450+
oplist_header_name = None,
451+
portable_header_lib = None,
452+
feature = None,
453+
expose_operator_symbols = False,
454+
visibility = ["@EXECUTORCH_CLIENTS"]):
450455
"""
456+
WARNING: Before using this, please consider using executorch_generated_lib instead. This
457+
function is only for special cases where you need to build a portable kernel library with
458+
dtype selective build enabled and also wants to share it across more than one executorch_generated_lib.
459+
Any other use case is likely wrong and you should use executorch_generated_lib instead.
460+
461+
Create a new portable kernel library based on `portable_header_lib`. `portable_header_lib`
462+
should contain the header `selected_op_variants.h` generated by `dtype_header_genrule`.
463+
464+
Notice that this is giving a library that is different than //executorch/kernels/portable/cpu:cpu,
465+
because of the generated header `selected_op_variants.h`. The original portable kernel library
466+
doesn't have that header and thus include all the dtypes possible.
467+
468+
If no `portable_header_lib` is provided, try to create one based on the deps. In this case
469+
we require `deps` to be present. Notice that this way we are always enabling dtype selective
470+
build.
471+
472+
Args:
473+
name: name of the new portable kernel library.
474+
et_operator_lib_deps: list of deps to use to create the portable header library.
475+
oplist_header_name: the name of the header genrule (dtype_header_genrule)
476+
portable_header_lib: the name of the header library (build_portable_header_lib)
477+
feature: feature to use for the new portable kernel library.
478+
expose_operator_symbols: expose operator symbols to library users. This only works in xplat.
479+
visibility: visibility of the new portable kernel library.
480+
"""
481+
482+
if not portable_header_lib:
483+
if not oplist_header_name:
484+
if not et_operator_lib_deps:
485+
fail("Either et_operator_lib_deps or oplist_header_name must be provided.")
486+
oplist_header_name = name + "_header"
487+
dtype_header_genrule(
488+
name = oplist_header_name,
489+
deps = et_operator_lib_deps,
490+
visibility = visibility,
491+
)
492+
portable_header_lib = name + "_portable_header_lib"
493+
build_portable_header_lib(portable_header_lib, oplist_header_name, feature)
451494

452495
# Copy portable cpp files.
453496
portable_source_files = []
@@ -546,6 +589,72 @@ def build_optimized_lib(name, oplist_header_name, portable_header_lib, feature =
546589
feature = feature,
547590
)
548591

592+
def selected_operators_genrule(
593+
name,
594+
deps,
595+
platforms = get_default_executorch_platforms(),
596+
):
597+
"""Generates selected_operators.yaml from the list of deps. We look into the trasitive closure of all the deps,
598+
and look for macros `et_operator_library`.
599+
600+
`gen_all_oplist` is the python binary we use to aggregate all the `et_operator_library`s into single
601+
`selected_operators.yaml` file.
602+
603+
This file can be furthur used to generate `selected_op_variants.h` (see dtype_header_genrule) for dtype
604+
selective build work.
605+
"""
606+
runtime.genrule(
607+
name = name,
608+
macros_only = False,
609+
cmd = ("$(exe fbsource//xplat/executorch/codegen/tools:gen_all_oplist) " +
610+
"--model_file_list_path $(@query_outputs \'attrfilter(labels, et_operator_library, deps(set({deps})))\') " +
611+
"--allow_include_all_overloads " +
612+
"--output_dir $OUT ").format(deps = " ".join(["\"{}\"".format(d) for d in deps])),
613+
outs = {"selected_operators.yaml": ["selected_operators.yaml"]},
614+
default_outs = ["."],
615+
platforms = platforms,
616+
)
617+
618+
def dtype_header_genrule(
619+
name,
620+
visibility,
621+
deps = [],
622+
selected_operators_genrule_name = None,
623+
platforms = get_default_executorch_platforms(),
624+
):
625+
"""Generate selected_op_variants.h from selected_operators.yaml.
626+
627+
Given a `selected_operators.yaml` (passed in as selected_operators_genrule_name), we should be able to determine
628+
what dtypes to be enabled for kernels in the kernel library. For example, `add.out` kernel needs to support
629+
both float16 and float32 etc.
630+
631+
This information is recorded in `selected_op_variants.h` and it should be used to compile a new kernel library.
632+
633+
Notice that until this stage we are kernel library agnostic, meaning the header should be applicable to any
634+
kernel library that includes it.
635+
"""
636+
if not selected_operators_genrule_name:
637+
if not deps:
638+
fail("Either deps or selected_operators_genrule_name must be provided.")
639+
selected_operators_genrule_name = name + "_selected_operators"
640+
selected_operators_genrule(
641+
name = selected_operators_genrule_name,
642+
deps = deps,
643+
)
644+
645+
runtime.genrule(
646+
name = name,
647+
macros_only = False,
648+
cmd = ("$(exe //executorch/codegen/tools:gen_selected_op_variants) " +
649+
"--yaml_file_path $(location :{}[selected_operators.yaml]) " +
650+
"--output_dir $OUT").format(selected_operators_genrule_name),
651+
outs = {"selected_op_variants": ["selected_op_variants.h"]},
652+
default_outs = ["."],
653+
platforms = platforms,
654+
visibility = visibility,
655+
_is_external_target = True,
656+
)
657+
549658
def executorch_generated_lib(
550659
name,
551660
functions_yaml_target = None,
@@ -721,32 +830,11 @@ def executorch_generated_lib(
721830

722831
# genrule for selective build from static operator list
723832
oplist_dir_name = name + "_et_oplist"
724-
runtime.genrule(
725-
name = oplist_dir_name,
726-
macros_only = False,
727-
cmd = ("$(exe fbsource//xplat/executorch/codegen/tools:gen_all_oplist) " +
728-
"--model_file_list_path $(@query_outputs \'attrfilter(labels, et_operator_library, deps(set({deps})))\') " +
729-
"--allow_include_all_overloads " +
730-
"--output_dir $OUT ").format(deps = " ".join(["\"{}\"".format(d) for d in deps])),
731-
outs = {"selected_operators.yaml": ["selected_operators.yaml"]},
732-
default_outs = ["."],
733-
platforms = platforms,
734-
)
833+
selected_operators_genrule(name = oplist_dir_name, deps = deps, platforms = platforms)
735834

736835
# genrule to generate selected_op_variants.h from selected_operators.yaml above
737836
oplist_header_name = name + "_et_op_dtype_gen"
738-
runtime.genrule(
739-
name = oplist_header_name,
740-
macros_only = False,
741-
cmd = ("$(exe //executorch/codegen/tools:gen_selected_op_variants) " +
742-
"--yaml_file_path $(location :{}[selected_operators.yaml]) " +
743-
"--output_dir $OUT").format(oplist_dir_name),
744-
outs = {"selected_op_variants": ["selected_op_variants.h"]},
745-
default_outs = ["."],
746-
platforms = platforms,
747-
visibility = visibility,
748-
_is_external_target = True,
749-
)
837+
dtype_header_genrule(name = oplist_header_name, selected_operators_genrule_name = oplist_dir_name, platforms = platforms, visibility = visibility)
750838

751839
# codegen genrule(s). For ATen mode we expect two genrules, one for ATen ops one for custom ops.
752840
for genrule_name in genrules:
@@ -777,7 +865,7 @@ def executorch_generated_lib(
777865

778866
# Build portable lib.
779867
portable_lib_name = name + "_portable_lib"
780-
build_portable_lib(portable_lib_name, oplist_header_name, portable_header_lib, feature, expose_operator_symbols)
868+
build_portable_lib(name = portable_lib_name, portable_header_lib = portable_header_lib, feature = feature, expose_operator_symbols = expose_operator_symbols)
781869
kernel_deps.append(":{}".format(portable_lib_name))
782870

783871
if "//executorch/kernels/optimized:optimized_operators" in kernel_deps:

0 commit comments

Comments
 (0)