Skip to content
This repository has been archived by the owner on Feb 5, 2024. It is now read-only.

Add C++ support for raw CUDA pointer backed state-vector #16

Open
wants to merge 23 commits into
base: main
Choose a base branch
from

Conversation

mlxd
Copy link
Member

@mlxd mlxd commented Apr 21, 2022

Context: This PR allows an existing CUDA memory block to be accessed by LightningGPU through a new class StateVectorCudaRaw.

Description of the Change: New class allowing raw CUDA pointer access to cuQuantum routines. Associated tests extended for new class. Modified internal binding names and import structure. IN addition, following on from these supports, a new builder is added to allow Torch tensors to be mapped to the C++ class backend through the raw pointer class.

Benefits: Allows use of externally managed CUDA memory with LightningGPU

Possible Drawbacks: Additional maintenance overhead with additional class. Potential future restructure may be required.

Related GitHub Issues:

@github-actions
Copy link

Hello. You may have forgotten to update the changelog!
Please edit .github/CHANGELOG.md with:

  • A one-to-two sentence description of the change. You may include a small working example for new features.
  • A link back to this PR.
  • Your name (or GitHub username) in the contributors section.

@mlxd mlxd changed the title [WIP] Add support for raw CUDA pointer state-vector [WIP] Add support for raw CUDA pointer backed state-vector Apr 21, 2022
@mlxd mlxd changed the title [WIP] Add support for raw CUDA pointer backed state-vector [WIP] Add C++ support for raw CUDA pointer backed state-vector May 25, 2022
@mlxd mlxd changed the title [WIP] Add C++ support for raw CUDA pointer backed state-vector Add C++ support for raw CUDA pointer backed state-vector May 26, 2022
Copy link
Contributor

@AmintorDusko AmintorDusko left a comment

Choose a reason for hiding this comment

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

Nice PR! Excellent work!

@@ -41,7 +41,12 @@ jobs:
with:
access_token: ${{ github.token }}

- uses: actions/checkout@v2
- name: Remove unused SDKs for extra storage during build
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice!

static_cast<void>(ptr);
}

/*StateVectorCudaRaw(const StateVectorCudaRaw &other, cudaStream_t stream =
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason to keep this here as a comment?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nope, you are completely right. This can go.

}
}
/**
* @brief STL-fiendly variant of `applyOperation(
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @brief STL-fiendly variant of `applyOperation(
* @brief STL-friendly variant of `applyOperation(

Copy link
Member Author

Choose a reason for hiding this comment

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

Well spotted!

@AmintorDusko
Copy link
Contributor

Hey @mlxd, I just have one comment, one question, and one suggestion.

Copy link
Contributor

@chaeyeunpark chaeyeunpark left a comment

Choose a reason for hiding this comment

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

Nice work @mlxd! I just want to ask some questions.

const std::vector<Precision> &)>;
using FMap = std::unordered_map<std::string, ParFunc>;
const FMap par_gates_;
custatevecHandle_t handle;
Copy link
Contributor

Choose a reason for hiding this comment

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

why not

Suggested change
custatevecHandle_t handle;
custatevecHandle_t handle_;

?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, just as easily done.

StateVectorCudaRaw(void *gpu_data, size_t length, cudaStream_t stream = 0)
: StateVectorCudaRaw(Util::log2(length), stream) {
CFP_t *ptr = BaseType::getData();
ptr = reinterpret_cast<CFP_t *>(gpu_data);
Copy link
Contributor

Choose a reason for hiding this comment

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

What does this line do? (as ptr doesn't seem to be used)

Copy link
Member Author

Choose a reason for hiding this comment

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

I believe this is an error that I made on previous tests with casting rules --- completely skipped my brain, thanks for this.

* @tparam Precision Floating-point precision type.
*/
template <class Precision>
class SVCudaTorch final : public StateVectorCudaRaw<Precision> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I am curious what is the exact difference between this class and StateVectorCudaRaw. Can we just use StateVectorCudaRaw by providing a function converting torch::tensor to StateVectorCudaRaw?

Copy link
Member Author

Choose a reason for hiding this comment

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

That is a good idea, but the issue is with the lifetime of the torch objects --- when capturing a tensor, we can guarantee it's existence, but doing so with a raw pointer (assuming we cannot hold it elsewhere) the underlying allocator may move the pool, or just copy it to a new block and throw this away. I think it was safer to explicitly ensure the reference counter on a tensor was ticked up by capturing it here, rather than just grabbing the raw pointer to its data.

Copy link
Contributor

Choose a reason for hiding this comment

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

Aha I see. So we anyway need to keep torch::tensor instance for a lifetime.

std::string cls_name =
"LightningGPU_" + SVType<PrecisionT>::getClassName() + "_C" + bitsize;

py::class_<SVType<PrecisionT>>(m, cls_name.c_str())
Copy link
Contributor

Choose a reason for hiding this comment

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

I am also slightly worried about the code publication here (with bindings/Binding.cpp).

Copy link
Member Author

Choose a reason for hiding this comment

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

Yea, this was a nightmare to integrate with the existing bindings. The amount of duplication is a pain here, but we definitely want to keep these modules separated from another for now. I think this requires a complete reworking of the build system to better support such optional packages as this.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree that it is better to separate this module, but can we just make move this function to another header file and use them in both cases?

Copy link
Member Author

Choose a reason for hiding this comment

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

That is probably the better option here, thanks for the suggestion.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants