Skip to content
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

HSPotential Helper replace ifdefs with const expr templates #4623

Closed

Conversation

walshmm
Copy link
Contributor

@walshmm walshmm commented Jun 2, 2023

Please review the developer documentation
on the wiki of this project that contains help and requirements.

Proposed changes

This is a refactor of HSPotential_Helpers.cpp and HSPotential_Helpers.h in accordance with this gist https://gist.github.com/williamfgc/28ffbd23f6888ed89530e3f68c992c93#refactoring-strategy
It removes the QMC_COMPLEX ifdefs and replaces them with templates and const expr as to generate complex/real versions in one compile.

Describe what this PR changes and why. If it closes an issue, link to it here
with a supported keyword.

What type(s) of changes does this code introduce?

Delete the items that do not apply

  • Refactoring (no functional changes, no api changes)

Does this introduce a breaking change?

  • No

What systems has this change been tested on?

Checklist

Update the following with a yes where the items apply. If you're unsure about any of them, don't hesitate to ask. This is
simply a reminder of what we are going to look for before merging your code.

  • Yes. This PR is up to date with current the current state of 'develop'
  • Yes/No. Code added or changed in the PR has been clang-formatted
  • NA. This PR adds tests to cover any new code, or to catch a bug that is being fixed
  • NA. Documentation has been added (if appropriate)

@walshmm walshmm marked this pull request as ready for review June 2, 2023 17:50
@walshmm walshmm changed the title DRAFT: HSPotential Helper replace ifdefs with const expr templates HSPotential Helper replace ifdefs with const expr templates Jun 2, 2023
prckent
prckent previously approved these changes Jun 2, 2023
Copy link
Contributor

@prckent prckent left a comment

Choose a reason for hiding this comment

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

LGTM

Will need a non-ORNL merge.

We should talk if there is anything tricky under AFQMC given our focus on the real space code.

@prckent
Copy link
Contributor

prckent commented Jun 2, 2023

Note: we are at the mercy of the AFMC test coverage here. Recommend you have
QMC_DATA/NiO/NiO_afm_fcidump.h5
QMC_DATA/NiO/NiO_afm_wfn.dat
QMC_DATA/NiO/NiO_nm_choldump.h5
which are only used by AFQMC tests when developing.

Comment on lines 61 to 68
template <class T>
struct is_complex : std::false_type {};
template <>
struct is_complex<ComplexType> : std::true_type {};
template <>
struct is_complex<SPComplexType> : std::true_type {};

{};
Copy link
Contributor

@quantumsteve quantumsteve Jun 2, 2023

Choose a reason for hiding this comment

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

Suggested change
template <class T>
struct is_complex : std::false_type {};
template <>
struct is_complex<ComplexType> : std::true_type {};
template <>
struct is_complex<SPComplexType> : std::true_type {};
{};
template <class T>
struct is_complex : std::false_type {};
template <class T>
struct is_complex<std::complex<T>> : std::true_type {};
template< class T>
inline constexpr bool is_complex_v = is_complex<T>::value;

#if defined(QMC_COMPLEX)
count[2 * (*cik) + 1] += size_t(2); // Lik - 0
#endif
if constexpr (is_complex<T>::value)
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
if constexpr (is_complex<T>::value)
if constexpr (is_complex_v<T>)

Requires the helper function I suggested adding in config.0.h

@@ -35,7 +35,7 @@ namespace
{
//inline double const& ma::conj(double const& d){return d;}
//inline float const& ma::conj(float const& f){return f;}

template<class T>
Copy link
Contributor

Choose a reason for hiding this comment

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

Since these functions are in the implementation file we need to explicitly instantiate them.

William's branch has a couple macros to make this easier.

Copy link
Contributor

@ye-luo ye-luo Jun 2, 2023

Choose a reason for hiding this comment

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

I feel the template parameter should be bool instead of T. Then the explicit instantiation only needs true and false two times.

Copy link
Contributor

Choose a reason for hiding this comment

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

If we go that route, make it an enum or enum class. Names would be clearer than true and false and if in the future we want to add more template options (mixed precision?) there is less to change.

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point @quantumsteve . We will want to add mixed precision support in future to do away with QMC_MIXED_PRECISION. If we can pick a pattern that make both r/c and sp/dp combinations simpler to support, we should.

Copy link
Contributor

Choose a reason for hiding this comment

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

There's another problem here. Something that was overlooked here is that the type of the SpVType_shm_csr_matrix function parameter for these functions would need to become a template parameter since it is dependent on the SPValueType. Following that we could use the CSR_matrix_type::value_type to determine if we're dealing with complex or not.

To Ye's suggestion then, we would still need to make explicit instantiations for just the two sp value types (where the rest of the specialization of csr_matrix remains the same: int, std::size_t, shared_allocator).

* update is_complex template tree to look for generic complex
* ask for is_complex_v instead of is_complex::value
* macro instantiate template functions to help avoid linking errors
@walshmm walshmm force-pushed the hspotentialhelper_complex-real_refactor branch from ebc93c0 to 4fdd6d2 Compare June 2, 2023 20:16
Comment on lines +26 to +27
QMC_FOREACH_REAL_TYPE(MACRO) \
QMC_FOREACH_COMPLEX_TYPE(MACRO)
Copy link
Contributor

Choose a reason for hiding this comment

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

We may want to pick one the other based on QMC_COMPLEX.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if we're going for a unified build, shouldnt both be available?

@@ -23,15 +23,17 @@ namespace afqmc
{
namespace HamHelper
{
template<class T>
Copy link
Contributor

Choose a reason for hiding this comment

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

I think making template<bool IS_COMPLEX> reduce the complexity of explicit template instantiation cases.

Comment on lines 61 to 65
template <class T>
struct is_complex : std::false_type {};

template <class T>
struct is_complex<std::complex<T>> : std::true_type {};
Copy link
Contributor

Choose a reason for hiding this comment

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

is_complex is already in the codebase

template<typename T>

Copy link
Contributor

Choose a reason for hiding this comment

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

Naming convention is also wrong here.

Copy link
Contributor

@PDoakORNL PDoakORNL left a comment

Choose a reason for hiding this comment

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

I think this can be made a bit simpler and more readable by reexamining the typealias choices made in config.h.

csr_matrix lacks meaningful documentation but pretty clearly is primarily templated on a VALUE type

Comment on lines 61 to 65
template <class T>
struct is_complex : std::false_type {};

template <class T>
struct is_complex<std::complex<T>> : std::true_type {};
Copy link
Contributor

Choose a reason for hiding this comment

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

Naming convention is also wrong here.

std::vector<std::size_t> count_nnz_per_cholvec(double cut, TaskGroup_& TG, SpVType_shm_csr_matrix& V2, int NMO);

template<class T>
Copy link
Contributor

Choose a reason for hiding this comment

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

in config.h replace

using SpCType_shm_csr_matrix =
    ma::sparse::csr_matrix<SPComplexType, int, std::size_t, shared_allocator<SPComplexType>, ma::sparse::is_root>;
using SpVType_shm_csr_matrix =
    ma::sparse::csr_matrix<SPValueType, int, std::size_t, shared_allocator<SPValueType>, ma::sparse::is_root>;
using CType_shm_csr_matrix =
    ma::sparse::csr_matrix<ComplexType, int, std::size_t, shared_allocator<ComplexType>, ma::sparse::is_root>;
using VType_shm_csr_matrix =
    ma::sparse::csr_matrix<ValueType, int, std::size_t, shared_allocator<ValueType>, ma::sparse::is_root>;

with

template<typename T>
using CSRMtrxShared<T> = ma::sparse::csr_matrix<SPComplexType, int, std::size_t, shared_allocator<SPComplexType>, ma::sparse::is_root>;

In most cases this will just read
CSRMatrixShared<Value> or CSRMatrixShared<Complex> which is much easier to read quickly and surfaces the important parameter for both read and specializing code.

then one can write

template<typename T>
...(...
     CSRMatrix<T>  WorthlessTwoLetterVariableName,
     ...)
{
....
if constexpr (IsComplex_t<T>::value) {
  ...
}
...
}

assert(map_[2 * (*ci) + 1] >= 0);
assert(map_[2 * (*ci) + 1] - c_origin < vn.size(1));
vn.emplace_back({ik, (map_[2 * (*ci) + 1] - c_origin)},
static_cast<SPValueType>(half * im * (*vi - ma::conj(*vi)))); // Lii - Lii*
Copy link
Contributor

Choose a reason for hiding this comment

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

this should be static_cast<decltype(vn)::value_type>

@walshmm walshmm marked this pull request as draft June 23, 2023 15:14
* use existing is_complex evaluators
* add templated CSR Matrix
* extend IsComplex evaluators with valued version
@walshmm walshmm closed this Nov 10, 2023
Sign up for free to 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.

6 participants