-
Notifications
You must be signed in to change notification settings - Fork 17
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
Encapsulate Storage_base class #528
base: dev-master
Are you sure you want to change the base?
Conversation
0dd1be9
to
97a2597
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev-master #528 +/- ##
==============================================
+ Coverage 17.58% 17.71% +0.12%
==============================================
Files 211 211
Lines 44733 44748 +15
Branches 14941 13920 -1021
==============================================
+ Hits 7868 7928 +60
- Misses 32751 32774 +23
+ Partials 4114 4046 -68 ☔ View full report in Codecov by Sentry. |
@@ -392,6 +392,9 @@ namespace cytnx { | |||
return nullptr; | |||
} | |||
|
|||
/** | |||
* @deprecated This method is not in use anymore. | |||
*/ | |||
virtual void *get_raw_address() const { | |||
cytnx_error_msg(true, "[ERROR] Void Type Scalar cannot have operation!!%s", "\n"); | |||
return nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mark this function as deprecated. It may be deleted or renamed to data()
like std
convention.
cytnx_error_msg(true, "Not implemented.%s", ""); | ||
} | ||
virtual const unsigned long long size() const { | ||
cytnx_error_msg(true, "Not implemented.%s", ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to return a const reference for the ScalarType.
virtual const unsigned long long size() const { | ||
cytnx_error_msg(true, "Not implemented.%s", ""); | ||
} | ||
virtual ~Storage_base(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Base classes must have a virtual deconstructor. Without virtual
, the deconstructor will not be called when deleting the instance of the derived class held by the pointer of the base classes.
// throw a runtime error here. | ||
virtual void *data() const { return nullptr; } | ||
virtual int dtype() const { return Type.Void; } | ||
virtual int device() const { return Device.cpu; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New getters due to the variables of Storage_base
are moved to the derived class.
start_ = nullptr; | ||
size_ = 0; | ||
capacity_ = 0; | ||
return original_start; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should only be used in the functions converting Tensor
and Storage
to numpy arrays.
unsigned long long size_; | ||
unsigned long long capacity_; | ||
unsigned int dtype_; | ||
int device_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variables moved from Storage_base
class to its derived class, StorageImplementation<DType>
.
// delegate numpy array with it's ptr, and swap a auxiliary ptr for intrusive_ptr to | ||
// free. | ||
void *pswap = malloc(sizeof(bool)); | ||
tmpIN._impl->Mem = pswap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variables should be private. release()
is designed to provide the same functionality.
// free. | ||
if (share_mem == false) { | ||
void *pswap = malloc(sizeof(bool)); | ||
tmpIN.storage()._impl->Mem = pswap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do the similar change as the change for Storage
.
Storage Cnst(1, lc.dtype()); | ||
Cnst.set_item(0, lc); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To prevent direct access to the variables defined in a class, we should use the public interface of the class. Copying a scalar is cheap almost like assigning a pointer, so we don't have to worry about the cost here.
I also did the same job in Cpr.cpp, Div.cpp, Mod.cpp, Mul.cpp, and Sub.cpp.
f.write((char *)&this->size(), sizeof(unsigned long long)); | ||
f.write((char *)&this->dtype(), sizeof(unsigned int)); | ||
f.write((char *)&this->device(), sizeof(int)); | ||
auto write_number = [&f](auto number) { | ||
f.write(reinterpret_cast<char *>(&number), sizeof(number)); | ||
}; | ||
write_number(this->size()); | ||
write_number(this->dtype()); | ||
write_number(this->device()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this->size()
and the other statements are not lvalue now, so we cannot access the address by &
.
src/Tensor.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where are these functions used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`Storage::release()` serves for the function converting Storage and Tensor to the numpy array. The reason for implementing this method is that we are encapsulating Storage and the relative classes, which mean we don't want other classes or functions to directly access the member variables. This is just a temporary solution and will be removed when we use std::vector as the underlying storage because it is impossible to make std::vector drops its ownership of the underlying storage.
The size of Scalar is small, so it's cheap for creating a temporary Storage containing only a copy of the value of Scalar. This change is a step toward encapsulating the classes related to Storage.
97a2597
to
36f65fd
Compare
With the current class definition, developers are able to change the variable storing the size of the storage without allocating the underlying storage, which potentially causes memory leaks. To ensure there will be no surprising behavior caused by directly accessing the variables of Storage_base, all variables of Stroage_base are moved to its subclass, StorageImplementation<DType>, and are set as private. All functions outside of StorageImplementation<DType> should access the value of the variable via the getters. The next step in refactoring the components related to Storage is to remove the Storage_base class.
We can check whether HPTT is enabled from the compiler definitions in compile_commands.json.
36f65fd
to
09b2c37
Compare
The first two commits are the same as #525. Please start to review from the third commit.
There are too many files changed to review. I leave comments on the changed lines which are not trivially renaming the variables. You can just review those parts.
With the current class definition, developers are able to change the variable storing the size of the storage without allocating the underlying storage, which potentially causes memory leaks.
To ensure there will be no surprising behavior caused by directly accessing the variables of Storage_base, all variables of Stroage_base are moved to its subclass, StorageImplementation, and are set as private. All functions outside of StorageImplementation should access the value of the variable via the getters.
The next step in refactoring the components related to Storage is to remove the Storage_base class.
Test result
This PR breaks no tests with CUDA, cuQuantum, cuTENSOR, MKL, CUTT, and HPTT enabled.