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

fresh rebase of threading for DAGMC #561

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from

Conversation

makeclean
Copy link
Contributor

This finally adds thread support to DAGMC, this includes the most efficient method of creating a new DAGMC constructor that allows reuse of the GTT that way there is no duplication of OBB's. This is neede for @pshriwise for OpenMC work.

As ever all comments welcome :)

Also, please let me know the new requirements for PR's

@pshriwise
Copy link
Member

Thank you @makeclean!! This is going to be extremely helpful.

One new thing we do is add a short blurb file (basically the PR description) to the news directory.

I'll take a look at the code changes soon!

@pshriwise
Copy link
Member

Code style needs an update and it looks this is relying on some std library calls that don't exist in older compiler versions.

@makeclean
Copy link
Contributor Author

I will PR those changes later tonight :)

Copy link
Member

@pshriwise pshriwise left a comment

Choose a reason for hiding this comment

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

I have a few questions, but this looks great @makeclean!

list(APPEND DAGMC_SRC_FILES ${CMAKE_SOURCE_DIR}/src/uwuw/uwuw.cpp)

# Public headers
list(APPEND DAGMC_PUB_HEADERS DagMC.hpp)
list(APPEND DAGMC_PUB_HEADERS dagmcmetadata.hpp)
list(APPEND DAGMC_PUB_HEADERS thread_manager.hpp)
Copy link
Member

Choose a reason for hiding this comment

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

If this is going to be a public header, we might want to get DAGMC or DAG into its name to avoid clashing with another header in the future.

delete GTT;
if(gtt_instance_created)
delete GTT;

delete GQT;
Copy link
Member

Choose a reason for hiding this comment

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

We can always delete the GQT safely too?

@@ -30,6 +29,10 @@ namespace moab {

class CartVect;

#define DAGMC_VERSION 3.0
Copy link
Member

Choose a reason for hiding this comment

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

These are no longer included from the DagMCVersion header?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thats either a new one on me, or one I was never aware of. Should I just include DagMCVersion.hpp?

@@ -26,6 +26,15 @@ setup_test(dagmc_pointinvol_test cpp ${DRIVER} "${LINK_LIBS}")
setup_test(dagmc_rayfire_test cpp ${DRIVER} "${LINK_LIBS}")
setup_test(dagmc_simple_test cpp ${DRIVER} "${LINK_LIBS}")

if(OPENMP_BUILD)
Copy link
Member

Choose a reason for hiding this comment

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

Is OPENMP_BUILD a DAGMC CMake variable? Should we add it as an option in the main CMakeLists file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since the threadmanager does not itself depend on OpenMP this was only so that the test actually uses it. So I'll defer on that one, all the -D options are all global anyhow, so if you set

cmake -DOPENMP_BUILD=ON ..... 

Then its throughout all the Cmakefiles anyhow


// set the number of threads
if ( argc > 1 ) {
num_thread_to_run = std::atoi(argv[1]);
Copy link
Member

Choose a reason for hiding this comment

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

This is that line causing some of the unit tests to fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, that one can be fixed.

}

// set the number of threads
void DagThreadManager::set_num_threads(int thread_count) {
Copy link
Member

Choose a reason for hiding this comment

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

I was a little confused by this. Is this something that might change often?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no, but I through habit always give a public member function to change stuff through the constructor. Like you could call with 1 thread to the main constructor, the use case I had in mind was that at the time of loading the DAGMC geometry, one didnt know the number of threads. Some time later, you figure out the number of threads, you can then set the number of threads with that function and then setup accordingly.

Copy link
Member

Choose a reason for hiding this comment

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

I see what you mean. There should probably be some way to handle going from N to M threads, deleting or constructing instances as needed, yeah?

The case where M < N is probably not very likely, but tackling the general problem early will mean it's taken care of for good. Could there be a method called update_child_threads which would handle this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TBH I only really imagined from going from 1->M, I hadnt thought about going down, but yes to do it properly one should have an update method.

@pshriwise
Copy link
Member

One thing I was wondering about the interface is if we want to replicate some of the DAGMC calls via the interface, but with an additional thread argument at the end. So DAGMC->ray_fire(vol, pos, dir, dist, surf)
would become DAGMC->ray_fire(vol, pos, dir, dist, surf, thread_id) in the threaded interface.

Additionally, it might be nice to have a constructor which will create all of the DAGMC instances, setup the OBB tree, and initialize all instances in one step, so it looks very much like our current DAGMC constructor, but, again, with an additional argument indicating the number of threads.

@makeclean
Copy link
Contributor Author

re the constructor it's bad practise to have operations that can fail, so setting up obbs can fail hence why it's done outside the constructor now. Unless something has changed and I don't realise it? Right now we construct, load_file and then init_OBBs after right? If what you want really is to mask the cruft of setting up threads, I can have a think how that could be done.

@pshriwise
Copy link
Member

True about having potential failure points in the constructor.

Yeah I think that's mainly what I'm going for. In the case of what I'll call "thread 0" operations, those could be wrapped automatically to the 0th DAGMC instance.

moab::ErrorCode DagMCThreadManager::init_OBBs() { return dagmc_instances[0]->init_OBBs(); }

@makeclean
Copy link
Contributor Author

I see, so you want the thread manager functions to more closely mimic the main DagMC interface?

@pshriwise
Copy link
Member

Wherever possible, yeah. Users can still access DAGMC instances manually with what's there already. Tricky parts may involve places in MC interface code where we interface directly with RayHistory objects - doing resets and such. I'm thinking of MCNP here.

But I suppose there's no reason we couldn't forward those calls to the right object as well.

@makeclean
Copy link
Contributor Author

makeclean commented Sep 18, 2018

Hence the macros

#define DAGMC(X) DTM->get_dagmc_instance(X)
#define RAY_HISTORY(X) DTM->get_ray_history(X)

That's what the macros are intended to simplify. e.g.

RAY_HISTORY(omp_get_thread_num()).reset();
RAY_HISTORY(omp_get_thread_num()).rollback();

Is that insufficient? Or is it more that there needs to be a neater way? I mean you could actually change a whole bunch of stuff around. So for example

DTM *DAGMC = new DagThreadManager();
DAGMC->ray_fire(...,ray_history(thread_id), thread_id);
DAGMC->point_in_vol(...,ray_history(thread_id), thread_id);

The biggest pain here is going to be the number of default arguments that we typically don't use, see

ErrorCode ray_fire(const EntityHandle volume, const double ray_start[3],
                     const double ray_dir[3], EntityHandle& next_surf,
                     double& next_surf_dist,
                     RayHistory* history = NULL,
                     double dist_limit = 0, int ray_orientation = 1,
                     OrientedBoxTreeTool::TrvStats* stats = NULL);

But I do appreciate the simplicity of just passing in the thread id to function. This is one of the reasons I went the way I did, to avoid adding even more arguments to our already long list. What do you think?

@pshriwise
Copy link
Member

pshriwise commented Sep 18, 2018

I don't see the macros in this PR, but I know what you're talking about. I think they're a really good way to simplify those calls, but they'd either have to be redefined in every implementation we use or be exposed as part of the threading interface header somehow. At that point, it seems like they might as well be functions in the interface.

For the ray history, the default could be to look up the appropriate instance with the option of the user overriding that argument by passing NULL? Not totally happy with that, but I'd like to avoid extra calls in the physics codes if possible. The cleaner it looks there, the less perceived overhead DAGMC has and it keeps the focus on how to fit it into the transport process.

Re: default args - Yeah that would be a bit of a hassle, but not too bad, right? Just a copy of the signature and its defaults.

@makeclean
Copy link
Contributor Author

My bad, I thought they were, I'll include them in the header, then the physics codes have access to them for free by bringing them in from the header. Actually, maybe you cant since you wont know the name for the thread manager pointer. I'll see what I can come up with.

@makeclean
Copy link
Contributor Author

Hmm, when I run astyle I get 44 files reformatted, files that I haven't touched, im running astyle as in the travis test, but I have to remove the line continuation 80 line ( my package manager version doesnt support that one), does this sound right @ljacobson64?

@ljacobson64
Copy link
Member

@makeclean Unfortunately, different version of astyle give different results. Travis is using version 3.0.1. Can you try that one and see if the tests pass?

@gonuke
Copy link
Member

gonuke commented Dec 13, 2018

This probably needs a rebase, but is it otherwise ready?

@pshriwise
Copy link
Member

Is this still a work in progress @makeclean?

@ahnaf-tahmid-chowdhury
Copy link
Member

Any update?

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.

None yet

5 participants