Skip to content

chore: cache deserialized_module and script_module #4196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 11, 2024

Conversation

njzjz
Copy link
Member

@njzjz njzjz commented Oct 8, 2024

Summary by CodeRabbit

  • New Features
    • Enhanced performance of module serialization and deserialization by converting instance properties to class methods for improved access and efficiency.
  • Bug Fixes
    • Resolved issues related to instance-level access, now allowing direct class-level method access for better functionality.
  • Refactor
    • Updated property signatures to utilize class methods for caching results, optimizing performance and resource management.

@njzjz njzjz added the Test CUDA Trigger test CUDA workflow label Oct 8, 2024
@github-actions github-actions bot added the Python label Oct 8, 2024
Copy link
Contributor

coderabbitai bot commented Oct 8, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

The changes involve modifications to the DPTestCase and PTTestCase classes in their respective files. The deserialized_module property in DPTestCase has been converted from an instance property to a class method, now decorated with @lru_cache(maxsize=1). In PTTestCase, both script_module and deserialized_module properties have been transformed into class methods with similar caching mechanisms. Additionally, both classes have introduced a tearDownClass method to clear caches and manage the module attribute.

Changes

File Path Change Summary
source/tests/universal/dpmodel/backend.py deserialized_module changed from instance property to class method with @lru_cache(maxsize=1). A new method _get_deserialized_module added. tearDownClass method added.
source/tests/universal/pt/backend.py script_module and deserialized_module changed from instance properties to class methods with @lru_cache(maxsize=1) decorators. New methods _get_script_module and _get_deserialized_module added. tearDownClass method added.

Sequence Diagram(s)

sequenceDiagram
    participant DPTestCase
    participant PTTestCase
    participant Module

    DPTestCase->>Module: Access class-level module
    Module-->>DPTestCase: Return module data
    DPTestCase->>DPTestCase: Deserialize module
    DPTestCase-->>DPTestCase: Return deserialized module

    PTTestCase->>Module: Access class-level module
    Module-->>PTTestCase: Return module data
    PTTestCase->>Module: Script module with torch.jit.script
    PTTestCase-->>PTTestCase: Return script module
    PTTestCase->>PTTestCase: Deserialize module
    PTTestCase-->>PTTestCase: Return deserialized module
Loading

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (2)
source/tests/universal/dpmodel/backend.py (1)

37-40: LGTM: Caching and class method conversion for deserialized_module.

The changes to deserialized_module are well-implemented:

  1. Converting to a class method is appropriate as it doesn't rely on instance-specific state.
  2. The @cache decorator will improve performance by memoizing the result.
  3. The use of cls instead of self is correct for a class method.

These changes align well with the PR objective of caching deserialized_module.

Consider adding a docstring to explain the purpose of this method and the effect of caching. For example:

@classmethod
@cache
def deserialized_module(cls):
    """
    Returns a deserialized version of the module.
    
    This method is cached, so subsequent calls will return the same object,
    improving performance for repeated access.
    """
    return cls.module.deserialize(cls.module.serialize())
source/tests/universal/pt/backend.py (1)

Line range hint 36-41: Consider minor optimization in modules_to_test.

The modules_to_test property remains functionally correct. However, for consistency with the new class method implementation of deserialized_module, consider changing self.deserialized_module to self.deserialized_module(). This would explicitly call the method and potentially leverage the caching mechanism more effectively.

Here's a suggested change:

@property
def modules_to_test(self):
    modules = [
        self.module,
-       self.deserialized_module,
+       self.deserialized_module(),
    ]
    return modules
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b807bb4 and 95e4adf.

📒 Files selected for processing (2)
  • source/tests/universal/dpmodel/backend.py (2 hunks)
  • source/tests/universal/pt/backend.py (2 hunks)
🧰 Additional context used
🔇 Additional comments (6)
source/tests/universal/dpmodel/backend.py (2)

2-4: LGTM: Import of cache decorator.

The import of cache from functools is correct and follows Python's import style guidelines. It's appropriately used later in the file.


Line range hint 1-40: Summary: Effective implementation of caching for deserialized_module.

The changes in this file successfully implement caching for the deserialized_module method:

  1. The cache decorator is correctly imported from functools.
  2. The deserialized_module method is converted to a class method and decorated with @cache.

These changes align well with the PR objective of caching deserialized_module. They should improve performance by avoiding repeated serialization and deserialization operations.

The modifications are localized and don't appear to affect other parts of the class or file negatively. Overall, this is a well-implemented performance optimization.

source/tests/universal/pt/backend.py (4)

2-4: LGTM: Import of cache decorator.

The addition of the cache import from functools is appropriate for the subsequent changes in the file. It's correctly placed at the top of the file, following Python's import conventions.


25-29: Excellent optimization: Caching script_module.

The conversion of script_module to a class method with @cache decoration is a great optimization. This change will memoize the result, preventing unnecessary recomputation of the scripted module. The use of cls.module is correct for a class method, and the retention of the torch.jit.optimized_execution(False) context ensures the original behavior is maintained.


31-34: Great optimization: Caching deserialized_module.

The conversion of deserialized_module to a class method with @cache decoration is an excellent optimization. This change will memoize the result, preventing unnecessary serialization and deserialization operations. The use of cls.module is correct for a class method, and the core logic of serialization and deserialization remains intact.


Line range hint 1-95: Overall: Excellent optimizations with caching.

The changes in this file are well-implemented and should significantly improve performance by caching the results of script_module and deserialized_module. The conversion to class methods and the use of the @cache decorator are appropriate and maintain the original functionality while reducing unnecessary computations.

A minor suggestion was made to update the modules_to_test property for consistency, but this is not critical to the functionality.

Great job on these optimizations!

@github-actions github-actions bot removed the Test CUDA Trigger test CUDA workflow label Oct 8, 2024
Signed-off-by: Jinzhe Zeng <[email protected]>
@njzjz njzjz added the Test CUDA Trigger test CUDA workflow label Oct 8, 2024
@github-actions github-actions bot removed the Test CUDA Trigger test CUDA workflow label Oct 8, 2024
Signed-off-by: Jinzhe Zeng <[email protected]>
@njzjz njzjz added the Test CUDA Trigger test CUDA workflow label Oct 8, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (2)
source/tests/universal/dpmodel/backend.py (2)

37-40: LGTM: Well-implemented caching method for deserialization.

The new _get_deserialized_module class method is well-implemented, using appropriate decorators and correctly accessing the class-level module attribute.

Consider adding a brief docstring to explain the purpose of this method and its caching behavior, e.g.:

@classmethod
@cache
def _get_deserialized_module(cls):
    """Returns a deserialized version of the module, caching the result for efficiency."""
    return cls.module.deserialize(cls.module.serialize())

44-45: LGTM: Efficient use of cached deserialization.

The modification to the deserialized_module property effectively utilizes the new cached _get_deserialized_module method while maintaining backwards compatibility.

For improved clarity, consider renaming the condition to explicitly state its purpose:

if hasattr(self.__class__, "module"):
    return self._get_deserialized_module()
else:
    # Fallback for backwards compatibility
    return self.module.deserialize(self.module.serialize())

This change makes the intent of the condition more explicit and adds a comment explaining the fallback behavior.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 013883c and bf6db03.

📒 Files selected for processing (2)
  • source/tests/universal/dpmodel/backend.py (2 hunks)
  • source/tests/universal/pt/backend.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/tests/universal/pt/backend.py
🧰 Additional context used
🔇 Additional comments (2)
source/tests/universal/dpmodel/backend.py (2)

2-4: LGTM: Appropriate import of cache decorator.

The addition of the cache import from functools is correct and follows good practices for import statements.


Line range hint 1-54: Overall: Well-implemented caching for deserialized module.

The changes introduce efficient caching for the deserialized module, which can significantly improve performance for repeated access. The implementation is clean, maintains backwards compatibility, and follows good coding practices. The suggestions provided are minor and focus on improving documentation and clarity.

@github-actions github-actions bot removed the Test CUDA Trigger test CUDA workflow label Oct 8, 2024
Copy link

codecov bot commented Oct 8, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 83.44%. Comparing base (b807bb4) to head (fac7a26).
Report is 194 commits behind head on devel.

Additional details and impacted files
@@            Coverage Diff             @@
##            devel    #4196      +/-   ##
==========================================
- Coverage   83.44%   83.44%   -0.01%     
==========================================
  Files         537      537              
  Lines       52140    52140              
  Branches     3043     3047       +4     
==========================================
- Hits        43509    43508       -1     
  Misses       7683     7683              
- Partials      948      949       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Signed-off-by: Jinzhe Zeng <[email protected]>
@njzjz njzjz added the Test CUDA Trigger test CUDA workflow label Oct 8, 2024
@github-actions github-actions bot removed the Test CUDA Trigger test CUDA workflow label Oct 8, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (7)
source/tests/universal/dpmodel/backend.py (2)

37-41: LGTM: Efficient caching of deserialized module.

The new _get_deserialized_module method effectively caches the deserialized module, which can improve performance. The implementation looks correct.

Consider adding a brief docstring to explain the purpose of this method and its caching behavior. For example:

@classmethod
@cache
def _get_deserialized_module(cls):
    """Returns a deserialized version of the module, caching the result."""
    return cls.module.deserialize(cls.module.serialize())

56-61: LGTM: Proper cleanup in tearDownClass method.

The new tearDownClass method effectively cleans up resources and clears the cache, which is crucial for maintaining a clean state between tests.

Consider adding a try-except block when clearing the cache to handle potential errors gracefully:

@classmethod
def tearDownClass(cls):
    super().tearDownClass()
    if hasattr(cls, "module"):
        del cls.module
    try:
        cls._get_deserialized_module.cache_clear()
    except AttributeError:
        pass  # Cache clearing is not critical if it fails

This change ensures that even if there's an issue with cache clearing (e.g., if the method doesn't exist), the teardown process will complete successfully.

source/tests/universal/pt/backend.py (5)

25-29: LGTM: Addition of _get_script_module method.

The new _get_script_module method is well-implemented:

  • The use of @cache is appropriate for preventing unnecessary recomputation.
  • Using cls.module is correct for a class method.
  • The torch.jit.optimized_execution(False) ensures consistent behavior during testing.

Consider adding a docstring to explain the purpose of this method and its caching behavior.


32-35: LGTM: Improved script_module property.

The modifications to the script_module property are well-implemented:

  • It now leverages class-level caching when possible, which can improve performance.
  • The fallback to the previous implementation ensures backward compatibility.
  • The use of self.__class__ to check for the class attribute is a good practice.

Consider adding a comment explaining the purpose of the hasattr check and why it falls back to the previous implementation.


38-46: LGTM: Addition of _get_deserialized_module and improvements to deserialized_module.

The new _get_deserialized_module method and the changes to the deserialized_module property are well-implemented:

  • The use of @cache in _get_deserialized_module is appropriate for preventing unnecessary recomputation.
  • The modifications to deserialized_module property leverage class-level caching when possible, improving performance.
  • These changes are consistent with the modifications made to script_module.

Consider adding docstrings to both _get_deserialized_module and deserialized_module to explain their purpose and caching behavior.


57-63: LGTM: Addition of tearDownClass method.

The new tearDownClass method is well-implemented:

  • It correctly calls the superclass's tearDownClass method.
  • Deleting the module attribute and clearing the caches helps prevent test interdependence and ensures a clean state for each test run.
  • This implementation follows good practices for cleaning up after tests.

Consider adding a comment explaining why clearing the caches and deleting the module attribute is important for maintaining test isolation.


Line range hint 1-64: Overall assessment: Well-implemented caching and organization improvements.

The changes to this file significantly enhance the PTTestCase class:

  1. Introduction of caching mechanisms for script_module and deserialized_module.
  2. Improved organization with new private methods _get_script_module and _get_deserialized_module.
  3. Addition of a tearDownClass method for proper cleanup.

These modifications should lead to improved performance in tests, especially when running multiple tests that use the same module. The code is well-structured and maintains backward compatibility.

Consider the following to further improve the code:

  1. Add comprehensive docstrings to new methods and properties.
  2. If not already present, consider adding unit tests specifically for these caching mechanisms to ensure they behave as expected under various scenarios.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between bf6db03 and f270632.

📒 Files selected for processing (2)
  • source/tests/universal/dpmodel/backend.py (3 hunks)
  • source/tests/universal/pt/backend.py (3 hunks)
🧰 Additional context used
🔇 Additional comments (3)
source/tests/universal/dpmodel/backend.py (2)

2-4: LGTM: Appropriate import for caching mechanism.

The addition of cache from functools is necessary and appropriate for the new caching mechanism implemented in the class.


44-45: LGTM: Improved efficiency in deserialized_module property.

The changes to the deserialized_module property effectively utilize the new caching mechanism while maintaining backwards compatibility. This should improve performance in most cases.

source/tests/universal/pt/backend.py (1)

2-4: LGTM: Import of cache decorator.

The addition of the cache import from functools is appropriate for the subsequent use of caching in the class methods. This can potentially improve performance by memoizing results of expensive computations.

@njzjz njzjz added the Test CUDA Trigger test CUDA workflow label Oct 9, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (4)
source/tests/universal/pt/backend.py (4)

25-29: LGTM: Efficient implementation of _get_script_module.

The use of @lru_cache(maxsize=1) and @classmethod decorators is an excellent approach to optimize the scripting process. This ensures that the expensive operation of scripting the module is performed only once and the result is cached, improving performance in subsequent calls.

Consider adding a brief comment explaining why torch.jit.optimized_execution(False) is used, as it might not be immediately clear to other developers why optimization is turned off.


31-36: LGTM: Efficient use of cached _get_script_module.

The modification to use the cached _get_script_module method when the module is a class attribute is a good optimization. The fallback to the original implementation ensures backwards compatibility.

Consider adding a brief comment explaining the purpose of the hasattr check, as it might not be immediately clear why this condition is necessary.


38-46: LGTM: Efficient caching of deserialized module.

The implementation of _get_deserialized_module and the modifications to deserialized_module property mirror the changes made to script_module, which is a good consistent approach. The use of @lru_cache(maxsize=1) ensures that the potentially expensive deserialization operation is performed only once.

For consistency with the script_module property, consider adding a comment explaining the purpose of the hasattr check in the deserialized_module property.


57-63: LGTM: Proper cleanup in tearDownClass.

The implementation of tearDownClass is thorough, ensuring that caches are cleared and the module attribute is removed. This is crucial for maintaining test isolation and preventing cached data from affecting subsequent tests.

For added robustness, consider wrapping the cache clearing operations in try-except blocks to handle potential AttributeErrors if the methods don't exist for some reason. This would prevent any issues if the class structure changes in the future.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between f270632 and fac7a26.

📒 Files selected for processing (2)
  • source/tests/universal/dpmodel/backend.py (3 hunks)
  • source/tests/universal/pt/backend.py (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/tests/universal/dpmodel/backend.py
🧰 Additional context used
🔇 Additional comments (2)
source/tests/universal/pt/backend.py (2)

2-4: LGTM: Import of lru_cache is appropriate.

The addition of lru_cache from functools is necessary for the caching mechanism implemented in the subsequent code changes. This import supports the performance improvements made in the class.


Line range hint 1-64: Overall: Excellent performance optimizations with proper cleanup.

The changes implemented in this file are well-thought-out and should significantly improve performance:

  1. The caching mechanism for script_module and deserialized_module using @lru_cache will avoid repeated expensive operations.
  2. The new tearDownClass method ensures proper cleanup and test isolation.
  3. The changes are consistent across different methods, which is good for maintainability.

These optimizations should not introduce any breaking changes to existing functionality. The code is now more efficient while maintaining its original behavior.

Great job on these improvements!

@github-actions github-actions bot removed the Test CUDA Trigger test CUDA workflow label Oct 9, 2024
@njzjz
Copy link
Member Author

njzjz commented Oct 9, 2024

img_v3_02fg_dc5cd45e-1ee1-4708-85ef-526fade56e0g
img_v3_02fg_c9fcb3b1-3c65-4759-baf7-4100816ef4ag

45 minutes are saved

@njzjz njzjz marked this pull request as ready for review October 9, 2024 04:59
@njzjz njzjz requested review from iProzd and wanghan-iapcm October 9, 2024 04:59
@wanghan-iapcm wanghan-iapcm added this pull request to the merge queue Oct 11, 2024
Merged via the queue into deepmodeling:devel with commit 2ca1c06 Oct 11, 2024
63 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants