Skip to content

Conversation

@davpoolechem
Copy link
Contributor

@davpoolechem davpoolechem commented Jan 11, 2023

Description

This PR is the start of a two-part mini-project regarding the two DFJK algorithms present in Psi4 - MemDFJK and DiskDFJK. This first PR handles some changes to MemDFJK, while the next PR in this project will handle the same changes to DiskDFJK.

So, what are the changes? MemDFJK and DiskDFJK hold a rather interesting property. Each of them is actually a combination of two sub-algorithms - one sub-algorithm which is optimized for storing ERIs in memory, and the other sub-algorithm which is optimized for storing ERIs on disk. This, in total, leads to a potential combination of 4 algorithms that can be utilized when one sets SCF_TYPE to DF. Now, one can set SCF_TYPE to either MEM_DF to DISK_DF to use MemDFJK or DIskDFJK, respectively. However, one cannot explicitly use a keyword to control whether MemDFJK or DiskDFJK uses its corresponding in-core or out-of-core sub-algorithm. Which sub-algorithm is used, is entirely dictated by the amount of memory allocated to Psi4 compared to the amount of memory needed to store ERIs.

This PR project seeks to remedy the aforementioned issue by implementing exactly such a keyword for both MemDFJK and DiskDFJK, to control whether they use their in-core or out-of-core sub-algorithms. The new keyword is FORCE_MEM, which can take three options. FORCE_MEM=AUTO (the default) maintains the previous behavior, in which a sub-algorithm is selected based on user-supplied memory. FORCE_MEM=NO_INCORE forces the DF algorithm to use its out-of-core sub-algorithm, even if enough memory is given to run the calculation in-core. Finally, FORCE_MEM=FORCE_INCORE forces the DF algorithm to run its in-core sub-algorithm, and causes the calculation to throw an exception if not enough memory is given to Psi4 to utilize the in-core sub-algorithm.

So why, exactly, do we want this? In truth, this is mostly a debug and expert option. The entire reason I started this PR project is actually because the lack of control over in-core vs. out-of-core DF algorithms was a bit of a thorn in my side in my JK benchmarks. That said, it still works well as a debug option, wherein you can enforce looking at either the in-core or out-of-core algorithm for either MemDFJK or DiskDFJK. Also, FORCE_MEM=FORCE_INCORE has a neat practical application in that you can lock the calculation out of doing on-disk calculations, if one desires to not do so for time's sake.

This first PR implements the FORCE_MEM keyword and applies it to the MemDFJK algorithm. The second half of this PR project will apply the FORCE_MEM keyword to DIskDFJK.

User API & Changelog headlines

  • The "FORCE_MEM" expert option has been added to Psi4, enabling more fine-grained control over the behavior of the SCF_TYPE="DF" algorithms.

Dev notes & details

  • Adds a new keyword "FORCE_MEM" to Psi4. The FORCE_MEM keyword allows the user to specify, for MemDFJK (in this PR) and DiskDFJK (the next PR), whether the algorithm uses its in-core (FORCE_MEM=FORCE_INCORE) or out-of-core (FORCE_MEM=NO_INCORE) sub-algorithm, or whether the sub-algorithm is selected automatically based on allocated memory (FORCE_MEM=AUTO, the default).
  • Implements functionality of the FORCE_MEM keyword to the MemDFJK class (i.e., the MEM_DF SCF_TYPE).

Questions

  • Would "FORCE_DF_MEM" be a better name for the new keyword?

Checklist

Status

  • Ready for review
  • Ready for merge

@davpoolechem davpoolechem force-pushed the dpoole34/jk-io-control branch 3 times, most recently from ec29614 to fd95bd4 Compare January 19, 2023 16:06
a |globals__scf_type| ``DIRECT`` calculation -*/
options.add_bool("DF_SCF_GUESS", true);
/*- Forcibly disable or enable in- or out-of-core algorithms for MemDF/DiskDF. For debug purposes. !expert -*/
options.add_str("FORCE_MEM", "AUTO", "AUTO FORCE_INCORE NO_INCORE");
Copy link
Member

Choose a reason for hiding this comment

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

I guess what troubles me about this PR is that it's adding a new option FORCE_MEM that pertains to one SCF_TYPE, but there's a PK_NO_INCORE already that does a partial job of the same but for a different single SCF_TYPE.

I wonder if there should be a single INCORE_TYPE option with values AUTO, INCORE, OUTOFCORE (or MEM/DISK or FORCE_INCORE/NO_INCORE or any combination thereof) and have it work for PK (will need more logic b/c mem-only not selectable at present), MEM_DF, DISK_DF (in future PR), and maybe DF (auto-selection of MEM_DF/DISK_DF)? What do folks think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just as a note, this PR applies FORCE_MEM to both SCF_TYPE=MEM_DF and SCF_TYPE=DF (the latter when MemDFJK is automatically selected, of course). The implementation of FORCE_MEM in MemDFJK/DFHelper is independent of the SCF_TYPE used to utilize it.

I do see what you mean about overlapping keywords, though. This PR set is currently planned to be a two-part project, where FORCE_MEM will apply to both the MemDFJK and DiskDFJK algorithms by the end. Based on what you mentioned, it may be worth combining the PK_NO_INCORE keyword with the FORCE_MEM option so that all of MEM_DF, DISK_DF, DF, and PK use it.

Such a plan should be doable across separate PRs, of which this PR is one. That said, this all does bring up the question of PR ordering. This PR introduces the FORCE_MEM option and implements it into MemDFJK, but maybe it is better to split those two and have the introduction of FORCE_MEM replace PK_NO_INCORE for the initial PR?

Copy link
Member

Choose a reason for hiding this comment

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

what do you think of the below?

/*- For certain |globals__scf_type| algorithms that have internal sub-algorithms
    depending on available memory or other hardware constraints, allow the best
    sub-algorithm for the molecule and conditions (``AUTO`` ; usual mode) or
    forcibly select a sub-algorithm (usually only for debugging or profiling).
    Presently, ``SCF_TYPE=MEM_DF`` can have ``INCORE`` or ``OUT_OF_CORE`` selected.
    (This also applies for ``SCF_TYPE=DF`` when ``MEM_DF`` active.) !expert -*/
options.add_str("SCF_SUBTYPE", "AUTO", "AUTO INCORE OUT_OF_CORE");

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Although I do hold some reservations on using SCF_SUBTYPE (that being that it is a little too general, since only specific JK algorithms could take advantage of it), it is worth noting that Composite methods, and particularly the CompositeJK class, would be a very possible use case of this keyword.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All right, after further discussion of the idea at the Psi4 dev meeting, I understand the scope of this suggestion better; and I will implement it!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done and done!

@davpoolechem davpoolechem force-pushed the dpoole34/jk-io-control branch from fd95bd4 to af4d230 Compare January 23, 2023 16:12
a |globals__scf_type| ``DIRECT`` calculation -*/
options.add_bool("DF_SCF_GUESS", true);
/*- Forcibly disable or enable in- or out-of-core algorithms for MemDF/DiskDF. For debug purposes. !expert -*/
options.add_str("FORCE_MEM", "AUTO", "AUTO FORCE_INCORE NO_INCORE");
Copy link
Member

Choose a reason for hiding this comment

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

what do you think of the below?

/*- For certain |globals__scf_type| algorithms that have internal sub-algorithms
    depending on available memory or other hardware constraints, allow the best
    sub-algorithm for the molecule and conditions (``AUTO`` ; usual mode) or
    forcibly select a sub-algorithm (usually only for debugging or profiling).
    Presently, ``SCF_TYPE=MEM_DF`` can have ``INCORE`` or ``OUT_OF_CORE`` selected.
    (This also applies for ``SCF_TYPE=DF`` when ``MEM_DF`` active.) !expert -*/
options.add_str("SCF_SUBTYPE", "AUTO", "AUTO INCORE OUT_OF_CORE");

@davpoolechem davpoolechem force-pushed the dpoole34/jk-io-control branch from af4d230 to cb9a154 Compare February 1, 2023 14:19
public:
DFHelper(std::shared_ptr<BasisSet> primary, std::shared_ptr<BasisSet> aux);
DFHelper(std::shared_ptr<BasisSet> primary, std::shared_ptr<BasisSet> aux,
Options& options);
Copy link
Member

Choose a reason for hiding this comment

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

There's no easy way around adding Options to DFHelper?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Theoretically, one could simply pass the setting of the "SCF_SUBTYPE" keyword itself through the constructor instead of the entire options object, as "SCF_SUBTYPE" is the only option DFHelper really uses right now. I went with this way, though, because I consider it more elegant (more in line with the JK constructors), and it helps future-proof in the case that options are needed in DFHelper in the future.

Copy link
Contributor Author

@davpoolechem davpoolechem Feb 7, 2023

Choose a reason for hiding this comment

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

Looking into it some more, it may be possible to access the "SCF_SUBTYPE" variable through Process::environment instead of passing an options object. I'm exploring this possibility currently.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So it seems Process::environment can be used to get "SCF_SUBTYPE", instead of passing an options object! If this is the preferred methodology, I'll be happy to use that way instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After further discussion with Lori, I have reimplemented options access in DFHelper using Process::environment!

@davpoolechem davpoolechem force-pushed the dpoole34/jk-io-control branch 2 times, most recently from 8d87006 to 0f72c6b Compare February 16, 2023 20:42
MemDFJK::MemDFJK(std::shared_ptr<BasisSet> primary, std::shared_ptr<BasisSet> auxiliary)
: JK(primary), auxiliary_(auxiliary) {
MemDFJK::MemDFJK(std::shared_ptr<BasisSet> primary, std::shared_ptr<BasisSet> auxiliary,
Options& options) : JK(primary), auxiliary_(auxiliary), options_(options) {
Copy link
Member

Choose a reason for hiding this comment

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

Options remains in the MemDFJK constructor?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This actually opens up a potential route of discussion!

Yes, options remains in the MemDFJK constructor. Of the JK derived classes, all of them contain an options_ member variable, except for GTFockJK, MemDFJK, and DiskDFJK (and CDJK by extension). I originally added options to the MemDFJK constructor to define its own options_ member variable, which was then passed to DFHelper for this PR. However, even with the removal of explicit options-passing to DFHelper, having an options_ member variable for MemDFJK is still reasonable from a standardization perspective. in my opinion.

What are your thoughts on the matter?

Copy link
Member

Choose a reason for hiding this comment

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

ah, thanks for the clarification! yes, I agree with adding options_ for standardization. it'll be easier to deal with these classes if they have consistent member data.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I would agree! In that case, I will keep this as it is, then.

Copy link
Member

@loriab loriab left a comment

Choose a reason for hiding this comment

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

lgtm, thanks for the new knob!

@loriab loriab added the scf Involves general SCF: convergence algorithms, RHF/UHF/ROHF/CUHF... label Feb 17, 2023
@loriab loriab added this to the Psi4 1.8 milestone Feb 17, 2023
@davpoolechem davpoolechem force-pushed the dpoole34/jk-io-control branch 2 times, most recently from 9184115 to 9c2727b Compare March 1, 2023 14:26
@davpoolechem davpoolechem force-pushed the dpoole34/jk-io-control branch from 9c2727b to 8e19547 Compare March 17, 2023 13:55
@davpoolechem davpoolechem force-pushed the dpoole34/jk-io-control branch from 8e19547 to 0ae0243 Compare March 27, 2023 14:24
@davpoolechem davpoolechem force-pushed the dpoole34/jk-io-control branch from 0ae0243 to dabf33c Compare April 4, 2023 15:00
@JonathonMisiewicz
Copy link
Contributor

To be clear, AO_core_ controls which subalgorithm is used? If so, that should be mentioned in a comment.

@davpoolechem
Copy link
Contributor Author

To be clear, AO_core_ controls which subalgorithm is used? If so, that should be mentioned in a comment.

That's correct! AO_core_ = true means the in-core subalgorithm is used, while AO_core_ = false means the out-of-core subalgorithm is used. I added comments to clarify.

Copy link
Contributor

@JonathonMisiewicz JonathonMisiewicz left a comment

Choose a reason for hiding this comment

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

Please fix verb tense.

@davpoolechem davpoolechem force-pushed the dpoole34/jk-io-control branch from f37c4e8 to 9bb87c8 Compare April 11, 2023 17:47
@davpoolechem davpoolechem added this pull request to the merge queue Apr 19, 2023
Merged via the queue into psi4:master with commit 824d07d Apr 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scf Involves general SCF: convergence algorithms, RHF/UHF/ROHF/CUHF...

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants