[microNPU] Integrate the cascader - #10862

Merged
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2
Apr 25, 2022
Merged

[microNPU] Integrate the cascader#10862
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2

Conversation

@ekalda

Copy link
Copy Markdown
Contributor

Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.

Co-authored-by: Matthew Barrett matthew.barrett@arm.com

@ekalda

Copy link
Copy Markdown
ContributorAuthor

@ekalda

Copy link
Copy Markdown
ContributorAuthor

This patch supersedes #10377, so that one can be closed.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ekalda!

It is nice to see this working and green in CI.

I have left few comments around testing and user facing errors.

Comment threadpython/tvm/relay/backend/contrib/ethosu/codegen.py Outdated

def _ethos_u55_cascader() -> Callable:
flash = MemoryRegion(name="FLASH", size=10 ** 7, read_bandwidth=4, write_bandwidth=4)
sram = MemoryRegion(name="SRAM", size=10 ** 6, read_bandwidth=16, write_bandwidth=16)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Maybe for a subsequent PR] Will it be possible plumb these values using this :

IRModule func_module = WithAttrs(IRModule::FromExpr(func),
{{tvm::attr::kExecutor, executor_},
{tvm::attr::kRuntime, runtime_},
{tvm::attr::kWorkspaceMemoryPools, workspace_memory_pools_}});

An example test :

https://github.com/apache/tvm/blob/main/tests/python/relay/aot/test_crt_aot_usmp.py#L341-L383

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, with the caveat that we'll assume that there is one workspace pool in the system - is it ok to assume that for now or should we handle the case where there are several workspace pools where some of them are not accessible for the NPU?


return conv2d

infra.compare_tvm_with_tflite(tf_graph, [ifm_shape], accel_type, enable_cascader=True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these tests, I think we need to ensure the memory usage is reduced.

We could use calculate_workspace_size TIR analysis utility for that. E.g. :

asserttvm.tir.analysis.calculate_workspace_bytes(primfunc, alignment) ==size

OR we could use the final memory calculation in a non-USMP flow as follows :

deftest_workspace_calculation(workspace_byte_alignment, main_workspace_size):
mod, params=tvm.relay.testing.synthetic.get_workload()
target="c"
runtime=Runtime("crt")
executor=Executor(
"aot",
{
"workspace-byte-alignment": workspace_byte_alignment,
},
)
withtvm.transform.PassContext(
opt_level=3,
config={
"tir.disable_vectorize": True,
},
):
lib=tvm.relay.build(mod, target, executor=executor, runtime=runtime, params=params)
mlf_memory_map=mlf._build_function_memory_map(lib.function_metadata)
assertmlf_memory_map["main"][0]["workspace_size_bytes"] ==main_workspace_size

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the tests to check for reduction in memory instead of bitwise accuracy with TFLite (I think it would be still good to have some FVP based tests when cascader is enabled, but it looks like that would need quite a bit of infra refactor, so I'll do it in a separate patch, if this is ok)

@lhutton1lhutton1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me modulo @manupa-arm's comments :)

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 1c20fcd to 2042445CompareApril 11, 2022 11:28
return compiler_attrs.accelerator_config


def enable_cascader():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better is_cascader_enabled, otherwise, it seems you are enabling it with this function.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I changed the function name to is_cascader_enabled, but kept the flag/variable as enable_cascader to align with the philosophy of enable_usmp

@NicolaLancellottiNicolaLancellotti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you @ekalda.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broadly looks great!

just a nit and a question

mod, params, accel_type, pool_size, enable_cascader=True
)

assert workspace_size_cascader_enabled < workspace_size_cascader_disabled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, should we not check for exact values ?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point, I changed it to check for the exact values

)


def _extract_memory_info(memory_pool):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better for this utility to be part of the cascader and not get exposed to the codegen here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch 4 times, most recently from e764f8c to 094fbcbCompareApril 21, 2022 13:46
ekaldaand others added 8 commits April 22, 2022 09:30
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 094fbcb to f212de6CompareApril 22, 2022 09:11

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a suggestion for a follow up.

), "Exactly one workspace pool needs to be provided for the U55 cascader"

sram = extract_memory_info(workspace_memory_pools.pools[0])
tir_mod = LowerToTIR(_ethos_u55_cascader(sram))(mod)

@manupakmanupakApr 25, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a followup : Please consider absorbing the call to extract_memory_info inside the cascader. (Sorry for not being clear before). Ideally, we'd want to remove the "MemoryRegion" construct and to get there in the current direction of travel, we should try to confine the usage of it inside the cascader. Therefore the interface of the cascader should be made to accept MemoryPool(s).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this would be the right way to go about it. Let's do it in a follow up!

@manupak
manupak merged commit d2db9cb into apache:mainApr 25, 2022
@manupak

Copy link
Copy Markdown
Contributor

Thanks @ekalda@mbaret@lhutton1@NicolaLancellotti !

This is merged now!

shtinsa pushed a commit to Deelvin/tvm that referenced this pull request May 17, 2022
* [microNPU] Integrate the cascader
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
* Fix linting and a docstring
* Plumbing and testing improvements
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
* enable_cascader() -> is_cascader_enabled()
* Check for the exact value of workspace size
* Remove unused ACCEL_TYPES
* Linting...
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
* Rebasing...
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@ekalda@manupak@NicolaLancellotti@lhutton1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[microNPU] Integrate the cascader - #10862

Merged
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2
Apr 25, 2022
Merged

[microNPU] Integrate the cascader#10862
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2

Conversation

@ekalda

Copy link
Copy Markdown
Contributor

Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.

Co-authored-by: Matthew Barrett matthew.barrett@arm.com

@ekalda

Copy link
Copy Markdown
ContributorAuthor

@ekalda

Copy link
Copy Markdown
ContributorAuthor

This patch supersedes #10377, so that one can be closed.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ekalda!

It is nice to see this working and green in CI.

I have left few comments around testing and user facing errors.

Comment threadpython/tvm/relay/backend/contrib/ethosu/codegen.py Outdated

def _ethos_u55_cascader() -> Callable:
flash = MemoryRegion(name="FLASH", size=10 ** 7, read_bandwidth=4, write_bandwidth=4)
sram = MemoryRegion(name="SRAM", size=10 ** 6, read_bandwidth=16, write_bandwidth=16)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Maybe for a subsequent PR] Will it be possible plumb these values using this :

IRModule func_module = WithAttrs(IRModule::FromExpr(func),
{{tvm::attr::kExecutor, executor_},
{tvm::attr::kRuntime, runtime_},
{tvm::attr::kWorkspaceMemoryPools, workspace_memory_pools_}});

An example test :

https://github.com/apache/tvm/blob/main/tests/python/relay/aot/test_crt_aot_usmp.py#L341-L383

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, with the caveat that we'll assume that there is one workspace pool in the system - is it ok to assume that for now or should we handle the case where there are several workspace pools where some of them are not accessible for the NPU?


return conv2d

infra.compare_tvm_with_tflite(tf_graph, [ifm_shape], accel_type, enable_cascader=True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these tests, I think we need to ensure the memory usage is reduced.

We could use calculate_workspace_size TIR analysis utility for that. E.g. :

asserttvm.tir.analysis.calculate_workspace_bytes(primfunc, alignment) ==size

OR we could use the final memory calculation in a non-USMP flow as follows :

deftest_workspace_calculation(workspace_byte_alignment, main_workspace_size):
mod, params=tvm.relay.testing.synthetic.get_workload()
target="c"
runtime=Runtime("crt")
executor=Executor(
"aot",
{
"workspace-byte-alignment": workspace_byte_alignment,
},
)
withtvm.transform.PassContext(
opt_level=3,
config={
"tir.disable_vectorize": True,
},
):
lib=tvm.relay.build(mod, target, executor=executor, runtime=runtime, params=params)
mlf_memory_map=mlf._build_function_memory_map(lib.function_metadata)
assertmlf_memory_map["main"][0]["workspace_size_bytes"] ==main_workspace_size

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the tests to check for reduction in memory instead of bitwise accuracy with TFLite (I think it would be still good to have some FVP based tests when cascader is enabled, but it looks like that would need quite a bit of infra refactor, so I'll do it in a separate patch, if this is ok)

@lhutton1lhutton1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me modulo @manupa-arm's comments :)

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 1c20fcd to 2042445CompareApril 11, 2022 11:28
return compiler_attrs.accelerator_config


def enable_cascader():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better is_cascader_enabled, otherwise, it seems you are enabling it with this function.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I changed the function name to is_cascader_enabled, but kept the flag/variable as enable_cascader to align with the philosophy of enable_usmp

@NicolaLancellottiNicolaLancellotti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you @ekalda.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broadly looks great!

just a nit and a question

mod, params, accel_type, pool_size, enable_cascader=True
)

assert workspace_size_cascader_enabled < workspace_size_cascader_disabled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, should we not check for exact values ?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point, I changed it to check for the exact values

)


def _extract_memory_info(memory_pool):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better for this utility to be part of the cascader and not get exposed to the codegen here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch 4 times, most recently from e764f8c to 094fbcbCompareApril 21, 2022 13:46
ekaldaand others added 8 commits April 22, 2022 09:30
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 094fbcb to f212de6CompareApril 22, 2022 09:11

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a suggestion for a follow up.

), "Exactly one workspace pool needs to be provided for the U55 cascader"

sram = extract_memory_info(workspace_memory_pools.pools[0])
tir_mod = LowerToTIR(_ethos_u55_cascader(sram))(mod)

@manupakmanupakApr 25, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a followup : Please consider absorbing the call to extract_memory_info inside the cascader. (Sorry for not being clear before). Ideally, we'd want to remove the "MemoryRegion" construct and to get there in the current direction of travel, we should try to confine the usage of it inside the cascader. Therefore the interface of the cascader should be made to accept MemoryPool(s).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this would be the right way to go about it. Let's do it in a follow up!

@manupak
manupak merged commit d2db9cb into apache:mainApr 25, 2022
@manupak

Copy link
Copy Markdown
Contributor

Thanks @ekalda@mbaret@lhutton1@NicolaLancellotti !

This is merged now!

shtinsa pushed a commit to Deelvin/tvm that referenced this pull request May 17, 2022
* [microNPU] Integrate the cascader
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
* Fix linting and a docstring
* Plumbing and testing improvements
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
* enable_cascader() -> is_cascader_enabled()
* Check for the exact value of workspace size
* Remove unused ACCEL_TYPES
* Linting...
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
* Rebasing...
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@ekalda@manupak@NicolaLancellotti@lhutton1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[microNPU] Integrate the cascader - #10862

Merged
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2
Apr 25, 2022
Merged

[microNPU] Integrate the cascader#10862
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2

Conversation

@ekalda

Copy link
Copy Markdown
Contributor

Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.

Co-authored-by: Matthew Barrett matthew.barrett@arm.com

@ekalda

Copy link
Copy Markdown
ContributorAuthor

@ekalda

Copy link
Copy Markdown
ContributorAuthor

This patch supersedes #10377, so that one can be closed.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ekalda!

It is nice to see this working and green in CI.

I have left few comments around testing and user facing errors.

Comment threadpython/tvm/relay/backend/contrib/ethosu/codegen.py Outdated

def _ethos_u55_cascader() -> Callable:
flash = MemoryRegion(name="FLASH", size=10 ** 7, read_bandwidth=4, write_bandwidth=4)
sram = MemoryRegion(name="SRAM", size=10 ** 6, read_bandwidth=16, write_bandwidth=16)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Maybe for a subsequent PR] Will it be possible plumb these values using this :

IRModule func_module = WithAttrs(IRModule::FromExpr(func),
{{tvm::attr::kExecutor, executor_},
{tvm::attr::kRuntime, runtime_},
{tvm::attr::kWorkspaceMemoryPools, workspace_memory_pools_}});

An example test :

https://github.com/apache/tvm/blob/main/tests/python/relay/aot/test_crt_aot_usmp.py#L341-L383

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, with the caveat that we'll assume that there is one workspace pool in the system - is it ok to assume that for now or should we handle the case where there are several workspace pools where some of them are not accessible for the NPU?


return conv2d

infra.compare_tvm_with_tflite(tf_graph, [ifm_shape], accel_type, enable_cascader=True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these tests, I think we need to ensure the memory usage is reduced.

We could use calculate_workspace_size TIR analysis utility for that. E.g. :

asserttvm.tir.analysis.calculate_workspace_bytes(primfunc, alignment) ==size

OR we could use the final memory calculation in a non-USMP flow as follows :

deftest_workspace_calculation(workspace_byte_alignment, main_workspace_size):
mod, params=tvm.relay.testing.synthetic.get_workload()
target="c"
runtime=Runtime("crt")
executor=Executor(
"aot",
{
"workspace-byte-alignment": workspace_byte_alignment,
},
)
withtvm.transform.PassContext(
opt_level=3,
config={
"tir.disable_vectorize": True,
},
):
lib=tvm.relay.build(mod, target, executor=executor, runtime=runtime, params=params)
mlf_memory_map=mlf._build_function_memory_map(lib.function_metadata)
assertmlf_memory_map["main"][0]["workspace_size_bytes"] ==main_workspace_size

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the tests to check for reduction in memory instead of bitwise accuracy with TFLite (I think it would be still good to have some FVP based tests when cascader is enabled, but it looks like that would need quite a bit of infra refactor, so I'll do it in a separate patch, if this is ok)

@lhutton1lhutton1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me modulo @manupa-arm's comments :)

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 1c20fcd to 2042445CompareApril 11, 2022 11:28
return compiler_attrs.accelerator_config


def enable_cascader():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better is_cascader_enabled, otherwise, it seems you are enabling it with this function.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I changed the function name to is_cascader_enabled, but kept the flag/variable as enable_cascader to align with the philosophy of enable_usmp

@NicolaLancellottiNicolaLancellotti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you @ekalda.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broadly looks great!

just a nit and a question

mod, params, accel_type, pool_size, enable_cascader=True
)

assert workspace_size_cascader_enabled < workspace_size_cascader_disabled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, should we not check for exact values ?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point, I changed it to check for the exact values

)


def _extract_memory_info(memory_pool):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better for this utility to be part of the cascader and not get exposed to the codegen here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch 4 times, most recently from e764f8c to 094fbcbCompareApril 21, 2022 13:46
ekaldaand others added 8 commits April 22, 2022 09:30
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 094fbcb to f212de6CompareApril 22, 2022 09:11

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a suggestion for a follow up.

), "Exactly one workspace pool needs to be provided for the U55 cascader"

sram = extract_memory_info(workspace_memory_pools.pools[0])
tir_mod = LowerToTIR(_ethos_u55_cascader(sram))(mod)

@manupakmanupakApr 25, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a followup : Please consider absorbing the call to extract_memory_info inside the cascader. (Sorry for not being clear before). Ideally, we'd want to remove the "MemoryRegion" construct and to get there in the current direction of travel, we should try to confine the usage of it inside the cascader. Therefore the interface of the cascader should be made to accept MemoryPool(s).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this would be the right way to go about it. Let's do it in a follow up!

@manupak
manupak merged commit d2db9cb into apache:mainApr 25, 2022
@manupak

Copy link
Copy Markdown
Contributor

Thanks @ekalda@mbaret@lhutton1@NicolaLancellotti !

This is merged now!

shtinsa pushed a commit to Deelvin/tvm that referenced this pull request May 17, 2022
* [microNPU] Integrate the cascader
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
* Fix linting and a docstring
* Plumbing and testing improvements
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
* enable_cascader() -> is_cascader_enabled()
* Check for the exact value of workspace size
* Remove unused ACCEL_TYPES
* Linting...
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
* Rebasing...
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@ekalda@manupak@NicolaLancellotti@lhutton1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[microNPU] Integrate the cascader - #10862

Merged
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2
Apr 25, 2022
Merged

[microNPU] Integrate the cascader#10862
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2

Conversation

@ekalda

Copy link
Copy Markdown
Contributor

Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.

Co-authored-by: Matthew Barrett matthew.barrett@arm.com

@ekalda

Copy link
Copy Markdown
ContributorAuthor

@ekalda

Copy link
Copy Markdown
ContributorAuthor

This patch supersedes #10377, so that one can be closed.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ekalda!

It is nice to see this working and green in CI.

I have left few comments around testing and user facing errors.

Comment threadpython/tvm/relay/backend/contrib/ethosu/codegen.py Outdated

def _ethos_u55_cascader() -> Callable:
flash = MemoryRegion(name="FLASH", size=10 ** 7, read_bandwidth=4, write_bandwidth=4)
sram = MemoryRegion(name="SRAM", size=10 ** 6, read_bandwidth=16, write_bandwidth=16)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Maybe for a subsequent PR] Will it be possible plumb these values using this :

IRModule func_module = WithAttrs(IRModule::FromExpr(func),
{{tvm::attr::kExecutor, executor_},
{tvm::attr::kRuntime, runtime_},
{tvm::attr::kWorkspaceMemoryPools, workspace_memory_pools_}});

An example test :

https://github.com/apache/tvm/blob/main/tests/python/relay/aot/test_crt_aot_usmp.py#L341-L383

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, with the caveat that we'll assume that there is one workspace pool in the system - is it ok to assume that for now or should we handle the case where there are several workspace pools where some of them are not accessible for the NPU?


return conv2d

infra.compare_tvm_with_tflite(tf_graph, [ifm_shape], accel_type, enable_cascader=True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these tests, I think we need to ensure the memory usage is reduced.

We could use calculate_workspace_size TIR analysis utility for that. E.g. :

asserttvm.tir.analysis.calculate_workspace_bytes(primfunc, alignment) ==size

OR we could use the final memory calculation in a non-USMP flow as follows :

deftest_workspace_calculation(workspace_byte_alignment, main_workspace_size):
mod, params=tvm.relay.testing.synthetic.get_workload()
target="c"
runtime=Runtime("crt")
executor=Executor(
"aot",
{
"workspace-byte-alignment": workspace_byte_alignment,
},
)
withtvm.transform.PassContext(
opt_level=3,
config={
"tir.disable_vectorize": True,
},
):
lib=tvm.relay.build(mod, target, executor=executor, runtime=runtime, params=params)
mlf_memory_map=mlf._build_function_memory_map(lib.function_metadata)
assertmlf_memory_map["main"][0]["workspace_size_bytes"] ==main_workspace_size

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the tests to check for reduction in memory instead of bitwise accuracy with TFLite (I think it would be still good to have some FVP based tests when cascader is enabled, but it looks like that would need quite a bit of infra refactor, so I'll do it in a separate patch, if this is ok)

@lhutton1lhutton1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me modulo @manupa-arm's comments :)

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 1c20fcd to 2042445CompareApril 11, 2022 11:28
return compiler_attrs.accelerator_config


def enable_cascader():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better is_cascader_enabled, otherwise, it seems you are enabling it with this function.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I changed the function name to is_cascader_enabled, but kept the flag/variable as enable_cascader to align with the philosophy of enable_usmp

@NicolaLancellottiNicolaLancellotti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you @ekalda.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broadly looks great!

just a nit and a question

mod, params, accel_type, pool_size, enable_cascader=True
)

assert workspace_size_cascader_enabled < workspace_size_cascader_disabled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, should we not check for exact values ?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point, I changed it to check for the exact values

)


def _extract_memory_info(memory_pool):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better for this utility to be part of the cascader and not get exposed to the codegen here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch 4 times, most recently from e764f8c to 094fbcbCompareApril 21, 2022 13:46
ekaldaand others added 8 commits April 22, 2022 09:30
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 094fbcb to f212de6CompareApril 22, 2022 09:11

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a suggestion for a follow up.

), "Exactly one workspace pool needs to be provided for the U55 cascader"

sram = extract_memory_info(workspace_memory_pools.pools[0])
tir_mod = LowerToTIR(_ethos_u55_cascader(sram))(mod)

@manupakmanupakApr 25, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a followup : Please consider absorbing the call to extract_memory_info inside the cascader. (Sorry for not being clear before). Ideally, we'd want to remove the "MemoryRegion" construct and to get there in the current direction of travel, we should try to confine the usage of it inside the cascader. Therefore the interface of the cascader should be made to accept MemoryPool(s).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this would be the right way to go about it. Let's do it in a follow up!

@manupak
manupak merged commit d2db9cb into apache:mainApr 25, 2022
@manupak

Copy link
Copy Markdown
Contributor

Thanks @ekalda@mbaret@lhutton1@NicolaLancellotti !

This is merged now!

shtinsa pushed a commit to Deelvin/tvm that referenced this pull request May 17, 2022
* [microNPU] Integrate the cascader
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
* Fix linting and a docstring
* Plumbing and testing improvements
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
* enable_cascader() -> is_cascader_enabled()
* Check for the exact value of workspace size
* Remove unused ACCEL_TYPES
* Linting...
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
* Rebasing...
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@ekalda@manupak@NicolaLancellotti@lhutton1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[microNPU] Integrate the cascader - #10862

Merged
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2
Apr 25, 2022
Merged

[microNPU] Integrate the cascader#10862
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2

Conversation

@ekalda

Copy link
Copy Markdown
Contributor

Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.

Co-authored-by: Matthew Barrett matthew.barrett@arm.com

@ekalda

Copy link
Copy Markdown
ContributorAuthor

@ekalda

Copy link
Copy Markdown
ContributorAuthor

This patch supersedes #10377, so that one can be closed.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ekalda!

It is nice to see this working and green in CI.

I have left few comments around testing and user facing errors.

Comment threadpython/tvm/relay/backend/contrib/ethosu/codegen.py Outdated

def _ethos_u55_cascader() -> Callable:
flash = MemoryRegion(name="FLASH", size=10 ** 7, read_bandwidth=4, write_bandwidth=4)
sram = MemoryRegion(name="SRAM", size=10 ** 6, read_bandwidth=16, write_bandwidth=16)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Maybe for a subsequent PR] Will it be possible plumb these values using this :

IRModule func_module = WithAttrs(IRModule::FromExpr(func),
{{tvm::attr::kExecutor, executor_},
{tvm::attr::kRuntime, runtime_},
{tvm::attr::kWorkspaceMemoryPools, workspace_memory_pools_}});

An example test :

https://github.com/apache/tvm/blob/main/tests/python/relay/aot/test_crt_aot_usmp.py#L341-L383

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, with the caveat that we'll assume that there is one workspace pool in the system - is it ok to assume that for now or should we handle the case where there are several workspace pools where some of them are not accessible for the NPU?


return conv2d

infra.compare_tvm_with_tflite(tf_graph, [ifm_shape], accel_type, enable_cascader=True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these tests, I think we need to ensure the memory usage is reduced.

We could use calculate_workspace_size TIR analysis utility for that. E.g. :

asserttvm.tir.analysis.calculate_workspace_bytes(primfunc, alignment) ==size

OR we could use the final memory calculation in a non-USMP flow as follows :

deftest_workspace_calculation(workspace_byte_alignment, main_workspace_size):
mod, params=tvm.relay.testing.synthetic.get_workload()
target="c"
runtime=Runtime("crt")
executor=Executor(
"aot",
{
"workspace-byte-alignment": workspace_byte_alignment,
},
)
withtvm.transform.PassContext(
opt_level=3,
config={
"tir.disable_vectorize": True,
},
):
lib=tvm.relay.build(mod, target, executor=executor, runtime=runtime, params=params)
mlf_memory_map=mlf._build_function_memory_map(lib.function_metadata)
assertmlf_memory_map["main"][0]["workspace_size_bytes"] ==main_workspace_size

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the tests to check for reduction in memory instead of bitwise accuracy with TFLite (I think it would be still good to have some FVP based tests when cascader is enabled, but it looks like that would need quite a bit of infra refactor, so I'll do it in a separate patch, if this is ok)

@lhutton1lhutton1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me modulo @manupa-arm's comments :)

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 1c20fcd to 2042445CompareApril 11, 2022 11:28
return compiler_attrs.accelerator_config


def enable_cascader():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better is_cascader_enabled, otherwise, it seems you are enabling it with this function.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I changed the function name to is_cascader_enabled, but kept the flag/variable as enable_cascader to align with the philosophy of enable_usmp

@NicolaLancellottiNicolaLancellotti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you @ekalda.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broadly looks great!

just a nit and a question

mod, params, accel_type, pool_size, enable_cascader=True
)

assert workspace_size_cascader_enabled < workspace_size_cascader_disabled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, should we not check for exact values ?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point, I changed it to check for the exact values

)


def _extract_memory_info(memory_pool):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better for this utility to be part of the cascader and not get exposed to the codegen here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch 4 times, most recently from e764f8c to 094fbcbCompareApril 21, 2022 13:46
ekaldaand others added 8 commits April 22, 2022 09:30
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 094fbcb to f212de6CompareApril 22, 2022 09:11

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a suggestion for a follow up.

), "Exactly one workspace pool needs to be provided for the U55 cascader"

sram = extract_memory_info(workspace_memory_pools.pools[0])
tir_mod = LowerToTIR(_ethos_u55_cascader(sram))(mod)

@manupakmanupakApr 25, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a followup : Please consider absorbing the call to extract_memory_info inside the cascader. (Sorry for not being clear before). Ideally, we'd want to remove the "MemoryRegion" construct and to get there in the current direction of travel, we should try to confine the usage of it inside the cascader. Therefore the interface of the cascader should be made to accept MemoryPool(s).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this would be the right way to go about it. Let's do it in a follow up!

@manupak
manupak merged commit d2db9cb into apache:mainApr 25, 2022
@manupak

Copy link
Copy Markdown
Contributor

Thanks @ekalda@mbaret@lhutton1@NicolaLancellotti !

This is merged now!

shtinsa pushed a commit to Deelvin/tvm that referenced this pull request May 17, 2022
* [microNPU] Integrate the cascader
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
* Fix linting and a docstring
* Plumbing and testing improvements
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
* enable_cascader() -> is_cascader_enabled()
* Check for the exact value of workspace size
* Remove unused ACCEL_TYPES
* Linting...
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
* Rebasing...
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@ekalda@manupak@NicolaLancellotti@lhutton1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[microNPU] Integrate the cascader - #10862

Merged
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2
Apr 25, 2022
Merged

[microNPU] Integrate the cascader#10862
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2

Conversation

@ekalda

Copy link
Copy Markdown
Contributor

Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.

Co-authored-by: Matthew Barrett matthew.barrett@arm.com

@ekalda

Copy link
Copy Markdown
ContributorAuthor

@ekalda

Copy link
Copy Markdown
ContributorAuthor

This patch supersedes #10377, so that one can be closed.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ekalda!

It is nice to see this working and green in CI.

I have left few comments around testing and user facing errors.

Comment threadpython/tvm/relay/backend/contrib/ethosu/codegen.py Outdated

def _ethos_u55_cascader() -> Callable:
flash = MemoryRegion(name="FLASH", size=10 ** 7, read_bandwidth=4, write_bandwidth=4)
sram = MemoryRegion(name="SRAM", size=10 ** 6, read_bandwidth=16, write_bandwidth=16)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Maybe for a subsequent PR] Will it be possible plumb these values using this :

IRModule func_module = WithAttrs(IRModule::FromExpr(func),
{{tvm::attr::kExecutor, executor_},
{tvm::attr::kRuntime, runtime_},
{tvm::attr::kWorkspaceMemoryPools, workspace_memory_pools_}});

An example test :

https://github.com/apache/tvm/blob/main/tests/python/relay/aot/test_crt_aot_usmp.py#L341-L383

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, with the caveat that we'll assume that there is one workspace pool in the system - is it ok to assume that for now or should we handle the case where there are several workspace pools where some of them are not accessible for the NPU?


return conv2d

infra.compare_tvm_with_tflite(tf_graph, [ifm_shape], accel_type, enable_cascader=True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these tests, I think we need to ensure the memory usage is reduced.

We could use calculate_workspace_size TIR analysis utility for that. E.g. :

asserttvm.tir.analysis.calculate_workspace_bytes(primfunc, alignment) ==size

OR we could use the final memory calculation in a non-USMP flow as follows :

deftest_workspace_calculation(workspace_byte_alignment, main_workspace_size):
mod, params=tvm.relay.testing.synthetic.get_workload()
target="c"
runtime=Runtime("crt")
executor=Executor(
"aot",
{
"workspace-byte-alignment": workspace_byte_alignment,
},
)
withtvm.transform.PassContext(
opt_level=3,
config={
"tir.disable_vectorize": True,
},
):
lib=tvm.relay.build(mod, target, executor=executor, runtime=runtime, params=params)
mlf_memory_map=mlf._build_function_memory_map(lib.function_metadata)
assertmlf_memory_map["main"][0]["workspace_size_bytes"] ==main_workspace_size

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the tests to check for reduction in memory instead of bitwise accuracy with TFLite (I think it would be still good to have some FVP based tests when cascader is enabled, but it looks like that would need quite a bit of infra refactor, so I'll do it in a separate patch, if this is ok)

@lhutton1lhutton1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me modulo @manupa-arm's comments :)

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 1c20fcd to 2042445CompareApril 11, 2022 11:28
return compiler_attrs.accelerator_config


def enable_cascader():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better is_cascader_enabled, otherwise, it seems you are enabling it with this function.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I changed the function name to is_cascader_enabled, but kept the flag/variable as enable_cascader to align with the philosophy of enable_usmp

@NicolaLancellottiNicolaLancellotti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you @ekalda.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broadly looks great!

just a nit and a question

mod, params, accel_type, pool_size, enable_cascader=True
)

assert workspace_size_cascader_enabled < workspace_size_cascader_disabled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, should we not check for exact values ?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point, I changed it to check for the exact values

)


def _extract_memory_info(memory_pool):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better for this utility to be part of the cascader and not get exposed to the codegen here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch 4 times, most recently from e764f8c to 094fbcbCompareApril 21, 2022 13:46
ekaldaand others added 8 commits April 22, 2022 09:30
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 094fbcb to f212de6CompareApril 22, 2022 09:11

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a suggestion for a follow up.

), "Exactly one workspace pool needs to be provided for the U55 cascader"

sram = extract_memory_info(workspace_memory_pools.pools[0])
tir_mod = LowerToTIR(_ethos_u55_cascader(sram))(mod)

@manupakmanupakApr 25, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a followup : Please consider absorbing the call to extract_memory_info inside the cascader. (Sorry for not being clear before). Ideally, we'd want to remove the "MemoryRegion" construct and to get there in the current direction of travel, we should try to confine the usage of it inside the cascader. Therefore the interface of the cascader should be made to accept MemoryPool(s).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this would be the right way to go about it. Let's do it in a follow up!

@manupak
manupak merged commit d2db9cb into apache:mainApr 25, 2022
@manupak

Copy link
Copy Markdown
Contributor

Thanks @ekalda@mbaret@lhutton1@NicolaLancellotti !

This is merged now!

shtinsa pushed a commit to Deelvin/tvm that referenced this pull request May 17, 2022
* [microNPU] Integrate the cascader
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
* Fix linting and a docstring
* Plumbing and testing improvements
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
* enable_cascader() -> is_cascader_enabled()
* Check for the exact value of workspace size
* Remove unused ACCEL_TYPES
* Linting...
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
* Rebasing...
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@ekalda@manupak@NicolaLancellotti@lhutton1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[microNPU] Integrate the cascader - #10862

Merged
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2
Apr 25, 2022
Merged

[microNPU] Integrate the cascader#10862
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2

Conversation

@ekalda

Copy link
Copy Markdown
Contributor

Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.

Co-authored-by: Matthew Barrett matthew.barrett@arm.com

@ekalda

Copy link
Copy Markdown
ContributorAuthor

@ekalda

Copy link
Copy Markdown
ContributorAuthor

This patch supersedes #10377, so that one can be closed.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ekalda!

It is nice to see this working and green in CI.

I have left few comments around testing and user facing errors.

Comment threadpython/tvm/relay/backend/contrib/ethosu/codegen.py Outdated

def _ethos_u55_cascader() -> Callable:
flash = MemoryRegion(name="FLASH", size=10 ** 7, read_bandwidth=4, write_bandwidth=4)
sram = MemoryRegion(name="SRAM", size=10 ** 6, read_bandwidth=16, write_bandwidth=16)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Maybe for a subsequent PR] Will it be possible plumb these values using this :

IRModule func_module = WithAttrs(IRModule::FromExpr(func),
{{tvm::attr::kExecutor, executor_},
{tvm::attr::kRuntime, runtime_},
{tvm::attr::kWorkspaceMemoryPools, workspace_memory_pools_}});

An example test :

https://github.com/apache/tvm/blob/main/tests/python/relay/aot/test_crt_aot_usmp.py#L341-L383

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, with the caveat that we'll assume that there is one workspace pool in the system - is it ok to assume that for now or should we handle the case where there are several workspace pools where some of them are not accessible for the NPU?


return conv2d

infra.compare_tvm_with_tflite(tf_graph, [ifm_shape], accel_type, enable_cascader=True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these tests, I think we need to ensure the memory usage is reduced.

We could use calculate_workspace_size TIR analysis utility for that. E.g. :

asserttvm.tir.analysis.calculate_workspace_bytes(primfunc, alignment) ==size

OR we could use the final memory calculation in a non-USMP flow as follows :

deftest_workspace_calculation(workspace_byte_alignment, main_workspace_size):
mod, params=tvm.relay.testing.synthetic.get_workload()
target="c"
runtime=Runtime("crt")
executor=Executor(
"aot",
{
"workspace-byte-alignment": workspace_byte_alignment,
},
)
withtvm.transform.PassContext(
opt_level=3,
config={
"tir.disable_vectorize": True,
},
):
lib=tvm.relay.build(mod, target, executor=executor, runtime=runtime, params=params)
mlf_memory_map=mlf._build_function_memory_map(lib.function_metadata)
assertmlf_memory_map["main"][0]["workspace_size_bytes"] ==main_workspace_size

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the tests to check for reduction in memory instead of bitwise accuracy with TFLite (I think it would be still good to have some FVP based tests when cascader is enabled, but it looks like that would need quite a bit of infra refactor, so I'll do it in a separate patch, if this is ok)

@lhutton1lhutton1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me modulo @manupa-arm's comments :)

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 1c20fcd to 2042445CompareApril 11, 2022 11:28
return compiler_attrs.accelerator_config


def enable_cascader():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better is_cascader_enabled, otherwise, it seems you are enabling it with this function.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I changed the function name to is_cascader_enabled, but kept the flag/variable as enable_cascader to align with the philosophy of enable_usmp

@NicolaLancellottiNicolaLancellotti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you @ekalda.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broadly looks great!

just a nit and a question

mod, params, accel_type, pool_size, enable_cascader=True
)

assert workspace_size_cascader_enabled < workspace_size_cascader_disabled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, should we not check for exact values ?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point, I changed it to check for the exact values

)


def _extract_memory_info(memory_pool):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better for this utility to be part of the cascader and not get exposed to the codegen here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch 4 times, most recently from e764f8c to 094fbcbCompareApril 21, 2022 13:46
ekaldaand others added 8 commits April 22, 2022 09:30
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 094fbcb to f212de6CompareApril 22, 2022 09:11

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a suggestion for a follow up.

), "Exactly one workspace pool needs to be provided for the U55 cascader"

sram = extract_memory_info(workspace_memory_pools.pools[0])
tir_mod = LowerToTIR(_ethos_u55_cascader(sram))(mod)

@manupakmanupakApr 25, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a followup : Please consider absorbing the call to extract_memory_info inside the cascader. (Sorry for not being clear before). Ideally, we'd want to remove the "MemoryRegion" construct and to get there in the current direction of travel, we should try to confine the usage of it inside the cascader. Therefore the interface of the cascader should be made to accept MemoryPool(s).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this would be the right way to go about it. Let's do it in a follow up!

@manupak
manupak merged commit d2db9cb into apache:mainApr 25, 2022
@manupak

Copy link
Copy Markdown
Contributor

Thanks @ekalda@mbaret@lhutton1@NicolaLancellotti !

This is merged now!

shtinsa pushed a commit to Deelvin/tvm that referenced this pull request May 17, 2022
* [microNPU] Integrate the cascader
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
* Fix linting and a docstring
* Plumbing and testing improvements
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
* enable_cascader() -> is_cascader_enabled()
* Check for the exact value of workspace size
* Remove unused ACCEL_TYPES
* Linting...
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
* Rebasing...
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@ekalda@manupak@NicolaLancellotti@lhutton1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[microNPU] Integrate the cascader - #10862

Merged
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2
Apr 25, 2022
Merged

[microNPU] Integrate the cascader#10862
manupak merged 8 commits into
apache:mainfrom
ekalda:integrate-cascader2

Conversation

@ekalda

Copy link
Copy Markdown
Contributor

Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.

Co-authored-by: Matthew Barrett matthew.barrett@arm.com

@ekalda

Copy link
Copy Markdown
ContributorAuthor

@ekalda

Copy link
Copy Markdown
ContributorAuthor

This patch supersedes #10377, so that one can be closed.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ekalda!

It is nice to see this working and green in CI.

I have left few comments around testing and user facing errors.

Comment threadpython/tvm/relay/backend/contrib/ethosu/codegen.py Outdated

def _ethos_u55_cascader() -> Callable:
flash = MemoryRegion(name="FLASH", size=10 ** 7, read_bandwidth=4, write_bandwidth=4)
sram = MemoryRegion(name="SRAM", size=10 ** 6, read_bandwidth=16, write_bandwidth=16)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Maybe for a subsequent PR] Will it be possible plumb these values using this :

IRModule func_module = WithAttrs(IRModule::FromExpr(func),
{{tvm::attr::kExecutor, executor_},
{tvm::attr::kRuntime, runtime_},
{tvm::attr::kWorkspaceMemoryPools, workspace_memory_pools_}});

An example test :

https://github.com/apache/tvm/blob/main/tests/python/relay/aot/test_crt_aot_usmp.py#L341-L383

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, with the caveat that we'll assume that there is one workspace pool in the system - is it ok to assume that for now or should we handle the case where there are several workspace pools where some of them are not accessible for the NPU?


return conv2d

infra.compare_tvm_with_tflite(tf_graph, [ifm_shape], accel_type, enable_cascader=True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these tests, I think we need to ensure the memory usage is reduced.

We could use calculate_workspace_size TIR analysis utility for that. E.g. :

asserttvm.tir.analysis.calculate_workspace_bytes(primfunc, alignment) ==size

OR we could use the final memory calculation in a non-USMP flow as follows :

deftest_workspace_calculation(workspace_byte_alignment, main_workspace_size):
mod, params=tvm.relay.testing.synthetic.get_workload()
target="c"
runtime=Runtime("crt")
executor=Executor(
"aot",
{
"workspace-byte-alignment": workspace_byte_alignment,
},
)
withtvm.transform.PassContext(
opt_level=3,
config={
"tir.disable_vectorize": True,
},
):
lib=tvm.relay.build(mod, target, executor=executor, runtime=runtime, params=params)
mlf_memory_map=mlf._build_function_memory_map(lib.function_metadata)
assertmlf_memory_map["main"][0]["workspace_size_bytes"] ==main_workspace_size

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the tests to check for reduction in memory instead of bitwise accuracy with TFLite (I think it would be still good to have some FVP based tests when cascader is enabled, but it looks like that would need quite a bit of infra refactor, so I'll do it in a separate patch, if this is ok)

@lhutton1lhutton1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me modulo @manupa-arm's comments :)

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 1c20fcd to 2042445CompareApril 11, 2022 11:28
return compiler_attrs.accelerator_config


def enable_cascader():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better is_cascader_enabled, otherwise, it seems you are enabling it with this function.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I changed the function name to is_cascader_enabled, but kept the flag/variable as enable_cascader to align with the philosophy of enable_usmp

@NicolaLancellottiNicolaLancellotti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you @ekalda.

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broadly looks great!

just a nit and a question

mod, params, accel_type, pool_size, enable_cascader=True
)

assert workspace_size_cascader_enabled < workspace_size_cascader_disabled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, should we not check for exact values ?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point, I changed it to check for the exact values

)


def _extract_memory_info(memory_pool):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better for this utility to be part of the cascader and not get exposed to the codegen here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@ekalda
ekaldaforce-pushed the integrate-cascader2 branch 4 times, most recently from e764f8c to 094fbcbCompareApril 21, 2022 13:46
ekaldaand others added 8 commits April 22, 2022 09:30
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
@ekalda
ekaldaforce-pushed the integrate-cascader2 branch from 094fbcb to f212de6CompareApril 22, 2022 09:11

@manupakmanupak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a suggestion for a follow up.

), "Exactly one workspace pool needs to be provided for the U55 cascader"

sram = extract_memory_info(workspace_memory_pools.pools[0])
tir_mod = LowerToTIR(_ethos_u55_cascader(sram))(mod)

@manupakmanupakApr 25, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a followup : Please consider absorbing the call to extract_memory_info inside the cascader. (Sorry for not being clear before). Ideally, we'd want to remove the "MemoryRegion" construct and to get there in the current direction of travel, we should try to confine the usage of it inside the cascader. Therefore the interface of the cascader should be made to accept MemoryPool(s).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this would be the right way to go about it. Let's do it in a follow up!

@manupak
manupak merged commit d2db9cb into apache:mainApr 25, 2022
@manupak

Copy link
Copy Markdown
Contributor

Thanks @ekalda@mbaret@lhutton1@NicolaLancellotti !

This is merged now!

shtinsa pushed a commit to Deelvin/tvm that referenced this pull request May 17, 2022
* [microNPU] Integrate the cascader
Integrate the cascader into the codegen and optionally enable it
with the enable_cascader flag. Includes placeholder MemoryRegions until
integration with the PoolInfos provided by a user.
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
* Fix linting and a docstring
* Plumbing and testing improvements
Plumb the workspace memory pools into into the cascader and make
the tests to check for the memory reduction.
* enable_cascader() -> is_cascader_enabled()
* Check for the exact value of workspace size
* Remove unused ACCEL_TYPES
* Linting...
Change-Id: If2d92846f05a7e8b21be767163841084538805a9
* Rebasing...
Co-authored-by: Matthew Barrett <matthew.barrett@arm.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@ekalda@manupak@NicolaLancellotti@lhutton1