Skip to content

Commit d465063

Browse files
committed
Update base for Update on "[ET-VK][Ez] Fix Validation Layer warnings about wrong image layout"
## Context Currently, when executing a `ComputeGraph` with prepacked tensors with [Vulkan Validation Layers](https://github.com/KhronosGroup/Vulkan-ValidationLayers) turned on, the following Validation Errors can be observed. Note that Validation Layers can be turned on by running Vulkan binaries on Mac with the `vkconfig` app opened. ``` UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout(ERROR / SPEC): msgNum: 1303270965 - Validation Error: [ UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout ] Object 0: handle = 0x7fb76dbbf988, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0x4dae5635 | vkQueueSubmit(): pSubmits[0].pCommandBuffers[0] command buffer VkCommandBuffer 0x7fb76dbbf988[] expects VkImage 0xd79c8a0000000f09[] (subresource: aspectMask 0x1 array layer 0, mip level 0) to be in layout VK_IMAGE_LAYOUT_GENERAL--instead, current layout is VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. Objects: 1 [0] 0x7fb76dbbf988, type: 6, name: NULL ``` The reason for this is that prepacked textures are written to with `WRITE` memory access during packing, which means they will be in the `VK_IMAGE_LAYOUT_GENERAL` layout. However, they will subsequently be read from during `graph.execute()`, meaning the texture will have transitioned to `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL`, but will be bound using the `VK_IMAGE_LAYOUT_GENERAL` layout. Subsequent calls to `execute()` will therefore see that the prepacked texture has been bound with the wrong layout, since after the first graph execution the texture will have the `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL` layout. The solution is to submit a no-op shader dispatch during prepacking to trigger a transition to the `READ_ONLY_OPTIMAL` layout. Differential Revision: [D55772003](https://our.internmc.facebook.com/intern/diff/D55772003/) [ghstack-poisoned]
2 parents f1badd0 + 9fd1a0e commit d465063

File tree

93 files changed

+2131
-795
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+2131
-795
lines changed

.ci/scripts/test_llama.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ EXPORTED_MODEL_NAME="${EXPORTED_MODEL_NAME}.pte"
118118
echo "Exporting ${EXPORTED_MODEL_NAME}"
119119
EXPORT_ARGS="-c stories110M.pt -p ${PARAMS} -d ${DTYPE} -n ${EXPORTED_MODEL_NAME}"
120120
if [[ "${MODE}" == "xnnpack" ]]; then
121-
EXPORT_ARGS="${EXPORT_ARGS} --pt2e_quantize xnnpack_dynamic"
121+
EXPORT_ARGS="${EXPORT_ARGS} -kv --use_sdpa_with_kv_cache -X -qmode 8da4w -G 128"
122122
fi
123123
$PYTHON_EXECUTABLE -m examples.models.llama2.export_llama ${EXPORT_ARGS}
124124

.github/workflows/apple.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,5 +157,6 @@ jobs:
157157
158158
for FILENAME in "${RUNNER_TEMP}"/frameworks-ios/*.zip; do
159159
[ -e "${FILENAME}" ] || continue
160+
shasum -a 256 "${FILENAME}"
160161
${AWS_CMD} "${FILENAME}" s3://ossci-ios/executorch/ --acl public-read
161162
done

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
buck-out/
33
cmake-out/
44
cmake-android-out/
5+
cmake-out-android/
56
cmake-ios-out/
67
ethos-u-scratch/
78
executorch.egg-info

Package.swift

Lines changed: 75 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -9,95 +9,93 @@
99

1010
import PackageDescription
1111

12-
let url = "https://ossci-ios.s3.amazonaws.com/executorch"
1312
let version = "0.1.0"
14-
let coreml_sha256 = "78d853d87be478696e56e658aa4ff17d47ae185a9a6a36316c821fa8b2d3aacd"
15-
let custom_sha256 = "f059f6716298403dff89a952a70e323c54911be140d05f2467bd5cc61aaefae3"
16-
let executorch_sha256 = "ba9a0c2b061afaedbc3c5454040a598b1371170bd9d9a30b7163c20e23339841"
17-
let mps_sha256 = "39542a8671cca1aa627102aa47785d0f6e2dfe9a40e2c22288a755057b00fbfa"
18-
let optimized_sha256 = "1d84fa16197bb6f0dec01aaa29d2a140c0e14d8e5e92630a7b4dd6f48012506d"
19-
let portable_sha256 = "4993904f89ecb4476677ff3c072ed1a314a608170f10d364cfd23947851ccbf3"
20-
let quantized_sha256 = "8d35ee0e7ca77c19782eaea07a1888f576cda679f8a4a5edb03d80ebe858047e"
21-
let xnnpack_sha256 = "380e5185c4c48ede7cc0d0f0657ffb26df83cd9f55813d78593aea8a93942caf"
22-
23-
struct Framework {
24-
let name: String
25-
let checksum: String
26-
var frameworks: [String] = []
27-
var libraries: [String] = []
28-
29-
func target() -> Target {
30-
.binaryTarget(
31-
name: name,
32-
url: "\(url)/\(name)-\(version).zip",
33-
checksum: checksum
34-
)
35-
}
36-
37-
func dependencies() -> Target {
38-
.target(
39-
name: "\(name)_dependencies",
40-
dependencies: [.target(name: name)],
41-
path: ".swift/\(name)",
42-
linkerSettings:
43-
frameworks.map { .linkedFramework($0) } +
44-
libraries.map { .linkedLibrary($0) }
45-
)
46-
}
47-
}
48-
49-
let frameworks = [
50-
Framework(
51-
name: "coreml_backend",
52-
checksum: coreml_sha256,
53-
frameworks: [
13+
let url = "https://ossci-ios.s3.amazonaws.com/executorch/"
14+
let debug = "_debug"
15+
let deliverables = [
16+
"coreml_backend": [
17+
"sha256": "5bfa35cb5143b4af6840e0e5dd2d40bce93dff331b8eb5798a46274239391a5d",
18+
"sha256" + debug: "1422019da9000f8ff7be597de9e0e3b2482f99cdaa75c2d179835778647be1a6",
19+
"frameworks": [
5420
"Accelerate",
5521
"CoreML",
5622
],
57-
libraries: [
23+
"libraries": [
5824
"sqlite3",
59-
]
60-
),
61-
Framework(
62-
name: "custom_backend",
63-
checksum: custom_sha256
64-
),
65-
Framework(
66-
name: "executorch",
67-
checksum: executorch_sha256
68-
),
69-
Framework(
70-
name: "mps_backend",
71-
checksum: mps_sha256,
72-
frameworks: [
25+
],
26+
],
27+
"custom_backend": [
28+
"sha256": "2201a61eaf7e06e1937cb73a469fb36cabc219496ba004b85feb2cc7c10f300d",
29+
"sha256" + debug: "3eb6eb97bf0641d2305b0f50ff05a8862d7d65e2491cf4aa05ef1d108649f07c",
30+
],
31+
"executorch": [
32+
"sha256": "2b55cbcff845ab9eaf16a21e520546b2975ef8c55b9e3fbbcc0c375334e40c6f",
33+
"sha256" + debug: "12933cedff6cf21c9d21668779f8d8af8049646fe7d290787b12227ff7abe4a7",
34+
],
35+
"mps_backend": [
36+
"sha256": "510d708361b6ea0692ce5aeb638725d6275824b37bbe744aa876fda24cc2bbbf",
37+
"sha256" + debug: "6a67ba0bf8033f17bd66acb222446df51cd1304e24a4fb2c6d97e15a30fb24f0",
38+
"frameworks": [
7339
"Metal",
7440
"MetalPerformanceShaders",
7541
"MetalPerformanceShadersGraph",
76-
]
77-
),
78-
Framework(
79-
name: "optimized_backend",
80-
checksum: optimized_sha256
81-
),
82-
Framework(
83-
name: "portable_backend",
84-
checksum: portable_sha256
85-
),
86-
Framework(
87-
name: "quantized_backend",
88-
checksum: quantized_sha256
89-
),
90-
Framework(
91-
name: "xnnpack_backend",
92-
checksum: xnnpack_sha256
93-
)
94-
]
42+
],
43+
],
44+
"optimized_backend": [
45+
"sha256": "50aaa54901a7cee1059e71cc623f054610406d65ba8fd6edb10b45861be67237",
46+
"sha256" + debug: "3f43f465727c8705432f4bb69260cc9501c519e5da006fc19ee2ab2ea260d1f0",
47+
],
48+
"portable_backend": [
49+
"sha256": "964238e92828665aa598c05b2264faab91fb13ce0f42633cc7d5653300af3e9b",
50+
"sha256" + debug: "d6d85304a4b40f13c9b893e8c264ebdb15307cacf8997494b3818a52e4914b28",
51+
],
52+
"quantized_backend": [
53+
"sha256": "37d31a319f92e26bab2b7ec5e783a8b14457dee0a4638dcdca1d9e17539ee3fb",
54+
"sha256" + debug: "6b45f66f60f6106a41e191418c970bf7b0605df73b9815a06441a5f0809b54e6",
55+
],
56+
"xnnpack_backend": [
57+
"sha256": "03d506243c392e872519ae1335a025ef202319c1db339a753f9d7d74cba226f0",
58+
"sha256" + debug: "3341e89abc99552a6a5bad360003baed194a83e865338bc07afe9e4f171ea169",
59+
],
60+
].reduce(into: [String: [String: Any]]()) {
61+
$0[$1.key] = $1.value
62+
$0[$1.key + debug] = $1.value
63+
}
64+
.reduce(into: [String: [String: Any]]()) {
65+
var newValue = $1.value
66+
if $1.key.hasSuffix(debug) {
67+
$1.value.forEach { key, value in
68+
if key.hasSuffix(debug) {
69+
newValue[String(key.dropLast(debug.count))] = value
70+
}
71+
}
72+
}
73+
$0[$1.key] = newValue.filter { key, _ in !key.hasSuffix(debug) }
74+
}
9575

9676
let package = Package(
9777
name: "executorch",
9878
platforms: [
9979
.iOS(.v15),
10080
],
101-
products: frameworks.map { .library(name: $0.name, targets: ["\($0.name)_dependencies"]) },
102-
targets: frameworks.flatMap { [$0.target(), $0.dependencies()] }
81+
products: deliverables.keys.map { key in
82+
.library(name: key, targets: ["\(key)_dependencies"])
83+
}.sorted { $0.name < $1.name },
84+
targets: deliverables.flatMap { key, value -> [Target] in
85+
[
86+
.binaryTarget(
87+
name: key,
88+
url: "\(url)\(key)-\(version).zip",
89+
checksum: value["sha256"] as? String ?? ""
90+
),
91+
.target(
92+
name: "\(key)_dependencies",
93+
dependencies: [.target(name: key)],
94+
path: ".swift/\(key)",
95+
linkerSettings:
96+
(value["frameworks"] as? [String] ?? []).map { .linkedFramework($0) } +
97+
(value["libraries"] as? [String] ?? []).map { .linkedLibrary($0) }
98+
),
99+
]
100+
}
103101
)

backends/qualcomm/builders/node_visitor.py

Lines changed: 22 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -150,19 +150,19 @@ def make_qnn_per_tensor_config(self, quant_attrs: Dict):
150150
quant_config,
151151
)
152152

153-
def get_quant_encoding_conf(self, node: torch.fx.Node) -> Tuple[Any, Dict]:
153+
def get_quant_encoding_conf(
154+
self, node: torch.fx.Node, is_input_tensor: bool = False
155+
) -> Tuple[Any, Dict]:
154156
if not node.meta.get("quant_attrs", None):
155157
return (
156158
PyQnnWrapper.Qnn_QuantizationEncoding_t.QNN_QUANTIZATION_ENCODING_UNDEFINED,
157159
{},
158160
)
159-
160161
quant_attrs = (
161-
node.meta["requantize"]["dq_attrs"]
162-
if "requantize" in node.meta
162+
node.meta["requantize"]
163+
if "requantize" in node.meta and is_input_tensor
163164
else node.meta["quant_attrs"]
164165
)
165-
166166
if quant_attrs["encoding"] in PER_CHANNEL_ENCODING:
167167
return self.make_qnn_per_channel_config(node, quant_attrs)
168168

@@ -275,15 +275,27 @@ def define_custom_tensor_wrapper(
275275
nodes_to_wrappers[node_name] = tensor_wrapper
276276
return tensor_wrapper
277277

278-
def define_value(
278+
def define_tensor(
279279
self,
280280
node: torch.fx.Node,
281281
tensor: torch.Tensor,
282282
tensor_type: PyQnnWrapper.Qnn_TensorType_t,
283283
nodes_to_wrappers: Dict[str, PyQnnWrapper.TensorWrapper],
284-
is_tensor: bool,
284+
is_input_tensor: bool,
285285
node_name: str = None,
286+
is_tensor: bool = True,
286287
) -> PyQnnWrapper.TensorWrapper:
288+
"""
289+
Covert torch.Tensor to TensorWrapper
290+
291+
Args:
292+
node: EdgeIR Node
293+
tensor: EdgeIR Tensor
294+
tensor_type: QNN tensor type
295+
nodes_to_wrappers: Set contains edge_graph values(node targets)
296+
is_input_tensor: Whether tensor is a fake input tensor relatively to
297+
the op builder that is calling this function
298+
"""
287299
if node_name is None:
288300
node_name = node.name
289301

@@ -294,7 +306,9 @@ def define_value(
294306
tensor_name = "output_" + tensor_name
295307
dims = [1] if len(tensor.size()) == 0 else tensor.size()
296308
tensor_type = self.get_tensor_type(node, tensor_type)
297-
quant_encoding, quant_configs = self.get_quant_encoding_conf(node)
309+
quant_encoding, quant_configs = self.get_quant_encoding_conf(
310+
node, is_input_tensor
311+
)
298312
dtype = self.get_data_type(tensor, quant_configs, is_tensor)
299313
if isinstance(tensor, torch._subclasses.fake_tensor.FakeTensor):
300314
tensor_wrapper = PyQnnWrapper.TensorWrapper(
@@ -330,52 +344,6 @@ def define_value(
330344
nodes_to_wrappers[node_name] = tensor_wrapper
331345
return tensor_wrapper
332346

333-
def define_scalar(
334-
self,
335-
node: torch.fx.Node,
336-
tensor: torch.Tensor,
337-
tensor_type: PyQnnWrapper.Qnn_TensorType_t,
338-
nodes_to_wrappers: Dict[torch.fx.Node, PyQnnWrapper.TensorWrapper],
339-
) -> PyQnnWrapper.TensorWrapper:
340-
"""
341-
Covert constant scalar to TensorWrapper
342-
343-
Args:
344-
tensor: EdgeIR Tensor
345-
nodes_to_wrappers: Set contains edge_graph values(node targets)
346-
"""
347-
return self.define_value(
348-
node,
349-
tensor,
350-
tensor_type,
351-
nodes_to_wrappers,
352-
is_tensor=False,
353-
)
354-
355-
def define_tensor(
356-
self,
357-
node: torch.fx.Node,
358-
tensor: torch.Tensor,
359-
tensor_type: PyQnnWrapper.Qnn_TensorType_t,
360-
nodes_to_wrappers: Dict[str, PyQnnWrapper.TensorWrapper],
361-
node_name: str = None,
362-
) -> PyQnnWrapper.TensorWrapper:
363-
"""
364-
Covert torch.Tensor to TensorWrapper
365-
366-
Args:
367-
tensor: EdgeIR Tensor
368-
nodes_to_wrappers: Set contains edge_graph values(node targets)
369-
"""
370-
return self.define_value(
371-
node,
372-
tensor,
373-
tensor_type,
374-
nodes_to_wrappers,
375-
is_tensor=True,
376-
node_name=node_name,
377-
)
378-
379347
def define_node(
380348
self,
381349
node: torch.fx.Node,

backends/qualcomm/builders/op_add.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def define_node(
3131
out_tensor,
3232
PyQnnWrapper.Qnn_TensorType_t.QNN_TENSOR_TYPE_NATIVE,
3333
nodes_to_wrappers,
34+
is_input_tensor=False,
3435
)
3536
add_output_tensors = [output_tensor_wrapper]
3637

@@ -45,6 +46,7 @@ def define_node(
4546
input_tensor,
4647
tensor_type,
4748
nodes_to_wrappers,
49+
is_input_tensor=True,
4850
)
4951
add_input_tensors.append(input_tensor_wrapper)
5052

backends/qualcomm/builders/op_avg_pool2d.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ def define_node(
3333
input_tensor,
3434
PyQnnWrapper.Qnn_TensorType_t.QNN_TENSOR_TYPE_NATIVE,
3535
nodes_to_wrappers,
36+
is_input_tensor=True,
3637
)
3738

3839
output_tensor = self.get_tensor(node, node)
@@ -41,6 +42,7 @@ def define_node(
4142
output_tensor,
4243
PyQnnWrapper.Qnn_TensorType_t.QNN_TENSOR_TYPE_NATIVE,
4344
nodes_to_wrappers,
45+
is_input_tensor=False,
4446
)
4547
# kernel info
4648
filter_size = cast(List[int], node.args[1])

backends/qualcomm/builders/op_batch_norm.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def define_node(
3838
input_tensor,
3939
PyQnnWrapper.Qnn_TensorType_t.QNN_TENSOR_TYPE_NATIVE,
4040
nodes_to_wrappers,
41+
is_input_tensor=True,
4142
)
4243

4344
bias_node = node.args[2]
@@ -52,6 +53,7 @@ def define_node(
5253
bias_tensor,
5354
PyQnnWrapper.Qnn_TensorType_t.QNN_TENSOR_TYPE_STATIC,
5455
nodes_to_wrappers,
56+
is_input_tensor=False,
5557
)
5658

5759
filter_tensor = filter_tensor / torch.sqrt(var_tensor + eps)
@@ -60,6 +62,7 @@ def define_node(
6062
filter_tensor,
6163
PyQnnWrapper.Qnn_TensorType_t.QNN_TENSOR_TYPE_STATIC,
6264
nodes_to_wrappers,
65+
is_input_tensor=False,
6366
)
6467

6568
batch_norm_input_tensors = [
@@ -74,6 +77,7 @@ def define_node(
7477
output_tensor,
7578
PyQnnWrapper.Qnn_TensorType_t.QNN_TENSOR_TYPE_NATIVE,
7679
nodes_to_wrappers,
80+
is_input_tensor=False,
7781
)
7882
batch_norm_output_tensors = [output_tensor_wrapper]
7983

backends/qualcomm/builders/op_bmm.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def define_node(
3535
input_tensor,
3636
PyQnnWrapper.Qnn_TensorType_t.QNN_TENSOR_TYPE_NATIVE,
3737
nodes_to_wrappers,
38+
is_input_tensor=True,
3839
)
3940
bmm_input_tensors.append(input_tensor_wrapper)
4041

@@ -44,6 +45,7 @@ def define_node(
4445
output_tensor,
4546
PyQnnWrapper.Qnn_TensorType_t.QNN_TENSOR_TYPE_NATIVE,
4647
nodes_to_wrappers,
48+
is_input_tensor=False,
4749
)
4850
bmm_output_tensors = [output_tensor_wrapper]
4951

0 commit comments

Comments
 (0)