Fix Neureka - #188
Conversation
d0ed93d to
5081593
Compare
64c4501 to
5e21145
Compare
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR removes the experimental ChangesNeureka 3x3 fix and depthwise lowering
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
Deeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.py (1)
103-109: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRedundant
elif depthwisebranch — collapse it.With the depthwise transpose removed earlier in
_weightEncode, theelif depthwiseandelsebranches now return an identical expression, so thedepthwiseflag no longer changes the produced layout. The branch (and possibly thedepthwiseparameter itself, if all callers can drop it) can be simplified.♻️ Proposed simplification
if height == 1 and width == 1: # (cout, cinMajor, Weight Bandwidth Bytes) return weight.reshape(cout, cinMajor, weightBandwidthBytes) - elif depthwise: - return weight.reshape(cout, cinMajor, bits, weightBandwidthBytes) - else: - return weight.reshape(cout, cinMajor, bits, weightBandwidthBytes) + return weight.reshape(cout, cinMajor, bits, weightBandwidthBytes)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Deeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.py` around lines 103 - 109, The `reshapeWeight` logic in `Passes.py` has a redundant `elif depthwise` branch because it returns the same layout as the `else` case. Simplify the conditional so the `depthwise` flag no longer affects the returned `weight.reshape(...)` result, and update the surrounding `_weightEncode`/`reshapeWeight` flow to remove `depthwise` entirely if no callers still need it.Deeploy/Targets/Neureka/Engine.py (1)
38-42: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueVerify that GVSOC logging should be unconditionally enabled at init.
neureka_gvsoc_log_activate(..., NEUREKA_GVSOC_LOG_LEVEL_ALL, ...)is now emitted into the standard init code for every Neureka deployment.LOG_LEVEL_ALLis very verbose and this appears to be a debug/tracing aid; enabling it unconditionally can drown simulation logs and slow runs. Consider gating it behind a debug/profiling flag if it isn't meant to be always-on.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Deeploy/Targets/Neureka/Engine.py` around lines 38 - 42, The Neureka init snippet in _neurekaInitCode always enables gvsoc logging with NEUREKA_GVSOC_LOG_LEVEL_ALL, which should not be unconditionally turned on in normal deployments. Update the init path in Engine.py so neureka_gvsoc_log_activate is only emitted when a debug/profiling flag or similar opt-in is enabled, while keeping neureka_nnx_init and the device setup unchanged. Use the existing _neurekaInitCode generation point to make the logging conditional.Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py (1)
234-235: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
cubeis unused in this loop.Since the DW weight is loaded in full per tile,
cubeis no longer referenced; iterate overinputLoadScheduledirectly for clarity.♻️ Optional cleanup
- for cube, load in zip(outputCubes, inputLoadSchedule): - load['weight'] = HyperRectangle((0,) * len(weightShape), tuple(weightShape)) + for load in inputLoadSchedule: + load['weight'] = HyperRectangle((0,) * len(weightShape), tuple(weightShape))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py` around lines 234 - 235, The loop in NeurekaDepthwiseConstraint is carrying an unused `cube` variable, since the DW weight is loaded in full per tile and only `inputLoadSchedule` is needed. Update the iteration in the relevant weight-loading block to loop directly over `inputLoadSchedule`, keeping the `load['weight'] = HyperRectangle(...)` assignment unchanged and removing the unused `cube` binding for clarity.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Deeploy/Targets/Neureka/Parsers.py`:
- Around line 109-119: Update the Neureka parser methods so they always return
the expected (NetworkContext, bool) tuple instead of a bare False. In
NeurekaDWConv2DParser.parseNodeCtxt, NeurekaPWConv2DParser.parseNodeCtxt, and
NeurekaDenseConv2DParser.parseNodeCtxt, make both failure paths (the
super().parseNodeCtxt call returning false and the weight-shape validation
failure) return the current context together with False, matching the
Tuple[NetworkContext, bool] contract used by the base parser and RQS parser.
Keep the successful return as (newCtxt, True) and ensure callers can safely
unpack the result.
---
Nitpick comments:
In `@Deeploy/Targets/Neureka/Engine.py`:
- Around line 38-42: The Neureka init snippet in _neurekaInitCode always enables
gvsoc logging with NEUREKA_GVSOC_LOG_LEVEL_ALL, which should not be
unconditionally turned on in normal deployments. Update the init path in
Engine.py so neureka_gvsoc_log_activate is only emitted when a debug/profiling
flag or similar opt-in is enabled, while keeping neureka_nnx_init and the device
setup unchanged. Use the existing _neurekaInitCode generation point to make the
logging conditional.
In `@Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py`:
- Around line 234-235: The loop in NeurekaDepthwiseConstraint is carrying an
unused `cube` variable, since the DW weight is loaded in full per tile and only
`inputLoadSchedule` is needed. Update the iteration in the relevant
weight-loading block to loop directly over `inputLoadSchedule`, keeping the
`load['weight'] = HyperRectangle(...)` assignment unchanged and removing the
unused `cube` binding for clarity.
In `@Deeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.py`:
- Around line 103-109: The `reshapeWeight` logic in `Passes.py` has a redundant
`elif depthwise` branch because it returns the same layout as the `else` case.
Simplify the conditional so the `depthwise` flag no longer affects the returned
`weight.reshape(...)` result, and update the surrounding
`_weightEncode`/`reshapeWeight` flow to remove `depthwise` entirely if no
callers still need it.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 4e9e3fa4-4260-4a98-9c31-0218ebe4ba82
📒 Files selected for processing (21)
CHANGELOG.mdDeeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.pyDeeploy/DeeployTypes.pyDeeploy/Targets/Neureka/Deployer.pyDeeploy/Targets/Neureka/Engine.pyDeeploy/Targets/Neureka/Parsers.pyDeeploy/Targets/Neureka/Templates/ConvTemplate.pyDeeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.pyDeeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.pyDeeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.pyDeeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.pyDeeploy/Targets/PULPOpen/TopologyOptimizationPasses/Passes.pyDeeployTest/Tests/Kernels/Integer/Conv/DW_3x3_RQ/inputs.npzDeeployTest/Tests/Kernels/Integer/Conv/DW_3x3_RQ/network.onnxDeeployTest/Tests/Kernels/Integer/Conv/DW_3x3_RQ/outputs.npzDeeployTest/Tests/Kernels/Integer/Conv/Regular_3x3_RQ/inputs.npzDeeployTest/Tests/Kernels/Integer/Conv/Regular_3x3_RQ/network.onnxDeeployTest/Tests/Kernels/Integer/Conv/Regular_3x3_RQ/outputs.npzDeeployTest/testMVP.pyDeeployTest/testUtils/deeployRunner.pyDeeployTest/test_siracusa_neureka_tiled_config.py
💤 Files with no reviewable changes (1)
- DeeployTest/testMVP.py
There was a problem hiding this comment.
🧹 Nitpick comments (1)
Deeploy/Targets/Neureka/Engine.py (1)
41-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider removing the commented-out GVSOC log line.
The commented-out
neureka_gvsoc_log_activate(...)call is dead code in the generated init string. If it's kept intentionally for easy debug toggling, a brief comment explaining that would help future readers.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Deeploy/Targets/Neureka/Engine.py` at line 41, Remove the commented-out neureka_gvsoc_log_activate call from the init string, or if you want to keep it for debug toggling, replace it with a brief explanatory comment so the intent is clear. Update the Neureka engine initialization logic in Engine.py around the generated init string to avoid leaving dead code in the output.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@Deeploy/Targets/Neureka/Engine.py`:
- Line 41: Remove the commented-out neureka_gvsoc_log_activate call from the
init string, or if you want to keep it for debug toggling, replace it with a
brief explanatory comment so the intent is clear. Update the Neureka engine
initialization logic in Engine.py around the generated init string to avoid
leaving dead code in the output.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0934c17d-b027-42c9-83a5-2d1681520b68
📒 Files selected for processing (4)
Deeploy/Targets/Neureka/Engine.pyDeeploy/Targets/Neureka/Parsers.pyDeeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.pyDeeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.py
🚧 Files skipped from review as they are similar to previous changes (3)
- Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py
- Deeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.py
- Deeploy/Targets/Neureka/Parsers.py
Victor-Jung
left a comment
There was a problem hiding this comment.
Good PR with good test coverage, I just have one small question.
PS: There is a bug wiht the XDNA CI that I will address in a hotfix, it is not necessary for the XDNA CI to pass for merging.
|
@marchioa Can you rebase and then I'd merge. |
…te conv layers - in parser, weights are contrained to have 3 dimensions. That is correct for PW only. DW and Dense require 4 dimensions. The fix allows weights with 4 dimensions for DW and Dense. - in tiler, again only 3-dim weights for PW is supported. Add support for 4-dim weights for DW and Dense. - in test-runner, arguments for neureka are ignored. Add support for `enable-3x3` and `neureka-wmem` arguments.
…the bias is coherent with requantshift add vector
The flag avoid that aliases of input/output (such as a no-op reshape view) is deallocated
…totally supported
… DW and Dense 3x3 tests, general tile constraint refactor
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
Deeploy/Targets/Neureka/TileConstraints/NeurekaConvTileConstraint.py (1)
98-126: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse
strict=Truewhen zipping counter names with template counters, and drop the unused unpack.
getCounters()returning a differently-sized tuple would silently drop replacements instead of failing loudly.COffseton Line 99 is also unused (ruff RUF059).♻️ Proposed tweak
- (_, _, _, COffset) = cube.offset (_, HSize, WSize, CSize) = cube.dims @@ - for name, value in zip(_COUNTER_NAMES, counters): + for name, value in zip(_COUNTER_NAMES, counters, strict = True): rep.append(name, uint16_t, value)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Deeploy/Targets/Neureka/TileConstraints/NeurekaConvTileConstraint.py` around lines 98 - 126, Update the counter loop in the output-cube representation logic to use strict zip behavior when pairing _COUNTER_NAMES with counters, so mismatched lengths fail visibly. Remove the unused COffset unpack from cube.offset while preserving the remaining offset handling.Source: Linters/SAST tools
Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py (1)
97-113: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAxis/constant pairing is crossed.
dim_im_out_xis paired with_NEUREKA_PE_Wbut constrainsoutputHeightVar, anddim_im_out_y/_NEUREKA_PE_HconstrainsoutputWidthVar. Behaviour is identical today only because both constants are 6; swapping the constants (or renaming) makes the intent robust if they ever diverge.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py` around lines 97 - 113, Correct the axis/constant pairing in the pointwise constraints: update the dim_im_out_x branch to constrain outputWidthVar with _NEUREKA_PE_W, and the dim_im_out_y branch to constrain outputHeightVar with _NEUREKA_PE_H. Apply the same mapping in both addTileSizeDivisibleConstraint and Max() constraints.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Deeploy/Targets/Neureka/Parsers.py`:
- Around line 60-66: Update the condition in the visible validation block to use
boolean negation for channels_first: replace the comparison in the all(...)
expression with the equivalent not channels_first check, leaving the other shape
validations unchanged.
---
Nitpick comments:
In `@Deeploy/Targets/Neureka/TileConstraints/NeurekaConvTileConstraint.py`:
- Around line 98-126: Update the counter loop in the output-cube representation
logic to use strict zip behavior when pairing _COUNTER_NAMES with counters, so
mismatched lengths fail visibly. Remove the unused COffset unpack from
cube.offset while preserving the remaining offset handling.
In `@Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py`:
- Around line 97-113: Correct the axis/constant pairing in the pointwise
constraints: update the dim_im_out_x branch to constrain outputWidthVar with
_NEUREKA_PE_W, and the dim_im_out_y branch to constrain outputHeightVar with
_NEUREKA_PE_H. Apply the same mapping in both addTileSizeDivisibleConstraint and
Max() constraints.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 641fdec2-2d3e-4fd0-9695-eba53bcea1d1
📒 Files selected for processing (28)
CHANGELOG.mdDeeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.pyDeeploy/DeeployTypes.pyDeeploy/Targets/Neureka/Deployer.pyDeeploy/Targets/Neureka/Engine.pyDeeploy/Targets/Neureka/Parsers.pyDeeploy/Targets/Neureka/Templates/ConvTemplate.pyDeeploy/Targets/Neureka/TileConstraints/NeurekaConvTileConstraint.pyDeeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.pyDeeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.pyDeeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.pyDeeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.pyDeeploy/Targets/PULPOpen/TopologyOptimizationPasses/Passes.pyDeeployTest/Tests/Kernels/Integer/Conv/DW_3x3/inputs.npzDeeployTest/Tests/Kernels/Integer/Conv/DW_3x3/network.onnxDeeployTest/Tests/Kernels/Integer/Conv/DW_3x3/outputs.npzDeeployTest/Tests/Kernels/Integer/Conv/DW_3x3_RQ/inputs.npzDeeployTest/Tests/Kernels/Integer/Conv/DW_3x3_RQ/network.onnxDeeployTest/Tests/Kernels/Integer/Conv/DW_3x3_RQ/outputs.npzDeeployTest/Tests/Kernels/Integer/Conv/Regular_3x3/inputs.npzDeeployTest/Tests/Kernels/Integer/Conv/Regular_3x3/network.onnxDeeployTest/Tests/Kernels/Integer/Conv/Regular_3x3/outputs.npzDeeployTest/Tests/Kernels/Integer/Conv/Regular_3x3_RQ/inputs.npzDeeployTest/Tests/Kernels/Integer/Conv/Regular_3x3_RQ/network.onnxDeeployTest/Tests/Kernels/Integer/Conv/Regular_3x3_RQ/outputs.npzDeeployTest/testMVP.pyDeeployTest/testUtils/deeployRunner.pyDeeployTest/test_siracusa_neureka_tiled_config.py
💤 Files with no reviewable changes (1)
- DeeployTest/testMVP.py
🚧 Files skipped from review as they are similar to previous changes (14)
- DeeployTest/testUtils/deeployRunner.py
- DeeployTest/test_siracusa_neureka_tiled_config.py
- DeeployTest/Tests/Kernels/Integer/Conv/DW_3x3/network.onnx
- DeeployTest/Tests/Kernels/Integer/Conv/Regular_3x3/inputs.npz
- DeeployTest/Tests/Kernels/Integer/Conv/DW_3x3/outputs.npz
- DeeployTest/Tests/Kernels/Integer/Conv/DW_3x3/inputs.npz
- Deeploy/Targets/Neureka/Templates/ConvTemplate.py
- DeeployTest/Tests/Kernels/Integer/Conv/Regular_3x3/outputs.npz
- CHANGELOG.md
- Deeploy/Targets/Neureka/Engine.py
- Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py
- Deeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.py
- Deeploy/Targets/Neureka/Deployer.py
- Deeploy/Targets/PULPOpen/TopologyOptimizationPasses/Passes.py
Current implementation of Neureka has a few bugs that need to be fixed. This PR wants to fix those bugs and provide some test to check the functionality. Most changes are related to the tiler for Dense and DW Convolutions.
Added
NeurekaNCHWtoNHWCDwConvPasswhich apply the weight layout depending on the engine.Changed
NeurekaReshapePointwiseConvolutionPass_requantized_gemm_to_pw_fun, add a guard onmulandaddshapes to check if they are consistent with PW output channels.Fixed
_merge_conv_rq_funlowering pass (which mergesConvandRequantShiftintoRequantConv) to make the Engine color be inherited fromConvinstead ofRequantShift._createIOBindings, set_live = Trueon network input and output buffers. They are externally allocated and effectively reserved for the whole inference (mirroringConstantBuffer, which already hardcodes_live = True). This makeshas_live_aliases()correctly see them as live, so any buffer aliasing a network I/O tensor is no longer deallocated while the I/O tensor is still in use.has_live_aliases():visited = set(self.name)built a set of the name's characters instead of{self.name}PR Merge Checklist
develcommit and pointing todevel.CHANGELOG.mdfile has been updated.