Skip to content

High number of calls of copy constructor/assigment operator for ModelType #39

Open
@qacwnfq

Description

Hey,

I was just benchmarking DNest4 for some of my more memory intensive/complex models and I noticed, that
the copy constructor and assigment operators were called quite often. This leads to some low performance in my use cases, which is why I tried to identify the code, where it happens.

I think this is the place in SamplerImpl.h:

	LikelihoodType& logl = log_likelihoods[which];

	// Do the proposal for the particle
	ModelType proposal = particle;
	double log_H = proposal.perturb(rng);

	// Prevent unnecessary exponentiation of a large number
	if(log_H > 0.0)
		log_H = 0.0;

    if(rng.rand() <= exp(log_H))
    {
    	LikelihoodType logl_proposal(proposal.log_likelihood(), logl.get_tiebreaker());

    	// Do the proposal for the tiebreaker
    	log_H += logl_proposal.perturb(rng);

	    // Accept?
	    if(level.get_log_likelihood() < logl_proposal)
	    {
		    particle = proposal;
		    logl = logl_proposal;
		    level.increment_accepts(1);
	    }

There are two lines here which impact performance:
The first is
ModelType propsal=particle;
and the second is
particle = proposal;

I believe these copies can be replaced by something more efficient for complex models, because we actually only have to track the proposal and log(H) and then decide if the ModelType should set state to the value of proposal or if it should keep the state it already had. In this case we wouldn't need to copy the whole model every time we try to update a particle, we would only change the internal state, which can probably even be done by std::move or std::swap since we discard the rejected proposals in this snippet.

I can make a PR for this, but I'm unsure how to deal with the changes in the interface for ModelType.

One solution which would not break existing code (but uses some more complex template code) is to check at compile time if the ModelType has the required members to circumvent copying and otherwise to sample like it is sampling now.
This is something we've used in our convex polytope sampling library, see for example https://github.com/modsim/hops/blob/main/include/hops/MarkovChain/MarkovChainAdapter.hpp.

Any thoughts on this?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions